From 21c1bc1cd5fa738c0f48dac66dd1543710753da8 Mon Sep 17 00:00:00 2001 From: Grigoriy Gusev Date: Sun, 22 Sep 2024 09:27:30 +0300 Subject: [PATCH 1/5] init --- README-PYPI.md | 16 +- README.md | 24 +- README.ru.md | 24 +- pyproject.toml | 59 +++ src/streamdeck_sdk/__init__.py | 10 + src/streamdeck_sdk/event_routings.py | 59 +++ src/streamdeck_sdk/logger.py | 60 +++ src/streamdeck_sdk/mixins/__init__.py | 10 + .../mixins/debug_server_mixin.py | 50 +++ .../mixins/event_routing_mixin.py | 134 ++++++ .../mixins/handle_event_mixins.py | 72 +++ .../mixins/send_event_mixins.py | 421 ++++++++++++++++++ src/streamdeck_sdk/sd_objs/__init__.py | 3 + .../sd_objs/events_received_objs/__init__.py | 23 + .../application_did_launch.py | 25 ++ .../application_did_terminate.py | 25 ++ .../events_received_objs/assets/__init__.py | 0 .../assets/controller_enum.py | 9 + .../assets/key_coordinates.py | 9 + .../device_did_connect.py | 37 ++ .../device_did_disconnect.py | 14 + .../sd_objs/events_received_objs/dial_down.py | 37 ++ .../events_received_objs/dial_rotate.py | 42 ++ .../sd_objs/events_received_objs/dial_up.py | 37 ++ .../did_receive_deep_link.py | 27 ++ .../did_receive_global_settings.py | 19 + .../did_receive_settings.py | 39 ++ .../sd_objs/events_received_objs/key_down.py | 44 ++ .../sd_objs/events_received_objs/key_up.py | 44 ++ .../property_inspector_did_appear.py | 19 + .../property_inspector_did_disappear.py | 18 + .../events_received_objs/send_to_plugin.py | 18 + .../send_to_property_inspector.py | 19 + .../system_did_wake_up.py | 16 + .../title_parameters_did_change.py | 59 +++ .../sd_objs/events_received_objs/touch_tap.py | 43 ++ .../events_received_objs/will_appear.py | 50 +++ .../events_received_objs/will_disappear.py | 48 ++ .../sd_objs/events_sent_objs/__init__.py | 17 + .../events_sent_objs/get_global_settings.py | 17 + .../sd_objs/events_sent_objs/get_settings.py | 17 + .../sd_objs/events_sent_objs/log_message.py | 24 + .../sd_objs/events_sent_objs/open_url.py | 22 + .../events_sent_objs/send_to_plugin.py | 21 + .../send_to_property_inspector.py | 19 + .../sd_objs/events_sent_objs/set_feedback.py | 20 + .../events_sent_objs/set_feedback_layout.py | 26 ++ .../events_sent_objs/set_global_settings.py | 23 + .../sd_objs/events_sent_objs/set_image.py | 35 ++ .../sd_objs/events_sent_objs/set_settings.py | 22 + .../sd_objs/events_sent_objs/set_state.py | 23 + .../sd_objs/events_sent_objs/set_title.py | 33 ++ .../set_trigger_description.py | 39 ++ .../sd_objs/events_sent_objs/show_alert.py | 15 + .../sd_objs/events_sent_objs/show_ok.py | 15 + .../events_sent_objs/switch_to_profile.py | 32 ++ .../sd_objs/registration_objs.py | 87 ++++ src/streamdeck_sdk/sdk.py | 166 +++++++ src/streamdeck_sdk/simple_ws/__init__.py | 1 + src/streamdeck_sdk/simple_ws/client.py | 61 +++ src/streamdeck_sdk/utils/__init__.py | 2 + src/streamdeck_sdk/utils/image_converters.py | 22 + .../utils/in_separate_thread.py | 41 ++ 63 files changed, 2412 insertions(+), 51 deletions(-) create mode 100644 pyproject.toml create mode 100644 src/streamdeck_sdk/__init__.py create mode 100644 src/streamdeck_sdk/event_routings.py create mode 100644 src/streamdeck_sdk/logger.py create mode 100644 src/streamdeck_sdk/mixins/__init__.py create mode 100644 src/streamdeck_sdk/mixins/debug_server_mixin.py create mode 100644 src/streamdeck_sdk/mixins/event_routing_mixin.py create mode 100644 src/streamdeck_sdk/mixins/handle_event_mixins.py create mode 100644 src/streamdeck_sdk/mixins/send_event_mixins.py create mode 100644 src/streamdeck_sdk/sd_objs/__init__.py create mode 100644 src/streamdeck_sdk/sd_objs/events_received_objs/__init__.py create mode 100644 src/streamdeck_sdk/sd_objs/events_received_objs/application_did_launch.py create mode 100644 src/streamdeck_sdk/sd_objs/events_received_objs/application_did_terminate.py create mode 100644 src/streamdeck_sdk/sd_objs/events_received_objs/assets/__init__.py create mode 100644 src/streamdeck_sdk/sd_objs/events_received_objs/assets/controller_enum.py create mode 100644 src/streamdeck_sdk/sd_objs/events_received_objs/assets/key_coordinates.py create mode 100644 src/streamdeck_sdk/sd_objs/events_received_objs/device_did_connect.py create mode 100644 src/streamdeck_sdk/sd_objs/events_received_objs/device_did_disconnect.py create mode 100644 src/streamdeck_sdk/sd_objs/events_received_objs/dial_down.py create mode 100644 src/streamdeck_sdk/sd_objs/events_received_objs/dial_rotate.py create mode 100644 src/streamdeck_sdk/sd_objs/events_received_objs/dial_up.py create mode 100644 src/streamdeck_sdk/sd_objs/events_received_objs/did_receive_deep_link.py create mode 100644 src/streamdeck_sdk/sd_objs/events_received_objs/did_receive_global_settings.py create mode 100644 src/streamdeck_sdk/sd_objs/events_received_objs/did_receive_settings.py create mode 100644 src/streamdeck_sdk/sd_objs/events_received_objs/key_down.py create mode 100644 src/streamdeck_sdk/sd_objs/events_received_objs/key_up.py create mode 100644 src/streamdeck_sdk/sd_objs/events_received_objs/property_inspector_did_appear.py create mode 100644 src/streamdeck_sdk/sd_objs/events_received_objs/property_inspector_did_disappear.py create mode 100644 src/streamdeck_sdk/sd_objs/events_received_objs/send_to_plugin.py create mode 100644 src/streamdeck_sdk/sd_objs/events_received_objs/send_to_property_inspector.py create mode 100644 src/streamdeck_sdk/sd_objs/events_received_objs/system_did_wake_up.py create mode 100644 src/streamdeck_sdk/sd_objs/events_received_objs/title_parameters_did_change.py create mode 100644 src/streamdeck_sdk/sd_objs/events_received_objs/touch_tap.py create mode 100644 src/streamdeck_sdk/sd_objs/events_received_objs/will_appear.py create mode 100644 src/streamdeck_sdk/sd_objs/events_received_objs/will_disappear.py create mode 100644 src/streamdeck_sdk/sd_objs/events_sent_objs/__init__.py create mode 100644 src/streamdeck_sdk/sd_objs/events_sent_objs/get_global_settings.py create mode 100644 src/streamdeck_sdk/sd_objs/events_sent_objs/get_settings.py create mode 100644 src/streamdeck_sdk/sd_objs/events_sent_objs/log_message.py create mode 100644 src/streamdeck_sdk/sd_objs/events_sent_objs/open_url.py create mode 100644 src/streamdeck_sdk/sd_objs/events_sent_objs/send_to_plugin.py create mode 100644 src/streamdeck_sdk/sd_objs/events_sent_objs/send_to_property_inspector.py create mode 100644 src/streamdeck_sdk/sd_objs/events_sent_objs/set_feedback.py create mode 100644 src/streamdeck_sdk/sd_objs/events_sent_objs/set_feedback_layout.py create mode 100644 src/streamdeck_sdk/sd_objs/events_sent_objs/set_global_settings.py create mode 100644 src/streamdeck_sdk/sd_objs/events_sent_objs/set_image.py create mode 100644 src/streamdeck_sdk/sd_objs/events_sent_objs/set_settings.py create mode 100644 src/streamdeck_sdk/sd_objs/events_sent_objs/set_state.py create mode 100644 src/streamdeck_sdk/sd_objs/events_sent_objs/set_title.py create mode 100644 src/streamdeck_sdk/sd_objs/events_sent_objs/set_trigger_description.py create mode 100644 src/streamdeck_sdk/sd_objs/events_sent_objs/show_alert.py create mode 100644 src/streamdeck_sdk/sd_objs/events_sent_objs/show_ok.py create mode 100644 src/streamdeck_sdk/sd_objs/events_sent_objs/switch_to_profile.py create mode 100644 src/streamdeck_sdk/sd_objs/registration_objs.py create mode 100644 src/streamdeck_sdk/sdk.py create mode 100644 src/streamdeck_sdk/simple_ws/__init__.py create mode 100644 src/streamdeck_sdk/simple_ws/client.py create mode 100644 src/streamdeck_sdk/utils/__init__.py create mode 100644 src/streamdeck_sdk/utils/image_converters.py create mode 100644 src/streamdeck_sdk/utils/in_separate_thread.py diff --git a/README-PYPI.md b/README-PYPI.md index 6e3f3aa..2b6634f 100644 --- a/README-PYPI.md +++ b/README-PYPI.md @@ -38,18 +38,8 @@ Library for creating Stream Deck plugins in Python. ## Installation -> ⚠️ To work correctly on Windows, you need to enable `LongPaths` support in -> the system: [manual](https://www.backupery.com/how-to-enable-ntfs-long-paths-in-windows/). -> Without this setting, installation problems may occur! - -```shell -pip install streamdeck-sdk -``` - -or - ```shell -pip install streamdeck_sdk +pip install streamdeck-sdk[dev] ``` ## Features @@ -75,10 +65,6 @@ pip install streamdeck_sdk 1. Plugin requirements should take no longer than 30 seconds to install. This is a feature of Stream Deck on Windows, since the program restarts the plugin if a websocket connection has not been established within 30 seconds. Therefore, you need a good Internet connection when installing and updating the plugin. -2. You need to enable `LongPaths` support in the system - registry: [manual](https://www.backupery.com/how-to-enable-ntfs-long-paths-in-windows/). - - Without this setting, the created plugins will not work! ## Examples diff --git a/README.md b/README.md index 9aadca5..18ae53b 100644 --- a/README.md +++ b/README.md @@ -45,18 +45,8 @@ Library for creating Stream Deck plugins in Python. ## Installation -> ⚠️ To work correctly on Windows, you need to enable `LongPaths` support in -> the system: [manual](https://www.backupery.com/how-to-enable-ntfs-long-paths-in-windows/). -> Without this setting, installation problems may occur! - ```shell -pip install streamdeck-sdk -``` - -or - -```shell -pip install streamdeck_sdk +pip install streamdeck-sdk[dev] ``` ## Features @@ -82,10 +72,6 @@ pip install streamdeck_sdk 1. Plugin requirements should take no longer than 30 seconds to install. This is a feature of Stream Deck on Windows, since the program restarts the plugin if a websocket connection has not been established within 30 seconds. Therefore, you need a good Internet connection when installing and updating the plugin. -2. You need to enable `LongPaths` support in the system - registry: [manual](https://www.backupery.com/how-to-enable-ntfs-long-paths-in-windows/). - - Without this setting, the created plugins will not work! ## Quick Start @@ -94,7 +80,7 @@ pip install streamdeck_sdk 3. Go to the project folder, activate `venv` and install the `streamdeck-sdk` library: ```shell -pip install streamdeck-sdk +pip install streamdeck-sdk[dev] ``` 4. Run the command to start the project: @@ -107,6 +93,8 @@ After completing this step, the folder `com.bestdeveloper.mytestplugin.sdPlugin` 5. Build the plugin using the command: +> ⚠️ The `requirements.txt` file should not contain the `streamdeck-sdk-*` libraries. If there are any, remove them. + ```shell streamdeck_sdk build -i com.bestdeveloper.mytestplugin.sdPlugin ``` @@ -245,7 +233,7 @@ Here are the elements available for generation in Python: ```python from pathlib import Path -from streamdeck_sdk.property_inspector import * +from streamdeck_sdk_pi import * OUTPUT_DIR = Path(__file__).parent TEMPLATE = Path(__file__).parent / "pi_template.html" @@ -544,7 +532,7 @@ For example, you made a Property Inspector like this and generated it: ```python from pathlib import Path -from streamdeck_sdk.property_inspector import * +from streamdeck_sdk_pi import * OUTPUT_DIR = Path(__file__).parent TEMPLATE = Path(__file__).parent / "pi_template.html" diff --git a/README.ru.md b/README.ru.md index 25b7a5d..5941ccf 100644 --- a/README.ru.md +++ b/README.ru.md @@ -45,18 +45,8 @@ ## Установка -> ⚠️ Для корректной работы на Windows нужно включить поддержку `LongPaths` в -> системе: [manual](https://www.backupery.com/how-to-enable-ntfs-long-paths-in-windows/). -> Без этой настройки возможны проблемы с установкой! - ```shell -pip install streamdeck-sdk -``` - -or - -```shell -pip install streamdeck_sdk +pip install streamdeck-sdk[dev] ``` ## Возможности @@ -82,10 +72,6 @@ pip install streamdeck_sdk 1. Зависимости плагина должны устанавливаться не дольше 30 секунд. Это особенность Stream Deck на Windows, так как программа перезапускает плагин, если в течение 30 секунд не было установлено websocket соединение. Поэтому нужен хороший интернет при установке и обновлении плагина. -2. Нужно включить поддержку `LongPaths` в реестре - системы: [manual](https://www.backupery.com/how-to-enable-ntfs-long-paths-in-windows/). - - Без этой настройки созданные плагины не будут работать! ## Быстрый старт @@ -94,7 +80,7 @@ pip install streamdeck_sdk 3. Перейдите в папку проекта, активируйте `venv` и установите библиотеку `streamdeck-sdk`: ```shell -pip install streamdeck-sdk +pip install streamdeck-sdk[dev] ``` 4. Выполните команду для старта проекта: @@ -107,6 +93,8 @@ streamdeck_sdk startproject 5. Соберите плагин с помощью команды: +> ⚠️ В файле `requirements.txt` не должно быть библиотек `streamdeck-sdk-*`. Если они есть - удалите их. + ```shell streamdeck_sdk build -i com.bestdeveloper.mytestplugin.sdPlugin ``` @@ -245,7 +233,7 @@ $PI.onSendToPropertyInspector("com.ggusev.keyboard.write", jsn => { ```python from pathlib import Path -from streamdeck_sdk.property_inspector import * +from streamdeck_sdk_pi import * OUTPUT_DIR = Path(__file__).parent TEMPLATE = Path(__file__).parent / "pi_template.html" @@ -544,7 +532,7 @@ if __name__ == '__main__': ```python from pathlib import Path -from streamdeck_sdk.property_inspector import * +from streamdeck_sdk_pi import * OUTPUT_DIR = Path(__file__).parent TEMPLATE = Path(__file__).parent / "pi_template.html" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..d550539 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,59 @@ +[build-system] +requires = ["setuptools >= 60.0"] +build-backend = "setuptools.build_meta" + +[project] +name = "streamdeck_sdk" +version = "1.2.0.dev4" +authors = [ + { name = "Grigoriy Gusev", email = "thegrigus@gmail.com" }, +] +description = "Library for creating Stream Deck plugins in Python." +readme = "README-PYPI.md" +dependencies = [ + "annotated-types==0.7.0", + "decohints==1.0.9", + "pydantic==2.8.2", + "pydantic_core==2.20.1", + "typing_extensions==4.12.2", + "websockets==13.0.1", +] +requires-python = ">=3.8" +keywords = [ + "property inspector", + "property inspector generator", + "streamdeck property inspector generator", + "streamdeck property inspector", + "streamdeck pi", + "python", + "sdk", + "streamdeck", + "streamdeck-sdk", + "streamdeck_sdk", + "stream deck sdk", + "stream deck", + "elgato", + "elgato sdk", + "elgato stream deck", + "streamdeck-python-sdk", + "streamdeck_python_sdk", + "streamdeck python sdk", +] +classifiers = [ + "Programming Language :: Python :: 3.10", + "License :: OSI Approved :: Apache Software License", + "Operating System :: OS Independent", +] + +[project.optional-dependencies] +dev = [ + "streamdeck-sdk-cli>=0.0.1.dev6,<0.0.2", + "streamdeck-sdk-pi>=0.0.1.dev1,<0.0.2", +] + +[project.urls] +Homepage = "https://github.com/gri-gus/streamdeck-python-sdk" +Source = "https://github.com/gri-gus/streamdeck-python-sdk" + +[tool.setuptools.packages.find] +where = ["src"] diff --git a/src/streamdeck_sdk/__init__.py b/src/streamdeck_sdk/__init__.py new file mode 100644 index 0000000..c642ca1 --- /dev/null +++ b/src/streamdeck_sdk/__init__.py @@ -0,0 +1,10 @@ +from . import mixins +from .logger import logger, log_errors +from .sd_objs import events_received_objs, events_sent_objs, registration_objs +from .sdk import StreamDeck, Action +from .utils import image_file_to_base64, image_bytes_to_base64, in_separate_thread + +try: + from streamdeck_sdk_pi import property_inspector +except Exception: + pass diff --git a/src/streamdeck_sdk/event_routings.py b/src/streamdeck_sdk/event_routings.py new file mode 100644 index 0000000..eedd66d --- /dev/null +++ b/src/streamdeck_sdk/event_routings.py @@ -0,0 +1,59 @@ +from enum import Enum +from typing import Type, Dict, get_type_hints + +from pydantic import BaseModel + +from . import mixins + + +class EventRoutingObjTypes(Enum): + ACTION = "ACTION" + PLUGIN = "PLUGIN" + + +class EventRoutingObj(BaseModel): + handler_name: str + obj_type: Type[BaseModel] + type: EventRoutingObjTypes + + +EVENT_ROUTING_MAP: Dict[str, EventRoutingObj] = {} + + +def fill_routing_map( + routing_map: Dict[str, EventRoutingObj], + event_handler_mixin: mixins.BaseEventHandlerMixin, + event_routing_obj_type: EventRoutingObjTypes, +) -> None: + event_handler_mixin_dict = dict(event_handler_mixin.__dict__) + for attr, value in event_handler_mixin_dict.items(): + attr: str + if not attr.startswith("on_"): + continue + assert callable(value) + + handler_type_hints = get_type_hints(value) + obj_type = handler_type_hints["obj"] + obj = obj_type.construct() + event_name = obj.event + handler_name = value.__name__ + routing_map[event_name] = EventRoutingObj( + handler_name=handler_name, + obj_type=obj_type, + type=event_routing_obj_type, + ) + + +def fill_event_routing_map() -> None: + for event_handler_mixin, event_routing_obj_type in ( + (mixins.ActionEventHandlersMixin, EventRoutingObjTypes.ACTION), + (mixins.PluginEventHandlersMixin, EventRoutingObjTypes.PLUGIN), + ): + fill_routing_map( + routing_map=EVENT_ROUTING_MAP, + event_handler_mixin=event_handler_mixin, + event_routing_obj_type=event_routing_obj_type, + ) + + +fill_event_routing_map() diff --git a/src/streamdeck_sdk/logger.py b/src/streamdeck_sdk/logger.py new file mode 100644 index 0000000..2b6ffba --- /dev/null +++ b/src/streamdeck_sdk/logger.py @@ -0,0 +1,60 @@ +import logging +from functools import wraps +from logging.handlers import RotatingFileHandler +from pathlib import Path + +from decohints import decohints + +_root_logger: logging.Logger = logging.getLogger() +_log_errors_decorator_logger = logging.getLogger("log_errors_decorator") +logger = logging.getLogger("streamdeck_plugin") + + +def init_root_logger( + log_file: Path, + log_level: int = logging.DEBUG, + log_max_bytes: int = 3 * 1024 * 1024, + log_backup_count: int = 2, +) -> None: + _root_logger.setLevel(log_level) + logs_dir: Path = log_file.parent + logs_dir.mkdir(parents=True, exist_ok=True) + rfh = RotatingFileHandler( + log_file, + mode='a', + maxBytes=log_max_bytes, + backupCount=log_backup_count, + encoding="utf-8", + delay=False, + ) + rfh.setLevel(logging.DEBUG) + formatter = logging.Formatter( + "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d): %(message)s" + ) + rfh.setFormatter(formatter) + _root_logger.addHandler(rfh) + + +@decohints +def log_errors(func): + """ + A decorator that logs and suppresses errors in the function being decorated. + """ + + @wraps(func) + def wrapper(*args, **kwargs): + try: + result = func(*args, **kwargs) + except SystemExit as err: + _log_errors_decorator_logger.exception(str(err)) + raise err + except BaseException as err: + _log_errors_decorator_logger.exception(str(err)) + return + return result + + return wrapper + + +def rename_plugin_logger(name: str): + logger.name = name diff --git a/src/streamdeck_sdk/mixins/__init__.py b/src/streamdeck_sdk/mixins/__init__.py new file mode 100644 index 0000000..dc1eecc --- /dev/null +++ b/src/streamdeck_sdk/mixins/__init__.py @@ -0,0 +1,10 @@ +from .handle_event_mixins import * +from .send_event_mixins import * + + +class Base( + PluginEventHandlersMixin, + ActionEventHandlersMixin, + EventsSendMixin, +): + pass diff --git a/src/streamdeck_sdk/mixins/debug_server_mixin.py b/src/streamdeck_sdk/mixins/debug_server_mixin.py new file mode 100644 index 0000000..06ba65d --- /dev/null +++ b/src/streamdeck_sdk/mixins/debug_server_mixin.py @@ -0,0 +1,50 @@ +import logging +from typing import Set + +from websockets.sync.server import ( + ServerConnection, + WebSocketServer, # noqa + serve, +) + +from src.streamdeck_sdk.mixins import SendMixin +from src.streamdeck_sdk.simple_ws.client import WebSocketClientApp +from src.streamdeck_sdk.utils.in_separate_thread import in_separate_thread + +logger = logging.getLogger(__name__) + + +class DebugServerMixin(SendMixin): + debug_clients: Set[ServerConnection] + debug_port: int + + @in_separate_thread(daemon=True) + def _debug_server_run(self): + server: WebSocketServer = serve( + handler=self._debug_server_handler, + host="localhost", + port=self.debug_port, + ) + server.serve_forever() + + def _debug_server_handler(self, websocket: ServerConnection): + self.debug_clients.add(websocket) + logger.debug(f"Client {websocket} added, clients: {self.debug_clients}.") + try: + for message in websocket: + logger.debug(f"Message {message} received from StreamDeckPlugin.") + self.ws.send(message) + logger.debug(f"Message {message} sent to StreamDeck.") + except Exception: # noqa + self.debug_clients.remove(websocket) + logger.debug(f"Client {websocket} removed, clients: {self.debug_clients}") + + def _debug_server_on_message( + self, + ws: WebSocketClientApp, # noqa + message: str, + ) -> None: + logger.debug(f"Received message from StreamDeck. message={message}.") + for client in self.debug_clients: + client.send(message) + logger.debug(f"Message sent to StreamDeckPlugin {client}. message={message}.") diff --git a/src/streamdeck_sdk/mixins/event_routing_mixin.py b/src/streamdeck_sdk/mixins/event_routing_mixin.py new file mode 100644 index 0000000..dbfbf78 --- /dev/null +++ b/src/streamdeck_sdk/mixins/event_routing_mixin.py @@ -0,0 +1,134 @@ +import json +import logging +from typing import Callable + +import pydantic + +from src.streamdeck_sdk import event_routings +from src.streamdeck_sdk.logger import ( + log_errors, +) +from src.streamdeck_sdk.mixins import EventsSendMixin +from src.streamdeck_sdk.simple_ws.client import WebSocketClientApp + +logger = logging.getLogger(__name__) + + +class EventRoutingMixin(EventsSendMixin): + registration_dict: dict + actions: dict + + @log_errors + def ws_on_open( + self, + ws: WebSocketClientApp, # noqa + ) -> None: + logger.info("WS OPENED") + self.send(data=self.registration_dict) + + @log_errors + def ws_on_close( + self, + ws: WebSocketClientApp, # noqa + close_status_code: int, + close_msg: str, + ) -> None: + logger.debug(f"{close_status_code=}; {close_msg=}") + logger.info(f"WS CLOSED") + exit(0) + + @log_errors + def ws_on_error( + self, + ws: WebSocketClientApp, # noqa + error, + ) -> None: + logger.error(f"{error=}") + + @log_errors + def ws_on_message( + self, + ws: WebSocketClientApp, # noqa + message: str, + ) -> None: + logger.info(f"Message processing has started. message={message}") + message_dict = json.loads(message) + logger.debug(f"{message_dict=}") + event = message_dict["event"] + logger.debug(f"{event=}") + event_routing = event_routings.EVENT_ROUTING_MAP.get(event) + if event_routing is None: + logger.warning("event_routing is None") + return + + obj = event_routing.obj_type.model_validate(message_dict) + logger.debug(f"{obj=}") + + self.route_event_in_plugin_handler(event_routing=event_routing, obj=obj) + if event_routing.type is event_routings.EventRoutingObjTypes.ACTION: + self.route_action_event_in_action_handler(event_routing=event_routing, obj=obj) + elif event_routing.type is event_routings.EventRoutingObjTypes.PLUGIN: + self.route_plugin_event_in_action_handlers(event_routing=event_routing, obj=obj) + logger.info(f"Message processing completed. message={message}") + + @log_errors + def route_event_in_plugin_handler( + self, + event_routing: event_routings.EventRoutingObj, + obj: pydantic.BaseModel, + ) -> None: + try: + handler: Callable = getattr(self, event_routing.handler_name) + except AttributeError as err: + logger.error(f"Handler missing: {str(err)}", exc_info=True) + return + self.handle_message(handler=handler, obj=obj) + + @log_errors + def route_action_event_in_action_handler( + self, + event_routing: event_routings.EventRoutingObj, + obj: pydantic.BaseModel, + ) -> None: + try: + action_uuid = getattr(obj, "action") + except AttributeError as err: + logger.error(str(err), exc_info=True) + return + action_obj = self.actions.get(action_uuid) + if action_obj is None: + logger.warning(f"{action_uuid=} not registered") + return + try: + handler: Callable = getattr(action_obj, event_routing.handler_name) + except AttributeError as err: + logger.error(f"Handler missing: {str(err)}", exc_info=True) + return + self.handle_message(handler=handler, obj=obj) + + @log_errors + def route_plugin_event_in_action_handlers( + self, + event_routing: event_routings.EventRoutingObj, + obj: pydantic.BaseModel, + ) -> None: + for action_obj in self.actions.values(): + try: + handler: Callable = getattr(action_obj, event_routing.handler_name) + except AttributeError as err: + logger.error(f"Handler missing: {str(err)}", exc_info=True) + return + self.handle_message(handler=handler, obj=obj) + + @log_errors + def handle_message( + self, + handler: Callable, + obj: pydantic.BaseModel + ) -> None: + try: + handler(obj) + except Exception: + self.show_alert( + context=obj.context, + ) diff --git a/src/streamdeck_sdk/mixins/handle_event_mixins.py b/src/streamdeck_sdk/mixins/handle_event_mixins.py new file mode 100644 index 0000000..82832b5 --- /dev/null +++ b/src/streamdeck_sdk/mixins/handle_event_mixins.py @@ -0,0 +1,72 @@ +from ..sd_objs import events_received_objs + + +class BaseEventHandlerMixin: + pass + + +class ActionEventHandlersMixin(BaseEventHandlerMixin): + def on_did_receive_settings(self, obj: events_received_objs.DidReceiveSettings) -> None: + pass + + def on_key_down(self, obj: events_received_objs.KeyDown) -> None: + pass + + def on_key_up(self, obj: events_received_objs.KeyUp) -> None: + pass + + def on_touch_tap(self, obj: events_received_objs.TouchTap) -> None: + pass + + def on_dial_down(self, obj: events_received_objs.DialDown) -> None: + pass + + def on_dial_up(self, obj: events_received_objs.DialUp) -> None: + pass + + def on_dial_rotate(self, obj: events_received_objs.DialRotate) -> None: + pass + + def on_will_appear(self, obj: events_received_objs.WillAppear) -> None: + pass + + def on_did_receive_deep_link(self, obj: events_received_objs.DidReceiveDeepLink) -> None: + pass + + def on_will_disappear(self, obj: events_received_objs.WillDisappear) -> None: + pass + + def on_title_parameters_did_change(self, obj: events_received_objs.TitleParametersDidChange) -> None: + pass + + def on_property_inspector_did_appear(self, obj: events_received_objs.PropertyInspectorDidAppear) -> None: + pass + + def on_property_inspector_did_disappear(self, obj: events_received_objs.PropertyInspectorDidDisappear) -> None: + pass + + def on_send_to_plugin(self, obj: events_received_objs.SendToPlugin) -> None: + pass + + def on_send_to_property_inspector(self, obj: events_received_objs.SendToPropertyInspector) -> None: + pass + + +class PluginEventHandlersMixin(BaseEventHandlerMixin): + def on_did_receive_global_settings(self, obj: events_received_objs.DidReceiveGlobalSettings) -> None: + pass + + def on_device_did_connect(self, obj: events_received_objs.DeviceDidConnect) -> None: + pass + + def on_device_did_disconnect(self, obj: events_received_objs.DeviceDidDisconnect) -> None: + pass + + def on_application_did_launch(self, obj: events_received_objs.ApplicationDidLaunch) -> None: + pass + + def on_application_did_terminate(self, obj: events_received_objs.ApplicationDidTerminate) -> None: + pass + + def on_system_did_wake_up(self, obj: events_received_objs.SystemDidWakeUp) -> None: + pass diff --git a/src/streamdeck_sdk/mixins/send_event_mixins.py b/src/streamdeck_sdk/mixins/send_event_mixins.py new file mode 100644 index 0000000..ed0f915 --- /dev/null +++ b/src/streamdeck_sdk/mixins/send_event_mixins.py @@ -0,0 +1,421 @@ +import json +import logging +from typing import Union, Optional + +import pydantic + +from ..logger import log_errors +from ..sd_objs import events_sent_objs +from ..simple_ws.client import WebSocketClientApp + +logger = logging.getLogger(__name__) + + +class SendMixin: + ws: WebSocketClientApp + + @log_errors + def send( + self, + data: Union[pydantic.BaseModel, dict, str] + ) -> None: + """ + Converts the data value to json and sends it. + """ + if isinstance(data, pydantic.BaseModel): + data = json.dumps(data.model_dump(), ensure_ascii=True) + elif isinstance(data, dict): + data = json.dumps(data, ensure_ascii=False) + elif isinstance(data, str): + pass + else: + logger.warning(f"Invalid data type {type(data)} to send. The message will not be sent! data={data}") + return + self.ws.send(data) + + +class EventsSendMixin(SendMixin): + plugin_uuid: str + + def get_global_settings( + self, + ) -> None: + """ + The plugin and Property Inspector can request the persistent global data using the getGlobalSettings event. + The plugin or Property Inspector will receive asynchronously an event didReceiveGlobalSettings the p + containing the global settings. + + https://docs.elgato.com/sdk/plugins/events-sent#getglobalsettings + """ + message = events_sent_objs.GetGlobalSettings( + context=self.plugin_uuid, + ) + self.send(message) + + def get_settings( + self, + context: str, + ) -> None: + """ + The plugin and Property Inspector can request the persistent data stored for the action's + instance using the getSettings event. + + https://docs.elgato.com/sdk/plugins/events-sent#getsettings + + :param context: A value to Identify the instance's action or Property Inspector. In the case of + the Property Inspector, this value is received by the Property Inspector as parameter of + the connectElgatoStreamDeckSocket function. + """ + message = events_sent_objs.GetSettings( + context=context, + ) + self.send(message) + + def log_message( + self, + message: str, + ) -> None: + r""" + The plugin and Property Inspector can use the logMessage event to write a debug message to the logs file. + * Logs are saved to disk per plugin in the folder ~/Library/Logs/ElgatoStreamDeck/ on macOS + and %appdata%\Elgato\StreamDeck\logs\ on Windows. Note that the log files are rotated each time + the Stream Deck application is relaunched. + + https://docs.elgato.com/sdk/plugins/events-sent#logmessage + + :param message: A string to write to the logs file. + """ + message = events_sent_objs.LogMessage( + payload=events_sent_objs.LogMessagePayload( + message=message, + ), + ) + self.send(message) + + def open_url( + self, + url: str, + ) -> None: + """ + The plugin and Property Inspector can tell the Stream Deck application to open URL in the + default browser using the openUrl event. + + https://docs.elgato.com/sdk/plugins/events-sent#openurl + + :param url: An URL to open in the default browser. + """ + message = events_sent_objs.OpenUrl( + payload=events_sent_objs.OpenUrlPayload( + url=url, + ), + ) + self.send(message) + + def send_to_property_inspector( + self, + action: str, + context: str, + payload: dict, + ) -> None: + """ + The plugin can send a payload to the Property Inspector using the sendToPropertyInspector event. + The Property Inspector will receive asynchronously an event sendToPropertyInspector. + + https://docs.elgato.com/sdk/plugins/events-sent#sendtopropertyinspector + + :param action: The action's unique identifier. + :param context: A value to identify the instance's action. + :param payload: A JSON object that will be received by the Property Inspector. + """ + message = events_sent_objs.SendToPropertyInspector( + action=action, + context=context, + payload=payload, + ) + self.send(message) + + def set_feedback( + self, + context: str, + payload: dict, + ) -> None: + """ + (SD+) + The plugin can send a setFeedback event to the Stream Deck application to dynamically change properties of + items on the Stream Deck + touch display layout. + + https://docs.elgato.com/sdk/plugins/events-sent#setfeedback-sd + + :param context: A value to Identify the instance's action you want to modify. + :param payload: A dict object. + key: The key is a name of the element in layout to be changed with given value. + value: The value to be set in key named layout element. + """ + message = events_sent_objs.SetFeedback( + context=context, + payload=payload, + ) + self.send(message) + + def set_feedback_layout( + self, + context: str, + layout: str, + ) -> None: + """ + (SD+) + The plugin can send a setFeedbackLayout event to the Stream Deck application to dynamically change the + current Stream Deck + touch display layout. setFeedbackLayout can use the id of a built-in layout or + a relative path to a custom layout JSON file. See Layouts for more information. + + https://docs.elgato.com/sdk/plugins/events-sent#setfeedbacklayout-sd + + :param context: A value to Identify the instance's action you want to modify. + :param layout: A predefined layout identifier or the relative path to a json file that + contains a custom layout. + """ + message = events_sent_objs.SetFeedbackLayout( + context=context, + payload=events_sent_objs.SetFeedbackLayoutPayload( + layout=layout, + ), + ) + self.send(message) + + def set_global_settings( + self, + payload: dict, + ) -> None: + """ + The plugin and Property Inspector can save persistent data globally. The data + will be saved securely to the Keychain on macOS and the Credential Store on Windows. This API can + be used to save tokens that should be available to every action in the plugin. + Note that when the plugin uses this API, the Property Inspector will automatically receive + a didReceiveGlobalSettings callback with the new settings. Similarly, when the Property Inspector uses + this API, the plugin will automatically receive a didReceiveGlobalSettings callback with the new settings. + This API has been introduced in Stream Deck 4.1. + + https://docs.elgato.com/sdk/plugins/events-sent#setglobalsettings + + :param payload: A JSON object which is persistently saved globally. + """ + message = events_sent_objs.SetGlobalSettings( + context=self.plugin_uuid, + payload=payload, + ) + self.send(message) + + def set_image( + self, + context: str, + image: str, # base64 + target: int = 0, + state: Optional[int] = None, + ) -> None: + """ + The plugin can send a setImage event to the Stream Deck application to dynamically change the image displayed + by an instance of an action. + + https://docs.elgato.com/sdk/plugins/events-sent#setimage + + :param context: A value to Identify the instance's action you want to modify. + :param image: The image to display encoded in base64 with the image format declared in the mime + type (PNG, JPEG, BMP, ...). svg is also supported. If not provided, the image is + reset to the default image from the manifest. + You can use functions from image_converters.py for convert image in base64. + :param target: Specify if you want to display the title on the hardware and software (0), + only on the hardware (1), or only on the software (2). Default is 0. + :param state: A 0-based integer value representing the state of an action with multiple states. If not + specified, the image is set to all states. + """ + message = events_sent_objs.SetImage( + context=context, + payload=events_sent_objs.SetImagePayload( + image=image, + target=target, + state=state, + ), + ) + self.send(message) + + def set_settings( + self, + context: str, + payload: dict, + ) -> None: + """ + The plugin and Property Inspector can save data persistently for the action's instance using + the setSettings event. + Note that when the plugin uses this API, the Property Inspector will automatically receive a didReceiveSettings + callback with the new settings. Similarly, when the Property Inspector uses this API, the plugin will + automatically receive a didReceiveSettings callback with the new settings. + The setSettings API is available since Stream Deck 4.0 for the plugin. Starting + with Stream Deck 4.1, this API is available from the Property Inspector. + + https://docs.elgato.com/sdk/plugins/events-sent#setsettings + + :param context: A value to Identify the instance's action or Property Inspector. This value is received + by the Property Inspector as a parameter of the connectElgatoStreamDeckSocket function. + :param payload: A JSON object which is persistently saved for the action's instance. + """ + message = events_sent_objs.SetSettings( + context=context, + payload=payload, + ) + self.send(message) + + def set_state( + self, + context: str, + state: int, + ) -> None: + """ + This function can be used by a plugin to dynamically change the state of an action supporting multiple states. + + https://docs.elgato.com/sdk/plugins/events-sent#setstate + + :param context: A value to identify the instance's action. + :param state: A 0-based integer value representing the state requested. + """ + message = events_sent_objs.SetState( + context=context, + payload=events_sent_objs.SetStatePayload( + state=state, + ) + ) + self.send(message) + + def set_title( + self, + context: str, + title: str, + target: int = 0, + state: Optional[int] = None, + ) -> None: + """ + The plugin can send a setTitle event to the Stream Deck application to dynamically change the title + displayed by an instance of an action. + * Note: Show the title on your hardware or software using the Show Title checkbox in the Stream Deck window. + + https://docs.elgato.com/sdk/plugins/events-sent#settitle + + :param context: A value to Identify the instance's action you want to modify. + :param title: The title to display. If there is no title parameter, the title is reset to the title set + by the user. + :param target: Specify if you want to display the title on the hardware and software (0), only on the + hardware (1), or only on the software (2). Default is 0. + :param state: A 0-based integer value representing the state of an action with multiple states. If not + specified, the title is set to all states. + """ + message = events_sent_objs.SetTitle( + context=context, + payload=events_sent_objs.SetTitlePayload( + title=title, + target=target, + state=state, + ), + ) + self.send(message) + + def set_trigger_description( + self, + context: str, + *, + long_touch: Optional[str] = None, + push: Optional[str] = None, + rotate: Optional[str] = None, + touch: Optional[str] = None, + ) -> None: + """ + (SD+) + Sets the trigger descriptions associated with an encoder (touch display + dial) action instance. + All descriptions are optional; when one or more descriptions are defined all descriptions are + updated, with undefined values having their description hidden in Stream Deck. + To reset the descriptions to the default values defined + within the manifest, an empty payload can be sent as part of the event. + + https://docs.elgato.com/sdk/plugins/events-sent#settriggerdescription-sd + + :param context: A value to identify the instance's action. + :param long_touch: Optional value that describes the long-touch interaction with the touch display. When + undefined the description will be hidden. + :param push: Optional value that describes the push interaction with the dial. When undefined the + description will be hidden. + :param rotate: Optional value that describes the rotate interaction with the dial. When undefined + the description will be hidden. + :param touch: Optional value that describes the touch interaction with the touch display. When undefined + the description will be hidden. + """ + message = events_sent_objs.SetTriggerDescription( + context=context, + payload=events_sent_objs.SetTriggerDescriptionPayload( + longTouch=long_touch, + push=push, + rotate=rotate, + touch=touch, + ), + ) + self.send(message) + + def show_alert( + self, + context: str, + ) -> None: + """ + The plugin can send a showAlert event to the Stream Deck application to temporarily show an alert icon on the + image displayed by an instance of an action. + + https://docs.elgato.com/sdk/plugins/events-sent#showalert + + :param context: A value to identify the instance's action. + """ + message = events_sent_objs.ShowAlert( + context=context, + ) + self.send(message) + + def show_ok( + self, + context: str, + ) -> None: + """ + The plugin can send a showOk event to the Stream Deck application to temporarily show an OK checkmark icon on + the image displayed by an instance of an action. + + https://docs.elgato.com/sdk/plugins/events-sent#showok + + :param context: A value to identify the instance's action. + """ + message = events_sent_objs.ShowOk( + context=context, + ) + self.send(message) + + def switch_to_profile( + self, + device: str, + profile: str, + page: int, + ) -> None: + """ + The plugin can tell the Stream Deck application to switch to one of his preconfigured read-only profile + using the switchToProfile event. + * Note that a plugin can only switch to read-only profiles declared in its manifest.json file. If the profile + field is missing or empty, the Stream Deck application will switch to the previously selected profile. + + https://docs.elgato.com/sdk/plugins/events-sent#switchtoprofile + + :param device: A value to identify the device. + :param profile: The name of the profile to switch to. The name should be identical to the name provided + in the manifest.json file. + :param page: Page to show when switching to the profile; indexed from 0. + """ + message = events_sent_objs.SwitchToProfile( + context=self.plugin_uuid, + device=device, + payload=events_sent_objs.SwitchToProfilePayload( + profile=profile, + page=page, + ), + ) + self.send(message) diff --git a/src/streamdeck_sdk/sd_objs/__init__.py b/src/streamdeck_sdk/sd_objs/__init__.py new file mode 100644 index 0000000..8b029ce --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/__init__.py @@ -0,0 +1,3 @@ +from . import events_received_objs +from . import events_sent_objs +from . import registration_objs diff --git a/src/streamdeck_sdk/sd_objs/events_received_objs/__init__.py b/src/streamdeck_sdk/sd_objs/events_received_objs/__init__.py new file mode 100644 index 0000000..e7da765 --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_received_objs/__init__.py @@ -0,0 +1,23 @@ +from .application_did_launch import * +from .application_did_terminate import * +from .assets.controller_enum import * +from .assets.key_coordinates import * +from .device_did_connect import * +from .device_did_disconnect import * +from .dial_down import * +from .dial_rotate import * +from .dial_up import * +from .did_receive_deep_link import * +from .did_receive_global_settings import * +from .did_receive_settings import * +from .key_down import * +from .key_up import * +from .property_inspector_did_appear import * +from .property_inspector_did_disappear import * +from .send_to_plugin import * +from .send_to_property_inspector import * +from .system_did_wake_up import * +from .title_parameters_did_change import * +from .touch_tap import * +from .will_appear import * +from .will_disappear import * diff --git a/src/streamdeck_sdk/sd_objs/events_received_objs/application_did_launch.py b/src/streamdeck_sdk/sd_objs/events_received_objs/application_did_launch.py new file mode 100644 index 0000000..9bc289f --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_received_objs/application_did_launch.py @@ -0,0 +1,25 @@ +from pydantic import BaseModel + + +class ApplicationDidLaunchPayload(BaseModel): + """ + application: The identifier of the application that has been launched. + """ + application: str + + +class ApplicationDidLaunch(BaseModel): + """ + A plugin can request in its manifest.json to be notified when some applications are launched or + terminated. The manifest.json should contain an ApplicationsToMonitor object specifying the list of + application identifiers to monitor. On macOS, the application bundle identifier is used while the exe + filename is used on Windows. + For example, the Apple Mail: "application": "com.apple.mail" + + event: applicationDidLaunch + payload: A JSON object + + https://docs.elgato.com/sdk/plugins/events-received#applicationdidlaunch + """ + payload: ApplicationDidLaunchPayload + event: str = "applicationDidLaunch" diff --git a/src/streamdeck_sdk/sd_objs/events_received_objs/application_did_terminate.py b/src/streamdeck_sdk/sd_objs/events_received_objs/application_did_terminate.py new file mode 100644 index 0000000..1fe7d94 --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_received_objs/application_did_terminate.py @@ -0,0 +1,25 @@ +from pydantic import BaseModel + + +class ApplicationDidTerminatePayload(BaseModel): + """ + application: The identifier of the application that has been terminated. + """ + application: str + + +class ApplicationDidTerminate(BaseModel): + """ + A plugin can request in its manifest.json to be notified when some applications are launched + or terminated. The manifest.json should contain an ApplicationsToMonitor + object specifying the list of application identifiers to monitor. On macOS, the application bundle + identifier is used while the exe filename is used on Windows. + For example, the Apple Mail: "application": "com.apple.mail" + + event: applicationDidTerminate + payload: A JSON object + + https://docs.elgato.com/sdk/plugins/events-received#applicationdidterminate + """ + payload: ApplicationDidTerminatePayload + event: str = "applicationDidTerminate" diff --git a/src/streamdeck_sdk/sd_objs/events_received_objs/assets/__init__.py b/src/streamdeck_sdk/sd_objs/events_received_objs/assets/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/streamdeck_sdk/sd_objs/events_received_objs/assets/controller_enum.py b/src/streamdeck_sdk/sd_objs/events_received_objs/assets/controller_enum.py new file mode 100644 index 0000000..09d8b5c --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_received_objs/assets/controller_enum.py @@ -0,0 +1,9 @@ +from enum import Enum + + +class ControllerEnum(str, Enum): + """ + Types of controller. + """ + KEYPAD = "Keypad" + ENCODER = "Encoder" diff --git a/src/streamdeck_sdk/sd_objs/events_received_objs/assets/key_coordinates.py b/src/streamdeck_sdk/sd_objs/events_received_objs/assets/key_coordinates.py new file mode 100644 index 0000000..aa3e1e9 --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_received_objs/assets/key_coordinates.py @@ -0,0 +1,9 @@ +from pydantic import BaseModel + + +class KeyCoordinates(BaseModel): + """ + The coordinates of the action triggered. + """ + column: int + row: int diff --git a/src/streamdeck_sdk/sd_objs/events_received_objs/device_did_connect.py b/src/streamdeck_sdk/sd_objs/events_received_objs/device_did_connect.py new file mode 100644 index 0000000..6e09514 --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_received_objs/device_did_connect.py @@ -0,0 +1,37 @@ +from pydantic import BaseModel + + +class DeviceDidConnectDeviceInfoSize(BaseModel): + """ + The number of columns and rows of keys that the device owns. + """ + columns: int + rows: int + + +class DeviceDidConnectDeviceInfo(BaseModel): + """ + type: Type of device. Possible values are kESDSDKDeviceType_StreamDeck (0), + kESDSDKDeviceType_StreamDeckMini (1), kESDSDKDeviceType_StreamDeckXL (2), + kESDSDKDeviceType_StreamDeckMobile (3) and kESDSDKDeviceType_CorsairGKeys (4). + size: The number of columns and rows of keys that the device owns. + name: The name of the device set by the user. + """ + name: str + type: int + size: DeviceDidConnectDeviceInfoSize + + +class DeviceDidConnect(BaseModel): + """ + When a device is plugged into the computer, the plugin will receive a deviceDidConnect event. + + event: deviceDidConnect + device: A value to identify the device. + deviceInfo: A JSON object containing information about the device. + + https://docs.elgato.com/sdk/plugins/events-received#devicedidconnect + """ + device: str + deviceInfo: DeviceDidConnectDeviceInfo + event: str = "deviceDidConnect" diff --git a/src/streamdeck_sdk/sd_objs/events_received_objs/device_did_disconnect.py b/src/streamdeck_sdk/sd_objs/events_received_objs/device_did_disconnect.py new file mode 100644 index 0000000..4bc4c58 --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_received_objs/device_did_disconnect.py @@ -0,0 +1,14 @@ +from pydantic import BaseModel + + +class DeviceDidDisconnect(BaseModel): + """ + When a device is unplugged from the computer, the plugin will receive a deviceDidDisconnect event. + + event: deviceDidDisconnect + device: A value to identify the device. + + https://docs.elgato.com/sdk/plugins/events-received#devicediddisconnect + """ + device: str + event: str = "deviceDidDisconnect" diff --git a/src/streamdeck_sdk/sd_objs/events_received_objs/dial_down.py b/src/streamdeck_sdk/sd_objs/events_received_objs/dial_down.py new file mode 100644 index 0000000..68c2c93 --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_received_objs/dial_down.py @@ -0,0 +1,37 @@ +from pydantic import BaseModel + +from .assets.controller_enum import ControllerEnum +from .assets.key_coordinates import KeyCoordinates + + +class DialDownPayload(BaseModel): + """ + settings: This JSON object contains data that you can set and are stored persistently. + coordinates: The coordinates of the action triggered. + controller: Encoder. + """ + settings: dict + coordinates: KeyCoordinates + controller: ControllerEnum = ControllerEnum.ENCODER + + +class DialDown(BaseModel): + """ + (SD+) + When the user presses the encoder down, the plugin will receive the dialDown event (SD+). + + action: The action's unique identifier. If your plugin supports multiple actions, + you should use this value to see which action was triggered. + event: dialDown + context: A value identifying the instance's action. You will need to pass this + opaque value to several APIs like the setTitle API. + device: A value to identify the device. + payload: A JSON object + + https://docs.elgato.com/sdk/plugins/events-received#dialdown-sd + """ + action: str + context: str + device: str + payload: DialDownPayload + event: str = "dialDown" diff --git a/src/streamdeck_sdk/sd_objs/events_received_objs/dial_rotate.py b/src/streamdeck_sdk/sd_objs/events_received_objs/dial_rotate.py new file mode 100644 index 0000000..22b1db0 --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_received_objs/dial_rotate.py @@ -0,0 +1,42 @@ +from pydantic import BaseModel + +from .assets.controller_enum import ControllerEnum +from .assets.key_coordinates import KeyCoordinates + + +class DialRotatePayload(BaseModel): + """ + settings: This JSON object contains data that you can set and are stored persistently. + controller: Encoder. + coordinates: The coordinates of the action triggered. + ticks: The integer which holds the number of "ticks" on encoder rotation. Positive values are for clockwise + rotation, negative values are for counterclockwise rotation, zero value is never happen. + pressed: Boolean which is true on rotation when encoder pressed. + """ + settings: dict + coordinates: KeyCoordinates + ticks: int + pressed: bool + controller: ControllerEnum = ControllerEnum.ENCODER + + +class DialRotate(BaseModel): + """ + (SD+) + When the user rotates the encoder, the plugin will receive the dialRotate event. + + action: The action's unique identifier. If your plugin supports multiple actions, you should use this value + to see which action was triggered. + event: dialRotate + context: A value identifying the instance's action. You will need to pass this opaque value to + several APIs like the setTitle API. + device: A value to identify the device. + payload: A JSON object. + + https://docs.elgato.com/sdk/plugins/events-received#dialrotate-sd + """ + action: str + context: str + device: str + payload: DialRotatePayload + event: str = "dialRotate" diff --git a/src/streamdeck_sdk/sd_objs/events_received_objs/dial_up.py b/src/streamdeck_sdk/sd_objs/events_received_objs/dial_up.py new file mode 100644 index 0000000..4bae225 --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_received_objs/dial_up.py @@ -0,0 +1,37 @@ +from pydantic import BaseModel + +from .assets.controller_enum import ControllerEnum +from .assets.key_coordinates import KeyCoordinates + + +class DialUpPayload(BaseModel): + """ + settings: This JSON object contains data that you can set and are stored persistently. + coordinates: The coordinates of the action triggered. + controller: Encoder. + """ + settings: dict + coordinates: KeyCoordinates + controller: ControllerEnum = ControllerEnum.ENCODER + + +class DialUp(BaseModel): + """ + (SD+) + When the user releases a pressed encoder, the plugin will receive the dialUp event (SD+). + + action: The action's unique identifier. If your plugin supports multiple actions, you should use this + value to see which action was triggered. + event: dialUp + context: A value identifying the instance's action. You will need to pass this opaque value to + several APIs like the setTitle API. + device: A value to identify the device. + payload: A JSON object + + https://docs.elgato.com/sdk/plugins/events-received#dialup-sd + """ + action: str + context: str + device: str + payload: DialUpPayload + event: str = "dialUp" diff --git a/src/streamdeck_sdk/sd_objs/events_received_objs/did_receive_deep_link.py b/src/streamdeck_sdk/sd_objs/events_received_objs/did_receive_deep_link.py new file mode 100644 index 0000000..743bb73 --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_received_objs/did_receive_deep_link.py @@ -0,0 +1,27 @@ +from pydantic import BaseModel + + +class DidReceiveDeepLinkPayload(BaseModel): + """ + url: The deep-link URL, with the prefix omitted. For example + the URL streamdeck://plugins/message/com.elgato.test/hello-world would result in a url of hello-world. + """ + url: str + + +class DidReceiveDeepLink(BaseModel): + """ + ! Available from Stream Deck 6.5 onwards. + + Occurs when Stream Deck receives a deep-link message intended for the plugin. + The message is re-routed to the plugin, and provided as part of the payload. + One-way deep-link message can be routed to the plugin using the URL format: + streamdeck://plugins/message//{MESSAGE} + + event: didReceiveDeepLink + payload: A JSON object + + https://docs.elgato.com/sdk/plugins/events-received#didreceivedeeplink + """ + payload: DidReceiveDeepLinkPayload + event: str = "didReceiveDeepLink" diff --git a/src/streamdeck_sdk/sd_objs/events_received_objs/did_receive_global_settings.py b/src/streamdeck_sdk/sd_objs/events_received_objs/did_receive_global_settings.py new file mode 100644 index 0000000..b963858 --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_received_objs/did_receive_global_settings.py @@ -0,0 +1,19 @@ +from pydantic import BaseModel + + +class DidReceiveGlobalSettingsPayload(BaseModel): + settings: dict + + +class DidReceiveGlobalSettings(BaseModel): + """ + The didReceiveGlobalSettings event is received after calling the getGlobalSettings API + to retrieve the global persistent data stored for the plugin. + + event: didReceiveGlobalSettings + payload: A JSON object + + https://docs.elgato.com/sdk/plugins/events-received#didreceiveglobalsettings + """ + payload: DidReceiveGlobalSettingsPayload + event: str = "didReceiveGlobalSettings" diff --git a/src/streamdeck_sdk/sd_objs/events_received_objs/did_receive_settings.py b/src/streamdeck_sdk/sd_objs/events_received_objs/did_receive_settings.py new file mode 100644 index 0000000..01f67bf --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_received_objs/did_receive_settings.py @@ -0,0 +1,39 @@ +from typing import Optional + +from pydantic import BaseModel + +from .assets.key_coordinates import KeyCoordinates + + +class DidReceiveSettingsPayload(BaseModel): + """ + settings: This JSON object contains persistently stored data. + coordinates: The coordinates of the action triggered. + state: Only set when the action has multiple states defined in its manifest.json. The 0-based + value contains the current state of the action. + isInMultiAction: Boolean indicating if the action is inside a Multi-Action. + """ + settings: dict + coordinates: KeyCoordinates + isInMultiAction: bool + state: Optional[int] = None + + +class DidReceiveSettings(BaseModel): + """ + The didReceiveSettings event is received after calling the getSettings API + to retrieve the persistent data stored for the action. + + action: The action's unique identifier. + event: didReceiveSettings + context: A value identifying the instance's action. + device: A value to identify the device. + payload: A JSON object + + https://docs.elgato.com/sdk/plugins/events-received#didreceivesettings + """ + action: str + context: str + device: str + payload: DidReceiveSettingsPayload + event: str = "didReceiveSettings" diff --git a/src/streamdeck_sdk/sd_objs/events_received_objs/key_down.py b/src/streamdeck_sdk/sd_objs/events_received_objs/key_down.py new file mode 100644 index 0000000..c935ec0 --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_received_objs/key_down.py @@ -0,0 +1,44 @@ +from typing import Optional + +from pydantic import BaseModel + +from .assets.key_coordinates import KeyCoordinates + + +class KeyDownPayload(BaseModel): + """ + settings: This JSON object contains data that you can set and are stored persistently. + coordinates: The coordinates of the action triggered. + state: Only set when the action has multiple states defined in its manifest.json. The 0-based value + contains the current state of the action. + userDesiredState: Only set when the action is triggered with a specific value from a + Multi-Action. For example, if the user sets the Game Capture Record action to be disabled in + a Multi-Action, you would see the value 1. 0 and 1 are valid. + isInMultiAction: Boolean indicating if the action is inside a Multi-Action. + """ + settings: dict + isInMultiAction: bool + coordinates: Optional[KeyCoordinates] = None + state: Optional[int] = None + userDesiredState: Optional[int] = None + + +class KeyDown(BaseModel): + """ + When the user presses a key, the plugin will receive the keyDown event. + + action: The action's unique identifier. If your plugin supports multiple actions, you should use this value + to see which action was triggered. + event: keyDown + context: A value identifying the instance's action. You will need to pass this opaque value to + several APIs like the setTitle API. + device: A value to identify the device. + payload: A JSON object. + + https://docs.elgato.com/sdk/plugins/events-received#keydown + """ + action: str + context: str + device: str + payload: KeyDownPayload + event: str = "keyDown" diff --git a/src/streamdeck_sdk/sd_objs/events_received_objs/key_up.py b/src/streamdeck_sdk/sd_objs/events_received_objs/key_up.py new file mode 100644 index 0000000..5c4e71b --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_received_objs/key_up.py @@ -0,0 +1,44 @@ +from typing import Optional + +from pydantic import BaseModel + +from .assets.key_coordinates import KeyCoordinates + + +class KeyUpPayload(BaseModel): + """ + settings: This JSON object contains data that you can set and is stored persistently. + coordinates: The coordinates of the action triggered. + state: Only set when the action has multiple states defined in its manifest.json. The 0-based value contains + the current state of the action. + userDesiredState: Only set when the action is triggered with a specific value from a Multi-Action. For + example, if the user sets the Game Capture Record action to be disabled in a Multi-Action, you would see the + value 1. 0 and 1 are valid. + isInMultiAction: Boolean indicating if the action is inside a Multi-Action. + """ + settings: dict + isInMultiAction: bool + state: Optional[int] = None + coordinates: Optional[KeyCoordinates] = None + userDesiredState: Optional[int] = None + + +class KeyUp(BaseModel): + """ + When the user releases a key, the plugin will receive the keyUp event. + + action: The action's unique identifier. If your plugin supports multiple actions, you should use this value + to find out which action was triggered. + event: keyUp + context: A value to identify the instance's action. You will need to pass this opaque value + to several APIs like the setTitle API. + device: A value to identify the device. + payload: A JSON object + + https://docs.elgato.com/sdk/plugins/events-received#keyup + """ + action: str + context: str + device: str + payload: KeyUpPayload + event: str = "keyUp" diff --git a/src/streamdeck_sdk/sd_objs/events_received_objs/property_inspector_did_appear.py b/src/streamdeck_sdk/sd_objs/events_received_objs/property_inspector_did_appear.py new file mode 100644 index 0000000..ff1fc40 --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_received_objs/property_inspector_did_appear.py @@ -0,0 +1,19 @@ +from pydantic import BaseModel + + +class PropertyInspectorDidAppear(BaseModel): + """ + The plugin will receive a propertyInspectorDidAppear event when the Property Inspector appears. + * This API has been introduced in Stream Deck 4.1. + + action: The action's unique identifier. + event: propertyInspectorDidAppear + context: A value to identify the instance's action. + device: A value to identify the device. + + https://docs.elgato.com/sdk/plugins/events-received#propertyinspectordidappear + """ + action: str + context: str + device: str + event: str = "propertyInspectorDidAppear" diff --git a/src/streamdeck_sdk/sd_objs/events_received_objs/property_inspector_did_disappear.py b/src/streamdeck_sdk/sd_objs/events_received_objs/property_inspector_did_disappear.py new file mode 100644 index 0000000..2a56825 --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_received_objs/property_inspector_did_disappear.py @@ -0,0 +1,18 @@ +from pydantic import BaseModel + + +class PropertyInspectorDidDisappear(BaseModel): + """ + The plugin will receive a propertyInspectorDidDisappear event when the Property Inspector disappears. + + action: The action's unique identifier. + event: propertyInspectorDidDisappear + context: A value to identify the instance's action. + device: A value to identify the device. + + https://docs.elgato.com/sdk/plugins/events-received#propertyinspectordiddisappear + """ + action: str + context: str + device: str + event: str = "propertyInspectorDidDisappear" diff --git a/src/streamdeck_sdk/sd_objs/events_received_objs/send_to_plugin.py b/src/streamdeck_sdk/sd_objs/events_received_objs/send_to_plugin.py new file mode 100644 index 0000000..48c6542 --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_received_objs/send_to_plugin.py @@ -0,0 +1,18 @@ +from pydantic import BaseModel + + +class SendToPlugin(BaseModel): + """ + The plugin will receive a sendToPlugin event when the Property Inspector sends a sendToPlugin event. + + action: The action's unique identifier. + context: A value to identify the instance's action. + payload: A JSON object + event: sendToPlugin + + https://docs.elgato.com/sdk/plugins/events-received#sendtoplugin + """ + action: str + context: str + payload: dict + event: str = "sendToPlugin" diff --git a/src/streamdeck_sdk/sd_objs/events_received_objs/send_to_property_inspector.py b/src/streamdeck_sdk/sd_objs/events_received_objs/send_to_property_inspector.py new file mode 100644 index 0000000..b0f26c1 --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_received_objs/send_to_property_inspector.py @@ -0,0 +1,19 @@ +from pydantic import BaseModel + + +class SendToPropertyInspector(BaseModel): + """ + The Property Inspector will receive a sendToPropertyInspector event when the plugin + sends a sendToPropertyInspector event. + + action: The action's unique identifier. + context: A value to identify the instance's action. + payload: A JSON object + event: sendToPropertyInspector + + https://docs.elgato.com/sdk/plugins/events-received#sendtopropertyinspector + """ + action: str + context: str + payload: dict + event: str = "sendToPropertyInspector" diff --git a/src/streamdeck_sdk/sd_objs/events_received_objs/system_did_wake_up.py b/src/streamdeck_sdk/sd_objs/events_received_objs/system_did_wake_up.py new file mode 100644 index 0000000..c95d064 --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_received_objs/system_did_wake_up.py @@ -0,0 +1,16 @@ +from pydantic import BaseModel + + +class SystemDidWakeUp(BaseModel): + """ + When the computer wakes up, the plugin will receive the systemDidWakeUp event. + Several important points to note: + * A plugin could get multiple systemDidWakeUp events when waking up the computer + * When the plugin receives the systemDidWakeUp event, there is no guarantee that the devices are available + * This API has been introduced in Stream Deck 4.3. + + event: systemDidWakeUp + + https://docs.elgato.com/sdk/plugins/events-received#systemdidwakeup + """ + event: str = "systemDidWakeUp" diff --git a/src/streamdeck_sdk/sd_objs/events_received_objs/title_parameters_did_change.py b/src/streamdeck_sdk/sd_objs/events_received_objs/title_parameters_did_change.py new file mode 100644 index 0000000..346be12 --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_received_objs/title_parameters_did_change.py @@ -0,0 +1,59 @@ +from pydantic import BaseModel + +from .assets.key_coordinates import KeyCoordinates + + +class TitleParametersDidChangePayloadTitleParameters(BaseModel): + """ + fontFamily: The font family for the title. + fontSize: The font size for the title. + fontStyle: The font style for the title. + fontUnderline: Boolean indicating an underline under the title. + showTitle: Boolean indicating if the title is visible. + titleAlignment: Vertical alignment of the title. Possible values are "top", "bottom" and "middle". + titleColor: Title color. + """ + fontFamily: str + fontSize: int + fontStyle: str + fontUnderline: bool + showTitle: bool + titleAlignment: str + titleColor: str + + +class TitleParametersDidChangePayload(BaseModel): + """ + settings: This JSON object contains data that you can set and is stored persistently. + coordinates: The coordinates of the action triggered. + state: This value indicates which state of the action the title or title parameters have been changed. + title: The new title. + titleParameters: A JSON object describing the new title parameters. + """ + coordinates: KeyCoordinates + settings: dict + state: int + title: str + titleParameters: TitleParametersDidChangePayloadTitleParameters + + +class TitleParametersDidChange(BaseModel): + """ + When the user changes the title or title parameters of the instance of an action, the plugin will + receive a titleParametersDidChange event. + + action: The action's unique identifier. If your plugin supports multiple actions, you should use this value + to find out which action was triggered. + event: titleParametersDidChange + context: A value to identify the instance's action. You will need to pass this value to several APIs + like the setTitle API. + device: A value to identify the device. + payload: A JSON object + + https://docs.elgato.com/sdk/plugins/events-received#titleparametersdidchange + """ + action: str + context: str + device: str + payload: TitleParametersDidChangePayload + event: str = "titleParametersDidChange" diff --git a/src/streamdeck_sdk/sd_objs/events_received_objs/touch_tap.py b/src/streamdeck_sdk/sd_objs/events_received_objs/touch_tap.py new file mode 100644 index 0000000..baac0fe --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_received_objs/touch_tap.py @@ -0,0 +1,43 @@ +from typing import Tuple + +from pydantic import BaseModel + +from .assets.controller_enum import ControllerEnum +from .assets.key_coordinates import KeyCoordinates + + +class TouchTapPayload(BaseModel): + """ + settings: This JSON object contains data that you can set and are stored persistently. + controller: Encoder. + coordinates: The coordinates of the action triggered. + tapPos: The array which holds (x, y) coordinates as a position of tap inside of LCD slot associated with action. + hold: Boolean which is true when long tap happened + """ + settings: dict + coordinates: KeyCoordinates + tapPos: Tuple[int, int] + hold: bool + controller: ControllerEnum = ControllerEnum.ENCODER + + +class TouchTap(BaseModel): + """ + (SD+) + When the user touches the display, the plugin will receive the touchTap event. + + action: The action's unique identifier. If your plugin supports multiple actions, + you should use this value to see which action was triggered. + event: touchTap + context: A value identifying the instance's action. You will need to pass this opaque + value to several APIs like the setTitle API. + device: A value to identify the device. + payload: A JSON object + + https://docs.elgato.com/sdk/plugins/events-received#touchtap-sd + """ + action: str + context: str + device: str + payload: TouchTapPayload + event: str = "touchTap" diff --git a/src/streamdeck_sdk/sd_objs/events_received_objs/will_appear.py b/src/streamdeck_sdk/sd_objs/events_received_objs/will_appear.py new file mode 100644 index 0000000..adc77ac --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_received_objs/will_appear.py @@ -0,0 +1,50 @@ +from typing import Optional + +from pydantic import BaseModel + +from .assets.controller_enum import ControllerEnum +from .assets.key_coordinates import KeyCoordinates + + +class WillAppearPayload(BaseModel): + """ + settings: This JSON object contains data that you can set and are stored persistently. + coordinates: The coordinates of the action triggered. + controller: Defines the controller type the action is applicable to. Keypad refers to a standard action on + a Stream Deck device, e.g. 1 of the 15 buttons on the Stream Deck MK.2, or a pedal on the + Stream Deck Pedal, etc., whereas an Encoder refers to a dial / touchscreen on the Stream Deck+. + state: Only set when the action has multiple states defined in its manifest.json. The 0-based value + contains the current state of the action. + isInMultiAction: Boolean indicating if the action is inside a Multi-Action. + """ + settings: dict + isInMultiAction: bool + coordinates: Optional[KeyCoordinates] = None + state: Optional[int] = None + controller: Optional[ControllerEnum] = None + + +class WillAppear(BaseModel): + """ + When an instance of an action is displayed on Stream Deck, for example, when the hardware is first plugged + in or when a folder containing that action is entered, the plugin will receive a willAppear event. You will see + such an event when: + * the Stream Deck application is started + * the user switches between profiles + * the user sets a key to use your action + + action: The action's unique identifier. If your plugin supports multiple actions, you should use this value to + know which action was triggered. + event: willAppear + context: A value to identify the instance's action. You will need to pass this opaque value to several APIs + like the setTitle API. + device: A value to identify the device. + payload: A JSON object + + https://docs.elgato.com/sdk/plugins/events-received#willappear + """ + action: str + context: str + device: str + payload: WillAppearPayload + event: str = "willAppear" diff --git a/src/streamdeck_sdk/sd_objs/events_received_objs/will_disappear.py b/src/streamdeck_sdk/sd_objs/events_received_objs/will_disappear.py new file mode 100644 index 0000000..4b2619f --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_received_objs/will_disappear.py @@ -0,0 +1,48 @@ +from typing import Optional + +from pydantic import BaseModel + +from .assets.controller_enum import ControllerEnum +from .assets.key_coordinates import KeyCoordinates + + +class WillDisappearPayload(BaseModel): + """ + settings: This JSON object contains data that you can set and is stored persistently. + coordinates: The coordinates of the action triggered. + controller: Defines the controller type the action is applicable to. Keypad refers to a standard action + on a Stream Deck device, e.g. 1 of the 15 buttons on the Stream Deck MK.2, or a pedal on the Stream + Deck Pedal, etc., whereas an Encoder refers to a dial / touchscreen on the Stream Deck+. + state: Only set when the action has multiple states defined in its manifest.json. The 0-based value + contains the current state of the action. + isInMultiAction: Boolean indicating if the action is inside a Multi-Action. + """ + settings: dict + isInMultiAction: bool + coordinates: Optional[KeyCoordinates] = None + state: Optional[int] = None + controller: Optional[ControllerEnum] = None + + +class WillDisappear(BaseModel): + """ + When an instance of an action ceases to be displayed on Stream Deck, for example, when switching profiles + or folders, the plugin will receive a willDisappear event. You will see such an event when: + * the user switches between profiles + * the user deletes an action + + action: The action's unique identifier. If your plugin supports multiple actions, you should + use this value to find out which action was triggered. + event: willDisappear + context: A value to identify the instance's action. You will need to pass this opaque value + to several APIs like the setTitle API. + device: A value to identify the device. + payload: A JSON object + + https://docs.elgato.com/sdk/plugins/events-received#willdisappear + """ + action: str + context: str + device: str + payload: WillDisappearPayload + event: str = "willDisappear" diff --git a/src/streamdeck_sdk/sd_objs/events_sent_objs/__init__.py b/src/streamdeck_sdk/sd_objs/events_sent_objs/__init__.py new file mode 100644 index 0000000..b5c8f6c --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_sent_objs/__init__.py @@ -0,0 +1,17 @@ +from .get_global_settings import * +from .get_settings import * +from .log_message import * +from .open_url import * +from .send_to_plugin import * +from .send_to_property_inspector import * +from .set_feedback import * +from .set_feedback_layout import * +from .set_global_settings import * +from .set_image import * +from .set_settings import * +from .set_state import * +from .set_title import * +from .set_trigger_description import * +from .show_alert import * +from .show_ok import * +from .switch_to_profile import * diff --git a/src/streamdeck_sdk/sd_objs/events_sent_objs/get_global_settings.py b/src/streamdeck_sdk/sd_objs/events_sent_objs/get_global_settings.py new file mode 100644 index 0000000..bcd09ef --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_sent_objs/get_global_settings.py @@ -0,0 +1,17 @@ +from pydantic import BaseModel + + +class GetGlobalSettings(BaseModel): + """ + The plugin and Property Inspector can request the persistent global data using the getGlobalSettings event. + The plugin or Property Inspector will receive asynchronously an event didReceiveGlobalSettings the p + containing the global settings. + + event: getGlobalSettings + context: A value to Identify the plugin (inPluginUUID) or the Property Inspector (inPropertyInspectorUUID). This + value is received during the Registration procedure. + + https://docs.elgato.com/sdk/plugins/events-sent#getglobalsettings + """ + context: str + event: str = "getGlobalSettings" diff --git a/src/streamdeck_sdk/sd_objs/events_sent_objs/get_settings.py b/src/streamdeck_sdk/sd_objs/events_sent_objs/get_settings.py new file mode 100644 index 0000000..6482c7f --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_sent_objs/get_settings.py @@ -0,0 +1,17 @@ +from pydantic import BaseModel + + +class GetSettings(BaseModel): + """ + The plugin and Property Inspector can request the persistent data stored for the action's + instance using the getSettings event. + + event: getSettings + context: A value to Identify the instance's action or Property Inspector. In the case of + the Property Inspector, this value is received by the Property Inspector as parameter of + the connectElgatoStreamDeckSocket function. + + https://docs.elgato.com/sdk/plugins/events-sent#getsettings + """ + context: str + event: str = "getSettings" diff --git a/src/streamdeck_sdk/sd_objs/events_sent_objs/log_message.py b/src/streamdeck_sdk/sd_objs/events_sent_objs/log_message.py new file mode 100644 index 0000000..2e3901d --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_sent_objs/log_message.py @@ -0,0 +1,24 @@ +from pydantic import BaseModel + + +class LogMessagePayload(BaseModel): + """ + message: A string to write to the logs file. + """ + message: str + + +class LogMessage(BaseModel): + """ + The plugin and Property Inspector can use the logMessage event to write a debug message to the logs file. + * Logs are saved to disk per plugin in the folder ~/Library/Logs/ElgatoStreamDeck/ on macOS + and %appdata%\Elgato\StreamDeck\logs\ on Windows. Note that the log files are rotated each time + the Stream Deck application is relaunched. + + event: logMessage + payload: A JSON object + + https://docs.elgato.com/sdk/plugins/events-sent#logmessage + """ + payload: LogMessagePayload + event: str = "logMessage" diff --git a/src/streamdeck_sdk/sd_objs/events_sent_objs/open_url.py b/src/streamdeck_sdk/sd_objs/events_sent_objs/open_url.py new file mode 100644 index 0000000..d769914 --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_sent_objs/open_url.py @@ -0,0 +1,22 @@ +from pydantic import BaseModel + + +class OpenUrlPayload(BaseModel): + """ + url: An URL to open in the default browser. + """ + url: str + + +class OpenUrl(BaseModel): + """ + The plugin and Property Inspector can tell the Stream Deck application to open URL in the + default browser using the openUrl event. + + event: openUrl + payload: A JSON object + + https://docs.elgato.com/sdk/plugins/events-sent#openurl + """ + payload: OpenUrlPayload + event: str = "openUrl" diff --git a/src/streamdeck_sdk/sd_objs/events_sent_objs/send_to_plugin.py b/src/streamdeck_sdk/sd_objs/events_sent_objs/send_to_plugin.py new file mode 100644 index 0000000..d95609d --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_sent_objs/send_to_plugin.py @@ -0,0 +1,21 @@ +from pydantic import BaseModel + + +class SendToPlugin(BaseModel): + """ + The Property Inspector can send a payload to the plugin using the sendToPlugin event. + The plugin will receive asynchronously an event sendToPlugin. + + action: The action's unique identifier. If your plugin supports multiple actions, you should use this value to + find out which action was triggered. + event: sendToPlugin + context: A value to Identify the Property Inspector. This value is received by the Property Inspector as parameter + of the connectElgatoStreamDeckSocket function. + payload: A JSON object that will be received by the plugin. + + https://docs.elgato.com/sdk/plugins/events-sent#sendtoplugin + """ + action: str + context: str + payload: dict + event: str = "sendToPlugin" diff --git a/src/streamdeck_sdk/sd_objs/events_sent_objs/send_to_property_inspector.py b/src/streamdeck_sdk/sd_objs/events_sent_objs/send_to_property_inspector.py new file mode 100644 index 0000000..9a51cf0 --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_sent_objs/send_to_property_inspector.py @@ -0,0 +1,19 @@ +from pydantic import BaseModel + + +class SendToPropertyInspector(BaseModel): + """ + The plugin can send a payload to the Property Inspector using the sendToPropertyInspector event. + The Property Inspector will receive asynchronously an event sendToPropertyInspector. + + action: The action's unique identifier. + event: sendToPropertyInspector + context: A value to identify the instance's action. + payload: A JSON object that will be received by the Property Inspector. + + https://docs.elgato.com/sdk/plugins/events-sent#sendtopropertyinspector + """ + action: str + context: str + payload: dict + event: str = "sendToPropertyInspector" diff --git a/src/streamdeck_sdk/sd_objs/events_sent_objs/set_feedback.py b/src/streamdeck_sdk/sd_objs/events_sent_objs/set_feedback.py new file mode 100644 index 0000000..628f1a3 --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_sent_objs/set_feedback.py @@ -0,0 +1,20 @@ +from pydantic import BaseModel + + +class SetFeedback(BaseModel): + """ + (SD+) + The plugin can send a setFeedback event to the Stream Deck application to dynamically change properties of + items on the Stream Deck + touch display layout. + + event: setFeedback + context: A value to Identify the instance's action you want to modify. + payload: A JSON object. + key: The key is a name of the element in layout to be changed with given value. + value: The value to be set in key named layout element + + https://docs.elgato.com/sdk/plugins/events-sent#setfeedback-sd + """ + context: str + payload: dict + event: str = "setFeedback" diff --git a/src/streamdeck_sdk/sd_objs/events_sent_objs/set_feedback_layout.py b/src/streamdeck_sdk/sd_objs/events_sent_objs/set_feedback_layout.py new file mode 100644 index 0000000..0596726 --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_sent_objs/set_feedback_layout.py @@ -0,0 +1,26 @@ +from pydantic import BaseModel + + +class SetFeedbackLayoutPayload(BaseModel): + """ + layout: A predefined layout identifier or the relative path to a json file that contains a custom layout. + """ + layout: str + + +class SetFeedbackLayout(BaseModel): + """ + (SD+) + The plugin can send a setFeedbackLayout event to the Stream Deck application to dynamically change the + current Stream Deck + touch display layout. setFeedbackLayout can use the id of a built-in layout or + a relative path to a custom layout JSON file. See Layouts for more information. + + event: setFeedbackLayout + context: A value to Identify the instance's action you want to modify. + payload: Json + + https://docs.elgato.com/sdk/plugins/events-sent#setfeedbacklayout-sd + """ + context: str + payload: SetFeedbackLayoutPayload + event: str = "setFeedbackLayout" diff --git a/src/streamdeck_sdk/sd_objs/events_sent_objs/set_global_settings.py b/src/streamdeck_sdk/sd_objs/events_sent_objs/set_global_settings.py new file mode 100644 index 0000000..687666a --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_sent_objs/set_global_settings.py @@ -0,0 +1,23 @@ +from pydantic import BaseModel + + +class SetGlobalSettings(BaseModel): + """ + The plugin and Property Inspector can save persistent data globally. The data + will be saved securely to the Keychain on macOS and the Credential Store on Windows. This API can + be used to save tokens that should be available to every action in the plugin. + Note that when the plugin uses this API, the Property Inspector will automatically receive + a didReceiveGlobalSettings callback with the new settings. Similarly, when the Property Inspector uses + this API, the plugin will automatically receive a didReceiveGlobalSettings callback with the new settings. + This API has been introduced in Stream Deck 4.1. + + event: setGlobalSettings + context: A value to Identify the plugin (inPluginUUID) or the Property Inspector (inPropertyInspectorUUID). This + value is received during the Registration procedure. + payload: A JSON object which is persistently saved globally. + + https://docs.elgato.com/sdk/plugins/events-sent#setglobalsettings + """ + context: str + payload: dict + event: str = "setGlobalSettings" diff --git a/src/streamdeck_sdk/sd_objs/events_sent_objs/set_image.py b/src/streamdeck_sdk/sd_objs/events_sent_objs/set_image.py new file mode 100644 index 0000000..9145e52 --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_sent_objs/set_image.py @@ -0,0 +1,35 @@ +from typing import Optional + +from pydantic import BaseModel + + +class SetImagePayload(BaseModel): + """ + image: The image to display encoded in base64 with the image format declared in the mime + type (PNG, JPEG, BMP, ...). svg is also supported. If not provided, the image is + reset to the default image from the manifest. + You can use functions from image_converters.py for convert image in base64. + target: Specify if you want to display the title on the hardware and software (0), + only on the hardware (1), or only on the software (2). Default is 0. + state: A 0-based integer value representing the state of an action with multiple states. If not specified, + the image is set to all states. + """ + image: str # base64 + target: int = 0 + state: Optional[int] = None + + +class SetImage(BaseModel): + """ + The plugin can send a setImage event to the Stream Deck application to dynamically change the image displayed + by an instance of an action. + + event: setImage + context: A value to Identify the instance's action you want to modify. + payload: A JSON object + + https://docs.elgato.com/sdk/plugins/events-sent#setimage + """ + context: str + payload: SetImagePayload + event: str = "setImage" diff --git a/src/streamdeck_sdk/sd_objs/events_sent_objs/set_settings.py b/src/streamdeck_sdk/sd_objs/events_sent_objs/set_settings.py new file mode 100644 index 0000000..1e26074 --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_sent_objs/set_settings.py @@ -0,0 +1,22 @@ +from pydantic import BaseModel + + +class SetSettings(BaseModel): + """ + The plugin and Property Inspector can save data persistently for the action's instance using the setSettings event. + Note that when the plugin uses this API, the Property Inspector will automatically receive a didReceiveSettings + callback with the new settings. Similarly, when the Property Inspector uses this API, the plugin will + automatically receive a didReceiveSettings callback with the new settings. + The setSettings API is available since Stream Deck 4.0 for the plugin. Starting + with Stream Deck 4.1, this API is available from the Property Inspector. + + event: setSettings + context: A value to Identify the instance's action or Property Inspector. This value is received by + the Property Inspector as a parameter of the connectElgatoStreamDeckSocket function. + payload: A JSON object which is persistently saved for the action's instance. + + https://docs.elgato.com/sdk/plugins/events-sent#setsettings + """ + context: str + payload: dict + event: str = "setSettings" diff --git a/src/streamdeck_sdk/sd_objs/events_sent_objs/set_state.py b/src/streamdeck_sdk/sd_objs/events_sent_objs/set_state.py new file mode 100644 index 0000000..06c8e3b --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_sent_objs/set_state.py @@ -0,0 +1,23 @@ +from pydantic import BaseModel + + +class SetStatePayload(BaseModel): + """ + state: A 0-based integer value representing the state requested. + """ + state: int + + +class SetState(BaseModel): + """ + This function can be used by a plugin to dynamically change the state of an action supporting multiple states. + + event: setState + context: A value to identify the instance's action. + payload: A JSON object + + https://docs.elgato.com/sdk/plugins/events-sent#setstate + """ + context: str + payload: SetStatePayload + event: str = "setState" diff --git a/src/streamdeck_sdk/sd_objs/events_sent_objs/set_title.py b/src/streamdeck_sdk/sd_objs/events_sent_objs/set_title.py new file mode 100644 index 0000000..0002d71 --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_sent_objs/set_title.py @@ -0,0 +1,33 @@ +from typing import Optional + +from pydantic import BaseModel + + +class SetTitlePayload(BaseModel): + """ + title: The title to display. If there is no title parameter, the title is reset to the title set by the user. + target: Specify if you want to display the title on the hardware and software (0), only on the hardware (1), + or only on the software (2). Default is 0. + state: A 0-based integer value representing the state of an action with multiple states. If not specified, + the title is set to all states. + """ + title: str + target: int = 0 + state: Optional[int] = None + + +class SetTitle(BaseModel): + """ + The plugin can send a setTitle event to the Stream Deck application to dynamically change the title + displayed by an instance of an action. + * Note: Show the title on your hardware or software using the Show Title checkbox in the Stream Deck window. + + event: setTitle + context: A value to Identify the instance's action you want to modify. + payload: A JSON object + + https://docs.elgato.com/sdk/plugins/events-sent#settitle + """ + context: str + payload: SetTitlePayload + event: str = "setTitle" diff --git a/src/streamdeck_sdk/sd_objs/events_sent_objs/set_trigger_description.py b/src/streamdeck_sdk/sd_objs/events_sent_objs/set_trigger_description.py new file mode 100644 index 0000000..181fe07 --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_sent_objs/set_trigger_description.py @@ -0,0 +1,39 @@ +from typing import Optional + +from pydantic import BaseModel + + +class SetTriggerDescriptionPayload(BaseModel): + """ + longTouch: Optional value that describes the long-touch interaction with the touch display. When undefined the + description will be hidden. + push: Optional value that describes the push interaction with the dial. When undefined the description will + be hidden. + rotate: Optional value that describes the rotate interaction with the dial. When undefined the description will + be hidden. + touch: Optional value that describes the touch interaction with the touch display. When undefined the description + will be hidden. + """ + longTouch: Optional[str] = None + push: Optional[str] = None + rotate: Optional[str] = None + touch: Optional[str] = None + + +class SetTriggerDescription(BaseModel): + """ + (SD+) + Sets the trigger descriptions associated with an encoder (touch display + dial) action instance. All descriptions + are optional; when one or more descriptions are defined all descriptions are updated, with undefined values + having their description hidden in Stream Deck. To reset the descriptions to the default values defined + within the manifest, an empty payload can be sent as part of the event. + + event: setTriggerDescription + context: A value to identify the instance's action. + payload: A JSON object + + https://docs.elgato.com/sdk/plugins/events-sent#settriggerdescription-sd + """ + context: str + payload: SetTriggerDescriptionPayload + event: str = "setTriggerDescription" diff --git a/src/streamdeck_sdk/sd_objs/events_sent_objs/show_alert.py b/src/streamdeck_sdk/sd_objs/events_sent_objs/show_alert.py new file mode 100644 index 0000000..34709ca --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_sent_objs/show_alert.py @@ -0,0 +1,15 @@ +from pydantic import BaseModel + + +class ShowAlert(BaseModel): + """ + The plugin can send a showAlert event to the Stream Deck application to temporarily show an alert icon on the + image displayed by an instance of an action. + + event: showAlert + context: A value to identify the instance's action. + + https://docs.elgato.com/sdk/plugins/events-sent#showalert + """ + context: str + event: str = "showAlert" diff --git a/src/streamdeck_sdk/sd_objs/events_sent_objs/show_ok.py b/src/streamdeck_sdk/sd_objs/events_sent_objs/show_ok.py new file mode 100644 index 0000000..b53478a --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_sent_objs/show_ok.py @@ -0,0 +1,15 @@ +from pydantic import BaseModel + + +class ShowOk(BaseModel): + """ + The plugin can send a showOk event to the Stream Deck application to temporarily show an OK checkmark icon on + the image displayed by an instance of an action. + + event: showOk + context: A value to identify the instance's action. + + https://docs.elgato.com/sdk/plugins/events-sent#showok + """ + context: str + event: str = "showOk" diff --git a/src/streamdeck_sdk/sd_objs/events_sent_objs/switch_to_profile.py b/src/streamdeck_sdk/sd_objs/events_sent_objs/switch_to_profile.py new file mode 100644 index 0000000..a3e1d1c --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/events_sent_objs/switch_to_profile.py @@ -0,0 +1,32 @@ +from pydantic import BaseModel + + +class SwitchToProfilePayload(BaseModel): + """ + profile: The name of the profile to switch to. The name should be identical to the name provided + in the manifest.json file. + page: Page to show when switching to the profile; indexed from 0. + """ + profile: str + page: int + + +class SwitchToProfile(BaseModel): + """ + The plugin can tell the Stream Deck application to switch to one of his preconfigured read-only profile + using the switchToProfile event. + * Note that a plugin can only switch to read-only profiles declared in its manifest.json file. If the profile + field is missing or empty, the Stream Deck application will switch to the previously selected profile. + + event: switchToProfile + context: A value to Identify the plugin. This value should be set to the PluginUUID received during the + registration procedure. + device: A value to identify the device. + payload: A JSON object + + https://docs.elgato.com/sdk/plugins/events-sent#switchtoprofile + """ + device: str + context: str + payload: SwitchToProfilePayload + event: str = "switchToProfile" diff --git a/src/streamdeck_sdk/sd_objs/registration_objs.py b/src/streamdeck_sdk/sd_objs/registration_objs.py new file mode 100644 index 0000000..2419e1b --- /dev/null +++ b/src/streamdeck_sdk/sd_objs/registration_objs.py @@ -0,0 +1,87 @@ +from typing import List, Optional + +from pydantic import BaseModel + + +# region NestedModels +class InfoApplication(BaseModel): + """ + language: In which language the Stream Deck application is running. Possible values are en, fr, de, es, ja, zh_CN. + platform: On which platform the Stream Deck application is running. Possible values + are kESDSDKApplicationInfoPlatformMac ("mac") and kESDSDKApplicationInfoPlatformWindows ("windows"). + version: The Stream Deck application version. + platformVersion: The operating system version. + """ + font: str + language: str + platform: str + platformVersion: str + version: str + + +class InfoPlugin(BaseModel): + """ + version: The plugin version as written in the manifest.json. + uuid: The unique identifier of the plugin. + """ + uuid: str + version: str + + +class InfoColors(BaseModel): + """ + A JSON object containing information about the preferred user colors. + """ + buttonPressedBackgroundColor: str + buttonPressedBorderColor: str + buttonPressedTextColor: str + highlightColor: str + disabledColor: Optional[str] = None + mouseDownColor: Optional[str] = None + + +class InfoDeviceSize(BaseModel): + """ + The number of columns and rows of keys that the device owns. + """ + columns: int + rows: int + + +class InfoDevice(BaseModel): + """ + id: A value to identify the device. + type: Type of device. Possible values are kESDSDKDeviceType_StreamDeck (0), kESDSDKDeviceType_StreamDeckMini (1), + kESDSDKDeviceType_StreamDeckXL (2), kESDSDKDeviceType_StreamDeckMobile (3), kESDSDKDeviceType_CorsairGKeys (4), + kESDSDKDeviceType_StreamDeckPedal (5), kESDSDKDeviceType_CorsairVoyager (6), + and kESDSDKDeviceType_StreamDeckPlus (7). + size: The number of columns and rows of keys that the device owns. + name: The name of the device set by the user. + """ + id: str + name: str + size: InfoDeviceSize + type: int + + +# endregion NestedModels + +# region Models +class Info(BaseModel): + """ + The info parameter used in the registration process is A JSON object. + + application: A JSON object containing information about the application. + plugin: A JSON object containing information about the plugin. + devices: A JSON array containing information about the devices. + devicePixelRatio: Pixel ratio value to indicate if the Stream Deck application is running on a HiDPI screen. + colors: A JSON object containing information about the preferred user colors. + + https://docs.elgato.com/sdk/plugins/registration-procedure#info-parameter + """ + application: InfoApplication + plugin: InfoPlugin + devicePixelRatio: int + colors: InfoColors + devices: List[InfoDevice] +# endregion Models diff --git a/src/streamdeck_sdk/sdk.py b/src/streamdeck_sdk/sdk.py new file mode 100644 index 0000000..d433646 --- /dev/null +++ b/src/streamdeck_sdk/sdk.py @@ -0,0 +1,166 @@ +import argparse +import json +import logging +import sys +from os import PathLike +from pathlib import Path +from typing import Optional, List, Dict, Set + +from websockets.sync.server import ( + ServerConnection, +) + +from .logger import ( + init_root_logger, + log_errors, + rename_plugin_logger, +) +from .mixins import Base +from .mixins.event_routing_mixin import EventRoutingMixin +from .mixins.debug_server_mixin import DebugServerMixin +from .sd_objs import registration_objs +from .simple_ws.client import WebSocketClientApp + +logger = logging.getLogger(__name__) + + +class Action(Base): + UUID: str # Required + + def __init__(self): + self.plugin_uuid: Optional[str] = None + self.ws: Optional[WebSocketClientApp] = None + self.info: Optional[registration_objs.Info] = None + + +class StreamDeck( + Base, + EventRoutingMixin, + DebugServerMixin, +): + def __init__( + self, + actions: Optional[List[Action]] = None, + debug: bool = False, + debug_port: int = 5581, + *, + log_file: Optional[PathLike] = None, + log_level: int = logging.INFO, + log_max_bytes: int = 3 * 1024 * 1024, # 3 MB + log_backup_count: int = 2, + ): + if log_file is not None: + if debug: + log_level = logging.DEBUG + log_file: Path = Path(log_file) + init_root_logger( + log_file=log_file, + log_level=log_level, + log_max_bytes=log_max_bytes, + log_backup_count=log_backup_count, + ) + + self.actions_list = actions + self.actions: Dict[str, Action] = {} + + self.debug = debug + self.debug_port = debug_port + self.debug_clients: Set[ServerConnection] = set() + + self.ws: Optional[WebSocketClientApp] = None + self.port: Optional[int] = None + self.plugin_uuid: Optional[str] = None + self.register_event: Optional[str] = None + self.info: Optional[registration_objs.Info] = None + + self.registration_dict: Optional[dict] = None + + @log_errors + def run(self): + logger.debug(f"Plugin has been launched") + + if self.debug: + self.run_debug() + return + + self.__parse_args() + self.ws = WebSocketClientApp( + uri=f'ws://localhost:{self.port}/', + on_message=self.ws_on_message, + on_error=self.ws_on_error, + on_close=self.ws_on_close, + on_open=self.ws_on_open, + ) + self.__init_actions() + self.ws.run_forever() + + @log_errors + def run_debug(self): + logger.warning("Debug mode.") + + if len(sys.argv) == 1: # is client + try: + logger.info("Trying to connect to the debug server.") + self.ws = WebSocketClientApp( + uri=f'ws://localhost:{self.debug_port}/', + on_message=self.ws_on_message, + ) + logger.info(f"Successfully connected to the debug server.") + self.__init_actions() + self.ws.run_forever() + except Exception as err: + logger.exception(err) + logger.debug(f"Failed to connect to debug server.") + return + + logger.info("Trying to create a debug server.") + self.__parse_args() + self._debug_server_run() + logger.debug("Debug server is running.") + self.ws = WebSocketClientApp( + uri=f'ws://localhost:{self.port}/', + on_message=self._debug_server_on_message, + on_open=self.ws_on_open, + ) + logger.debug("Debug server connected to StreamDeck.") + self.ws.run_forever() + logger.info("Debug server stopped.") + + def __init_actions(self) -> None: + if self.actions_list is None: + return + + for action in self.actions_list: + try: + action_uuid = action.UUID + except AttributeError: + action_class = str(action.__class__) + message = f"{action_class} must have attribute UUID." + logger.error(message, exc_info=True) + raise AttributeError(message) + action.ws = self.ws + action.plugin_uuid = self.plugin_uuid + action.info = self.info + self.actions[action_uuid] = action + + def __parse_args(self): + logger.debug("Trying to parse arguments.") + parser = argparse.ArgumentParser(description='StreamDeck Plugin') + parser.add_argument('-port', dest='port', type=int, help="Port", required=True) + parser.add_argument('-pluginUUID', dest='pluginUUID', type=str, help="pluginUUID", required=True) + parser.add_argument('-registerEvent', dest='registerEvent', type=str, help="registerEvent", required=True) + parser.add_argument('-info', dest='info', type=str, help="info", required=True) + args = parser.parse_args() + logger.debug("Trying to parse arguments was successful.") + logger.debug(f"{args=}") + + self.port = args.port + self.plugin_uuid = args.pluginUUID + self.register_event = args.registerEvent + self.info = registration_objs.Info.parse_obj(json.loads(args.info)) + logger.debug(f"{self.info=}") + + rename_plugin_logger(name=self.info.plugin.uuid) + + self.registration_dict = {"event": self.register_event, "uuid": self.plugin_uuid} + logger.debug(f"{self.registration_dict=}") diff --git a/src/streamdeck_sdk/simple_ws/__init__.py b/src/streamdeck_sdk/simple_ws/__init__.py new file mode 100644 index 0000000..ba45768 --- /dev/null +++ b/src/streamdeck_sdk/simple_ws/__init__.py @@ -0,0 +1 @@ +from . import client diff --git a/src/streamdeck_sdk/simple_ws/client.py b/src/streamdeck_sdk/simple_ws/client.py new file mode 100644 index 0000000..02c5a8e --- /dev/null +++ b/src/streamdeck_sdk/simple_ws/client.py @@ -0,0 +1,61 @@ +import logging +from typing import Callable, Optional + +from websockets.exceptions import ConnectionClosedOK, ConnectionClosedError, ConnectionClosed +from websockets.sync.client import ClientConnection, connect + +logger = logging.getLogger('simple_ws_client') + + +class WebSocketClientApp: + def __init__( + self, + uri: str, + *, + on_open: Callable = None, + on_message: Callable = None, + on_error: Callable = None, + on_close: Callable = None, + ): + self.uri = uri + self.on_open = on_open + self.on_message = on_message + self.on_error = on_error + self.on_close = on_close + self.client: Optional[ClientConnection] = connect(uri=self.uri) + + def send(self, message): + self.client.send(message=message) + + def close(self): + self.client.close() + + def run_forever(self): + self._callback(self.on_open) + while True: + try: + message = self.client.recv() + logger.debug(f"Message received. {message=}") + except ConnectionClosedOK as err: + self._handle_connection_close(err=err) + break + except ConnectionClosedError as err: + self._callback(self.on_error, err) + self._handle_connection_close(err=err) + break + self._callback(self.on_message, message) + + def _handle_connection_close(self, err: ConnectionClosed): + close_status_code = getattr(err.rcvd, "code", None) + close_msg = getattr(err.rcvd, "reason", None) + self._callback(self.on_close, close_status_code, close_msg) + + def _callback(self, callback, *args): + if not callback: + return + try: + callback(self.client, *args) + except Exception as err: + logger.error(f"error from callback {callback}: {err}") + if self.on_error: + self.on_error(self, err) diff --git a/src/streamdeck_sdk/utils/__init__.py b/src/streamdeck_sdk/utils/__init__.py new file mode 100644 index 0000000..160204d --- /dev/null +++ b/src/streamdeck_sdk/utils/__init__.py @@ -0,0 +1,2 @@ +from .image_converters import image_file_to_base64, image_bytes_to_base64 +from .in_separate_thread import in_separate_thread diff --git a/src/streamdeck_sdk/utils/image_converters.py b/src/streamdeck_sdk/utils/image_converters.py new file mode 100644 index 0000000..7e8bcdb --- /dev/null +++ b/src/streamdeck_sdk/utils/image_converters.py @@ -0,0 +1,22 @@ +import base64 +import mimetypes +from pathlib import Path + + +def image_file_to_base64(file_path: Path) -> str: + image_mime = mimetypes.guess_type(file_path, strict=True)[0] + prefix = f"data:{image_mime};base64," + with open(file_path, "rb") as image_file: + image_base64: bytes = base64.b64encode(image_file.read()) + result = prefix + image_base64.decode("UTF-8") + return result + + +def image_bytes_to_base64(obj: bytes, image_mime: str) -> str: + """ + :param image_mime: Example: image/png, image/jpg, image/bmp, image/svg+xml + """ + prefix = f"data:{image_mime};base64," + image_base64: bytes = base64.b64encode(obj) + result = prefix + image_base64.decode("UTF-8") + return result diff --git a/src/streamdeck_sdk/utils/in_separate_thread.py b/src/streamdeck_sdk/utils/in_separate_thread.py new file mode 100644 index 0000000..66ac5b6 --- /dev/null +++ b/src/streamdeck_sdk/utils/in_separate_thread.py @@ -0,0 +1,41 @@ +from functools import wraps +from threading import Thread +from typing import Callable, Optional + + +class ThreadingFunc: + def __init__( + self, + func: Callable, + *, + daemon: Optional[bool] = None, + ): + self.func = func + self.daemon = daemon + + def __call__(self, *args, **kwargs) -> Thread: + thread = Thread(target=self.func, args=args, kwargs=kwargs, daemon=self.daemon) + thread.start() + return thread + + +def in_separate_thread(daemon: Optional[bool] = None): + """ + Decorator for executing the decorated function on a separate thread. + + :param daemon: A daemon thread (True) or not (False). If None, then its initial value is inherited + from the creating thread. + """ + + def _decorator(func: Callable): + @wraps(func) + def wrapper(*args, **kwargs): + return ThreadingFunc(func=func, daemon=_daemon)(*args, **kwargs) + + return wrapper + + _daemon: Optional[bool] = None + if callable(daemon): + return _decorator(func=daemon) + _daemon = daemon + return _decorator From 65b9176197436c16b2176540682bd1afa2e7636c Mon Sep 17 00:00:00 2001 From: Grigoriy Gusev Date: Sun, 22 Sep 2024 13:09:34 +0300 Subject: [PATCH 2/5] dev6 --- MANIFEST.in | 1 - pyproject.toml | 2 +- setup.py | 61 - src/streamdeck_sdk/__init__.py | 5 - .../sd_objs/events_sent_objs/log_message.py | 2 +- streamdeck_sdk/__init__.py | 5 - streamdeck_sdk/event_routings.py | 59 - .../executable/assets/DistributionTool | Bin 649904 -> 0 bytes .../executable/assets/DistributionTool.exe | Bin 333312 -> 0 bytes .../assets/category_icon.svg | 12 - .../assets/myaction/action_icon.svg | 12 - .../assets/myaction/key_icon.svg | 12 - .../assets/plugin_icon.svg | 12 - .../code/main.py | 25 - .../code/requirements.txt | 1 - .../code/settings.py | 8 - .../init.py | 261 --- .../manifest.json | 45 - .../property_inspector/myaction_pi.html | 133 -- .../property_inspector/myaction_pi.py | 26 - .../property_inspector/pi_template.html | 110 -- .../assets/caret.svg | 3 - .../assets/caret_closed.svg | 5 - .../assets/check.png | Bin 234 -> 0 bytes .../assets/check.svg | 3 - .../assets/elg_calendar.svg | 25 - .../assets/elg_calendar_inv.svg | 7 - .../assets/rcheck.svg | 3 - .../streamdeck-javascript-sdk/assets/tick.svg | 3 - .../streamdeck-javascript-sdk/css/sdpi.css | 1747 ----------------- .../streamdeck-javascript-sdk/js/action.js | 214 -- .../streamdeck-javascript-sdk/js/api.js | 351 ---- .../streamdeck-javascript-sdk/js/constants.js | 83 - .../js/dynamic-styles.js | 70 - .../streamdeck-javascript-sdk/js/events.js | 38 - .../js/property-inspector.js | 82 - .../js/prototypes.js | 26 - .../js/stream-deck.js | 295 --- .../streamdeck-javascript-sdk/js/timers.js | 95 - .../streamdeck-javascript-sdk/js/utils.js | 94 - .../run.bat | 66 - .../run.sh | 61 - streamdeck_sdk/executable/executable.py | 78 - streamdeck_sdk/logger.py | 60 - streamdeck_sdk/mixins/__init__.py | 10 - streamdeck_sdk/mixins/debug_server_mixin.py | 50 - streamdeck_sdk/mixins/event_routing_mixin.py | 134 -- streamdeck_sdk/mixins/handle_event_mixins.py | 72 - streamdeck_sdk/mixins/send_event_mixins.py | 421 ---- streamdeck_sdk/property_inspector/__init__.py | 2 - .../property_inspector/objs/__init__.py | 22 - .../property_inspector/objs/base.py | 52 - .../property_inspector/objs/checkbox.py | 105 - .../property_inspector/objs/color.py | 59 - .../property_inspector/objs/date_obj.py | 59 - .../property_inspector/objs/datetime_local.py | 59 - .../property_inspector/objs/details.py | 67 - .../property_inspector/objs/file.py | 99 - .../property_inspector/objs/group.py | 44 - .../property_inspector/objs/heading.py | 15 - .../property_inspector/objs/line.py | 7 - .../property_inspector/objs/message.py | 64 - .../property_inspector/objs/meter.py | 60 - .../property_inspector/objs/month.py | 59 - .../property_inspector/objs/password.py | 66 - .../property_inspector/objs/progress.py | 60 - .../property_inspector/objs/radio.py | 91 - .../property_inspector/objs/range.py | 99 - .../property_inspector/objs/select.py | 115 -- .../property_inspector/objs/textarea.py | 67 - .../property_inspector/objs/textfield.py | 66 - .../property_inspector/objs/time_obj.py | 59 - .../property_inspector/objs/week.py | 59 - .../property_inspector/property_inspector.py | 64 - streamdeck_sdk/sd_objs/__init__.py | 3 - .../sd_objs/events_received_objs/__init__.py | 23 - .../application_did_launch.py | 25 - .../application_did_terminate.py | 25 - .../events_received_objs/assets/__init__.py | 0 .../assets/controller_enum.py | 9 - .../assets/key_coordinates.py | 9 - .../device_did_connect.py | 37 - .../device_did_disconnect.py | 14 - .../sd_objs/events_received_objs/dial_down.py | 37 - .../events_received_objs/dial_rotate.py | 42 - .../sd_objs/events_received_objs/dial_up.py | 37 - .../did_receive_deep_link.py | 27 - .../did_receive_global_settings.py | 19 - .../did_receive_settings.py | 39 - .../sd_objs/events_received_objs/key_down.py | 44 - .../sd_objs/events_received_objs/key_up.py | 44 - .../property_inspector_did_appear.py | 19 - .../property_inspector_did_disappear.py | 18 - .../events_received_objs/send_to_plugin.py | 18 - .../send_to_property_inspector.py | 19 - .../system_did_wake_up.py | 16 - .../title_parameters_did_change.py | 59 - .../sd_objs/events_received_objs/touch_tap.py | 43 - .../events_received_objs/will_appear.py | 50 - .../events_received_objs/will_disappear.py | 48 - .../sd_objs/events_sent_objs/__init__.py | 17 - .../events_sent_objs/get_global_settings.py | 17 - .../sd_objs/events_sent_objs/get_settings.py | 17 - .../sd_objs/events_sent_objs/log_message.py | 24 - .../sd_objs/events_sent_objs/open_url.py | 22 - .../events_sent_objs/send_to_plugin.py | 21 - .../send_to_property_inspector.py | 19 - .../sd_objs/events_sent_objs/set_feedback.py | 20 - .../events_sent_objs/set_feedback_layout.py | 26 - .../events_sent_objs/set_global_settings.py | 23 - .../sd_objs/events_sent_objs/set_image.py | 35 - .../sd_objs/events_sent_objs/set_settings.py | 22 - .../sd_objs/events_sent_objs/set_state.py | 23 - .../sd_objs/events_sent_objs/set_title.py | 33 - .../set_trigger_description.py | 39 - .../sd_objs/events_sent_objs/show_alert.py | 15 - .../sd_objs/events_sent_objs/show_ok.py | 15 - .../events_sent_objs/switch_to_profile.py | 32 - streamdeck_sdk/sd_objs/registration_objs.py | 87 - streamdeck_sdk/sdk.py | 166 -- streamdeck_sdk/simple_ws/__init__.py | 1 - streamdeck_sdk/simple_ws/client.py | 61 - streamdeck_sdk/utils/__init__.py | 2 - streamdeck_sdk/utils/image_converters.py | 22 - streamdeck_sdk/utils/in_separate_thread.py | 41 - 125 files changed, 2 insertions(+), 7929 deletions(-) delete mode 100644 MANIFEST.in delete mode 100644 setup.py delete mode 100644 streamdeck_sdk/__init__.py delete mode 100644 streamdeck_sdk/event_routings.py delete mode 100644 streamdeck_sdk/executable/assets/DistributionTool delete mode 100644 streamdeck_sdk/executable/assets/DistributionTool.exe delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/assets/category_icon.svg delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/assets/myaction/action_icon.svg delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/assets/myaction/key_icon.svg delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/assets/plugin_icon.svg delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/code/main.py delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/code/requirements.txt delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/code/settings.py delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/init.py delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/manifest.json delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/myaction_pi.html delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/myaction_pi.py delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/pi_template.html delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/assets/caret.svg delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/assets/caret_closed.svg delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/assets/check.png delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/assets/check.svg delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/assets/elg_calendar.svg delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/assets/elg_calendar_inv.svg delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/assets/rcheck.svg delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/assets/tick.svg delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/css/sdpi.css delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/action.js delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/api.js delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/constants.js delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/dynamic-styles.js delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/events.js delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/property-inspector.js delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/prototypes.js delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/stream-deck.js delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/timers.js delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/utils.js delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/run.bat delete mode 100644 streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/run.sh delete mode 100644 streamdeck_sdk/executable/executable.py delete mode 100644 streamdeck_sdk/logger.py delete mode 100644 streamdeck_sdk/mixins/__init__.py delete mode 100644 streamdeck_sdk/mixins/debug_server_mixin.py delete mode 100644 streamdeck_sdk/mixins/event_routing_mixin.py delete mode 100644 streamdeck_sdk/mixins/handle_event_mixins.py delete mode 100644 streamdeck_sdk/mixins/send_event_mixins.py delete mode 100644 streamdeck_sdk/property_inspector/__init__.py delete mode 100644 streamdeck_sdk/property_inspector/objs/__init__.py delete mode 100644 streamdeck_sdk/property_inspector/objs/base.py delete mode 100644 streamdeck_sdk/property_inspector/objs/checkbox.py delete mode 100644 streamdeck_sdk/property_inspector/objs/color.py delete mode 100644 streamdeck_sdk/property_inspector/objs/date_obj.py delete mode 100644 streamdeck_sdk/property_inspector/objs/datetime_local.py delete mode 100644 streamdeck_sdk/property_inspector/objs/details.py delete mode 100644 streamdeck_sdk/property_inspector/objs/file.py delete mode 100644 streamdeck_sdk/property_inspector/objs/group.py delete mode 100644 streamdeck_sdk/property_inspector/objs/heading.py delete mode 100644 streamdeck_sdk/property_inspector/objs/line.py delete mode 100644 streamdeck_sdk/property_inspector/objs/message.py delete mode 100644 streamdeck_sdk/property_inspector/objs/meter.py delete mode 100644 streamdeck_sdk/property_inspector/objs/month.py delete mode 100644 streamdeck_sdk/property_inspector/objs/password.py delete mode 100644 streamdeck_sdk/property_inspector/objs/progress.py delete mode 100644 streamdeck_sdk/property_inspector/objs/radio.py delete mode 100644 streamdeck_sdk/property_inspector/objs/range.py delete mode 100644 streamdeck_sdk/property_inspector/objs/select.py delete mode 100644 streamdeck_sdk/property_inspector/objs/textarea.py delete mode 100644 streamdeck_sdk/property_inspector/objs/textfield.py delete mode 100644 streamdeck_sdk/property_inspector/objs/time_obj.py delete mode 100644 streamdeck_sdk/property_inspector/objs/week.py delete mode 100644 streamdeck_sdk/property_inspector/property_inspector.py delete mode 100644 streamdeck_sdk/sd_objs/__init__.py delete mode 100644 streamdeck_sdk/sd_objs/events_received_objs/__init__.py delete mode 100644 streamdeck_sdk/sd_objs/events_received_objs/application_did_launch.py delete mode 100644 streamdeck_sdk/sd_objs/events_received_objs/application_did_terminate.py delete mode 100644 streamdeck_sdk/sd_objs/events_received_objs/assets/__init__.py delete mode 100644 streamdeck_sdk/sd_objs/events_received_objs/assets/controller_enum.py delete mode 100644 streamdeck_sdk/sd_objs/events_received_objs/assets/key_coordinates.py delete mode 100644 streamdeck_sdk/sd_objs/events_received_objs/device_did_connect.py delete mode 100644 streamdeck_sdk/sd_objs/events_received_objs/device_did_disconnect.py delete mode 100644 streamdeck_sdk/sd_objs/events_received_objs/dial_down.py delete mode 100644 streamdeck_sdk/sd_objs/events_received_objs/dial_rotate.py delete mode 100644 streamdeck_sdk/sd_objs/events_received_objs/dial_up.py delete mode 100644 streamdeck_sdk/sd_objs/events_received_objs/did_receive_deep_link.py delete mode 100644 streamdeck_sdk/sd_objs/events_received_objs/did_receive_global_settings.py delete mode 100644 streamdeck_sdk/sd_objs/events_received_objs/did_receive_settings.py delete mode 100644 streamdeck_sdk/sd_objs/events_received_objs/key_down.py delete mode 100644 streamdeck_sdk/sd_objs/events_received_objs/key_up.py delete mode 100644 streamdeck_sdk/sd_objs/events_received_objs/property_inspector_did_appear.py delete mode 100644 streamdeck_sdk/sd_objs/events_received_objs/property_inspector_did_disappear.py delete mode 100644 streamdeck_sdk/sd_objs/events_received_objs/send_to_plugin.py delete mode 100644 streamdeck_sdk/sd_objs/events_received_objs/send_to_property_inspector.py delete mode 100644 streamdeck_sdk/sd_objs/events_received_objs/system_did_wake_up.py delete mode 100644 streamdeck_sdk/sd_objs/events_received_objs/title_parameters_did_change.py delete mode 100644 streamdeck_sdk/sd_objs/events_received_objs/touch_tap.py delete mode 100644 streamdeck_sdk/sd_objs/events_received_objs/will_appear.py delete mode 100644 streamdeck_sdk/sd_objs/events_received_objs/will_disappear.py delete mode 100644 streamdeck_sdk/sd_objs/events_sent_objs/__init__.py delete mode 100644 streamdeck_sdk/sd_objs/events_sent_objs/get_global_settings.py delete mode 100644 streamdeck_sdk/sd_objs/events_sent_objs/get_settings.py delete mode 100644 streamdeck_sdk/sd_objs/events_sent_objs/log_message.py delete mode 100644 streamdeck_sdk/sd_objs/events_sent_objs/open_url.py delete mode 100644 streamdeck_sdk/sd_objs/events_sent_objs/send_to_plugin.py delete mode 100644 streamdeck_sdk/sd_objs/events_sent_objs/send_to_property_inspector.py delete mode 100644 streamdeck_sdk/sd_objs/events_sent_objs/set_feedback.py delete mode 100644 streamdeck_sdk/sd_objs/events_sent_objs/set_feedback_layout.py delete mode 100644 streamdeck_sdk/sd_objs/events_sent_objs/set_global_settings.py delete mode 100644 streamdeck_sdk/sd_objs/events_sent_objs/set_image.py delete mode 100644 streamdeck_sdk/sd_objs/events_sent_objs/set_settings.py delete mode 100644 streamdeck_sdk/sd_objs/events_sent_objs/set_state.py delete mode 100644 streamdeck_sdk/sd_objs/events_sent_objs/set_title.py delete mode 100644 streamdeck_sdk/sd_objs/events_sent_objs/set_trigger_description.py delete mode 100644 streamdeck_sdk/sd_objs/events_sent_objs/show_alert.py delete mode 100644 streamdeck_sdk/sd_objs/events_sent_objs/show_ok.py delete mode 100644 streamdeck_sdk/sd_objs/events_sent_objs/switch_to_profile.py delete mode 100644 streamdeck_sdk/sd_objs/registration_objs.py delete mode 100644 streamdeck_sdk/sdk.py delete mode 100644 streamdeck_sdk/simple_ws/__init__.py delete mode 100644 streamdeck_sdk/simple_ws/client.py delete mode 100644 streamdeck_sdk/utils/__init__.py delete mode 100644 streamdeck_sdk/utils/image_converters.py delete mode 100644 streamdeck_sdk/utils/in_separate_thread.py diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index f88000b..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1 +0,0 @@ -recursive-include streamdeck_sdk * \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index d550539..fd2c999 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "streamdeck_sdk" -version = "1.2.0.dev4" +version = "1.2.0.dev6" authors = [ { name = "Grigoriy Gusev", email = "thegrigus@gmail.com" }, ] diff --git a/setup.py b/setup.py deleted file mode 100644 index 760de4a..0000000 --- a/setup.py +++ /dev/null @@ -1,61 +0,0 @@ -from pathlib import Path - -import setuptools - -VERSION = "1.1.2" -PACKAGE_DIR = "." -REQUIREMENTS_FILE = "./requirements.txt" -README = "README-PYPI.md" -BASE_DIR = Path(__file__).resolve().parent - -with open(REQUIREMENTS_FILE, "r") as f: - requirements = f.read().splitlines() - -with open(README, "r") as file: - long_description = file.read() - -[p.unlink() for p in BASE_DIR.rglob('*.py[co]')] -[p.rmdir() for p in BASE_DIR.rglob('__pycache__')] - -setuptools.setup( - name="streamdeck_sdk", - version=VERSION, - author="Grigoriy Gusev", - author_email="thegrigus@gmail.com", - description="Library for creating Stream Deck plugins in Python.", - long_description=long_description, - long_description_content_type="text/markdown", - url="https://github.com/gri-gus/streamdeck-python-sdk", - packages=setuptools.find_packages(where=PACKAGE_DIR), - include_package_data=True, - classifiers=[ - "Programming Language :: Python :: 3.10", - "License :: OSI Approved :: Apache Software License", - "Operating System :: OS Independent", - ], - python_requires='>=3.8', - license="Apache Software License", - keywords=[ - "python", - "sdk", - "streamdeck", - "streamdeck-sdk", - "streamdeck_sdk", - "stream deck sdk", - "stream deck", - "elgato", - "elgato sdk", - "elgato stream deck", - "streamdeck-python-sdk", - "streamdeck_python_sdk", - "streamdeck python sdk", - "streamdeck property inspector", - "streamdeck pi", - ], - install_requires=requirements, - entry_points={ - 'console_scripts': [ - 'streamdeck_sdk=streamdeck_sdk.executable.executable:main', - ], - }, -) diff --git a/src/streamdeck_sdk/__init__.py b/src/streamdeck_sdk/__init__.py index c642ca1..b350363 100644 --- a/src/streamdeck_sdk/__init__.py +++ b/src/streamdeck_sdk/__init__.py @@ -3,8 +3,3 @@ from .sd_objs import events_received_objs, events_sent_objs, registration_objs from .sdk import StreamDeck, Action from .utils import image_file_to_base64, image_bytes_to_base64, in_separate_thread - -try: - from streamdeck_sdk_pi import property_inspector -except Exception: - pass diff --git a/src/streamdeck_sdk/sd_objs/events_sent_objs/log_message.py b/src/streamdeck_sdk/sd_objs/events_sent_objs/log_message.py index 2e3901d..7019df1 100644 --- a/src/streamdeck_sdk/sd_objs/events_sent_objs/log_message.py +++ b/src/streamdeck_sdk/sd_objs/events_sent_objs/log_message.py @@ -9,7 +9,7 @@ class LogMessagePayload(BaseModel): class LogMessage(BaseModel): - """ + r""" The plugin and Property Inspector can use the logMessage event to write a debug message to the logs file. * Logs are saved to disk per plugin in the folder ~/Library/Logs/ElgatoStreamDeck/ on macOS and %appdata%\Elgato\StreamDeck\logs\ on Windows. Note that the log files are rotated each time diff --git a/streamdeck_sdk/__init__.py b/streamdeck_sdk/__init__.py deleted file mode 100644 index f830e03..0000000 --- a/streamdeck_sdk/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from . import mixins, property_inspector -from .logger import logger, log_errors -from .sd_objs import events_received_objs, events_sent_objs, registration_objs -from .sdk import StreamDeck, Action -from .utils import image_file_to_base64, image_bytes_to_base64, in_separate_thread diff --git a/streamdeck_sdk/event_routings.py b/streamdeck_sdk/event_routings.py deleted file mode 100644 index eedd66d..0000000 --- a/streamdeck_sdk/event_routings.py +++ /dev/null @@ -1,59 +0,0 @@ -from enum import Enum -from typing import Type, Dict, get_type_hints - -from pydantic import BaseModel - -from . import mixins - - -class EventRoutingObjTypes(Enum): - ACTION = "ACTION" - PLUGIN = "PLUGIN" - - -class EventRoutingObj(BaseModel): - handler_name: str - obj_type: Type[BaseModel] - type: EventRoutingObjTypes - - -EVENT_ROUTING_MAP: Dict[str, EventRoutingObj] = {} - - -def fill_routing_map( - routing_map: Dict[str, EventRoutingObj], - event_handler_mixin: mixins.BaseEventHandlerMixin, - event_routing_obj_type: EventRoutingObjTypes, -) -> None: - event_handler_mixin_dict = dict(event_handler_mixin.__dict__) - for attr, value in event_handler_mixin_dict.items(): - attr: str - if not attr.startswith("on_"): - continue - assert callable(value) - - handler_type_hints = get_type_hints(value) - obj_type = handler_type_hints["obj"] - obj = obj_type.construct() - event_name = obj.event - handler_name = value.__name__ - routing_map[event_name] = EventRoutingObj( - handler_name=handler_name, - obj_type=obj_type, - type=event_routing_obj_type, - ) - - -def fill_event_routing_map() -> None: - for event_handler_mixin, event_routing_obj_type in ( - (mixins.ActionEventHandlersMixin, EventRoutingObjTypes.ACTION), - (mixins.PluginEventHandlersMixin, EventRoutingObjTypes.PLUGIN), - ): - fill_routing_map( - routing_map=EVENT_ROUTING_MAP, - event_handler_mixin=event_handler_mixin, - event_routing_obj_type=event_routing_obj_type, - ) - - -fill_event_routing_map() diff --git a/streamdeck_sdk/executable/assets/DistributionTool b/streamdeck_sdk/executable/assets/DistributionTool deleted file mode 100644 index 36eac523e56751de9235c34cfb49173bf38148fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 649904 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 z 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%0Dd=;Ozxra13kyozaMR~?$T;R4}yPc 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 diff --git a/streamdeck_sdk/executable/assets/DistributionTool.exe b/streamdeck_sdk/executable/assets/DistributionTool.exe deleted file mode 100644 index 0d2f8315dc5839a299ed58da20b9a33efbe7e019..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 333312 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 - - - - - - - - - - - \ No newline at end of file diff --git a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/assets/myaction/action_icon.svg b/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/assets/myaction/action_icon.svg deleted file mode 100644 index d6b1b73..0000000 --- a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/assets/myaction/action_icon.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/assets/myaction/key_icon.svg b/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/assets/myaction/key_icon.svg deleted file mode 100644 index d6b1b73..0000000 --- a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/assets/myaction/key_icon.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/assets/plugin_icon.svg b/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/assets/plugin_icon.svg deleted file mode 100644 index d6b1b73..0000000 --- a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/assets/plugin_icon.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/code/main.py b/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/code/main.py deleted file mode 100644 index 64353ef..0000000 --- a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/code/main.py +++ /dev/null @@ -1,25 +0,0 @@ -import settings -from streamdeck_sdk import ( - StreamDeck, - Action, - events_received_objs, -) - - -class MyAction(Action): - UUID = "com.bestdeveloper.mytestplugin.myaction" - - def on_key_down(self, obj: events_received_objs.KeyDown): - self.open_url("https://github.com/gri-gus/streamdeck-python-sdk") - self.show_ok(context=obj.context) - - -if __name__ == '__main__': - StreamDeck( - actions=[ - MyAction(), - ], - log_file=settings.LOG_FILE_PATH, - log_level=settings.LOG_LEVEL, - log_backup_count=1, - ).run() diff --git a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/code/requirements.txt b/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/code/requirements.txt deleted file mode 100644 index f2faa1c..0000000 --- a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/code/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -streamdeck-sdk>=1.1.2 \ No newline at end of file diff --git a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/code/settings.py b/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/code/settings.py deleted file mode 100644 index 597b096..0000000 --- a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/code/settings.py +++ /dev/null @@ -1,8 +0,0 @@ -import logging -import os -from pathlib import Path - -PLUGIN_LOGS_DIR_PATH: Path = Path(os.environ.get("PLUGIN_LOGS_DIR_PATH", Path(__file__).parents[2] / "logs")) -PLUGIN_NAME: str = os.environ.get("PLUGIN_NAME", Path(__file__).parents[1].name) -LOG_FILE_PATH: Path = PLUGIN_LOGS_DIR_PATH / Path(f"{PLUGIN_NAME}.log") -LOG_LEVEL: int = logging.DEBUG diff --git a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/init.py b/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/init.py deleted file mode 100644 index 59a490e..0000000 --- a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/init.py +++ /dev/null @@ -1,261 +0,0 @@ -import logging -import os -import platform -import re -import shlex -import subprocess -import sys -import traceback -from logging.handlers import RotatingFileHandler -from pathlib import Path - -PYTHON_COMMAND: str = os.environ["PYTHON_COMMAND"] -PYTHON_MINIMUM_VERSION: str = os.environ["PYTHON_MINIMUM_VERSION"] - -PLUGIN_DIR_PATH: Path = Path(os.environ["PLUGIN_DIR_PATH"]) -PLUGIN_NAME: str = os.environ["PLUGIN_NAME"] -PLUGIN_LOGS_DIR_PATH: Path = Path(os.environ["PLUGIN_LOGS_DIR_PATH"]) - -PLUGIN_CODE_DIR_PATH: Path = Path(os.environ["PLUGIN_CODE_DIR_PATH"]) -PLUGIN_CODE_REQUIREMENTS_PATH: Path = Path(os.environ["PLUGIN_CODE_REQUIREMENTS_PATH"]) - -PLUGIN_CODE_VENV_DIR_PATH: Path = Path(os.environ["PLUGIN_CODE_VENV_DIR_PATH"]) -PLUGIN_CODE_VENV_ACTIVATE: Path = Path(os.environ["PLUGIN_CODE_VENV_ACTIVATE"]) - -SPACES_REGEX = re.compile(r" +", flags=re.MULTILINE) -BEGIN_END_WHITESPACES_REGEX = re.compile(r"^ +| +$", flags=re.MULTILINE) -LINE_TRANSLATION_REGEX = re.compile(r"\n|\r$", flags=re.MULTILINE) -BEGIN_S_REGEX = re.compile(r"^\s+|\s+$") -QUOTES_REGEX = re.compile(r"['\"`]") -PARSE_REQUIREMENTS_REGEX = re.compile(r"^\s*?(\S*).=", flags=re.MULTILINE) - -logger: logging.Logger = logging.getLogger(__name__) -MAX_MESSAGE_LEN: int = 500 -LOG_FILE_PATH: Path = PLUGIN_LOGS_DIR_PATH / Path("init.log") -LOG_LEVEL = logging.DEBUG - - -class InitError(Exception): - pass - - -def init_logger(log_file: Path, log_level: int = logging.DEBUG) -> None: - logger.setLevel(log_level) - logs_dir: Path = log_file.parent - logs_dir.mkdir(parents=True, exist_ok=True) - rfh = RotatingFileHandler( - log_file, - mode='a', - maxBytes=3 * 1024 * 1024, - backupCount=2, - encoding="utf-8", - delay=False, - ) - rfh.setLevel(logging.DEBUG) - formatter = logging.Formatter( - "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d): %(message)s" - ) - rfh.setFormatter(formatter) - logger.addHandler(rfh) - - -# region CleanUpFunctions - -def clean_up_command(text: str): - r1 = BEGIN_S_REGEX.sub("", text) - r2 = BEGIN_END_WHITESPACES_REGEX.sub("", r1) - r3 = LINE_TRANSLATION_REGEX.sub(" ", r2) - r4 = SPACES_REGEX.sub(" ", r3) - return r4 - - -def clean_up_command_result(text: str): - r1 = clean_up_command(text=text) - r2 = QUOTES_REGEX.sub(r'\"', r1) - return r2 - - -# endregion CleanUpFunctions - -# region DaemonCommands - -def create_venv_daemon() -> subprocess.Popen: - command = f'{PYTHON_COMMAND} -m venv "{PLUGIN_CODE_VENV_DIR_PATH}"' - command_split = shlex.split(command) - process = subprocess.Popen( - command_split, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - encoding="utf-8" - ) - return process - - -def install_requirements_daemon() -> subprocess.Popen: - if sys.platform.startswith("win") or sys.platform.startswith("cygwin"): - command = f''' - "{PLUGIN_CODE_VENV_ACTIVATE}" &&\ - {PYTHON_COMMAND} -m pip install --upgrade pip &&\ - {PYTHON_COMMAND} -m pip install -r "{PLUGIN_CODE_REQUIREMENTS_PATH}"\ - ''' - else: - command = f''' - source "{PLUGIN_CODE_VENV_ACTIVATE}" &&\ - export PYTHONPATH="{PLUGIN_CODE_DIR_PATH}" &&\ - {PYTHON_COMMAND} -m pip install --upgrade pip &&\ - {PYTHON_COMMAND} -m pip install -r "{PLUGIN_CODE_REQUIREMENTS_PATH}"\ - ''' - process = subprocess.Popen( - clean_up_command(command), - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - encoding="utf-8", - shell=True, - ) - return process - - -def pip_freeze_daemon() -> subprocess.Popen: - os_name = platform.system() - logger.info(os_name) - if os_name == "Darwin": - command = f''' - source "{PLUGIN_CODE_VENV_ACTIVATE}" &&\ - {PYTHON_COMMAND} -m pip freeze\ - ''' - elif os_name == "Windows": - command = f''' - "{PLUGIN_CODE_VENV_ACTIVATE}" &&\ - {PYTHON_COMMAND} -m pip freeze\ - ''' - else: - raise InitError("Unsupported Operation System.") - process = subprocess.Popen( - clean_up_command(command), - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - encoding="utf-8", - shell=True, - ) - return process - - -# endregion DaemonCommands - -def check_venv_activate_exists() -> bool: - if PLUGIN_CODE_VENV_ACTIVATE.exists(): - logger.info(f'venv activate already exists in "{PLUGIN_CODE_VENV_ACTIVATE}"') - return True - logger.info(f'venv activate is not exists in "{PLUGIN_CODE_VENV_ACTIVATE}"') - return False - - -def check_python_version() -> None: - minimum_python_version_splitted = PYTHON_MINIMUM_VERSION.split(".") - python_version_info = sys.version_info - python_version_str = ".".join([str(item) for item in python_version_info[:3]]) - - for index, minimum_python_version_item in enumerate(minimum_python_version_splitted): - if int(minimum_python_version_item) < python_version_info[index]: - logger.info(f'Current python version "{python_version_str}" > "{PYTHON_MINIMUM_VERSION}"') - return - elif int(minimum_python_version_item) > python_version_info[index]: - message = f'Current python version "{python_version_str}" < "{PYTHON_MINIMUM_VERSION}"' - logger.error(message) - raise InitError(message) - logger.info(f'Current python version "{python_version_str}" >= "{PYTHON_MINIMUM_VERSION}"') - - -def create_venv() -> None: - process = create_venv_daemon() - stdout, stderr = process.communicate() - if stderr: - logger.error(stderr) - raise InitError(stderr) - - -def install_requirements() -> None: - process = install_requirements_daemon() - stdout, stderr = process.communicate() - if stderr: - logger.error(stderr) - raise InitError(stderr) - - -def check_requirements(): - requirements_packages_text = PLUGIN_CODE_REQUIREMENTS_PATH.read_text("utf-8") - requirements_packages_names = PARSE_REQUIREMENTS_REGEX.findall(requirements_packages_text) - - process = pip_freeze_daemon() - installed_packages_text, stderr = process.communicate() - if stderr: - logger.warning(stderr) - - installed_packages_names = PARSE_REQUIREMENTS_REGEX.findall(installed_packages_text) - installed_packages_names_underscore = [package_name.replace("-", "_") for package_name in installed_packages_names] - installed_packages_names.extend(installed_packages_names_underscore) - - for requirements_package_name in requirements_packages_names: - requirements_package_name_underscore = requirements_package_name.replace("-", "_") - if not (requirements_package_name in installed_packages_names or - requirements_package_name_underscore in installed_packages_names): - message = f'Package "{requirements_package_name}" not installed' - logger.error(message) - raise InitError(message) - - -def init_project() -> None: - if check_venv_activate_exists(): - try: - check_requirements() - except InitError as err: - raise InitError(f"Current venv ERROR: {err}") - logger.info("Current venv is correct") - return - - try: - check_python_version() - except InitError as err: - raise InitError(f"Check python version ERROR: {err}") - logger.info("Python version is correct") - - try: - create_venv() - except InitError: - raise InitError(f"Create venv ERROR") - logger.info("venv created successfully") - - try: - install_requirements() - except InitError: - try: - check_requirements() - except InitError: - raise InitError(f"Install requirements ERROR") - logger.info("Requirements are successfully installed") - - -def main(): - try: - init_logger(log_file=LOG_FILE_PATH, log_level=LOG_LEVEL) - logger.info("INIT STARTED") - init_project() - result = True - except BaseException as err: - if isinstance(err, InitError): - message = str(err) - logger.error(message) - else: - message = "Init ERROR" - log_message = f"{message}: {str(type(err).__name__)}: {err}; Traceback: {traceback.format_exc()}" - logger.error(log_message) - result_message = f"{message}. See log file for details: {LOG_FILE_PATH}. " \ - f"You need to fix the problem and reinstall the plugin." - result = clean_up_command_result(text=str(result_message))[:MAX_MESSAGE_LEN] - logger.info(f"result={result}") - print(result) - logger.info("INIT ENDED") - - -if __name__ == '__main__': - main() diff --git a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/manifest.json b/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/manifest.json deleted file mode 100644 index dd51009..0000000 --- a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/manifest.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "Actions": [ - { - "UUID": "com.bestdeveloper.mytestplugin.myaction", - "Icon": "assets/myaction/action_icon", - "Name": "My action", - "States": [ - { - "Image": "assets/myaction/key_icon" - } - ], - "PropertyInspectorPath": "property_inspector/myaction_pi.html", - "SupportedInMultiActions": true, - "Controllers": [ - "Keypad" - ], - "Tooltip": "Open streamdeck_sdk github page.", - "UserTitleEnabled": true - } - ], - "Author": "BestDeveloper", - "CodePath": "run.sh", - "Description": "Open streamdeck_sdk github page.", - "Icon": "assets/plugin_icon", - "Name": "MyTestPlugin", - "Version": "0.0.4", - "SDKVersion": 2, - "OS": [ - { - "Platform": "mac", - "MinimumVersion": "10.14" - }, - { - "Platform": "windows", - "MinimumVersion": "10" - } - ], - "Software": { - "MinimumVersion": "6" - }, - "Category": "MyTestCategory", - "CategoryIcon": "assets/category_icon", - "CodePathMac": "run.sh", - "CodePathWin": "run.bat" -} diff --git a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/myaction_pi.html b/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/myaction_pi.html deleted file mode 100644 index 737e30f..0000000 --- a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/myaction_pi.html +++ /dev/null @@ -1,133 +0,0 @@ - - - - - - - - - com.bestdeveloper.mytestplugin.myaction Property Inspector - - - - -
- -
-
- Example message -

Example message text

-
-
- -
- - - - - - - - - - - - - - diff --git a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/myaction_pi.py b/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/myaction_pi.py deleted file mode 100644 index 2359f45..0000000 --- a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/myaction_pi.py +++ /dev/null @@ -1,26 +0,0 @@ -from pathlib import Path - -from streamdeck_sdk.property_inspector import * - -OUTPUT_DIR = Path(__file__).parent -TEMPLATE = Path(__file__).parent / "pi_template.html" - - -def main(): - pi = PropertyInspector( - action_uuid="com.bestdeveloper.mytestplugin.myaction", - elements=[ - Message( - uid="my_message", - heading="Example message", - message_type=MessageTypes.INFO, - text="Example message text", - ), - ] - ) - pi.build(output_dir=OUTPUT_DIR, template=TEMPLATE) - - -if __name__ == '__main__': - # Run to generate Property Inspector - main() diff --git a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/pi_template.html b/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/pi_template.html deleted file mode 100644 index 6f78d2b..0000000 --- a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/pi_template.html +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - - - YOUR_ACTION_UUID Property Inspector - - - - -
- - - -
- - - - - - - - - - - - - - diff --git a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/assets/caret.svg b/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/assets/caret.svg deleted file mode 100644 index 932fff4..0000000 --- a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/assets/caret.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/assets/caret_closed.svg b/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/assets/caret_closed.svg deleted file mode 100644 index 2678e69..0000000 --- a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/assets/caret_closed.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/assets/check.png b/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/assets/check.png deleted file mode 100644 index b5e9e622cb4cd2396d583bfde341ab09ad46b347..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 234 zcmeAS@N?(olHy`uVBq!ia0vp^JV4CF!3HE7boT!OQY`6?zK#qG8~eHcB(ehe3q4&N zLnI`V6BL;K{Qp0nx#MU@09PPWhz)bcd - - diff --git a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/assets/elg_calendar.svg b/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/assets/elg_calendar.svg deleted file mode 100644 index 851cc91..0000000 --- a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/assets/elg_calendar.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/assets/elg_calendar_inv.svg b/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/assets/elg_calendar_inv.svg deleted file mode 100644 index 4e47b6e..0000000 --- a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/assets/elg_calendar_inv.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/assets/rcheck.svg b/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/assets/rcheck.svg deleted file mode 100644 index c01a443..0000000 --- a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/assets/rcheck.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/assets/tick.svg b/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/assets/tick.svg deleted file mode 100644 index 1c59975..0000000 --- a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/assets/tick.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/css/sdpi.css b/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/css/sdpi.css deleted file mode 100644 index 33125af..0000000 --- a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/css/sdpi.css +++ /dev/null @@ -1,1747 +0,0 @@ -html { - --sdpi-bgcolor: #2D2D2D; - --sdpi-background: #3D3D3D; - --sdpi-color: #d8d8d8; - --sdpi-bordercolor: #3a3a3a; - --sdpi-buttonbordercolor: #969696; - --sdpi-borderradius: 0px; - --sdpi-width: 224px; - --sdpi-fontweight: 600; - --sdpi-letterspacing: -0.25pt; - --sdpi-tab-color: #969696; - --sdpi-tab-left-margin: 1px; - --sdpi-tab-top-offset: 1px; - --sdpi-tab-selected-color: #333333; - --sdpi-tab-selected-top-offset: 0px; - --sdpi-tab-font-size: 9pt; - --sdpi-tab-container-left-offset: 5px; - --sdpi-tab-padding-horizontal: 12px; - --sdpi-tab-padding-vertical: 5px; - --sdpi-linecolor: #454545; - height: 100%; - width: 100%; - overflow: hidden; - touch-action: none; -} - -html, -body { - font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; - font-size: 9pt; - background-color: var(--sdpi-bgcolor); - color: #9a9a9a; -} - -body { - height: 100%; - padding: 0; - overflow-x: hidden; - overflow-y: auto; - margin: 0; - -webkit-overflow-scrolling: touch; - -webkit-text-size-adjust: 100%; - -webkit-font-smoothing: antialiased; -} - -mark { - background-color: var(--sdpi-bgcolor); - color: var(--sdpi-color); -} - -hr, -hr2 { - -webkit-margin-before: 1em; - -webkit-margin-after: 1em; - border-style: none; - background: var(--sdpi-background); - height: 1px; -} - -hr2, -.sdpi-heading { - display: flex; - flex-basis: 100%; - align-items: center; - color: inherit; - font-size: 9pt; - margin: 8px 0px; -} - - -h1 { - font-size: 1.3em; - font-weight: 500; - text-align: center; - margin-bottom: 12px; -} - -.sdpi-heading::before, -.sdpi-heading::after { - content: ""; - flex-grow: 1; - background: var(--sdpi-background); - height: 1px; - font-size: 0px; - line-height: 0px; - margin: 0px 16px; -} - -hr2 { - height: 2px; -} - -hr, -hr2 { - margin-left: 16px; - margin-right: 16px; -} - -.sdpi-item-value, -option, -input, -select, -button { - font-size: 10pt; - font-weight: var(--sdpi-fontweight); - letter-spacing: var(--sdpi-letterspacing); -} - -.sdpi-item-value> :last-of-type, -.sdpi-item-value:last-child { - margin-bottom: 4px; -} - -.win .sdpi-item-value, -.win option, -.win input, -.win select, -.win button { - font-size: 11px; - font-style: normal; - letter-spacing: inherit; - font-weight: 100; -} - -.win button { - font-size: 12px; -} - -::-webkit-progress-value, -meter::-webkit-meter-optimum-value { - border-radius: 2px; - /* background: linear-gradient(#ccf, #99f 20%, #77f 45%, #77f 55%, #cdf); */ -} - -::-webkit-progress-bar, -meter::-webkit-meter-bar { - border-radius: 3px; - background: var(--sdpi-background); -} - -::-webkit-progress-bar:active, -meter::-webkit-meter-bar:active { - border-radius: 3px; - background: #222222; -} - -::-webkit-progress-value:active, -meter::-webkit-meter-optimum-value:active { - background: #99f; -} - -progress, -progress.sdpi-item-value { - min-height: 5px !important; - height: 5px; - background-color: #303030; -} - -progress { - margin-top: 8px !important; - margin-bottom: 8px !important; -} - -.full progress, -progress.full { - margin-top: 3px !important; -} - -::-webkit-progress-inner-element { - background-color: transparent; -} - - -.sdpi-item[type="progress"] { - margin-top: 4px !important; - margin-bottom: 12px; - min-height: 15px; -} - -.sdpi-item-child.full:last-child { - margin-bottom: 4px; -} - - -/* TABS */ - -.tabs { - /** - * Setting display to flex makes this container lay - * out its children using flexbox, the exact same - * as in the above "Stepper input" example. - */ - display: flex; - border-bottom: 1px solid rgba(255, 255, 255, 0.0); - flex-wrap: nowrap; - white-space: nowrap; - overflow-x: auto; - text-transform: capitalize; - background-color: transparent; - margin-left: var(--sdpi-tab-container-left-offset); -} - -.tabs::-webkit-scrollbar { - height: 4px; - display: none; -} - -.tabs::-webkit-scrollbar-track { - -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3); - box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3); - border-radius: 8px; -} - -.tabs::-webkit-scrollbar-thumb { - background-color: #444; - outline: 1px solid #444; - border-radius: 8px; -} - -.tab-separator { - margin-left: 100px; - max-width: 234px; - margin-bottom: 20px; - margin-top: -4px; -} - -.tab { - cursor: pointer; - padding: var(--sdpi-tab-padding-vertical) var(--sdpi-tab-padding-horizontal); - color: var(--sdpi-tab-color); - font-size: var(--sdpi-tab-font-size); - font-weight: var(--title-font-weight); - background-color: rgba(0, 0, 0, 0.1); - margin: 0px; - margin-top: var(--sdpi-tab-top-offset); - margin-left: var(--sdpi-tab-left-margin); - border-top-left-radius: 5px; - border-top-right-radius: 5px; - border: 1px solid rgba(255, 255, 255, 0.1); - border-bottom: 1px solid var(--sdpi-linecolor); - -webkit-user-select: none; - user-select: none; -} - -.tab:first-child { - margin-left: 0px; -} - -.tab-container { - margin-top: -14px; -} - -.tab-container>hr { - margin-left: 100px; - max-width: 234px; -} - -.tabs+hr { - margin-left: 0px; - max-width: 234px; - margin-top: -6px; -} - -.tab.selected { - color: white; - background-color: var(--sdpi-tab-selected-color); - border-bottom: 2px solid var(--sdpi-tab-selected-color); - margin-top: var(--sdpi-tab-selected-top-offset); -} - -.sdpi-item.tabgroup { - margin-top: 0px; -} - -.istab { - background-color: rgba(0, 0, 0, 0.2); - margin-bottom: 20px; - padding: 4px; -} - -select { - -webkit-appearance: none; - -moz-appearance: none; - -o-appearance: none; - appearance: none; - background: url(../assets/caret.svg) no-repeat 97% center; -} - -label.sdpi-file-label, -input[type="button"], -input[type="submit"], -input[type="reset"], -input[type="file"], -input[type=file]::-webkit-file-upload-button, -button, -select { - color: var(--sdpi-color); - border: 1pt solid #303030; - font-size: 8pt; - background-color: var(--sdpi-background); - border-radius: var(--sdpi-borderradius); -} - -label.sdpi-file-label, -input[type="button"], -input[type="submit"], -input[type="reset"], -input[type="file"], -input[type=file]::-webkit-file-upload-button, -button { - border: 1pt solid var(--sdpi-buttonbordercolor); - border-radius: var(--sdpi-borderradius); - border-color: var(--sdpi-buttonbordercolor); - min-height: 23px !important; - height: 23px !important; - margin-right: 8px; -} - -input[type=number]::-webkit-inner-spin-button, -input[type=number]::-webkit-outer-spin-button { - -webkit-appearance: none; - margin: 0; -} - -input[type="file"] { - border-radius: var(--sdpi-borderradius); - max-width: 220px; -} - -option { - height: 1.5em; - padding: 4px; -} - -/* SDPI */ - -.sdpi-wrapper { - overflow-x: hidden; - height: 100%; - margin-right: 1px; /* ensure scroller thumb is not clipped */ -} - -.sdpi-item { - display: flex; - flex-direction: row; - min-height: 30px; - align-items: first baseline; - margin-top: 2px; - max-width: 344px; - -webkit-user-drag: none; -} - -.sdpi-item[type="textarea"], -.sdpi-item[type="color"], -.sdpi-item[type="canvas"], -.sdpi-item .aligncenter { - align-items: center; -} - -.sdpi-item[type="color"]>.sdpi-item-label { - line-height: 22px; -} - -.sdpi-item:first-child { - margin-top: -1px; -} - -.sdpi-item:first-of-type { - margin-top: 2px; -} - -.sdpi-item[type="radio"]:first-of-type, -.sdpi-item[type="checkbox"]:first-of-type { - margin-top: -4px; -} - -.sdpi-item:last-child { - margin-bottom: 0px; -} - -.sdpi-item>*:not(.sdpi-item-label):not(meter):not(details):not(canvas) { - min-height: 26px; -} - -.sdpi-item>*:not(.sdpi-item-label.empty):not(meter) { - min-height: 26px; -} - -.sdpi-item>input { - padding: 0px 4px; -} - -.sdpi-item-group { - padding: 0 !important; -} - -meter.sdpi-item-value { - margin-left: 6px; -} - -.sdpi-item[type="group"] { - display: block; - margin-top: 12px; - margin-bottom: 12px; - /* border: 1px solid white; */ - flex-direction: unset; - text-align: left; -} - -.sdpi-item[type="group"]>.sdpi-item-label, -.sdpi-item[type="group"].sdpi-item-label { - width: 96%; - text-align: left; - font-weight: 700; - margin-bottom: 4px; - padding-left: 4px; -} - -dl, -ul, -ol { - -webkit-margin-before: 0px; - -webkit-margin-after: 4px; - -webkit-padding-start: 1em; - max-height: 90px; - overflow-y: scroll; - cursor: pointer; - user-select: none; -} - -table.sdpi-item-value, -dl.sdpi-item-value, -ul.sdpi-item-value, -ol.sdpi-item-value { - -webkit-margin-before: 4px; - -webkit-margin-after: 8px; - -webkit-padding-start: 1em; - width: var(--sdpi-width); - text-align: center; -} - -table>caption { - margin: 2px; -} - -.list, -.sdpi-item[type="list"] { - align-items: baseline; -} - -.sdpi-item-label { - text-align: right; - flex: none; - width: 94px; - padding-right: 5px; - font-weight: 600; - -webkit-user-select: none; - line-height: normal; - margin-left: -1px; -} - -.win .sdpi-item-label, -.sdpi-item-label>small { - font-weight: normal; -} - -.sdpi-item-label:after { - content: ": "; -} - -.sdpi-item-label.empty:after { - content: ""; -} - -.sdpi-test, -.sdpi-item-value { - flex: 1 0 0; - /* flex-grow: 1; - flex-shrink: 0; */ - margin-right: 14px; - margin-left: 4px; - justify-content: space-evenly; -} - -canvas.sdpi-item-value { - max-width: 144px; - max-height: 144px; - width: 144px; - height: 144px; - margin: 0 auto; - cursor: pointer; -} - -input.sdpi-item-value { - margin-left: 5px; -} - -.sdpi-item-value button, -button.sdpi-item-value { - margin-left: 6px; - margin-right: 14px; -} - -.sdpi-item-value.range { - margin-left: 0px; -} - -table, -dl.sdpi-item-value, -ul.sdpi-item-value, -ol.sdpi-item-value, -.sdpi-item-value>dl, -.sdpi-item-value>ul, -.sdpi-item-value>ol { - list-style-type: none; - list-style-position: outside; - margin-left: -4px; - margin-right: -4px; - padding: 4px; - border: 1px solid var(--sdpi-bordercolor); -} - -dl.sdpi-item-value, -ul.sdpi-item-value, -ol.sdpi-item-value, -.sdpi-item-value>ol { - list-style-type: none; - list-style-position: inside; - margin-left: 5px; - margin-right: 12px; - padding: 4px !important; - /* display: flex; - flex-direction: column; */ -} - -.two-items li { - display: flex; -} - -.two-items li>*:first-child { - flex: 0 0 50%; - text-align: left; -} - -.two-items.thirtyseventy li>*:first-child { - flex: 0 0 30%; -} - -ol.sdpi-item-value, -.sdpi-item-value>ol[listtype="none"] { - list-style-type: none; -} - -ol.sdpi-item-value[type="decimal"], -.sdpi-item-value>ol[type="decimal"] { - list-style-type: decimal; -} - -ol.sdpi-item-value[type="decimal-leading-zero"], -.sdpi-item-value>ol[type="decimal-leading-zero"] { - list-style-type: decimal-leading-zero; -} - -ol.sdpi-item-value[type="lower-alpha"], -.sdpi-item-value>ol[type="lower-alpha"] { - list-style-type: lower-alpha; -} - -ol.sdpi-item-value[type="upper-alpha"], -.sdpi-item-value>ol[type="upper-alpha"] { - list-style-type: upper-alpha; -} - -ol.sdpi-item-value[type="upper-roman"], -.sdpi-item-value>ol[type="upper-roman"] { - list-style-type: upper-roman; -} - -ol.sdpi-item-value[type="lower-roman"], -.sdpi-item-value>ol[type="lower-roman"] { - list-style-type: upper-roman; -} - -tr:nth-child(even), -.sdpi-item-value>ul>li:nth-child(even), -.sdpi-item-value>ol>li:nth-child(even), -li:nth-child(even) { - background-color: rgba(0, 0, 0, .2) -} - -td:hover, -.sdpi-item-value>ul>li:hover:nth-child(even), -.sdpi-item-value>ol>li:hover:nth-child(even), -li:hover:nth-child(even), -li:hover { - background-color: rgba(255, 255, 255, .1); -} - -td.selected, -td.selected:hover, -li.selected:hover, -li.selected { - color: white; - background-color: #77f; -} - -tr { - border: 1px solid var(--sdpi-bordercolor); -} - -td { - border-right: 1px solid var(--sdpi-bordercolor); - -webkit-user-select: none; -} - -tr:last-child, -td:last-child { - border: none; -} - -.sdpi-item-value.select, -.sdpi-item-value>select { - margin-right: 13px; - margin-left: 4px; - padding: 0px 4px; -} - -.sdpi-item-child, -.sdpi-item-group>.sdpi-item>input[type="color"] { - margin-top: 0.4em; - margin-right: 4px; - margin-left: 4px; -} - -.full, -.full *, -.sdpi-item-value.full, -.sdpi-item-child>full>*, -.sdpi-item-child.full, -.sdpi-item-child.full>*, -.full>.sdpi-item-child, -.full>.sdpi-item-child>* { - display: flex; - flex: 1 1 0; - margin-bottom: 4px; - margin-left: 0px; - width: 100%; - justify-content: space-evenly; -} - -.sdpi-item-group>.sdpi-item>input[type="color"] { - margin-top: 0px; -} - -::-webkit-calendar-picker-indicator:focus, -input[type=file]::-webkit-file-upload-button:focus, -button:focus, -textarea:focus, -input:focus, -select:focus, -option:focus, -details:focus, -summary:focus, -.custom-select select { - outline: none; -} - -summary { - cursor: default; - -webkit-user-select: none; -} - -.pointer, -summary .pointer { - cursor: pointer; -} - -.sdpi-item.details { - align-items: first baseline; -} - -/* needs Chromium update 2023 -.sdpi-item:has(>details) { - align-items: first baseline; -} -*/ - -details * { - font-size: 12px; - font-weight: normal; -} - -details.message { - padding: 4px 18px 4px 12px; -} - -details.message summary { - font-size: 10pt; - font-weight: 600; - min-height: 18px; -} - -details.message:first-child { - margin-top: 4px; - margin-left: 0; - padding-left: 102px !important; -} - -details.message>summary:first-of-type { - line-height: 20px; -} - -details.message h1 { - text-align: left; -} - -/* details:not(.pointer)>summary { - list-style: none; -} - -details > summary::-webkit-details-marker, -.message > summary::-webkit-details-marker { - display: none; -} */ - -.info20, -.question, -.caution, -.info { - background-repeat: no-repeat; - background-position: 72px center; -} - -.info20 { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Cpath fill='%23999' d='M10,20 C4.4771525,20 0,15.5228475 0,10 C0,4.4771525 4.4771525,0 10,0 C15.5228475,0 20,4.4771525 20,10 C20,15.5228475 15.5228475,20 10,20 Z M10,8 C8.8954305,8 8,8.84275812 8,9.88235294 L8,16.1176471 C8,17.1572419 8.8954305,18 10,18 C11.1045695,18 12,17.1572419 12,16.1176471 L12,9.88235294 C12,8.84275812 11.1045695,8 10,8 Z M10,3 C8.8954305,3 8,3.88165465 8,4.96923077 L8,5.03076923 C8,6.11834535 8.8954305,7 10,7 C11.1045695,7 12,6.11834535 12,5.03076923 L12,4.96923077 C12,3.88165465 11.1045695,3 10,3 Z'/%3E%3C/svg%3E%0A"); -} - -.info { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Cpath fill='%23999' d='M10,18 C5.581722,18 2,14.418278 2,10 C2,5.581722 5.581722,2 10,2 C14.418278,2 18,5.581722 18,10 C18,14.418278 14.418278,18 10,18 Z M10,8 C9.44771525,8 9,8.42137906 9,8.94117647 L9,14.0588235 C9,14.5786209 9.44771525,15 10,15 C10.5522847,15 11,14.5786209 11,14.0588235 L11,8.94117647 C11,8.42137906 10.5522847,8 10,8 Z M10,5 C9.44771525,5 9,5.44082732 9,5.98461538 L9,6.01538462 C9,6.55917268 9.44771525,7 10,7 C10.5522847,7 11,6.55917268 11,6.01538462 L11,5.98461538 C11,5.44082732 10.5522847,5 10,5 Z'/%3E%3C/svg%3E%0A"); -} - -.info2 { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 15 15'%3E%3Cpath fill='%23999' d='M7.5,15 C3.35786438,15 0,11.6421356 0,7.5 C0,3.35786438 3.35786438,0 7.5,0 C11.6421356,0 15,3.35786438 15,7.5 C15,11.6421356 11.6421356,15 7.5,15 Z M7.5,2 C6.67157287,2 6,2.66124098 6,3.47692307 L6,3.52307693 C6,4.33875902 6.67157287,5 7.5,5 C8.32842705,5 9,4.33875902 9,3.52307693 L9,3.47692307 C9,2.66124098 8.32842705,2 7.5,2 Z M5,6 L5,7.02155172 L6,7 L6,12 L5,12.0076778 L5,13 L10,13 L10,12 L9,12.0076778 L9,6 L5,6 Z'/%3E%3C/svg%3E%0A"); -} - -.sdpi-more-info { - background-image: linear-gradient(to right, #00000000 0%, #00000040 80%), url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cpolygon fill='%23999' points='4 7 8 7 8 5 12 8 8 11 8 9 4 9'/%3E%3C/svg%3E%0A"); -} - -.caution { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Cpath fill='%23999' fill-rule='evenodd' d='M9.03952676,0.746646542 C9.57068894,-0.245797319 10.4285735,-0.25196227 10.9630352,0.746646542 L19.7705903,17.2030214 C20.3017525,18.1954653 19.8777595,19 18.8371387,19 L1.16542323,19 C0.118729947,19 -0.302490098,18.2016302 0.231971607,17.2030214 L9.03952676,0.746646542 Z M10,2.25584053 L1.9601405,17.3478261 L18.04099,17.3478261 L10,2.25584053 Z M10,5.9375 C10.531043,5.9375 10.9615385,6.37373537 10.9615385,6.91185897 L10.9615385,11.6923077 C10.9615385,12.2304313 10.531043,12.6666667 10,12.6666667 C9.46895697,12.6666667 9.03846154,12.2304313 9.03846154,11.6923077 L9.03846154,6.91185897 C9.03846154,6.37373537 9.46895697,5.9375 10,5.9375 Z M10,13.4583333 C10.6372516,13.4583333 11.1538462,13.9818158 11.1538462,14.6275641 L11.1538462,14.6641026 C11.1538462,15.3098509 10.6372516,15.8333333 10,15.8333333 C9.36274837,15.8333333 8.84615385,15.3098509 8.84615385,14.6641026 L8.84615385,14.6275641 C8.84615385,13.9818158 9.36274837,13.4583333 10,13.4583333 Z'/%3E%3C/svg%3E%0A"); -} - -.question { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Cpath fill='%23999' d='M10,18 C5.581722,18 2,14.418278 2,10 C2,5.581722 5.581722,2 10,2 C14.418278,2 18,5.581722 18,10 C18,14.418278 14.418278,18 10,18 Z M6.77783203,7.65332031 C6.77783203,7.84798274 6.85929281,8.02888914 7.0222168,8.19604492 C7.18514079,8.36320071 7.38508996,8.44677734 7.62207031,8.44677734 C8.02409055,8.44677734 8.29703704,8.20768468 8.44091797,7.72949219 C8.59326248,7.27245865 8.77945854,6.92651485 8.99951172,6.69165039 C9.2195649,6.45678594 9.56233491,6.33935547 10.027832,6.33935547 C10.4256205,6.33935547 10.7006836,6.37695313 11.0021973,6.68847656 C11.652832,7.53271484 10.942627,8.472229 10.3750916,9.1321106 C9.80755615,9.79199219 8.29492188,11.9897461 10.027832,12.1347656 C10.4498423,12.1700818 10.7027991,11.9147157 10.7832031,11.4746094 C11.0021973,9.59857178 13.1254883,8.82415771 13.1254883,7.53271484 C13.1254883,7.07568131 12.9974785,6.65250846 12.7414551,6.26318359 C12.4854317,5.87385873 12.1225609,5.56600048 11.652832,5.33959961 C11.1831031,5.11319874 10.6414419,5 10.027832,5 C9.36767248,5 8.79004154,5.13541531 8.29492187,5.40625 C7.79980221,5.67708469 7.42317837,6.01879677 7.16503906,6.43139648 C6.90689975,6.8439962 6.77783203,7.25130007 6.77783203,7.65332031 Z M10.0099668,15 C10.2713191,15 10.5016601,14.9108147 10.7009967,14.7324415 C10.9003332,14.5540682 11,14.3088087 11,13.9966555 C11,13.7157177 10.9047629,13.4793767 10.7142857,13.2876254 C10.5238086,13.0958742 10.2890379,13 10.0099668,13 C9.72646591,13 9.48726565,13.0958742 9.2923588,13.2876254 C9.09745196,13.4793767 9,13.7157177 9,13.9966555 C9,14.313268 9.10077419,14.5596424 9.30232558,14.735786 C9.50387698,14.9119295 9.73975502,15 10.0099668,15 Z'/%3E%3C/svg%3E%0A"); -} - -.sdpi-more-info { - position: fixed; - left: 0px; - right: 0px; - bottom: 0px; - min-height: 16px; - padding-right: 16px; - text-align: right; - -webkit-touch-callout: none; - cursor: pointer; - user-select: none; - background-position: right center; - background-repeat: no-repeat; - border-radius: var(--sdpi-borderradius); - text-decoration: none; - color: var(--sdpi-color); -} - -.sdpi-more-info-button { - display: flex; - align-self: right; - margin-left: auto; - position: fixed; - right: 17px; - bottom: 0px; - user-select: none; -} - -.sdpi-bottom-bar { - display: flex; - align-self: right; - margin-left: auto; - position: fixed; - right: 17px; - bottom: 0px; - user-select: none; -} - -.sdpi-bottom-bar.right { - right: 0px; -} - -.sdpi-bottom-bar button { - min-height: 20px !important; - height: 20px !important; -} - -details a { - background-position: right !important; - min-height: 24px; - display: inline-block; - line-height: 24px; - padding-right: 28px; -} - -input:not([type="range"]), -textarea { - -webkit-appearance: none; - background: var(--sdpi-background); - color: var(--sdpi-color); - font-weight: normal; - font-size: 9pt; - border: none; - margin-top: 2px; - margin-bottom: 2px; - min-width: 219px; -} - -textarea+label { - display: flex; - justify-content: flex-end -} - -input[type="radio"], -input[type="checkbox"] { - display: none; -} - -input[type="radio"]+label, -input[type="checkbox"]+label { - font-size: 9pt; - color: var(--sdpi-color); - font-weight: normal; - margin-right: 8px; - -webkit-user-select: none; -} - -input[type="radio"]+label:after, -input[type="checkbox"]+label:after { - content: " " !important; -} - -.sdpi-item[type="radio"]>.sdpi-item-value, -.sdpi-item[type="checkbox"]>.sdpi-item-value { - padding-top: 2px; -} - -.sdpi-item[type="checkbox"]>.sdpi-item-value>* { - margin-top: 4px; -} - -.sdpi-item[type="checkbox"] .sdpi-item-child, -.sdpi-item[type="radio"] .sdpi-item-child { - display: inline-block; -} - -.sdpi-item[type="range"] .sdpi-item-value, -.sdpi-item[type="meter"] .sdpi-item-child, -.sdpi-item[type="progress"] .sdpi-item-child { - display: flex; -} - -.sdpi-item[type="range"] .sdpi-item-value { - min-height: 26px; -} - -.sdpi-item[type="range"] .sdpi-item-value span, -.sdpi-item[type="meter"] .sdpi-item-child span, -.sdpi-item[type="progress"] .sdpi-item-child span { - margin-top: -2px; - min-width: 8px; - text-align: right; - cursor: pointer; - -webkit-user-select: none; - user-select: none; -} - -.sdpi-item[type="range"] .sdpi-item-value span { - margin-top: 7px; - text-align: right; -} - -span+input[type="range"] { - display: flex; -} - -span+.range-container>input[type="range"], -span+input[type="range"] { - max-width: 168px; -} - -.sdpi-item[type="range"] .sdpi-item-value span:first-child, -.sdpi-item[type="meter"] .sdpi-item-child span:first-child, -.sdpi-item[type="progress"] .sdpi-item-child span:first-child { - margin-right: 4px; -} - -.sdpi-item[type="range"] .sdpi-item-value span:last-child, -.sdpi-item[type="meter"] .sdpi-item-child span:last-child, -.sdpi-item[type="progress"] .sdpi-item-child span:last-child { - margin-left: 4px; -} - -.reverse { - transform: rotate(180deg); -} - -.sdpi-item[type="meter"] .sdpi-item-child meter+span:last-child { - margin-left: -10px; -} - -.sdpi-item[type="progress"] .sdpi-item-child meter+span:last-child { - margin-left: -14px; -} - -.sdpi-item[type="radio"]>.sdpi-item-value>* { - margin-top: 2px; -} - -details { - padding: 8px 18px 8px 12px; - min-width: 86px; -} - -details>h4 { - border-bottom: 1px solid var(--sdpi-bordercolor); -} - -legend { - display: none; -} - -.sdpi-item-value>textarea { - padding: 0px; - width: 219px; - margin-left: 1px; - margin-top: 3px; - padding: 4px; -} - -input[type="radio"]+label span, -input[type="checkbox"]+label span { - display: inline-block; - width: 16px; - height: 16px; - margin: 2px 4px 2px 0; - border-radius: 3px; - vertical-align: middle; - background: var(--sdpi-background); - cursor: pointer; - border: 1px solid rgb(0, 0, 0, .2); -} - -input[type="radio"]+label span { - border-radius: 100%; -} - -input[type="radio"]:checked+label span, -input[type="checkbox"]:checked+label span { - background-color: #77f; - background-image: url(../assets/check.svg); - background-repeat: no-repeat; - background-position: center center; - border: 1px solid rgb(0, 0, 0, .4); -} - -input[type="radio"]:active:checked+label span, -input[type="radio"]:active+label span, -input[type="checkbox"]:active:checked+label span, -input[type="checkbox"]:active+label span { - background-color: #303030; -} - -input[type="radio"]:checked+label span { - background-image: url(../assets/rcheck.svg); -} - -input[type="range"] { - width: var(--sdpi-width); - height: 30px; - overflow: hidden; - cursor: pointer; - background: transparent !important; -} - -.sdpi-item>input[type="range"] { - margin-left: 2px; - max-width: var(--sdpi-width); - width: var(--sdpi-width); - padding: 0px; - margin-top: 2px; -} - -/* -input[type="range"], -input[type="range"]::-webkit-slider-runnable-track, -input[type="range"]::-webkit-slider-thumb { - -webkit-appearance: none; -} -*/ - -input[type="range"]::-webkit-slider-runnable-track { - height: 5px; - background: #979797; - border-radius: 3px; - padding: 0px !important; - border: 1px solid var(--sdpi-background); -} - -input[type="range"]::-webkit-slider-thumb { - position: relative; - -webkit-appearance: none; - background-color: var(--sdpi-color); - width: 12px; - height: 12px; - border-radius: 20px; - margin-top: -5px; - border: none; -} - -input[type="range" i] { - margin: 0; -} - -input[type="range"]::-webkit-slider-thumb::before { - position: absolute; - content: ""; - height: 5px; /* equal to height of runnable track or 1 less */ - width: 500px; /* make this bigger than the widest range input element */ - left: -502px; /* this should be -2px - width */ - top: 8px; /* don't change this */ - background: #77f; -} - -input[type="color"] { - min-width: 32px; - min-height: 32px; - width: 32px; - height: 32px; - padding: 0; - background-color: var(--sdpi-bgcolor); - flex: none; -} - -::-webkit-color-swatch { - min-width: 24px; -} - -textarea { - height: 3em; - word-break: break-word; - line-height: 1.5em; -} - -.textarea { - padding: 0px !important; -} - -textarea { - width: 219px; /*98%;*/ - height: 96%; - min-height: 6em; - resize: none; - border-radius: var(--sdpi-borderradius); -} - -/* CAROUSEL */ - -.sdpi-item[type="carousel"] {} - -.sdpi-item.card-carousel-wrapper, -.sdpi-item>.card-carousel-wrapper { - padding: 0; -} - -.card-carousel-wrapper { - display: flex; - align-items: center; - justify-content: center; - margin: 12px auto; - color: #666a73; -} - -.card-carousel { - display: flex; - justify-content: center; - width: 278px; -} - -.card-carousel--overflow-container { - overflow: hidden; -} - -.card-carousel--nav__left, -.card-carousel--nav__right { - /* display: inline-block; */ - width: 12px; - height: 12px; - border-top: 2px solid #42b883; - border-right: 2px solid #42b883; - cursor: pointer; - margin: 0 4px; - transition: transform 150ms linear; -} - -.card-carousel--nav__left[disabled], -.card-carousel--nav__right[disabled] { - opacity: 0.2; - border-color: black; -} - -.card-carousel--nav__left { - transform: rotate(-135deg); -} - -.card-carousel--nav__left:active { - transform: rotate(-135deg) scale(0.85); -} - -.card-carousel--nav__right { - transform: rotate(45deg); -} - -.card-carousel--nav__right:active { - transform: rotate(45deg) scale(0.85); -} - -.card-carousel-cards { - display: flex; - transition: transform 150ms ease-out; - transform: translatex(0px); -} - -.card-carousel-cards .card-carousel--card { - margin: 0 5px; - cursor: pointer; - /* box-shadow: 0 4px 15px 0 rgba(40, 44, 53, 0.06), 0 2px 2px 0 rgba(40, 44, 53, 0.08); */ - /* background-color: #fff; */ - text-align: center; - border-radius: 4px; - z-index: 3; -} - -.xxcard-carousel-cards .card-carousel--card:first-child { - margin-left: 0; -} - -.xxcard-carousel-cards .card-carousel--card:last-child { - margin-right: 0; -} - -.card-carousel-cards .card-carousel--card img { - vertical-align: bottom; - border-top-left-radius: 4px; - border-top-right-radius: 4px; - transition: opacity 150ms linear; - width: 60px; -} - -.card-carousel-cards .card-carousel--card img:hover { - opacity: 0.5; - background-color: rgba(255, 255, 255, .1); -} - -.card-carousel-cards .card-carousel--card--footer { - border-top: 0; - max-width: 80px; - overflow: hidden; - display: flex; - height: 100%; - flex-direction: column; -} - -.card-carousel-cards .card-carousel--card--footer p { - padding: 3px 0; - margin: 0; - margin-bottom: 2px; - font-size: 15px; - font-weight: 500; - color: #2c3e50; -} - -.card-carousel-cards .card-carousel--card--footer p:nth-of-type(2) { - font-size: 12px; - font-weight: 300; - padding: 6px; - color: #666a73; -} - -::-webkit-calendar-picker-indicator { - background: url(../assets/elg_calendar_inv.svg) no-repeat center; - font-size: 17px; -} - -::-webkit-calendar-picker-indicator:focus { - background-color: rgba(0, 0, 0, 0.2); -} - -input[type="text"]::-webkit-calendar-picker-indicator { - background: transparent; - font-size: 12px; -} - -input[type="date"] { - -webkit-align-items: center; - align-items: center; - display: -webkit-inline-flex; - overflow: hidden; - -webkit-padding-start: 1px; -} - -input::-webkit-datetime-edit { - flex: 1; - -webkit-user-modify: read-only !important; - user-modify: read-only !important; - display: inline-block; - min-width: 0; - overflow: hidden; - padding: 4px; - font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; - -} - -input[type="file"] { - opacity: 0; - display: none; -} - -.sdpi-item>input[type="file"] { - opacity: 1; - display: flex; -} - -input[type="file"]+span { - display: flex; - flex: 0 1 auto; - background-color: #0000ff50; -} - -label.sdpi-file-label { - cursor: pointer; - user-select: none; - display: inline-block; - min-height: 21px !important; - height: 21px !important; - line-height: 20px; - padding: 0px 4px; - margin: auto; - margin-right: 0px; - float: right; -} - -.sdpi-file-label>label:active, -.sdpi-file-label.file:active, -label.sdpi-file-label:active, -label.sdpi-file-info:active, -input[type="file"]::-webkit-file-upload-button:active, -button:active { - background-color: var(--sdpi-color); - color: #303030; -} - -input:required:invalid, -input:focus:invalid { - background: var(--sdpi-background) url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI5IiBoZWlnaHQ9IjkiIHZpZXdCb3g9IjAgMCA5IDkiPgogICAgPHBhdGggZmlsbD0iI0Q4RDhEOCIgZD0iTTQuNSwwIEM2Ljk4NTI4MTM3LC00LjU2NTM4NzgyZS0xNiA5LDIuMDE0NzE4NjMgOSw0LjUgQzksNi45ODUyODEzNyA2Ljk4NTI4MTM3LDkgNC41LDkgQzIuMDE0NzE4NjMsOSAzLjA0MzU5MTg4ZS0xNiw2Ljk4NTI4MTM3IDAsNC41IEMtMy4wNDM1OTE4OGUtMTYsMi4wMTQ3MTg2MyAyLjAxNDcxODYzLDQuNTY1Mzg3ODJlLTE2IDQuNSwwIFogTTQsMSBMNCw2IEw1LDYgTDUsMSBMNCwxIFogTTQuNSw4IEM0Ljc3NjE0MjM3LDggNSw3Ljc3NjE0MjM3IDUsNy41IEM1LDcuMjIzODU3NjMgNC43NzYxNDIzNyw3IDQuNSw3IEM0LjIyMzg1NzYzLDcgNCw3LjIyMzg1NzYzIDQsNy41IEM0LDcuNzc2MTQyMzcgNC4yMjM4NTc2Myw4IDQuNSw4IFoiLz4KICA8L3N2Zz4) no-repeat 98% center; -} - -input:required:valid { - background: var(--sdpi-background) url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI5IiBoZWlnaHQ9IjkiIHZpZXdCb3g9IjAgMCA5IDkiPjxwb2x5Z29uIGZpbGw9IiNEOEQ4RDgiIHBvaW50cz0iNS4yIDEgNi4yIDEgNi4yIDcgMy4yIDcgMy4yIDYgNS4yIDYiIHRyYW5zZm9ybT0icm90YXRlKDQwIDQuNjc3IDQpIi8+PC9zdmc+) no-repeat 98% center; -} - -.tooltip, -:tooltip, -:title { - color: yellow; -} - -.sdpi-item-group.file { - width: 232px; - display: flex; - align-items: center; -} - -.sdpi-file-info { - overflow-wrap: break-word; - word-wrap: break-word; - hyphens: auto; - min-width: 132px; - max-width: 144px; - max-height: 32px; - margin-top: 0px; - margin-left: 5px; - display: inline-block; - overflow: hidden; - padding: 6px 4px; - background-color: var(--sdpi-background); -} - -::-webkit-scrollbar { - width: 8px; -} - -::-webkit-scrollbar-track { - -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3); - box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3); - margin: 4px; - border-radius: 8px; -} - -::-webkit-scrollbar-thumb { - background-color: #999999; - outline: 1px solid slategrey; - border-radius: 8px; -} - -a { - color: #7397d2; -} - -input[type="week"] { - -webkit-appearance: auto !important; - appearance: auto !important; -} - -input[type="month"]+datalist, -input[type="day"]+datalist, -input[type="week"]+datalist, -input[type=text]+datalist { - display: none !important; -} - -input[type="range"] { - -webkit-appearance: auto; - appearance: auto; - height: 6px; - margin-top: 12px; - z-index: 0; - overflow: visible; -} - -input[type="range"]::-webkit-slider-runnable-track { - border: 0px solid transparent; -} - -.sdpi-item[type="range"] .sdpi-item-value.datalist { - flex-direction: column; -} - -datalist { - --sdpi-datalist-margin: 7px; - display: flex; - justify-content: space-between; - margin-top: 0px; - padding-top: 0px; - font-size: 12px; - margin-left: var(--sdpi-datalist-margin); - width: calc(100% - calc(var(--sdpi-datalist-margin) * 2.5)); -} - -datalist>option { - display: flex; - justify-content: center; - align-items: end; - /* background-image: url(../assets/tick.svg); */ - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='1' height='8' viewBox='0 0 1 8'%3E%3Crect width='1' height='6' x='0' y='1' fill='%23555'/%3E%3C/svg%3E%0A"); - padding: 0; - font-weight: 400; - font-size: 12px; - color: #9A9A99; - width: 1px; - height: 30px; - z-index: 1; - margin-top: -6px; - background-position: top 6px right 5px; - background-repeat: repeat no-repeat; /* fallback */ - background-repeat-y: no-repeat; - user-select: none; - -webkit-user-select: none; -} - -[role="spinbutton"] { - -webkit-appearance: auto; - appearance: auto; -} - -/* -input[type="range"]::-webkit-slider-thumb { - -webkit-appearance: none; - background-color: var(--sdpi-color); - width: 12px; - height: 12px; - border-radius: 20px; - margin-top: -6px; - border: none; -} */ - -:-webkit-slider-thumb { - -webkit-appearance: none; - background-color: var(--sdpi-color); - width: 16px; - height: 16px; - border-radius: 20px; - margin-top: -6px; - border: 1px solid #999999; -} - -.sdpi-item[type="range"] .sdpi-item-group { - display: flex; - flex-direction: column; -} - -.xxsdpi-item[type="range"] .sdpi-item-group input { - max-width: 204px; -} - -.sdpi-item[type="range"] .sdpi-item-group span { - margin-left: 0px !important; -} - -.sdpi-item[type="range"] .sdpi-item-group>.sdpi-item-child { - display: flex; - flex-direction: row; -} - -.rangeLabel { - position: absolute; - font-weight: normal; - margin-top: 24px; -} - -:disabled { - color: #993333; -} - -select, -select option { - color: var(--sdpi-color); -} - -select.disabled, -select option:disabled { - color: #fd9494; - font-style: italic; -} - -.runningAppsContainer { - display: none; -} - -.one-line { - min-height: 1.5em; -} - -.two-lines { - min-height: 3em; -} - -.three-lines { - min-height: 4.5em; -} - -.four-lines { - min-height: 6em; -} - -.min80>.sdpi-item-child { - min-width: 80px; -} - -.min100>.sdpi-item-child { - min-width: 100px; -} - -.min120>.sdpi-item-child { - min-width: 120px; -} - -.min140>.sdpi-item-child { - min-width: 140px; -} - -.min160>.sdpi-item-child { - min-width: 160px; -} - -.min200>.sdpi-item-child { - min-width: 200px; -} - -.max40 { - flex-basis: 40%; - flex-grow: 0; -} - -.max30 { - flex-basis: 30%; - flex-grow: 0; -} - -.max20 { - flex-basis: 20%; - flex-grow: 0; -} - -.up20 { - margin-top: -20px; -} - -.alignCenter { - align-items: center; -} - -.alignTop { - align-items: flex-start; -} - -.alignBaseline { - align-items: baseline; -} - -.noMargins, -.noMargins *, -.noInnerMargins * { - margin: 0; - padding: 0; -} - -.hidden { - display: none !important; -} - -.icon-help, -.icon-help-line, -.icon-help-fill, -.icon-help-inv, -.icon-brighter, -.icon-darker, -.icon-warmer, -.icon-cooler { - min-width: 20px; - width: 20px; - background-repeat: no-repeat; - opacity: 1; -} - -.icon-help:active, -.icon-help-line:active, -.icon-help-fill:active, -.icon-help-inv:active, -.icon-brighter:active, -.icon-darker:active, -.icon-warmer:active, -.icon-cooler:active { - opacity: 0.5; -} - -.icon-brighter, -.icon-darker, -.icon-warmer, -.icon-cooler { - margin-top: 5px !important; -} - -.icon-help, -.icon-help-line, -.icon-help-fill, -.icon-help-inv { - cursor: pointer; - margin: 0px; - margin-left: 4px; -} - -.icon-brighter { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Cg fill='%23999' fill-rule='evenodd'%3E%3Ccircle cx='10' cy='10' r='4'/%3E%3Cpath d='M14.8532861,7.77530426 C14.7173255,7.4682615 14.5540843,7.17599221 14.3666368,6.90157083 L16.6782032,5.5669873 L17.1782032,6.4330127 L14.8532861,7.77530426 Z M10.5,4.5414007 C10.2777625,4.51407201 10.051423,4.5 9.82179677,4.5 C9.71377555,4.5 9.60648167,4.50311409 9.5,4.50925739 L9.5,2 L10.5,2 L10.5,4.5414007 Z M5.38028092,6.75545367 C5.18389364,7.02383457 5.01124349,7.31068015 4.86542112,7.61289977 L2.82179677,6.4330127 L3.32179677,5.5669873 L5.38028092,6.75545367 Z M4.86542112,12.3871002 C5.01124349,12.6893198 5.18389364,12.9761654 5.38028092,13.2445463 L3.32179677,14.4330127 L2.82179677,13.5669873 L4.86542112,12.3871002 Z M9.5,15.4907426 C9.60648167,15.4968859 9.71377555,15.5 9.82179677,15.5 C10.051423,15.5 10.2777625,15.485928 10.5,15.4585993 L10.5,18 L9.5,18 L9.5,15.4907426 Z M14.3666368,13.0984292 C14.5540843,12.8240078 14.7173255,12.5317385 14.8532861,12.2246957 L17.1782032,13.5669873 L16.6782032,14.4330127 L14.3666368,13.0984292 Z'/%3E%3C/g%3E%3C/svg%3E"); -} - -.icon-darker { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Cg fill='%23999' fill-rule='evenodd'%3E%3Cpath d='M10 14C7.790861 14 6 12.209139 6 10 6 7.790861 7.790861 6 10 6 12.209139 6 14 7.790861 14 10 14 12.209139 12.209139 14 10 14zM10 13C11.6568542 13 13 11.6568542 13 10 13 8.34314575 11.6568542 7 10 7 8.34314575 7 7 8.34314575 7 10 7 11.6568542 8.34314575 13 10 13zM14.8532861 7.77530426C14.7173255 7.4682615 14.5540843 7.17599221 14.3666368 6.90157083L16.6782032 5.5669873 17.1782032 6.4330127 14.8532861 7.77530426zM10.5 4.5414007C10.2777625 4.51407201 10.051423 4.5 9.82179677 4.5 9.71377555 4.5 9.60648167 4.50311409 9.5 4.50925739L9.5 2 10.5 2 10.5 4.5414007zM5.38028092 6.75545367C5.18389364 7.02383457 5.01124349 7.31068015 4.86542112 7.61289977L2.82179677 6.4330127 3.32179677 5.5669873 5.38028092 6.75545367zM4.86542112 12.3871002C5.01124349 12.6893198 5.18389364 12.9761654 5.38028092 13.2445463L3.32179677 14.4330127 2.82179677 13.5669873 4.86542112 12.3871002zM9.5 15.4907426C9.60648167 15.4968859 9.71377555 15.5 9.82179677 15.5 10.051423 15.5 10.2777625 15.485928 10.5 15.4585993L10.5 18 9.5 18 9.5 15.4907426zM14.3666368 13.0984292C14.5540843 12.8240078 14.7173255 12.5317385 14.8532861 12.2246957L17.1782032 13.5669873 16.6782032 14.4330127 14.3666368 13.0984292z'/%3E%3C/g%3E%3C/svg%3E"); -} - -.icon-warmer { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Cg fill='%23999' fill-rule='evenodd'%3E%3Cpath d='M12.3247275 11.4890349C12.0406216 11.0007637 11.6761954 10.5649925 11.2495475 10.1998198 11.0890394 9.83238991 11 9.42659309 11 9 11 7.34314575 12.3431458 6 14 6 15.6568542 6 17 7.34314575 17 9 17 10.6568542 15.6568542 12 14 12 13.3795687 12 12.8031265 11.8116603 12.3247275 11.4890349zM17.6232392 11.6692284C17.8205899 11.4017892 17.9890383 11.1117186 18.123974 10.8036272L20.3121778 12.0669873 19.8121778 12.9330127 17.6232392 11.6692284zM18.123974 7.19637279C17.9890383 6.88828142 17.8205899 6.5982108 17.6232392 6.33077158L19.8121778 5.0669873 20.3121778 5.9330127 18.123974 7.19637279zM14.5 4.52746439C14.3358331 4.50931666 14.1690045 4.5 14 4.5 13.8309955 4.5 13.6641669 4.50931666 13.5 4.52746439L13.5 2 14.5 2 14.5 4.52746439zM13.5 13.4725356C13.6641669 13.4906833 13.8309955 13.5 14 13.5 14.1690045 13.5 14.3358331 13.4906833 14.5 13.4725356L14.5 16 13.5 16 13.5 13.4725356zM14 11C15.1045695 11 16 10.1045695 16 9 16 7.8954305 15.1045695 7 14 7 12.8954305 7 12 7.8954305 12 9 12 10.1045695 12.8954305 11 14 11zM9.5 11C10.6651924 11.4118364 11.5 12.5 11.5 14 11.5 16 10 17.5 8 17.5 6 17.5 4.5 16 4.5 14 4.5 12.6937812 5 11.5 6.5 11L6.5 7 9.5 7 9.5 11z'/%3E%3Cpath d='M12,14 C12,16.209139 10.209139,18 8,18 C5.790861,18 4,16.209139 4,14 C4,12.5194353 4.80439726,11.2267476 6,10.5351288 L6,4 C6,2.8954305 6.8954305,2 8,2 C9.1045695,2 10,2.8954305 10,4 L10,10.5351288 C11.1956027,11.2267476 12,12.5194353 12,14 Z M11,14 C11,12.6937812 10.1651924,11.5825421 9,11.1707057 L9,4 C9,3.44771525 8.55228475,3 8,3 C7.44771525,3 7,3.44771525 7,4 L7,11.1707057 C5.83480763,11.5825421 5,12.6937812 5,14 C5,15.6568542 6.34314575,17 8,17 C9.65685425,17 11,15.6568542 11,14 Z'/%3E%3C/g%3E%3C/svg%3E"); -} - -.icon-cooler { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20'%3E%3Cg fill='%23999' fill-rule='evenodd'%3E%3Cpath d='M10.4004569 11.6239517C10.0554735 10.9863849 9.57597206 10.4322632 9 9.99963381L9 9.7450467 9.53471338 9.7450467 10.8155381 8.46422201C10.7766941 8.39376637 10.7419749 8.32071759 10.7117062 8.2454012L9 8.2454012 9 6.96057868 10.6417702 6.96057868C10.6677696 6.86753378 10.7003289 6.77722682 10.7389179 6.69018783L9.44918707 5.40045694 9 5.40045694 9 4.34532219 9.32816127 4.34532219 9.34532219 2.91912025 10.4004569 2.91912025 10.4004569 4.53471338 11.6098599 5.74411634C11.7208059 5.68343597 11.8381332 5.63296451 11.9605787 5.59396526L11.9605787 3.8884898 10.8181818 2.74609294 11.5642748 2 12.5727518 3.00847706 13.5812289 2 14.3273218 2.74609294 13.2454012 3.82801356 13.2454012 5.61756719C13.3449693 5.65339299 13.4408747 5.69689391 13.5324038 5.74735625L14.7450467 4.53471338 14.7450467 2.91912025 15.8001815 2.91912025 15.8001815 4.34532219 17.2263834 4.34532219 17.2263834 5.40045694 15.6963166 5.40045694 14.4002441 6.69652946C14.437611 6.78161093 14.4692249 6.86979146 14.4945934 6.96057868L16.2570138 6.96057868 17.3994107 5.81818182 18.1455036 6.56427476 17.1370266 7.57275182 18.1455036 8.58122888 17.3994107 9.32732182 16.3174901 8.2454012 14.4246574 8.2454012C14.3952328 8.31861737 14.3616024 8.38969062 14.3240655 8.45832192L15.6107903 9.7450467 17.2263834 9.7450467 17.2263834 10.8001815 15.8001815 10.8001815 15.8001815 12.2263834 14.7450467 12.2263834 14.7450467 10.6963166 13.377994 9.32926387C13.3345872 9.34850842 13.2903677 9.36625331 13.2454012 9.38243281L13.2454012 11.3174901 14.3273218 12.3994107 13.5812289 13.1455036 12.5848864 12.1491612 11.5642748 13.1455036 10.8181818 12.3994107 11.9605787 11.2570138 11.9605787 9.40603474C11.8936938 9.38473169 11.828336 9.36000556 11.7647113 9.33206224L10.4004569 10.6963166 10.4004569 11.6239517zM12.75 8.5C13.3022847 8.5 13.75 8.05228475 13.75 7.5 13.75 6.94771525 13.3022847 6.5 12.75 6.5 12.1977153 6.5 11.75 6.94771525 11.75 7.5 11.75 8.05228475 12.1977153 8.5 12.75 8.5zM9.5 14C8.5 16.3333333 7.33333333 17.5 6 17.5 4.66666667 17.5 3.5 16.3333333 2.5 14L9.5 14z'/%3E%3Cpath d='M10,14 C10,16.209139 8.209139,18 6,18 C3.790861,18 2,16.209139 2,14 C2,12.5194353 2.80439726,11.2267476 4,10.5351288 L4,4 C4,2.8954305 4.8954305,2 6,2 C7.1045695,2 8,2.8954305 8,4 L8,10.5351288 C9.19560274,11.2267476 10,12.5194353 10,14 Z M9,14 C9,12.6937812 8.16519237,11.5825421 7,11.1707057 L7,4 C7,3.44771525 6.55228475,3 6,3 C5.44771525,3 5,3.44771525 5,4 L5,11.1707057 C3.83480763,11.5825421 3,12.6937812 3,14 C3,15.6568542 4.34314575,17 6,17 C7.65685425,17 9,15.6568542 9,14 Z'/%3E%3C/g%3E%3C/svg%3E"); -} - -.icon-help { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20'%3E%3Cpath fill='%23999' d='M11.292 12.516l.022 1.782H9.07v-1.804c0-1.98 1.276-2.574 2.662-3.278h-.022c.814-.44 1.65-.88 1.694-2.2.044-1.386-1.122-2.728-3.234-2.728-1.518 0-2.662.902-3.366 2.354L5 5.608C5.946 3.584 7.662 2 10.17 2c3.564 0 5.632 2.442 5.588 5.06-.066 2.618-1.716 3.41-3.102 4.158-.704.374-1.364.682-1.364 1.298zm-1.122 2.442c.858 0 1.452.594 1.452 1.452 0 .682-.594 1.408-1.452 1.408-.77 0-1.386-.726-1.386-1.408 0-.858.616-1.452 1.386-1.452z'/%3E%3C/svg%3E"); -} - -.icon-help-line { - background-image: url("data:image/svg+xml,%3Csvg width='20' height='20' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%23999' fill-rule='evenodd'%3E%3Cpath d='M10 20C4.477 20 0 15.523 0 10S4.477 0 10 0s10 4.477 10 10-4.477 10-10 10zm0-1a9 9 0 1 0 0-18 9 9 0 0 0 0 18z'/%3E%3Cpath d='M10.848 12.307l.02 1.578H8.784v-1.597c0-1.753 1.186-2.278 2.474-2.901h-.02c.756-.39 1.533-.78 1.574-1.948.041-1.226-1.043-2.414-3.006-2.414-1.41 0-2.474.798-3.128 2.083L5 6.193C5.88 4.402 7.474 3 9.805 3 13.118 3 15.04 5.161 15 7.478c-.061 2.318-1.595 3.019-2.883 3.68-.654.332-1.268.604-1.268 1.15zM9.805 14.47c.798 0 1.35.525 1.35 1.285 0 .603-.552 1.246-1.35 1.246-.715 0-1.288-.643-1.288-1.246 0-.76.573-1.285 1.288-1.285z' fill-rule='nonzero'/%3E%3C/g%3E%3C/svg%3E"); -} - -.icon-help-fill { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Ccircle cx='10' cy='10' r='10' fill='%23999'/%3E%3Cpath fill='%23FFF' fill-rule='nonzero' d='M8.368 7.189H5C5 3.5 7.668 2 10.292 2 13.966 2 16 4.076 16 7.012c0 3.754-3.849 3.136-3.849 5.211v1.656H8.455v-1.832c0-2.164 1.4-2.893 2.778-3.6.437-.242 1.006-.574 1.006-1.236 0-2.208-3.871-2.142-3.871-.022zM10.25 18a1.75 1.75 0 1 1 0-3.5 1.75 1.75 0 0 1 0 3.5z'/%3E%3C/g%3E%3C/svg%3E"); -} - -.icon-help-inv { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20'%3E%3Cpath fill='%23999' fill-rule='evenodd' d='M10 20C4.477 20 0 15.523 0 10S4.477 0 10 0s10 4.477 10 10-4.477 10-10 10zM8.368 7.189c0-2.12 3.87-2.186 3.87.022 0 .662-.568.994-1.005 1.236-1.378.707-2.778 1.436-2.778 3.6v1.832h3.696v-1.656c0-2.075 3.849-1.457 3.849-5.21C16 4.075 13.966 2 10.292 2 7.668 2 5 3.501 5 7.189h3.368zM10.25 18a1.75 1.75 0 1 0 0-3.5 1.75 1.75 0 0 0 0 3.5z'/%3E%3C/svg%3E"); -} - -.kelvin::after { - content: "K"; -} - -.mired::after { - content: " Mired"; -} - -.percent::after { - content: "%"; -} - -.sdpi-item-value+.icon-cooler, -.sdpi-item-value+.icon-warmer { - margin-left: 0px !important; - margin-top: 15px !important; -} - -/** - CONTROL-CENTER STYLES -*/ -input[type="range"].colorbrightness::-webkit-slider-runnable-track, -input[type="range"].colortemperature::-webkit-slider-runnable-track { - height: 8px; - background: #979797; - border-radius: 4px; - background-image: linear-gradient(to right, #94d0ec, #ffb165); -} - -input[type="range"].colorbrightness.greyscale::-webkit-slider-runnable-track, -input[type="range"].colorbrightness.grayscale::-webkit-slider-runnable-track { - background-color: #efefef; - background-image: linear-gradient(to right, black, rgba(0, 0, 0, 0)); -} - - -input[type="range"].colorbrightness::-webkit-slider-thumb, -input[type="range"].colortemperature::-webkit-slider-thumb { - width: 16px; - height: 16px; - border-radius: 20px; - margin-top: -5px; - background-color: #86c6e8; - box-shadow: 0px 0px 1px #000000; - border: 1px solid #d8d8d8; -} - -.sdpi-info-label { - display: inline-block; - user-select: none; - position: absolute; - height: 15px; - width: auto; - text-align: center; - border-radius: 4px; - min-width: 44px; - max-width: 80px; - background: white; - font-size: 11px; - color: black; - z-index: 1000; - box-shadow: 0px 0px 12px rgba(0, 0, 0, .8); - padding: 2px; - -} - -.sdpi-info-label.hidden { - opacity: 0; - transition: opacity 0.25s linear; -} - -.sdpi-info-label.shown { - position: absolute; - opacity: 1; - transition: opacity 0.25s ease-out; -} - -/* adding some styles here that override sdpi things so we can use this as notes for sdpi updates*/ -select { - min-width: 0px; - - /* this is a clunky fix for using background image as select arrow with long text options */ - /* -webkit-appearance: media-slider; */ - text-overflow: ellipsis; -} - -/*--------- context menu ----------*/ - -.context-menu { - display: none; - position: absolute; - z-index: 10; - padding: 12px 0; - width: 120px; - background-color: #3D3D3D; - border: solid 1px #dfdfdf; - box-shadow: 1px 1px 2px #cfcfcf; -} - -.context-menu--active { - display: block; -} - -.context-menu__items { - list-style: none; - margin: 0; - padding: 0; - overflow-y: auto; -} - -.context-menu__item { - display: block; - margin-bottom: 4px; - background-color: #3D3D3D !important; -} - -.context-menu__item:last-child { - margin-bottom: 0; -} - -.context-menu__link { - display: block; - padding: 4px 12px; - color: #ffff; - text-decoration: none; - white-space: nowrap; -} - -.context-menu__link:hover { - color: #fff; - background-color: #0066aa; -} - -.context-menu_message { - cursor: default; -} diff --git a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/action.js b/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/action.js deleted file mode 100644 index 2e4f5e2..0000000 --- a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/action.js +++ /dev/null @@ -1,214 +0,0 @@ -/// - -/** - * @class Action - * A Stream Deck plugin action, where you can register callback functions for different events - */ -class ELGSDAction { - UUID; - on = EventEmitter.on; - emit = EventEmitter.emit; - - constructor(UUID) { - if (!UUID) { - console.error( - 'An action UUID matching the action UUID in your manifest is required when creating Actions.' - ); - } - - this.UUID = UUID; - } - - /** - * Registers a callback function for the didReceiveSettings event, which fires when calling getSettings - * @param {function} fn - */ - onDidReceiveSettings(fn) { - if (!fn) { - console.error( - 'A callback function for the didReceiveSettings event is required for onDidReceiveSettings.' - ); - } - - this.on(`${this.UUID}.${Events.didReceiveSettings}`, (jsn) => fn(jsn)); - return this; - } - - /** - * Registers a callback function for the keyDown event, which fires when pressing a key down - * @param {function} fn - */ - onKeyDown(fn) { - if (!fn) { - console.error('A callback function for the keyDown event is required for onKeyDown.'); - } - - this.on(`${this.UUID}.${Events.keyDown}`, (jsn) => fn(jsn)); - return this; - } - - /** - * Registers a callback function for the keyUp event, which fires when releasing a key - * @param {function} fn - */ - onKeyUp(fn) { - if (!fn) { - console.error('A callback function for the keyUp event is required for onKeyUp.'); - } - - this.on(`${this.UUID}.${Events.keyUp}`, (jsn) => fn(jsn)); - return this; - } - - /** - * Registers a callback function for the willAppear event, which fires when an action appears on the canvas - * @param {function} fn - */ - onWillAppear(fn) { - if (!fn) { - console.error('A callback function for the willAppear event is required for onWillAppear.'); - } - - this.on(`${this.UUID}.${Events.willAppear}`, (jsn) => fn(jsn)); - return this; - } - - /** - * Registers a callback function for the willAppear event, which fires when an action disappears on the canvas - * @param {function} fn - */ - onWillDisappear(fn) { - if (!fn) { - console.error( - 'A callback function for the willDisappear event is required for onWillDisappear.' - ); - } - - this.on(`${this.UUID}.${Events.willDisappear}`, (jsn) => fn(jsn)); - return this; - } - - /** - * Registers a callback function for the titleParametersDidChange event, which fires when a user changes the key title - * @param {function} fn - */ - onTitleParametersDidChange(fn) { - if (!fn) { - console.error( - 'A callback function for the titleParametersDidChange event is required for onTitleParametersDidChange.' - ); - } - - this.on(`${this.UUID}.${Events.titleParametersDidChange}`, (jsn) => fn(jsn)); - return this; - } - - /** - * Registers a callback function for the propertyInspectorDidAppear event, which fires when the property inspector is displayed - * @param {function} fn - */ - onPropertyInspectorDidAppear(fn) { - if (!fn) { - console.error( - 'A callback function for the propertyInspectorDidAppear event is required for onPropertyInspectorDidAppear.' - ); - } - - this.on(`${this.UUID}.${Events.propertyInspectorDidAppear}`, (jsn) => fn(jsn)); - return this; - } - - /** - * Registers a callback function for the propertyInspectorDidDisappear event, which fires when the property inspector is closed - * @param {function} fn - */ - onPropertyInspectorDidDisappear(fn) { - if (!fn) { - console.error( - 'A callback function for the propertyInspectorDidDisappear event is required for onPropertyInspectorDidDisappear.' - ); - } - - this.on(`${this.UUID}.${Events.propertyInspectorDidDisappear}`, (jsn) => fn(jsn)); - return this; - } - - /** - * Registers a callback function for the sendToPlugin event, which fires when the property inspector uses the sendToPlugin api - * @param {function} fn - */ - onSendToPlugin(fn) { - if (!fn) { - console.error( - 'A callback function for the sendToPlugin event is required for onSendToPlugin.' - ); - } - - this.on(`${this.UUID}.${Events.sendToPlugin}`, (jsn) => fn(jsn)); - return this; - } - - /** - * Registers a callback function for the onDialRotate event, which fires when a SD+ dial was rotated - * @param {function} fn - */ - onDialRotate(fn) { - if (!fn) { - console.error('A callback function for the onDialRotate event is required for onDialRotate.'); - } - this.on(`${this.UUID}.${Events.dialRotate}`, (jsn) => fn(jsn)); - return this; - } - - /** - * Registers a callback function for the dialPress event, which fires when a SD+ dial was pressed or released - * @deprecated Use onDialUp and onDialDown instead - */ - onDialPress(fn) { - if (!fn) { - console.error('A callback function for the dialPress event is required for onDialPress.'); - } - this.on(`${this.UUID}.${Events.dialPress}`, (jsn) => fn(jsn)); - return this; - } - - /** - * Registers a callback function for the dialDown event, which fires when a SD+ dial was pressed - * @param {function} fn - */ - onDialDown(fn) { - if (!fn) { - console.error('A callback function for the dialDown event is required for onDialDown.'); - } - this.on(`${this.UUID}.${Events.dialDown}`, (jsn) => fn(jsn)); - return this; - } - - /** - * Registers a callback function for the dialUp event, which fires when a pressed SD+ dial was released - * @param {function} fn - */ - onDialUp(fn) { - if (!fn) { - console.error('A callback function for the dialUp event is required for onDialUp.'); - } - this.on(`${this.UUID}.${Events.dialUp}`, (jsn) => fn(jsn)); - return this; - } - - /** - * Registers a callback function for the touchTap event, which fires when a SD+ touch panel was touched quickly - * @param {function} fn - */ - onTouchTap(fn) { - if (!fn) { - console.error( - 'A callback function for the onTouchTap event is required for onTouchTap.' - ); - } - this.on(`${this.UUID}.${Events.touchTap}`, (jsn) => fn(jsn)); - return this; - } -} - -const Action = ELGSDAction; diff --git a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/api.js b/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/api.js deleted file mode 100644 index 09f07dd..0000000 --- a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/api.js +++ /dev/null @@ -1,351 +0,0 @@ -/// - -class ELGSDPlugin { - #data = {}; - #language = 'en'; - #localization; - test = new Set(); - on = EventEmitter.on; - emit = EventEmitter.emit; - - localizationLoaded = false; - constructor () { - // super(); - if(ELGSDPlugin.__instance) { - return ELGSDPlugin.__instance; - } - - ELGSDPlugin.__instance = this; - const pathArr = location.pathname.split("/"); - const idx = pathArr.findIndex(f => f.endsWith('sdPlugin')); - this.#data.__filename = pathArr[pathArr.length - 1]; - this.#data.__dirname = pathArr[pathArr.length - 2]; - this.#data.__folderpath = `${pathArr.slice(0, idx + 1).join("/")}/`; - this.#data.__folderroot = `${pathArr.slice(0, idx).join("/")}/`; - this.#data.__parentdir = `${pathArr.slice(0, idx-1).join("/")}/`; - } - - set language(value) { - this.#language = value; - this.loadLocalization(this.#data.__folderpath) - .then(l => { - this.emit('languageChanged', value); - }) - .catch(() => console.warn(`Localization for '${this.#language}' couldn't be loaded`)) - } - - get language() { - return this.#language; - } - - set localization(value) { - this.#localization = value; - this.localizeUI(); - this.emit('localizationChanged', value); - } - - get localization() { - return this.#localization; - } - - get __filename() { - return this.#data.__filename; - } - - get __dirname() { - return this.#data.__dirname; - } - - get __folderpath() { - return this.#data.__folderpath; - } - get __folderroot() { - return this.#data.__folderroot; - } - get data() { - return this.#data; - } - - /** - * Finds the original key of the string value - * Note: This is used by the localization UI to find the original key (not used here) - * @param {string} str - * @returns {string} - */ - - localizedString(str) { - return Object.keys(this.localization).find(e => e == str); - } - - /** - * Returns the localized string or the original string if not found - * @param {string} str - * @returns {string} - */ - - localize(s) { - if(typeof s === 'undefined') return ''; - let str = String(s); - try { - str = this.localization[str] || str; - } catch(b) {} - return str; - }; - - /** - * Searches the document tree to find elements with data-localize attributes - * and replaces their values with the localized string - * @returns {} - */ - - localizeUI = () => { - const el = document.querySelector('.sdpi-wrapper'); - if(!el) return console.warn("No element found to localize"); - const selectorsList = '[data-localize]'; - // see if we have any data-localize attributes - // that means we can skip the rest of the DOM - el.querySelectorAll(selectorsList).forEach(e => { - const s = e.innerText.trim(); - e.innerHTML = e.innerHTML.replace(s, this.localize(s)); - if(e.placeholder && e.placeholder.length) { - e.placeholder = this.localize(e.placeholder); - } - if(e.title && e.title.length) { - e.title = this.localize(e.title); - } - }); - }; - /** - * Fetches the specified language json file - * @param {string} pathPrefix - * @returns {Promise} - */ -async loadLocalization(pathPrefix) { - if(!pathPrefix) { - pathPrefix = this.#data.__folderpath; - } - // here we save the promise to the JSON-reader result, - // which we can later re-use to see, if the strings are already loaded - this.localizationLoaded = this.readJson(`${pathPrefix}${this.language}.json`); - const manifest = await this.localizationLoaded; - this.localization = manifest['Localization'] ?? null; - window.$localizedStrings = this.localization; - this.emit('localizationLoaded', this.localization); - - return this.localization; -} - - /** - * - * @param {string} path - * @returns {Promise} json - */ - async readJson(path) { - if(!path) { - console.error('A path is required to readJson.'); - } - - return new Promise((resolve, reject) => { - const req = new XMLHttpRequest(); - req.onerror = reject; - req.overrideMimeType('application/json'); - req.open('GET', path, true); - req.onreadystatechange = (response) => { - if(req.readyState === 4) { - const jsonString = response?.target?.response; - if(jsonString) { - resolve(JSON.parse(response?.target?.response)); - } else { - reject(); - } - } - }; - - req.send(); - }); - } -} - -class ELGSDApi extends ELGSDPlugin { - port; - uuid; - messageType; - actionInfo; - websocket; - appInfo; - #data = {}; - - /** - * Connect to Stream Deck - * @param {string} port - * @param {string} uuid - * @param {string} messageType - * @param {string} appInfoString - * @param {string} actionString - */ - connect(port, uuid, messageType, appInfoString, actionString) { - this.port = port; - this.uuid = uuid; - this.messageType = messageType; - this.actionInfo = actionString ? JSON.parse(actionString) : null; - this.appInfo = JSON.parse(appInfoString); - this.language = this.appInfo?.application?.language ?? null; - - if(this.websocket) { - this.websocket.close(); - this.websocket = null; - } - - this.websocket = new WebSocket('ws://127.0.0.1:' + this.port); - - this.websocket.onopen = () => { - const json = { - event: this.messageType, - uuid: this.uuid, - }; - - this.websocket.send(JSON.stringify(json)); - - this.emit(Events.connected, { - connection: this.websocket, - port: this.port, - uuid: this.uuid, - actionInfo: this.actionInfo, - appInfo: this.appInfo, - messageType: this.messageType, - }); - }; - - this.websocket.onerror = (evt) => { - const error = `WEBSOCKET ERROR: ${evt}, ${evt.data}, ${SocketErrors[evt?.code]}`; - console.warn(error); - this.logMessage(error); - }; - - this.websocket.onclose = (evt) => { - console.warn('WEBSOCKET CLOSED:', SocketErrors[evt?.code]); - }; - - this.websocket.onmessage = (evt) => { - const data = evt?.data ? JSON.parse(evt.data) : null; - - const {action, event} = data; - const message = action ? `${action}.${event}` : event; - if(message && message !== '') this.emit(message, data); - }; - } - - /** - * Write to log file - * @param {string} message - */ - logMessage(message) { - if(!message) { - console.error('A message is required for logMessage.'); - } - - try { - if(this.websocket) { - const json = { - event: Events.logMessage, - payload: { - message: message, - }, - }; - this.websocket.send(JSON.stringify(json)); - } else { - console.error('Websocket not defined'); - } - } catch(e) { - console.error('Websocket not defined'); - } - } - - /** - * Send JSON payload to StreamDeck - * @param {string} context - * @param {string} event - * @param {object} [payload] - */ - send(context, event, payload = {}) { - this.websocket && this.websocket.send(JSON.stringify({context, event, ...payload})); - } - - /** - * Save the plugin's persistent data - * @param {object} payload - */ - setGlobalSettings(payload) { - this.send(this.uuid, Events.setGlobalSettings, { - payload: payload, - }); - } - - /** - * Request the plugin's persistent data. StreamDeck does not return the data, but trigger the plugin/property inspectors didReceiveGlobalSettings event - */ - getGlobalSettings() { - this.send(this.uuid, Events.getGlobalSettings); - } - - /** - * Opens a URL in the default web browser - * @param {string} url - */ - openUrl(url) { - if(!url) { - console.error('A url is required for openUrl.'); - } - - this.send(this.uuid, Events.openUrl, { - payload: { - url, - }, - }); - } - - /** - * Registers a callback function for when Stream Deck is connected - * @param {function} fn - * @returns ELGSDStreamDeck - */ - onConnected(fn) { - if(!fn) { - console.error('A callback function for the connected event is required for onConnected.'); - } - - this.on(Events.connected, (jsn) => fn(jsn)); - return this; - } - - /** - * Registers a callback function for the didReceiveGlobalSettings event, which fires when calling getGlobalSettings - * @param {function} fn - */ - onDidReceiveGlobalSettings(fn) { - if(!fn) { - console.error( - 'A callback function for the didReceiveGlobalSettings event is required for onDidReceiveGlobalSettings.' - ); - } - - this.on(Events.didReceiveGlobalSettings, (jsn) => fn(jsn)); - return this; - } - - /** - * Registers a callback function for the didReceiveSettings event, which fires when calling getSettings - * @param {string} action - * @param {function} fn - */ - onDidReceiveSettings(action, fn) { - if(!fn) { - console.error( - 'A callback function for the didReceiveSettings event is required for onDidReceiveSettings.' - ); - } - - this.on(`${action}.${Events.didReceiveSettings}`, (jsn) => fn(jsn)); - return this; - } -} diff --git a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/constants.js b/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/constants.js deleted file mode 100644 index 21a3f80..0000000 --- a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/constants.js +++ /dev/null @@ -1,83 +0,0 @@ -/** - * Errors received from WebSocket - */ -const SocketErrors = { - 0: 'The connection has not yet been established', - 1: 'The connection is established and communication is possible', - 2: 'The connection is going through the closing handshake', - 3: 'The connection has been closed or could not be opened', - 1000: 'Normal Closure. The purpose for which the connection was established has been fulfilled.', - 1001: 'Going Away. An endpoint is "going away", such as a server going down or a browser having navigated away from a page.', - 1002: 'Protocol error. An endpoint is terminating the connection due to a protocol error', - 1003: "Unsupported Data. An endpoint received a type of data it doesn't support.", - 1004: '--Reserved--. The specific meaning might be defined in the future.', - 1005: 'No Status. No status code was actually present.', - 1006: 'Abnormal Closure. The connection was closed abnormally, e.g., without sending or receiving a Close control frame', - 1007: 'Invalid frame payload data. The connection was closed, because the received data was not consistent with the type of the message (e.g., non-UTF-8 [http://tools.ietf.org/html/rfc3629]).', - 1008: 'Policy Violation. The connection was closed, because current message data "violates its policy". This reason is given either if there is no other suitable reason, or if there is a need to hide specific details about the policy.', - 1009: 'Message Too Big. Connection closed because the message is too big for it to process.', - 1010: "Mandatory Extension. Connection is terminated the connection because the server didn't negotiate one or more extensions in the WebSocket handshake.", - 1011: 'Internl Server Error. Connection closed because it encountered an unexpected condition that prevented it from fulfilling the request.', - 1015: "TLS Handshake. The connection was closed due to a failure to perform a TLS handshake (e.g., the server certificate can't be verified).", -}; - -/** - * Events used for communicating with Stream Deck - */ -const Events = { - didReceiveSettings: 'didReceiveSettings', - didReceiveGlobalSettings: 'didReceiveGlobalSettings', - keyDown: 'keyDown', - keyUp: 'keyUp', - willAppear: 'willAppear', - willDisappear: 'willDisappear', - titleParametersDidChange: 'titleParametersDidChange', - deviceDidConnect: 'deviceDidConnect', - deviceDidDisconnect: 'deviceDidDisconnect', - applicationDidLaunch: 'applicationDidLaunch', - applicationDidTerminate: 'applicationDidTerminate', - systemDidWakeUp: 'systemDidWakeUp', - propertyInspectorDidAppear: 'propertyInspectorDidAppear', - propertyInspectorDidDisappear: 'propertyInspectorDidDisappear', - sendToPlugin: 'sendToPlugin', - sendToPropertyInspector: 'sendToPropertyInspector', - connected: 'connected', - setImage: 'setImage', - setXYWHImage: 'setXYWHImage', - setTitle: 'setTitle', - setState: 'setState', - showOk: 'showOk', - showAlert: 'showAlert', - openUrl: 'openUrl', - setGlobalSettings: 'setGlobalSettings', - getGlobalSettings: 'getGlobalSettings', - setSettings: 'setSettings', - getSettings: 'getSettings', - registerPropertyInspector: 'registerPropertyInspector', - registerPlugin: 'registerPlugin', - logMessage: 'logMessage', - switchToProfile: 'switchToProfile', - dialRotate: 'dialRotate', - dialPress: 'dialPress', - dialDown: 'dialDown', - dialUp: 'dialUp', - touchTap: 'touchTap', - setFeedback: 'setFeedback', - setFeedbackLayout: 'setFeedbackLayout', -}; - -/** - * Constants used for Stream Deck - */ -const Constants = { - dataLocalize: '[data-localize]', - hardwareAndSoftware: 0, - hardwareOnly: 1, - softwareOnly: 2, -}; - -const DestinationEnum = { - HARDWARE_AND_SOFTWARE: 0, - HARDWARE_ONLY: 1, - SOFTWARE_ONLY: 2, -}; diff --git a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/dynamic-styles.js b/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/dynamic-styles.js deleted file mode 100644 index 901c4ce..0000000 --- a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/dynamic-styles.js +++ /dev/null @@ -1,70 +0,0 @@ -const fadeColor = function (col, amt) { - const min = Math.min, - max = Math.max; - const num = parseInt(col.replace(/#/g, ''), 16); - const r = min(255, max((num >> 16) + amt, 0)); - const g = min(255, max((num & 0x0000ff) + amt, 0)); - const b = min(255, max(((num >> 8) & 0x00ff) + amt, 0)); - return '#' + (g | (b << 8) | (r << 16)).toString(16).padStart(6, 0); -}; - -$PI.onConnected(({appInfo}) => { - if (!appInfo?.colors) return; - const clrs = appInfo.colors; - const node = document.getElementById('#sdpi-dynamic-styles') || document.createElement('style'); - if (!clrs.mouseDownColor) clrs.mouseDownColor = fadeColor(clrs.highlightColor, -100); - const clr = clrs.highlightColor.slice(0, 7); - const clr1 = fadeColor(clr, 100); - const clr2 = fadeColor(clr, 60); - const metersActiveColor = fadeColor(clr, -60); - - node.setAttribute('id', 'sdpi-dynamic-styles'); - node.innerHTML = ` - - input[type="radio"]:checked + label span, - input[type="checkbox"]:checked + label span { - background-color: ${clrs.highlightColor}; - } - - input[type="radio"]:active:checked + label span, - input[type="checkbox"]:active:checked + label span { - background-color: ${clrs.mouseDownColor}; - } - - input[type="radio"]:active + label span, - input[type="checkbox"]:active + label span { - background-color: ${clrs.buttonPressedBorderColor}; - } - - td.selected, - td.selected:hover, - li.selected:hover, - li.selected { - color: white; - background-color: ${clrs.highlightColor}; - } - - .sdpi-file-label > label:active, - .sdpi-file-label.file:active, - label.sdpi-file-label:active, - label.sdpi-file-info:active, - input[type="file"]::-webkit-file-upload-button:active, - button:active { - border: 1pt solid ${clrs.buttonPressedBorderColor}; - background-color: ${clrs.buttonPressedBackgroundColor}; - color: ${clrs.buttonPressedTextColor}; - border-color: ${clrs.buttonPressedBorderColor}; - } - - ::-webkit-progress-value, - meter::-webkit-meter-optimum-value { - background: linear-gradient(${clr2}, ${clr1} 20%, ${clr} 45%, ${clr} 55%, ${clr2}) - } - - ::-webkit-progress-value:active, - meter::-webkit-meter-optimum-value:active { - background: linear-gradient(${clr}, ${clr2} 20%, ${metersActiveColor} 45%, ${metersActiveColor} 55%, ${clr}) - } - `; - document.body.appendChild(node); -}); diff --git a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/events.js b/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/events.js deleted file mode 100644 index cc18825..0000000 --- a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/events.js +++ /dev/null @@ -1,38 +0,0 @@ -/** ELGEvents - * Publish/Subscribe pattern to quickly signal events to - * the plugin, property inspector and data. - */ - -const ELGEvents = { - eventEmitter: function (name, fn) { - const eventList = new Map(); - - const on = (name, fn) => { - if (!eventList.has(name)) eventList.set(name, ELGEvents.pubSub()); - - return eventList.get(name).sub(fn); - }; - - const has = name => eventList.has(name); - - const emit = (name, data) => eventList.has(name) && eventList.get(name).pub(data); - - return Object.freeze({on, has, emit, eventList}); - }, - - pubSub: function pubSub() { - const subscribers = new Set(); - - const sub = fn => { - subscribers.add(fn); - return () => { - subscribers.delete(fn); - }; - }; - - const pub = data => subscribers.forEach(fn => fn(data)); - return Object.freeze({pub, sub}); - } -}; - -const EventEmitter = ELGEvents.eventEmitter(); \ No newline at end of file diff --git a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/property-inspector.js b/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/property-inspector.js deleted file mode 100644 index d8b6705..0000000 --- a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/property-inspector.js +++ /dev/null @@ -1,82 +0,0 @@ -/// -/// - -class ELGSDPropertyInspector extends ELGSDApi { - constructor() { - super(); - if (ELGSDPropertyInspector.__instance) { - return ELGSDPropertyInspector.__instance; - } - - ELGSDPropertyInspector.__instance = this; - } - - /** - * Registers a callback function for when Stream Deck sends data to the property inspector - * @param {string} actionUUID - * @param {function} fn - * @returns ELGSDStreamDeck - */ - onSendToPropertyInspector(actionUUID, fn) { - if (typeof actionUUID != 'string') { - console.error('An action UUID string is required for onSendToPropertyInspector.'); - } - - if (!fn) { - console.error( - 'A callback function for the sendToPropertyInspector event is required for onSendToPropertyInspector.' - ); - } - - this.on(`${actionUUID}.${Events.sendToPropertyInspector}`, (jsn) => fn(jsn)); - return this; - } - - /** - * Send payload from the property inspector to the plugin - * @param {object} payload - */ - sendToPlugin(payload) { - this.send(this.uuid, Events.sendToPlugin, { - action: this?.actionInfo?.action, - payload: payload || null, - }); - } - - /** - * Save the actions's persistent data. - * @param {object} payload - */ - setSettings(payload) { - this.send(this.uuid, Events.setSettings, { - action: this?.actionInfo?.action, - payload: payload || null, - }); - } - - /** - * Request the actions's persistent data. StreamDeck does not return the data, but trigger the actions's didReceiveSettings event - */ - getSettings() { - this.send(this.uuid, Events.getSettings); - } -} - -const $PI = new ELGSDPropertyInspector(); - -/** - * connectElgatoStreamDeckSocket - * This is the first function StreamDeck Software calls, when - * establishing the connection to the plugin or the Property Inspector - * @param {string} port - The socket's port to communicate with StreamDeck software. - * @param {string} uuid - A unique identifier, which StreamDeck uses to communicate with the plugin - * @param {string} messageType - Identifies, if the event is meant for the property inspector or the plugin. - * @param {string} appInfoString - Information about the host (StreamDeck) application - * @param {string} actionInfo - Context is an internal identifier used to communicate to the host application. - */ -function connectElgatoStreamDeckSocket(port, uuid, messageType, appInfoString, actionInfo) { - const delay = window?.initialConnectionDelay || 0; - setTimeout(() => { - $PI.connect(port, uuid, messageType, appInfoString, actionInfo); - }, delay); -} diff --git a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/prototypes.js b/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/prototypes.js deleted file mode 100644 index e3b84fe..0000000 --- a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/prototypes.js +++ /dev/null @@ -1,26 +0,0 @@ -/** reaches out for a magical global localization object, hopefully loaded by $SD and swaps the string **/ -String.prototype.lox = function () { - var a = String(this); - try { - a = $localizedStrings[a] || a; - } catch (b) { - } - return a; -}; - -String.prototype.sprintf = function (inArr) { - let i = 0; - const args = inArr && Array.isArray(inArr) ? inArr : arguments; - return this.replace(/%s/g, function () { - return args[i++]; - }); -}; - -WebSocket.prototype.sendJSON = function (jsn, log) { - if (log) { - console.log('SendJSON', this, jsn); - } - // if (this.readyState) { - this.send(JSON.stringify(jsn)); - // } -}; diff --git a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/stream-deck.js b/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/stream-deck.js deleted file mode 100644 index aa7485e..0000000 --- a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/stream-deck.js +++ /dev/null @@ -1,295 +0,0 @@ -/// -/// - -var $localizedStrings = $localizedStrings || {}; - -/** - * @class StreamDeck - * StreamDeck object containing all required code to establish - * communication with SD-Software and the Property Inspector - */ -class ELGSDStreamDeck extends ELGSDApi { - constructor() { - super(); - if (ELGSDStreamDeck.__instance) { - return ELGSDStreamDeck.__instance; - } - - ELGSDStreamDeck.__instance = this; - } - - /** - * Display alert triangle on actions key - * @param {string} context - */ - showAlert(context) { - if (!context) { - console.error('A context is required to showAlert on the key.'); - } - - this.send(context, Events.showAlert); - } - - /** - * Display ok check mark on actions key - * @param {string} context - */ - showOk(context) { - if (!context) { - console.error('A context is required to showOk on the key.'); - } - - this.send(context, Events.showOk); - } - - /** - * Save the actions's persistent data. - * @param context - * @param {object} payload - */ - setSettings(context, payload) { - this.send(context, Events.setSettings, { - action: this?.actionInfo?.action, - payload: payload || null, - targetContext: context, - }); - } - - /** - * Request the actions's persistent data. StreamDeck does not return the data, but trigger the actions's didReceiveSettings event - * @param {string} [context] - */ - getSettings(context) { - this.send(context, Events.getSettings); - } - - /** - * Set the state of the actions - * @param {string} context - * @param {number} [state] - */ - setState(context, state) { - if (!context) { - console.error('A context is required when using setState.'); - } - - this.send(context, Events.setState, { - payload: { - state: Number(state), - }, - }); - } - - /** - * Set the title of the action's key - * @param {string} context - * @param {string} title - * @param [target] - */ - setTitle(context, title = '', target = Constants.hardwareAndSoftware) { - if (!context) { - console.error('A key context is required for setTitle.'); - } - - this.send(context, Events.setTitle, { - payload: { - title: title ? `${title}` : '', - target, - }, - }); - } - - /** - * - * @param {string} context - * @param {number} [target] - */ - clearTitle(context, target) { - if (!context) { - console.error('A key context is required to clearTitle.'); - } - - this.setTitle(context, null, target); - } - - /** - * Send payload to property inspector - * @param {string} context - * @param {object} payload - * @param {string} [action] - */ - sendToPropertyInspector(context, payload = null, action = null) { - if (typeof context != 'string') { - console.error('A key context is required to sendToPropertyInspector.'); - } - - this.send(context, Events.sendToPropertyInspector, { - action, - payload, - }); - } - - /** - * Set the actions key image - * @param {string} context - * @param {string} [image] - * @param {number} [state] - * @param {number} [target] - */ - setImage(context, image, state, target = Constants.hardwareAndSoftware) { - if (!context) { - console.error('A key context is required for setImage.'); - } - - this.send(context, Events.setImage, { - payload: { - image, - target, - state, - }, - }); - } - - /** - * Set the properties of the layout on the Stream Deck + touch display - * @param {*} context - * @param {*} payload - */ - setFeedback(context, payload) { - if (!context) { - console.error('A context is required for setFeedback.'); - } - - this.send(context, Events.setFeedback, { - payload, - }); - } - - /** - * Set the active layout by ID or path for the Stream Deck + touch display - * @param {*} context - * @param {*} layout - */ - setFeedbackLayout(context, layout) { - if (!context) { - console.error('A context is required for setFeedbackLayout.'); - } - - this.send(context, Events.setFeedbackLayout, { - payload: { layout }, - }); - } - - /** - * Registers a callback function for the deviceDidConnect event, which fires when a device is plugged in - * @param {function} fn - * @returns ELGSDStreamDeck - */ - onDeviceDidConnect(fn) { - if (!fn) { - console.error( - 'A callback function for the deviceDidConnect event is required for onDeviceDidConnect.' - ); - } - - this.on(Events.deviceDidConnect, (jsn) => fn(jsn)); - return this; - } - - /** - * Registers a callback function for the deviceDidDisconnect event, which fires when a device is unplugged - * @param {function} fn - * @returns ELGSDStreamDeck - */ - onDeviceDidDisconnect(fn) { - if (!fn) { - console.error( - 'A callback function for the deviceDidDisconnect event is required for onDeviceDidDisconnect.' - ); - } - - this.on(Events.deviceDidDisconnect, (jsn) => fn(jsn)); - return this; - } - - /** - * Registers a callback function for the applicationDidLaunch event, which fires when the application starts - * @param {function} fn - * @returns ELGSDStreamDeck - */ - onApplicationDidLaunch(fn) { - if (!fn) { - console.error( - 'A callback function for the applicationDidLaunch event is required for onApplicationDidLaunch.' - ); - } - - this.on(Events.applicationDidLaunch, (jsn) => fn(jsn)); - return this; - } - - /** - * Registers a callback function for the applicationDidTerminate event, which fires when the application exits - * @param {function} fn - * @returns ELGSDStreamDeck - */ - onApplicationDidTerminate(fn) { - if (!fn) { - console.error( - 'A callback function for the applicationDidTerminate event is required for onApplicationDidTerminate.' - ); - } - - this.on(Events.applicationDidTerminate, (jsn) => fn(jsn)); - return this; - } - - /** - * Registers a callback function for the systemDidWakeUp event, which fires when the computer wakes - * @param {function} fn - * @returns ELGSDStreamDeck - */ - onSystemDidWakeUp(fn) { - if (!fn) { - console.error( - 'A callback function for the systemDidWakeUp event is required for onSystemDidWakeUp.' - ); - } - - this.on(Events.systemDidWakeUp, (jsn) => fn(jsn)); - return this; - } - - /** - * Switches to a readonly profile or returns to previous profile - * @param {string} device - * @param {string} [profile] - */ - switchToProfile(device, profile) { - if (!device) { - console.error('A device id is required for switchToProfile.'); - } - - this.send(this.uuid, Events.switchToProfile, { device, payload: { profile } }); - } -} - -const $SD = new ELGSDStreamDeck(); - -/** - * connectElgatoStreamDeckSocket - * This is the first function StreamDeck Software calls, when - * establishing the connection to the plugin or the Property Inspector - * @param {string} port - The socket's port to communicate with StreamDeck software. - * @param {string} uuid - A unique identifier, which StreamDeck uses to communicate with the plugin - * @param {string} messageType - Identifies, if the event is meant for the property inspector or the plugin. - * @param {string} appInfoString - Information about the host (StreamDeck) application - * @param {string} actionInfo - Context is an internal identifier used to communicate to the host application. - */ -function connectElgatoStreamDeckSocket(port, uuid, messageType, appInfoString, actionInfo) { - const delay = window?.initialConnectionDelay || 0; - - setTimeout(() => { - $SD.connect(port, uuid, messageType, appInfoString, actionInfo); - }, delay); -} diff --git a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/timers.js b/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/timers.js deleted file mode 100644 index 5d74e36..0000000 --- a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/timers.js +++ /dev/null @@ -1,95 +0,0 @@ -/* global ESDTimerWorker */ -/*eslint no-unused-vars: "off"*/ -/*eslint-env es6*/ - -let ESDTimerWorker = new Worker(URL.createObjectURL( - new Blob([timerFn.toString().replace(/^[^{]*{\s*/, '').replace(/\s*}[^}]*$/, '')], {type: 'text/javascript'}) -)); -ESDTimerWorker.timerId = 1; -ESDTimerWorker.timers = {}; -const ESDDefaultTimeouts = { - timeout: 0, - interval: 10 -}; - -Object.freeze(ESDDefaultTimeouts); - -function _setTimer(callback, delay, type, params) { - const id = ESDTimerWorker.timerId++; - ESDTimerWorker.timers[id] = {callback, params}; - ESDTimerWorker.onmessage = (e) => { - if (ESDTimerWorker.timers[e.data.id]) { - if (e.data.type === 'clearTimer') { - delete ESDTimerWorker.timers[e.data.id]; - } else { - const cb = ESDTimerWorker.timers[e.data.id].callback; - if (cb && typeof cb === 'function') cb(...ESDTimerWorker.timers[e.data.id].params); - } - } - }; - ESDTimerWorker.postMessage({type, id, delay}); - return id; -} - -function _setTimeoutESD(...args) { - let [callback, delay = 0, ...params] = [...args]; - return _setTimer(callback, delay, 'setTimeout', params); -} - -function _setIntervalESD(...args) { - let [callback, delay = 0, ...params] = [...args]; - return _setTimer(callback, delay, 'setInterval', params); -} - -function _clearTimeoutESD(id) { - ESDTimerWorker.postMessage({type: 'clearTimeout', id}); // ESDTimerWorker.postMessage({type: 'clearInterval', id}); = same thing - delete ESDTimerWorker.timers[id]; -} - -window.setTimeout = _setTimeoutESD; -window.setInterval = _setIntervalESD; -window.clearTimeout = _clearTimeoutESD; //timeout and interval share the same timer-pool -window.clearInterval = _clearTimeoutESD; - -/** This is our worker-code - * It is executed in it's own (global) scope - * which is wrapped above @ `let ESDTimerWorker` - */ - -function timerFn() { - /*eslint indent: ["error", 4, { "SwitchCase": 1 }]*/ - - let timers = {}; - let debug = false; - let supportedCommands = ['setTimeout', 'setInterval', 'clearTimeout', 'clearInterval']; - - function log(e) { - console.log('Worker-Info::Timers', timers); - } - - function clearTimerAndRemove(id) { - if (timers[id]) { - if (debug) console.log('clearTimerAndRemove', id, timers[id], timers); - clearTimeout(timers[id]); - delete timers[id]; - postMessage({type: 'clearTimer', id: id}); - if (debug) log(); - } - } - - onmessage = function (e) { - // first see, if we have a timer with this id and remove it - // this automatically fulfils clearTimeout and clearInterval - supportedCommands.includes(e.data.type) && timers[e.data.id] && clearTimerAndRemove(e.data.id); - if (e.data.type === 'setTimeout') { - timers[e.data.id] = setTimeout(() => { - postMessage({id: e.data.id}); - clearTimerAndRemove(e.data.id); //cleaning up - }, Math.max(e.data.delay || 0)); - } else if (e.data.type === 'setInterval') { - timers[e.data.id] = setInterval(() => { - postMessage({id: e.data.id}); - }, Math.max(e.data.delay || ESDDefaultTimeouts.interval)); - } - }; -} diff --git a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/utils.js b/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/utils.js deleted file mode 100644 index a7b84cc..0000000 --- a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/property_inspector/streamdeck-javascript-sdk/js/utils.js +++ /dev/null @@ -1,94 +0,0 @@ -class Utils { - /** - * Returns the value from a form using the form controls name property - * @param {Element | string} form - * @returns - */ - static getFormValue(form) { - if (typeof form === 'string') { - form = document.querySelector(form); - } - - const elements = form?.elements; - - if (!elements) { - console.error('Could not find form!'); - } - - const formData = new FormData(form); - let formValue = {}; - - formData.forEach((value, key) => { - if (!Reflect.has(formValue, key)) { - formValue[key] = value; - return; - } - if (!Array.isArray(formValue[key])) { - formValue[key] = [formValue[key]]; - } - formValue[key].push(value); - }); - - return formValue; - } - - /** - * Sets the value of form controls using their name attribute and the jsn object key - * @param {*} jsn - * @param {Element | string} form - */ - static setFormValue(jsn, form) { - if (!jsn) { - return; - } - - if (typeof form === 'string') { - form = document.querySelector(form); - } - - const elements = form?.elements; - - if (!elements) { - console.error('Could not find form!'); - } - - Array.from(elements) - .filter((element) => element?.name) - .forEach((element) => { - const { name, type } = element; - const value = name in jsn ? jsn[name] : null; - const isCheckOrRadio = type === 'checkbox' || type === 'radio'; - - if (value === null) return; - - if (isCheckOrRadio) { - const isSingle = value === element.value; - if (isSingle || (Array.isArray(value) && value.includes(element.value))) { - element.checked = true; - } - } else { - element.value = value ?? ''; - } - }); - } - - /** - * This provides a slight delay before processing rapid events - * @param {number} wait - delay before processing function (recommended time 150ms) - * @param {function} fn - * @returns - */ - static debounce(wait, fn) { - let timeoutId = null; - return (...args) => { - window.clearTimeout(timeoutId); - timeoutId = window.setTimeout(() => { - fn.apply(null, args); - }, wait); - }; - } - - static delay(wait) { - return new Promise((fn) => setTimeout(fn, wait)); - } -} diff --git a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/run.bat b/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/run.bat deleted file mode 100644 index 456e760..0000000 --- a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/run.bat +++ /dev/null @@ -1,66 +0,0 @@ -@echo off - -SET PYTHON_COMMAND=python -SET PYTHON_OK_VERSION=Python 3 -SET PYTHON_MINIMUM_VERSION=3.8 - -SET BASE_PATH=%~dp0 -SET PLUGIN_DIR_PATH=%BASE_PATH:~0,-1% -for %%I in ("%PLUGIN_DIR_PATH%") do set PLUGIN_NAME=%%~nxI -SET PLUGIN_LOGS_DIR_PATH=%PLUGIN_DIR_PATH%\logs -SET PYTHON_INIT_PATH=%PLUGIN_DIR_PATH%\init.py - -SET PLUGIN_CODE_DIR_PATH=%PLUGIN_DIR_PATH%\code -SET PLUGIN_CODE_REQUIREMENTS_PATH=%PLUGIN_CODE_DIR_PATH%\requirements.txt -SET PLUGIN_CODE_PATH=%PLUGIN_CODE_DIR_PATH%\main.py - -SET PLUGIN_CODE_VENV_DIR_PATH=%PLUGIN_CODE_DIR_PATH%\venv -SET PLUGIN_CODE_VENV_ACTIVATE=%PLUGIN_CODE_VENV_DIR_PATH%\Scripts\Activate -SET PLUGIN_CODE_VENV_PYTHON=%PLUGIN_CODE_VENV_DIR_PATH%\Scripts\python.exe - -echo "%PYTHON_COMMAND%" -echo "%PYTHON_OK_VERSION%" -echo "%PYTHON_MINIMUM_VERSION%" - -echo "%BASE_PATH%" -echo "%PLUGIN_DIR_PATH%" -echo "%PLUGIN_NAME%" -echo "%PLUGIN_LOGS_DIR_PATH%" -echo "%PYTHON_INIT_PATH%" - -echo "%PLUGIN_CODE_DIR_PATH%" -echo "%PLUGIN_CODE_REQUIREMENTS_PATH%" -echo "%PLUGIN_CODE_PATH%" - -echo "%PLUGIN_CODE_VENV_DIR_PATH%" -echo "%PLUGIN_CODE_VENV_ACTIVATE%" -echo "%PLUGIN_CODE_VENV_PYTHON%" - -FOR /F "tokens=* USEBACKQ" %%F IN (`%PYTHON_COMMAND% -V`) DO SET PYTHON_VERSION=%%F -echo "%PYTHON_VERSION%" - -IF "%PYTHON_VERSION%" == "" ( -echo "bad python" -powershell -Command "& {Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.MessageBox]::Show('%PYTHON_OK_VERSION% not installed', 'StreamDeck \"%PLUGIN_NAME%\" plugin ERROR', 'OK', [System.Windows.Forms.MessageBoxIcon]::Information);}" -exit -) - -IF NOT "%PYTHON_VERSION:~0,8%" == "%PYTHON_OK_VERSION%" ( -echo "bad python" -powershell -Command "& {Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.MessageBox]::Show('%PYTHON_OK_VERSION% not installed', 'StreamDeck \"%PLUGIN_NAME%\" plugin ERROR', 'OK', [System.Windows.Forms.MessageBoxIcon]::Information);}" -exit -) - -FOR /F "tokens=* USEBACKQ" %%F IN (`%PYTHON_COMMAND% "%PYTHON_INIT_PATH%"`) DO SET INIT_RESULT=%%F -echo "%INIT_RESULT%" - -IF NOT "%INIT_RESULT%" == "True" ( -echo "bad python" -powershell -Command "& {Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.MessageBox]::Show('%INIT_RESULT%', 'StreamDeck \"%PLUGIN_NAME%\" plugin ERROR', 'OK', [System.Windows.Forms.MessageBoxIcon]::Information);}" -exit -) - -SET PYTHONPATH="%PLUGIN_CODE_DIR_PATH%" -echo "%PYTHONPATH%" - -"%PLUGIN_CODE_VENV_PYTHON%" "%PLUGIN_CODE_PATH%" %* diff --git a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/run.sh b/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/run.sh deleted file mode 100644 index 30785b4..0000000 --- a/streamdeck_sdk/executable/assets/base_project/com.bestdeveloper.mytestplugin.sdPlugin/run.sh +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/sh - -export PYTHON_COMMAND="python3" -export PYTHON_OK_VERSION="Python 3" -export PYTHON_MINIMUM_VERSION="3.8" - -export PLUGIN_DIR_PATH=$(dirname "$0") -export PLUGIN_NAME=$(basename "$PLUGIN_DIR_PATH") -export PLUGIN_LOGS_DIR_PATH="${PLUGIN_DIR_PATH}/logs" -export PYTHON_INIT_PATH="${PLUGIN_DIR_PATH}/init.py" - -export PLUGIN_CODE_DIR_PATH="${PLUGIN_DIR_PATH}/code" -export PLUGIN_CODE_REQUIREMENTS_PATH="${PLUGIN_CODE_DIR_PATH}/requirements.txt" -export PLUGIN_CODE_PATH="${PLUGIN_CODE_DIR_PATH}/main.py" - -export PLUGIN_CODE_VENV_DIR_PATH="${PLUGIN_CODE_DIR_PATH}/venv" -export PLUGIN_CODE_VENV_ACTIVATE="${PLUGIN_CODE_VENV_DIR_PATH}/bin/activate" -export PLUGIN_CODE_VENV_PYTHON="${PLUGIN_CODE_VENV_DIR_PATH}/bin/python" - -echo $PYTHON_COMMAND -echo $PYTHON_OK_VERSION -echo $PYTHON_MINIMUM_VERSION - -echo $PLUGIN_DIR_PATH -echo $PLUGIN_NAME -echo $PLUGIN_LOGS_DIR_PATH -echo $PYTHON_INIT_PATH - -echo $PLUGIN_CODE_DIR_PATH -echo $PLUGIN_CODE_REQUIREMENTS_PATH -echo $PLUGIN_CODE_PATH - -echo $PLUGIN_CODE_VENV_DIR_PATH -echo $PLUGIN_CODE_VENV_ACTIVATE -echo $PLUGIN_CODE_VENV_PYTHON - -PYTHON_VERSION=$(${PYTHON_COMMAND} -V) -echo $PYTHON_VERSION - -if [[ $PYTHON_VERSION != $PYTHON_OK_VERSION* ]]; then - echo "bad python" - python_error_massage="StreamDeck '${PLUGIN_NAME}' plugin ERROR\n\n${PYTHON_OK_VERSION} not installed" - osascript -e "display dialog \"${python_error_massage}\"" - exit -fi - -INIT_RESULT=$(${PYTHON_COMMAND} "${PYTHON_INIT_PATH}") -echo $INIT_RESULT - -if [ "$INIT_RESULT" != "True" ]; then - echo "bad python" - python_error_massage="StreamDeck '${PLUGIN_NAME}' plugin ERROR\n\n${INIT_RESULT}" - osascript -e "display dialog \"${python_error_massage}\"" - exit -fi - -export PYTHONPATH="${PLUGIN_CODE_DIR_PATH}" -echo $PYTHONPATH - -"${PLUGIN_CODE_VENV_PYTHON}" "${PLUGIN_CODE_PATH}" "$@" -osascript -e "display dialog \"$@\"" \ No newline at end of file diff --git a/streamdeck_sdk/executable/executable.py b/streamdeck_sdk/executable/executable.py deleted file mode 100644 index c223b8e..0000000 --- a/streamdeck_sdk/executable/executable.py +++ /dev/null @@ -1,78 +0,0 @@ -import argparse -import logging -import os -import platform -import shutil -import subprocess -from datetime import datetime -from pathlib import Path - -logger = logging.getLogger(__name__) - -BASE_DIR = Path(Path().resolve()) -ASSETS_DIR = Path(__file__).parent / "assets" -BASE_PROJECT_DIR = ASSETS_DIR / "base_project" - -DISTRIBUTION_TOOL_MACOS = ASSETS_DIR / "DistributionTool" -DISTRIBUTION_TOOL_WINDOWS = ASSETS_DIR / "DistributionTool.exe" - - -def main(): - parser = argparse.ArgumentParser(description="StreamDeckSDK") - parser.add_argument("command") - parser.add_argument("-i", default=None, required=False, type=str, help="Input file", ) - parser.add_argument('-F', action='store_true', help="Force build", ) - args = parser.parse_args() - logger.info(args) - command = args.command - if command == "startproject": - shutil.copytree(str(BASE_PROJECT_DIR.resolve()), str(BASE_DIR.resolve()), symlinks=False, dirs_exist_ok=True) - elif command == "build": - if args.i is None: - raise ValueError("Invalid value for -i param.") - input_file = str(Path(args.i).resolve()) - - now = datetime.now() - dt = now.strftime("%Y_%m_%d_%H_%M_%S") - release_dir = BASE_DIR / f"releases/{dt}" - release_dir.mkdir(exist_ok=True, parents=True) - release_dir = str(release_dir.resolve()) - - [p.unlink() for p in BASE_DIR.rglob('*.py[co]')] - [p.rmdir() for p in BASE_DIR.rglob('__pycache__')] - - force = args.F - if force: - force_build(i=input_file, o=release_dir) - return - - os_name = platform.system() - logger.info(os_name) - if os_name == "Darwin": - distribution_tool = str(DISTRIBUTION_TOOL_MACOS.resolve()) - elif os_name == "Windows": - distribution_tool = str(DISTRIBUTION_TOOL_WINDOWS.resolve()) - else: - raise ValueError("Unsupported Operation System.") - os.chmod(distribution_tool, 755, ) - subprocess.run( - [distribution_tool, "-b", "-i", input_file, "-o", release_dir], - ) - - -def force_build(i: str, o: str) -> None: - i = Path(i) - o = Path(o) - output_zip_base_name = o / i.name - shutil.make_archive( - base_name=str(output_zip_base_name.resolve()), - format="zip", - root_dir=str(i.parent.resolve()), - base_dir=i.name, - ) - output_zip_file_path = o / f"{i.name}.zip" - output_plugin_file_path = o / i.name.replace(".sdPlugin", ".streamDeckPlugin") - os.rename( - str(output_zip_file_path.resolve()), - str(output_plugin_file_path.resolve()) - ) diff --git a/streamdeck_sdk/logger.py b/streamdeck_sdk/logger.py deleted file mode 100644 index 2b6ffba..0000000 --- a/streamdeck_sdk/logger.py +++ /dev/null @@ -1,60 +0,0 @@ -import logging -from functools import wraps -from logging.handlers import RotatingFileHandler -from pathlib import Path - -from decohints import decohints - -_root_logger: logging.Logger = logging.getLogger() -_log_errors_decorator_logger = logging.getLogger("log_errors_decorator") -logger = logging.getLogger("streamdeck_plugin") - - -def init_root_logger( - log_file: Path, - log_level: int = logging.DEBUG, - log_max_bytes: int = 3 * 1024 * 1024, - log_backup_count: int = 2, -) -> None: - _root_logger.setLevel(log_level) - logs_dir: Path = log_file.parent - logs_dir.mkdir(parents=True, exist_ok=True) - rfh = RotatingFileHandler( - log_file, - mode='a', - maxBytes=log_max_bytes, - backupCount=log_backup_count, - encoding="utf-8", - delay=False, - ) - rfh.setLevel(logging.DEBUG) - formatter = logging.Formatter( - "%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d): %(message)s" - ) - rfh.setFormatter(formatter) - _root_logger.addHandler(rfh) - - -@decohints -def log_errors(func): - """ - A decorator that logs and suppresses errors in the function being decorated. - """ - - @wraps(func) - def wrapper(*args, **kwargs): - try: - result = func(*args, **kwargs) - except SystemExit as err: - _log_errors_decorator_logger.exception(str(err)) - raise err - except BaseException as err: - _log_errors_decorator_logger.exception(str(err)) - return - return result - - return wrapper - - -def rename_plugin_logger(name: str): - logger.name = name diff --git a/streamdeck_sdk/mixins/__init__.py b/streamdeck_sdk/mixins/__init__.py deleted file mode 100644 index dc1eecc..0000000 --- a/streamdeck_sdk/mixins/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -from .handle_event_mixins import * -from .send_event_mixins import * - - -class Base( - PluginEventHandlersMixin, - ActionEventHandlersMixin, - EventsSendMixin, -): - pass diff --git a/streamdeck_sdk/mixins/debug_server_mixin.py b/streamdeck_sdk/mixins/debug_server_mixin.py deleted file mode 100644 index 55554da..0000000 --- a/streamdeck_sdk/mixins/debug_server_mixin.py +++ /dev/null @@ -1,50 +0,0 @@ -import logging -from typing import Set - -from websockets.sync.server import ( - ServerConnection, - WebSocketServer, # noqa - serve, -) - -from streamdeck_sdk.mixins import SendMixin -from streamdeck_sdk.simple_ws.client import WebSocketClientApp -from streamdeck_sdk.utils.in_separate_thread import in_separate_thread - -logger = logging.getLogger(__name__) - - -class DebugServerMixin(SendMixin): - debug_clients: Set[ServerConnection] - debug_port: int - - @in_separate_thread(daemon=True) - def _debug_server_run(self): - server: WebSocketServer = serve( - handler=self._debug_server_handler, - host="localhost", - port=self.debug_port, - ) - server.serve_forever() - - def _debug_server_handler(self, websocket: ServerConnection): - self.debug_clients.add(websocket) - logger.debug(f"Client {websocket} added, clients: {self.debug_clients}.") - try: - for message in websocket: - logger.debug(f"Message {message} received from StreamDeckPlugin.") - self.ws.send(message) - logger.debug(f"Message {message} sent to StreamDeck.") - except Exception: # noqa - self.debug_clients.remove(websocket) - logger.debug(f"Client {websocket} removed, clients: {self.debug_clients}") - - def _debug_server_on_message( - self, - ws: WebSocketClientApp, # noqa - message: str, - ) -> None: - logger.debug(f"Received message from StreamDeck. message={message}.") - for client in self.debug_clients: - client.send(message) - logger.debug(f"Message sent to StreamDeckPlugin {client}. message={message}.") diff --git a/streamdeck_sdk/mixins/event_routing_mixin.py b/streamdeck_sdk/mixins/event_routing_mixin.py deleted file mode 100644 index e0611e2..0000000 --- a/streamdeck_sdk/mixins/event_routing_mixin.py +++ /dev/null @@ -1,134 +0,0 @@ -import json -import logging -from typing import Callable - -import pydantic - -from streamdeck_sdk import event_routings -from streamdeck_sdk.logger import ( - log_errors, -) -from streamdeck_sdk.mixins import EventsSendMixin -from streamdeck_sdk.simple_ws.client import WebSocketClientApp - -logger = logging.getLogger(__name__) - - -class EventRoutingMixin(EventsSendMixin): - registration_dict: dict - actions: dict - - @log_errors - def ws_on_open( - self, - ws: WebSocketClientApp, # noqa - ) -> None: - logger.info("WS OPENED") - self.send(data=self.registration_dict) - - @log_errors - def ws_on_close( - self, - ws: WebSocketClientApp, # noqa - close_status_code: int, - close_msg: str, - ) -> None: - logger.debug(f"{close_status_code=}; {close_msg=}") - logger.info(f"WS CLOSED") - exit(0) - - @log_errors - def ws_on_error( - self, - ws: WebSocketClientApp, # noqa - error, - ) -> None: - logger.error(f"{error=}") - - @log_errors - def ws_on_message( - self, - ws: WebSocketClientApp, # noqa - message: str, - ) -> None: - logger.info(f"Message processing has started. message={message}") - message_dict = json.loads(message) - logger.debug(f"{message_dict=}") - event = message_dict["event"] - logger.debug(f"{event=}") - event_routing = event_routings.EVENT_ROUTING_MAP.get(event) - if event_routing is None: - logger.warning("event_routing is None") - return - - obj = event_routing.obj_type.model_validate(message_dict) - logger.debug(f"{obj=}") - - self.route_event_in_plugin_handler(event_routing=event_routing, obj=obj) - if event_routing.type is event_routings.EventRoutingObjTypes.ACTION: - self.route_action_event_in_action_handler(event_routing=event_routing, obj=obj) - elif event_routing.type is event_routings.EventRoutingObjTypes.PLUGIN: - self.route_plugin_event_in_action_handlers(event_routing=event_routing, obj=obj) - logger.info(f"Message processing completed. message={message}") - - @log_errors - def route_event_in_plugin_handler( - self, - event_routing: event_routings.EventRoutingObj, - obj: pydantic.BaseModel, - ) -> None: - try: - handler: Callable = getattr(self, event_routing.handler_name) - except AttributeError as err: - logger.error(f"Handler missing: {str(err)}", exc_info=True) - return - self.handle_message(handler=handler, obj=obj) - - @log_errors - def route_action_event_in_action_handler( - self, - event_routing: event_routings.EventRoutingObj, - obj: pydantic.BaseModel, - ) -> None: - try: - action_uuid = getattr(obj, "action") - except AttributeError as err: - logger.error(str(err), exc_info=True) - return - action_obj = self.actions.get(action_uuid) - if action_obj is None: - logger.warning(f"{action_uuid=} not registered") - return - try: - handler: Callable = getattr(action_obj, event_routing.handler_name) - except AttributeError as err: - logger.error(f"Handler missing: {str(err)}", exc_info=True) - return - self.handle_message(handler=handler, obj=obj) - - @log_errors - def route_plugin_event_in_action_handlers( - self, - event_routing: event_routings.EventRoutingObj, - obj: pydantic.BaseModel, - ) -> None: - for action_obj in self.actions.values(): - try: - handler: Callable = getattr(action_obj, event_routing.handler_name) - except AttributeError as err: - logger.error(f"Handler missing: {str(err)}", exc_info=True) - return - self.handle_message(handler=handler, obj=obj) - - @log_errors - def handle_message( - self, - handler: Callable, - obj: pydantic.BaseModel - ) -> None: - try: - handler(obj) - except Exception: - self.show_alert( - context=obj.context, - ) diff --git a/streamdeck_sdk/mixins/handle_event_mixins.py b/streamdeck_sdk/mixins/handle_event_mixins.py deleted file mode 100644 index 82832b5..0000000 --- a/streamdeck_sdk/mixins/handle_event_mixins.py +++ /dev/null @@ -1,72 +0,0 @@ -from ..sd_objs import events_received_objs - - -class BaseEventHandlerMixin: - pass - - -class ActionEventHandlersMixin(BaseEventHandlerMixin): - def on_did_receive_settings(self, obj: events_received_objs.DidReceiveSettings) -> None: - pass - - def on_key_down(self, obj: events_received_objs.KeyDown) -> None: - pass - - def on_key_up(self, obj: events_received_objs.KeyUp) -> None: - pass - - def on_touch_tap(self, obj: events_received_objs.TouchTap) -> None: - pass - - def on_dial_down(self, obj: events_received_objs.DialDown) -> None: - pass - - def on_dial_up(self, obj: events_received_objs.DialUp) -> None: - pass - - def on_dial_rotate(self, obj: events_received_objs.DialRotate) -> None: - pass - - def on_will_appear(self, obj: events_received_objs.WillAppear) -> None: - pass - - def on_did_receive_deep_link(self, obj: events_received_objs.DidReceiveDeepLink) -> None: - pass - - def on_will_disappear(self, obj: events_received_objs.WillDisappear) -> None: - pass - - def on_title_parameters_did_change(self, obj: events_received_objs.TitleParametersDidChange) -> None: - pass - - def on_property_inspector_did_appear(self, obj: events_received_objs.PropertyInspectorDidAppear) -> None: - pass - - def on_property_inspector_did_disappear(self, obj: events_received_objs.PropertyInspectorDidDisappear) -> None: - pass - - def on_send_to_plugin(self, obj: events_received_objs.SendToPlugin) -> None: - pass - - def on_send_to_property_inspector(self, obj: events_received_objs.SendToPropertyInspector) -> None: - pass - - -class PluginEventHandlersMixin(BaseEventHandlerMixin): - def on_did_receive_global_settings(self, obj: events_received_objs.DidReceiveGlobalSettings) -> None: - pass - - def on_device_did_connect(self, obj: events_received_objs.DeviceDidConnect) -> None: - pass - - def on_device_did_disconnect(self, obj: events_received_objs.DeviceDidDisconnect) -> None: - pass - - def on_application_did_launch(self, obj: events_received_objs.ApplicationDidLaunch) -> None: - pass - - def on_application_did_terminate(self, obj: events_received_objs.ApplicationDidTerminate) -> None: - pass - - def on_system_did_wake_up(self, obj: events_received_objs.SystemDidWakeUp) -> None: - pass diff --git a/streamdeck_sdk/mixins/send_event_mixins.py b/streamdeck_sdk/mixins/send_event_mixins.py deleted file mode 100644 index ed0f915..0000000 --- a/streamdeck_sdk/mixins/send_event_mixins.py +++ /dev/null @@ -1,421 +0,0 @@ -import json -import logging -from typing import Union, Optional - -import pydantic - -from ..logger import log_errors -from ..sd_objs import events_sent_objs -from ..simple_ws.client import WebSocketClientApp - -logger = logging.getLogger(__name__) - - -class SendMixin: - ws: WebSocketClientApp - - @log_errors - def send( - self, - data: Union[pydantic.BaseModel, dict, str] - ) -> None: - """ - Converts the data value to json and sends it. - """ - if isinstance(data, pydantic.BaseModel): - data = json.dumps(data.model_dump(), ensure_ascii=True) - elif isinstance(data, dict): - data = json.dumps(data, ensure_ascii=False) - elif isinstance(data, str): - pass - else: - logger.warning(f"Invalid data type {type(data)} to send. The message will not be sent! data={data}") - return - self.ws.send(data) - - -class EventsSendMixin(SendMixin): - plugin_uuid: str - - def get_global_settings( - self, - ) -> None: - """ - The plugin and Property Inspector can request the persistent global data using the getGlobalSettings event. - The plugin or Property Inspector will receive asynchronously an event didReceiveGlobalSettings the p - containing the global settings. - - https://docs.elgato.com/sdk/plugins/events-sent#getglobalsettings - """ - message = events_sent_objs.GetGlobalSettings( - context=self.plugin_uuid, - ) - self.send(message) - - def get_settings( - self, - context: str, - ) -> None: - """ - The plugin and Property Inspector can request the persistent data stored for the action's - instance using the getSettings event. - - https://docs.elgato.com/sdk/plugins/events-sent#getsettings - - :param context: A value to Identify the instance's action or Property Inspector. In the case of - the Property Inspector, this value is received by the Property Inspector as parameter of - the connectElgatoStreamDeckSocket function. - """ - message = events_sent_objs.GetSettings( - context=context, - ) - self.send(message) - - def log_message( - self, - message: str, - ) -> None: - r""" - The plugin and Property Inspector can use the logMessage event to write a debug message to the logs file. - * Logs are saved to disk per plugin in the folder ~/Library/Logs/ElgatoStreamDeck/ on macOS - and %appdata%\Elgato\StreamDeck\logs\ on Windows. Note that the log files are rotated each time - the Stream Deck application is relaunched. - - https://docs.elgato.com/sdk/plugins/events-sent#logmessage - - :param message: A string to write to the logs file. - """ - message = events_sent_objs.LogMessage( - payload=events_sent_objs.LogMessagePayload( - message=message, - ), - ) - self.send(message) - - def open_url( - self, - url: str, - ) -> None: - """ - The plugin and Property Inspector can tell the Stream Deck application to open URL in the - default browser using the openUrl event. - - https://docs.elgato.com/sdk/plugins/events-sent#openurl - - :param url: An URL to open in the default browser. - """ - message = events_sent_objs.OpenUrl( - payload=events_sent_objs.OpenUrlPayload( - url=url, - ), - ) - self.send(message) - - def send_to_property_inspector( - self, - action: str, - context: str, - payload: dict, - ) -> None: - """ - The plugin can send a payload to the Property Inspector using the sendToPropertyInspector event. - The Property Inspector will receive asynchronously an event sendToPropertyInspector. - - https://docs.elgato.com/sdk/plugins/events-sent#sendtopropertyinspector - - :param action: The action's unique identifier. - :param context: A value to identify the instance's action. - :param payload: A JSON object that will be received by the Property Inspector. - """ - message = events_sent_objs.SendToPropertyInspector( - action=action, - context=context, - payload=payload, - ) - self.send(message) - - def set_feedback( - self, - context: str, - payload: dict, - ) -> None: - """ - (SD+) - The plugin can send a setFeedback event to the Stream Deck application to dynamically change properties of - items on the Stream Deck + touch display layout. - - https://docs.elgato.com/sdk/plugins/events-sent#setfeedback-sd - - :param context: A value to Identify the instance's action you want to modify. - :param payload: A dict object. - key: The key is a name of the element in layout to be changed with given value. - value: The value to be set in key named layout element. - """ - message = events_sent_objs.SetFeedback( - context=context, - payload=payload, - ) - self.send(message) - - def set_feedback_layout( - self, - context: str, - layout: str, - ) -> None: - """ - (SD+) - The plugin can send a setFeedbackLayout event to the Stream Deck application to dynamically change the - current Stream Deck + touch display layout. setFeedbackLayout can use the id of a built-in layout or - a relative path to a custom layout JSON file. See Layouts for more information. - - https://docs.elgato.com/sdk/plugins/events-sent#setfeedbacklayout-sd - - :param context: A value to Identify the instance's action you want to modify. - :param layout: A predefined layout identifier or the relative path to a json file that - contains a custom layout. - """ - message = events_sent_objs.SetFeedbackLayout( - context=context, - payload=events_sent_objs.SetFeedbackLayoutPayload( - layout=layout, - ), - ) - self.send(message) - - def set_global_settings( - self, - payload: dict, - ) -> None: - """ - The plugin and Property Inspector can save persistent data globally. The data - will be saved securely to the Keychain on macOS and the Credential Store on Windows. This API can - be used to save tokens that should be available to every action in the plugin. - Note that when the plugin uses this API, the Property Inspector will automatically receive - a didReceiveGlobalSettings callback with the new settings. Similarly, when the Property Inspector uses - this API, the plugin will automatically receive a didReceiveGlobalSettings callback with the new settings. - This API has been introduced in Stream Deck 4.1. - - https://docs.elgato.com/sdk/plugins/events-sent#setglobalsettings - - :param payload: A JSON object which is persistently saved globally. - """ - message = events_sent_objs.SetGlobalSettings( - context=self.plugin_uuid, - payload=payload, - ) - self.send(message) - - def set_image( - self, - context: str, - image: str, # base64 - target: int = 0, - state: Optional[int] = None, - ) -> None: - """ - The plugin can send a setImage event to the Stream Deck application to dynamically change the image displayed - by an instance of an action. - - https://docs.elgato.com/sdk/plugins/events-sent#setimage - - :param context: A value to Identify the instance's action you want to modify. - :param image: The image to display encoded in base64 with the image format declared in the mime - type (PNG, JPEG, BMP, ...). svg is also supported. If not provided, the image is - reset to the default image from the manifest. - You can use functions from image_converters.py for convert image in base64. - :param target: Specify if you want to display the title on the hardware and software (0), - only on the hardware (1), or only on the software (2). Default is 0. - :param state: A 0-based integer value representing the state of an action with multiple states. If not - specified, the image is set to all states. - """ - message = events_sent_objs.SetImage( - context=context, - payload=events_sent_objs.SetImagePayload( - image=image, - target=target, - state=state, - ), - ) - self.send(message) - - def set_settings( - self, - context: str, - payload: dict, - ) -> None: - """ - The plugin and Property Inspector can save data persistently for the action's instance using - the setSettings event. - Note that when the plugin uses this API, the Property Inspector will automatically receive a didReceiveSettings - callback with the new settings. Similarly, when the Property Inspector uses this API, the plugin will - automatically receive a didReceiveSettings callback with the new settings. - The setSettings API is available since Stream Deck 4.0 for the plugin. Starting - with Stream Deck 4.1, this API is available from the Property Inspector. - - https://docs.elgato.com/sdk/plugins/events-sent#setsettings - - :param context: A value to Identify the instance's action or Property Inspector. This value is received - by the Property Inspector as a parameter of the connectElgatoStreamDeckSocket function. - :param payload: A JSON object which is persistently saved for the action's instance. - """ - message = events_sent_objs.SetSettings( - context=context, - payload=payload, - ) - self.send(message) - - def set_state( - self, - context: str, - state: int, - ) -> None: - """ - This function can be used by a plugin to dynamically change the state of an action supporting multiple states. - - https://docs.elgato.com/sdk/plugins/events-sent#setstate - - :param context: A value to identify the instance's action. - :param state: A 0-based integer value representing the state requested. - """ - message = events_sent_objs.SetState( - context=context, - payload=events_sent_objs.SetStatePayload( - state=state, - ) - ) - self.send(message) - - def set_title( - self, - context: str, - title: str, - target: int = 0, - state: Optional[int] = None, - ) -> None: - """ - The plugin can send a setTitle event to the Stream Deck application to dynamically change the title - displayed by an instance of an action. - * Note: Show the title on your hardware or software using the Show Title checkbox in the Stream Deck window. - - https://docs.elgato.com/sdk/plugins/events-sent#settitle - - :param context: A value to Identify the instance's action you want to modify. - :param title: The title to display. If there is no title parameter, the title is reset to the title set - by the user. - :param target: Specify if you want to display the title on the hardware and software (0), only on the - hardware (1), or only on the software (2). Default is 0. - :param state: A 0-based integer value representing the state of an action with multiple states. If not - specified, the title is set to all states. - """ - message = events_sent_objs.SetTitle( - context=context, - payload=events_sent_objs.SetTitlePayload( - title=title, - target=target, - state=state, - ), - ) - self.send(message) - - def set_trigger_description( - self, - context: str, - *, - long_touch: Optional[str] = None, - push: Optional[str] = None, - rotate: Optional[str] = None, - touch: Optional[str] = None, - ) -> None: - """ - (SD+) - Sets the trigger descriptions associated with an encoder (touch display + dial) action instance. - All descriptions are optional; when one or more descriptions are defined all descriptions are - updated, with undefined values having their description hidden in Stream Deck. - To reset the descriptions to the default values defined - within the manifest, an empty payload can be sent as part of the event. - - https://docs.elgato.com/sdk/plugins/events-sent#settriggerdescription-sd - - :param context: A value to identify the instance's action. - :param long_touch: Optional value that describes the long-touch interaction with the touch display. When - undefined the description will be hidden. - :param push: Optional value that describes the push interaction with the dial. When undefined the - description will be hidden. - :param rotate: Optional value that describes the rotate interaction with the dial. When undefined - the description will be hidden. - :param touch: Optional value that describes the touch interaction with the touch display. When undefined - the description will be hidden. - """ - message = events_sent_objs.SetTriggerDescription( - context=context, - payload=events_sent_objs.SetTriggerDescriptionPayload( - longTouch=long_touch, - push=push, - rotate=rotate, - touch=touch, - ), - ) - self.send(message) - - def show_alert( - self, - context: str, - ) -> None: - """ - The plugin can send a showAlert event to the Stream Deck application to temporarily show an alert icon on the - image displayed by an instance of an action. - - https://docs.elgato.com/sdk/plugins/events-sent#showalert - - :param context: A value to identify the instance's action. - """ - message = events_sent_objs.ShowAlert( - context=context, - ) - self.send(message) - - def show_ok( - self, - context: str, - ) -> None: - """ - The plugin can send a showOk event to the Stream Deck application to temporarily show an OK checkmark icon on - the image displayed by an instance of an action. - - https://docs.elgato.com/sdk/plugins/events-sent#showok - - :param context: A value to identify the instance's action. - """ - message = events_sent_objs.ShowOk( - context=context, - ) - self.send(message) - - def switch_to_profile( - self, - device: str, - profile: str, - page: int, - ) -> None: - """ - The plugin can tell the Stream Deck application to switch to one of his preconfigured read-only profile - using the switchToProfile event. - * Note that a plugin can only switch to read-only profiles declared in its manifest.json file. If the profile - field is missing or empty, the Stream Deck application will switch to the previously selected profile. - - https://docs.elgato.com/sdk/plugins/events-sent#switchtoprofile - - :param device: A value to identify the device. - :param profile: The name of the profile to switch to. The name should be identical to the name provided - in the manifest.json file. - :param page: Page to show when switching to the profile; indexed from 0. - """ - message = events_sent_objs.SwitchToProfile( - context=self.plugin_uuid, - device=device, - payload=events_sent_objs.SwitchToProfilePayload( - profile=profile, - page=page, - ), - ) - self.send(message) diff --git a/streamdeck_sdk/property_inspector/__init__.py b/streamdeck_sdk/property_inspector/__init__.py deleted file mode 100644 index ccfd487..0000000 --- a/streamdeck_sdk/property_inspector/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .objs import * -from .property_inspector import PropertyInspector diff --git a/streamdeck_sdk/property_inspector/objs/__init__.py b/streamdeck_sdk/property_inspector/objs/__init__.py deleted file mode 100644 index a37c18a..0000000 --- a/streamdeck_sdk/property_inspector/objs/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -from .base import BasePIElement -from .checkbox import Checkbox, CheckboxItem -from .color import Color -from .date_obj import Date -from .datetime_local import DateTimeLocal -from .details import Details -from .file import File -from .group import Group -from .heading import Heading -from .line import Line -from .message import Message, MessageTypes -from .meter import Meter -from .month import Month -from .password import Password -from .progress import Progress -from .radio import Radio, RadioItem -from .range import Range -from .select import Select -from .textarea import Textarea -from .textfield import Textfield -from .time_obj import Time -from .week import Week diff --git a/streamdeck_sdk/property_inspector/objs/base.py b/streamdeck_sdk/property_inspector/objs/base.py deleted file mode 100644 index 0b35454..0000000 --- a/streamdeck_sdk/property_inspector/objs/base.py +++ /dev/null @@ -1,52 +0,0 @@ -import re - -from abc import ABC, abstractmethod - -UID_PATTERN = re.compile(r'^[a-z][a-z0-9_]*$') -UIDS = [] - - -def is_valid_uid(uid): - if UID_PATTERN.match(uid): - return True - else: - return False - - -class UidCheckMixin: - def __setattr__(self, key, value): - if key != "uid": - return super().__setattr__(key, value) - - if value in UIDS: - raise ValueError(f"uid must be unique. uid={value}") - if not value: - raise ValueError(f"uid must not be empty. uid={value}") - if not isinstance(value, str): - raise ValueError(f"uid must be str. uid={value}") - if not is_valid_uid(uid=value): - raise ValueError(f"uid does not match pattern {UID_PATTERN}. uid={value}") - UIDS.append(value) - return super().__setattr__(key, value) - - -class BaseElement(UidCheckMixin): - pass - - -class BasePIElement(BaseElement, ABC): - @abstractmethod - def get_html_element(self) -> str: - pass - - def get_js_code(self) -> str: - return "" - - def get_on_connect_js(self) -> str: - return "" - - def get_js_consts(self) -> str: - return "" - - def get_on_did_receive_settings_js(self) -> str: - return self.get_on_connect_js() diff --git a/streamdeck_sdk/property_inspector/objs/checkbox.py b/streamdeck_sdk/property_inspector/objs/checkbox.py deleted file mode 100644 index 39c275b..0000000 --- a/streamdeck_sdk/property_inspector/objs/checkbox.py +++ /dev/null @@ -1,105 +0,0 @@ -from string import Template -from typing import List - -from .base import BasePIElement, BaseElement - - -class CheckboxItem(BaseElement): - def __init__( - self, - uid: str, - label: str = "", - checked: bool = False, - ): - self.uid = uid - self.label = label - self.checked = checked - self.js_el_const = f"{self.uid}_el" - self.onchange = f"onchange_{self.uid}" - - def get_html_element(self) -> str: - checked = "checked" if self.checked else "" - label = self.label if self.label else "" - - res = f""" -
- - -
- """ - return res - - def get_js_code(self) -> str: - template = Template(""" - const ${onchange} = () => { - console.log(${js_el_const}.checked); - settings["${uid}"] = ${js_el_const}.checked - $$PI.setSettings(settings); - } - """) - - res = template.substitute(onchange=self.onchange, uid=self.uid, js_el_const=self.js_el_const) - return res - - def get_on_connect_js(self) -> str: - template = Template(""" - if (settings["${uid}"] !== undefined) { - ${js_el_const}.checked = settings.${uid} - } else { - settings["${uid}"] = ${js_el_const}.checked - } - """) - res = template.substitute(uid=self.uid, js_el_const=self.js_el_const) - - return res - - def get_on_did_receive_settings_js(self) -> str: - return self.get_on_connect_js() - - def get_js_consts(self) -> str: - res = f""" - const {self.js_el_const} = document.getElementById("{self.uid}") - """ - return res - - -class Checkbox(BasePIElement): - def __init__( - self, - label: str, - items: List[CheckboxItem], - ): - self.label = label - self.items = items - - def get_html_element(self) -> str: - items = "\n".join([element.get_html_element() for element in self.items]) - - res = f""" -
-
{self.label}
-
- {items} -
-
- """ - return res - - def get_js_code(self) -> str: - res = "\n".join([element.get_js_code() for element in self.items]) - return res - - def get_on_connect_js(self) -> str: - res = "\n".join([element.get_on_connect_js() for element in self.items]) - return res - - def get_js_consts(self) -> str: - res = "\n".join([element.get_js_consts() for element in self.items]) - return res - - def get_on_did_receive_settings_js(self) -> str: - res = "\n".join([element.get_on_did_receive_settings_js() for element in self.items]) - return res diff --git a/streamdeck_sdk/property_inspector/objs/color.py b/streamdeck_sdk/property_inspector/objs/color.py deleted file mode 100644 index 47bcee4..0000000 --- a/streamdeck_sdk/property_inspector/objs/color.py +++ /dev/null @@ -1,59 +0,0 @@ -from string import Template -from typing import Optional - -from .base import BasePIElement - - -class Color(BasePIElement): - def __init__( - self, - label: str, - uid: str, - default_value: Optional[str] = None, - ): - self.label = label - self.default_value = default_value - self.uid = uid - self.js_el_const = f"{self.uid}_el" - self.onchange = f"onchange_{self.uid}" - - def get_html_element(self) -> str: - value = f'value="{self.default_value}"' if {self.default_value} else "" - - res = f""" -
-
{self.label}
- -
- """ - return res - - def get_js_code(self) -> str: - template = Template(""" - const ${onchange} = () => { - console.log(${js_el_const}.value); - settings["${uid}"] = ${js_el_const}.value; - $$PI.setSettings(settings); - } - """) - - res = template.substitute(onchange=self.onchange, uid=self.uid, js_el_const=self.js_el_const) - return res - - def get_on_connect_js(self) -> str: - template = Template(""" - if (settings["${uid}"] !== undefined) { - ${js_el_const}.value = settings.${uid} - } else { - settings["${uid}"] = ${js_el_const}.value - } - """) - res = template.substitute(uid=self.uid, js_el_const=self.js_el_const) - - return res - - def get_js_consts(self) -> str: - res = f""" - const {self.js_el_const} = document.getElementById("{self.uid}") - """ - return res diff --git a/streamdeck_sdk/property_inspector/objs/date_obj.py b/streamdeck_sdk/property_inspector/objs/date_obj.py deleted file mode 100644 index 0fb38d2..0000000 --- a/streamdeck_sdk/property_inspector/objs/date_obj.py +++ /dev/null @@ -1,59 +0,0 @@ -from string import Template -from typing import Optional - -from .base import BasePIElement - - -class Date(BasePIElement): - def __init__( - self, - label: str, - uid: str, - default_value: Optional[str] = None, - ): - self.label = label - self.default_value = default_value - self.uid = uid - self.js_el_const = f"{self.uid}_el" - self.onchange = f"onchange_{self.uid}" - - def get_html_element(self) -> str: - value = f'value="{self.default_value}"' if {self.default_value} else "" - - res = f""" -
-
{self.label}
- -
- """ - return res - - def get_js_code(self) -> str: - template = Template(""" - const ${onchange} = () => { - console.log(${js_el_const}.value); - settings["${uid}"] = ${js_el_const}.value; - $$PI.setSettings(settings); - } - """) - - res = template.substitute(onchange=self.onchange, uid=self.uid, js_el_const=self.js_el_const) - return res - - def get_on_connect_js(self) -> str: - template = Template(""" - if (settings["${uid}"] !== undefined) { - ${js_el_const}.value = settings.${uid} - } else { - settings["${uid}"] = ${js_el_const}.value - } - """) - res = template.substitute(uid=self.uid, js_el_const=self.js_el_const) - - return res - - def get_js_consts(self) -> str: - res = f""" - const {self.js_el_const} = document.getElementById("{self.uid}") - """ - return res diff --git a/streamdeck_sdk/property_inspector/objs/datetime_local.py b/streamdeck_sdk/property_inspector/objs/datetime_local.py deleted file mode 100644 index 8cf8b8b..0000000 --- a/streamdeck_sdk/property_inspector/objs/datetime_local.py +++ /dev/null @@ -1,59 +0,0 @@ -from string import Template -from typing import Optional - -from .base import BasePIElement - - -class DateTimeLocal(BasePIElement): - def __init__( - self, - label: str, - uid: str, - default_value: Optional[str] = None, - ): - self.label = label - self.default_value = default_value - self.uid = uid - self.js_el_const = f"{self.uid}_el" - self.onchange = f"onchange_{self.uid}" - - def get_html_element(self) -> str: - value = f'value="{self.default_value}"' if {self.default_value} else "" - - res = f""" -
-
{self.label}
- -
- """ - return res - - def get_js_code(self) -> str: - template = Template(""" - const ${onchange} = () => { - console.log(${js_el_const}.value); - settings["${uid}"] = ${js_el_const}.value; - $$PI.setSettings(settings); - } - """) - - res = template.substitute(onchange=self.onchange, uid=self.uid, js_el_const=self.js_el_const) - return res - - def get_on_connect_js(self) -> str: - template = Template(""" - if (settings["${uid}"] !== undefined) { - ${js_el_const}.value = settings.${uid} - } else { - settings["${uid}"] = ${js_el_const}.value - } - """) - res = template.substitute(uid=self.uid, js_el_const=self.js_el_const) - - return res - - def get_js_consts(self) -> str: - res = f""" - const {self.js_el_const} = document.getElementById("{self.uid}") - """ - return res diff --git a/streamdeck_sdk/property_inspector/objs/details.py b/streamdeck_sdk/property_inspector/objs/details.py deleted file mode 100644 index 0d26f93..0000000 --- a/streamdeck_sdk/property_inspector/objs/details.py +++ /dev/null @@ -1,67 +0,0 @@ -from string import Template -from typing import Optional - -from .base import BasePIElement - - -class Details(BasePIElement): - def __init__( - self, - uid: str, - label: str = "", - text: str = "", - heading: Optional[str] = None, - full_width: bool = False, - default_open: bool = False, - ): - self.heading = heading - self.text = text - self.default_open = default_open - self.full_width = full_width - self.label = label - self.uid = uid - self.js_el_const = f"{self.uid}_el" - - def get_html_element(self) -> str: - default_open = f'open' if self.default_open else "" - if self.label: - label = f'
{self.label}
' - elif not self.full_width: - label = f'
' - else: - label = "" - text = "\n".join([f"

{line.strip()}

" for line in self.text.splitlines() if line.strip()]) - heading = f'{self.heading}' if self.heading else "" - - res = f""" -
- {label} -
- {heading} -
{text}
-
-
- """ - return res - - def get_on_connect_js(self) -> str: - template = Template(r""" - if (settings["${uid}"] !== undefined) { - ${js_el_const}.innerHTML = settings.${uid} - .split('\n') - .map(line => line.trim()) - .filter(line => line) - .map(line => `

$${line}

`) - .join('\n'); - } else { - settings["${uid}"] = ${js_el_const}.textContent; - } - """) - res = template.substitute(uid=self.uid, js_el_const=self.js_el_const) - return res - - def get_js_consts(self) -> str: - res = f""" - const {self.js_el_const} = document.getElementById("{self.uid}") - """ - return res diff --git a/streamdeck_sdk/property_inspector/objs/file.py b/streamdeck_sdk/property_inspector/objs/file.py deleted file mode 100644 index 93270ea..0000000 --- a/streamdeck_sdk/property_inspector/objs/file.py +++ /dev/null @@ -1,99 +0,0 @@ -from string import Template -from typing import List, Optional - -from .base import BasePIElement - - -class File(BasePIElement): - def __init__( - self, - label: str, - uid: str, - accept: Optional[List[str]] = None, - placeholder: str = "no file...", - ): - if accept: - self.accept = ", ".join(accept) - else: - self.accept = None - self.label = label - self.placeholder = placeholder - self.uid = uid - self.uid_label = f"{self.uid}_label" - self.js_el_const = f"{self.uid}_el" - self.js_el_label_const = f"{self.uid_label}_el" - self.onchange = f"onchange_{self.uid}" - - def get_html_element(self) -> str: - accept = f'accept="{self.accept}"' if self.accept else "" - - res = f""" -
-
{self.label}
-
- - - -
-
- """ - return res - - def get_js_code(self) -> str: - template = Template(r""" - function ${onchange}() { - if (${js_el_const}.type !== "file") { - return - } - let result = decodeURIComponent(${js_el_const}.value.replace(/^C:\\fakepath\\/, '')); - console.log(result) - if (result) { - ${js_el_label_const}.textContent = result; - settings["${uid}"] = result; - } else { - ${js_el_label_const}.textContent = "${placeholder}"; - settings["${uid}"] = null; - } - $$PI.setSettings(settings) - } - """) - - res = template.substitute( - uid=self.uid, - js_el_const=self.js_el_const, - js_el_label_const=self.js_el_label_const, - onchange=self.onchange, - placeholder=self.placeholder, - ) - return res - - def get_on_connect_js(self) -> str: - template = Template(""" - if (settings["${uid}"] !== undefined) { - if (settings.${uid}) { - ${js_el_label_const}.textContent = settings.${uid}; - } else { - ${js_el_label_const}.textContent = "${placeholder}"; - } - } else { - ${js_el_label_const}.textContent = "${placeholder}"; - settings["${uid}"] = null; - } - """) - res = template.substitute( - uid=self.uid, - js_el_label_const=self.js_el_label_const, - placeholder=self.placeholder, - ) - - return res - - def get_js_consts(self) -> str: - res = f""" - const {self.js_el_const} = document.getElementById("{self.uid}") - const {self.js_el_label_const} = document.getElementById("{self.uid_label}") - """ - return res diff --git a/streamdeck_sdk/property_inspector/objs/group.py b/streamdeck_sdk/property_inspector/objs/group.py deleted file mode 100644 index 0be7da6..0000000 --- a/streamdeck_sdk/property_inspector/objs/group.py +++ /dev/null @@ -1,44 +0,0 @@ -from typing import List - -from .base import BasePIElement - - -class Group(BasePIElement): - def __init__( - self, - items: List[BasePIElement], - label: str = "", - ): - self.items = items - self.label = label - - def get_html_element(self) -> str: - items = "\n".join([element.get_html_element() for element in self.items]) - - label = f'
{self.label}
' if self.label else "" - - res = f""" -
- {label} -
- {items} -
-
- """ - return res - - def get_js_code(self) -> str: - res = "\n".join([element.get_js_code() for element in self.items]) - return res - - def get_on_connect_js(self) -> str: - res = "\n".join([element.get_on_connect_js() for element in self.items]) - return res - - def get_js_consts(self) -> str: - res = "\n".join([element.get_js_consts() for element in self.items]) - return res - - def get_on_did_receive_settings_js(self) -> str: - res = "\n".join([element.get_on_did_receive_settings_js() for element in self.items]) - return res diff --git a/streamdeck_sdk/property_inspector/objs/heading.py b/streamdeck_sdk/property_inspector/objs/heading.py deleted file mode 100644 index 370a003..0000000 --- a/streamdeck_sdk/property_inspector/objs/heading.py +++ /dev/null @@ -1,15 +0,0 @@ -from .base import BasePIElement - - -class Heading(BasePIElement): - def __init__( - self, - label: str, - ): - self.label = label - - def get_html_element(self) -> str: - res = f""" -
{self.label}
- """ - return res diff --git a/streamdeck_sdk/property_inspector/objs/line.py b/streamdeck_sdk/property_inspector/objs/line.py deleted file mode 100644 index 43469c1..0000000 --- a/streamdeck_sdk/property_inspector/objs/line.py +++ /dev/null @@ -1,7 +0,0 @@ -from .base import BasePIElement - - -class Line(BasePIElement): - def get_html_element(self) -> str: - res = "
" - return res diff --git a/streamdeck_sdk/property_inspector/objs/message.py b/streamdeck_sdk/property_inspector/objs/message.py deleted file mode 100644 index 6d9ba11..0000000 --- a/streamdeck_sdk/property_inspector/objs/message.py +++ /dev/null @@ -1,64 +0,0 @@ -from enum import Enum -from string import Template - -from .base import BasePIElement - - -class MessageTypes(Enum): - INFO = "info" - CAUTION = "caution" - QUESTION = "question" - NONE = "" - - -class Message(BasePIElement): - def __init__( - self, - uid: str, - heading: str, - text: str = "", - message_type: MessageTypes = MessageTypes.INFO, - default_open: bool = False, - ): - self.heading = heading - self.text = text - self.message_type = message_type - self.default_open = default_open - self.uid = uid - self.js_el_const = f"{self.uid}_el" - - def get_html_element(self) -> str: - default_open = f'open' if self.default_open else "" - text = "\n".join([f"

{line.strip()}

" for line in self.text.splitlines() if line.strip()]) - - res = f""" -
-
- {self.heading} -
{text}
-
-
- """ - return res - - def get_on_connect_js(self) -> str: - template = Template(r""" - if (settings["${uid}"] !== undefined) { - ${js_el_const}.innerHTML = settings.${uid} - .split('\n') - .map(line => line.trim()) - .filter(line => line) - .map(line => `

$${line}

`) - .join('\n'); - } else { - settings["${uid}"] = ${js_el_const}.textContent; - } - """) - res = template.substitute(uid=self.uid, js_el_const=self.js_el_const) - return res - - def get_js_consts(self) -> str: - res = f""" - const {self.js_el_const} = document.getElementById("{self.uid}") - """ - return res diff --git a/streamdeck_sdk/property_inspector/objs/meter.py b/streamdeck_sdk/property_inspector/objs/meter.py deleted file mode 100644 index 910b2ff..0000000 --- a/streamdeck_sdk/property_inspector/objs/meter.py +++ /dev/null @@ -1,60 +0,0 @@ -from string import Template -from typing import Optional - -from .base import BasePIElement - - -class Meter(BasePIElement): - def __init__( - self, - label: str, - uid: str, - max_value: float = 1, - default_value: float = 0, - left_label: Optional[str] = None, - right_label: Optional[str] = None, - ): - self.left_label = left_label - self.right_label = right_label - self.max_value = max_value - self.label = label - self.default_value = default_value - self.uid = uid - self.js_el_const = f"{self.uid}_el" - self.onchange = f"onchange_{self.uid}" - - def get_html_element(self) -> str: - left_label = f"{self.left_label}" if self.left_label else "" - right_label = f"{self.right_label}" if self.right_label else "" - - res = f""" -
-
{self.label}
- {left_label} - - - {right_label} -
- """ - return res - - def get_js_code(self) -> str: - return "" - - def get_on_connect_js(self) -> str: - template = Template(""" - if (settings["${uid}"] !== undefined) { - ${js_el_const}.value = settings.${uid} - } else { - settings["${uid}"] = ${js_el_const}.value - } - """) - res = template.substitute(uid=self.uid, js_el_const=self.js_el_const) - - return res - - def get_js_consts(self) -> str: - res = f""" - const {self.js_el_const} = document.getElementById("{self.uid}") - """ - return res diff --git a/streamdeck_sdk/property_inspector/objs/month.py b/streamdeck_sdk/property_inspector/objs/month.py deleted file mode 100644 index 09dfd9a..0000000 --- a/streamdeck_sdk/property_inspector/objs/month.py +++ /dev/null @@ -1,59 +0,0 @@ -from string import Template -from typing import Optional - -from .base import BasePIElement - - -class Month(BasePIElement): - def __init__( - self, - label: str, - uid: str, - default_value: Optional[str] = None, - ): - self.label = label - self.default_value = default_value - self.uid = uid - self.js_el_const = f"{self.uid}_el" - self.onchange = f"onchange_{self.uid}" - - def get_html_element(self) -> str: - value = f'value="{self.default_value}"' if {self.default_value} else "" - - res = f""" -
-
{self.label}
- -
- """ - return res - - def get_js_code(self) -> str: - template = Template(""" - const ${onchange} = () => { - console.log(${js_el_const}.value); - settings["${uid}"] = ${js_el_const}.value; - $$PI.setSettings(settings); - } - """) - - res = template.substitute(onchange=self.onchange, uid=self.uid, js_el_const=self.js_el_const) - return res - - def get_on_connect_js(self) -> str: - template = Template(""" - if (settings["${uid}"] !== undefined) { - ${js_el_const}.value = settings.${uid} - } else { - settings["${uid}"] = ${js_el_const}.value - } - """) - res = template.substitute(uid=self.uid, js_el_const=self.js_el_const) - - return res - - def get_js_consts(self) -> str: - res = f""" - const {self.js_el_const} = document.getElementById("{self.uid}") - """ - return res diff --git a/streamdeck_sdk/property_inspector/objs/password.py b/streamdeck_sdk/property_inspector/objs/password.py deleted file mode 100644 index 2c36958..0000000 --- a/streamdeck_sdk/property_inspector/objs/password.py +++ /dev/null @@ -1,66 +0,0 @@ -from string import Template - -from .base import BasePIElement - - -class Password(BasePIElement): - def __init__( - self, - label: str, - uid: str, - required: bool = False, - pattern: str = "", - placeholder: str = "", - default_value: str = "", - ): - self.label = label - self.placeholder = placeholder - self.required = required - self.pattern = pattern - self.default_value = default_value - self.uid = uid - self.js_el_const = f"{self.uid}_el" - self.onchange = f"onchange_{self.uid}" - - def get_html_element(self) -> str: - required = "required" if self.required else "" - pattern = f'pattern="{self.pattern}"' if self.pattern else "" - - res = f""" -
-
{self.label}
- -
- """ - return res - - def get_js_code(self) -> str: - template = Template(""" - const ${onchange} = () => { - console.log(${js_el_const}.value); - settings["${uid}"] = ${js_el_const}.value; - $$PI.setSettings(settings); - } - """) - - res = template.substitute(onchange=self.onchange, uid=self.uid, js_el_const=self.js_el_const) - return res - - def get_on_connect_js(self) -> str: - template = Template(""" - if (settings["${uid}"] !== undefined) { - ${js_el_const}.value = settings.${uid} - } else { - settings["${uid}"] = ${js_el_const}.value - } - """) - res = template.substitute(uid=self.uid, js_el_const=self.js_el_const) - - return res - - def get_js_consts(self) -> str: - res = f""" - const {self.js_el_const} = document.getElementById("{self.uid}") - """ - return res diff --git a/streamdeck_sdk/property_inspector/objs/progress.py b/streamdeck_sdk/property_inspector/objs/progress.py deleted file mode 100644 index c6fba9b..0000000 --- a/streamdeck_sdk/property_inspector/objs/progress.py +++ /dev/null @@ -1,60 +0,0 @@ -from string import Template -from typing import Optional - -from .base import BasePIElement - - -class Progress(BasePIElement): - def __init__( - self, - label: str, - uid: str, - max_value: float = 1, - default_value: float = 0, - left_label: Optional[str] = None, - right_label: Optional[str] = None, - ): - self.left_label = left_label - self.right_label = right_label - self.max_value = max_value - self.label = label - self.default_value = default_value - self.uid = uid - self.js_el_const = f"{self.uid}_el" - self.onchange = f"onchange_{self.uid}" - - def get_html_element(self) -> str: - left_label = f"{self.left_label}" if self.left_label else "" - right_label = f"{self.right_label}" if self.right_label else "" - - res = f""" -
-
{self.label}
- {left_label} - - - {right_label} -
- """ - return res - - def get_js_code(self) -> str: - return "" - - def get_on_connect_js(self) -> str: - template = Template(""" - if (settings["${uid}"] !== undefined) { - ${js_el_const}.value = settings.${uid} - } else { - settings["${uid}"] = ${js_el_const}.value - } - """) - res = template.substitute(uid=self.uid, js_el_const=self.js_el_const) - - return res - - def get_js_consts(self) -> str: - res = f""" - const {self.js_el_const} = document.getElementById("{self.uid}") - """ - return res diff --git a/streamdeck_sdk/property_inspector/objs/radio.py b/streamdeck_sdk/property_inspector/objs/radio.py deleted file mode 100644 index b4b1f70..0000000 --- a/streamdeck_sdk/property_inspector/objs/radio.py +++ /dev/null @@ -1,91 +0,0 @@ -from string import Template -from typing import List - -from .base import BasePIElement, BaseElement - - -class RadioItem(BaseElement): - def __init__( - self, - value: str, - label: str = "", - checked: bool = False, - ): - self.label = label - self.checked = checked - self.value = value - - def get_html_element(self, uid: str, name: str) -> str: - checked = "checked" if self.checked else "" - label = self.label if self.label else "" - - res = f""" - - - - - """ - return res - - -class Radio(BasePIElement): - def __init__( - self, - label: str, - uid: str, - items: List[RadioItem], - ): - self.label = label - self.items = items - self.uid = uid - - def get_html_element(self) -> str: - item_html_elements = [] - for index, item in enumerate(self.items): - item_uid = f"{self.uid}_item_{index}" - item_html_element = item.get_html_element(uid=item_uid, name=self.uid) - item_html_elements.append(item_html_element) - items = "\n".join(item_html_elements) - - res = f""" -
-
{self.label}
-
- {items} -
-
- """ - - return res - - def get_js_code(self) -> str: - template = Template(""" - document.addEventListener('input',(e)=>{ - if(e.target.getAttribute('name')==="${uid}") { - console.log(e.target.name, e.target.value) - settings["${uid}"] = e.target.value - $$PI.setSettings(settings);} - }) - """) - res = template.substitute(uid=self.uid) - return res - - def get_on_connect_js(self) -> str: - template = Template(""" - let ${uid}_el; - if (settings["${uid}"] !== undefined) { - ${uid}_el = document.querySelector(`input[type="radio"][name="${uid}"][value="$${settings.${uid}}"]`) - ${uid}_el.checked = true - } else { - ${uid}_el = document.querySelector('input[type="radio"][name="${uid}"]:checked') - settings["${uid}"] = ${uid}_el.value - } - """) - res = template.substitute(uid=self.uid) - return res - - def get_js_consts(self) -> str: - return "" diff --git a/streamdeck_sdk/property_inspector/objs/range.py b/streamdeck_sdk/property_inspector/objs/range.py deleted file mode 100644 index 76d2e3a..0000000 --- a/streamdeck_sdk/property_inspector/objs/range.py +++ /dev/null @@ -1,99 +0,0 @@ -from string import Template -from typing import List, Optional - -from .base import BasePIElement - - -class Range(BasePIElement): - def __init__( - self, - label: str, - uid: str, - max_value: float = 100, - min_value: float = 0, - default_value: float = 0, - step: Optional[float] = None, - left_label: Optional[str] = None, - right_label: Optional[str] = None, - datalist: Optional[List[str]] = None, - ): - if (right_label or left_label) and datalist: - raise ValueError("(right_label or left_label) and datalist are not supported together") - - self.step = step - self.left_label = left_label - self.right_label = right_label - self.max_value = max_value - self.min_value = min_value - self.label = label - self.default_value = default_value - self.uid = uid - self.js_el_const = f"{self.uid}_el" - self.onchange = f"onchange_{self.uid}" - self.datalist = datalist - - def get_html_element(self) -> str: - if not self.datalist: - datalist_class = "" - range_list = "" - datalist = "" - left_label = f"{self.left_label}" if self.left_label else "" - right_label = f"{self.right_label}" if self.right_label else "" - else: - datalist_class = " datalist" - datalist_id = f"{self.uid}datalist" - range_list = f' list="{datalist_id}"' - datalist_items = "\n".join([f'' for datalist_label in self.datalist]) - datalist = f""" - - {datalist_items} - - """ - left_label = "" - right_label = "" - - step = f' step="{self.step}"' if self.step else "" - - res = f""" -
-
{self.label}
-
- {left_label} - - {datalist} - {right_label} -
-
- """ - return res - - def get_js_code(self) -> str: - template = Template(""" - const ${onchange} = () => { - console.log(${js_el_const}.value); - settings["${uid}"] = ${js_el_const}.value; - $$PI.setSettings(settings); - } - """) - - res = template.substitute(onchange=self.onchange, uid=self.uid, js_el_const=self.js_el_const) - return res - - def get_on_connect_js(self) -> str: - template = Template(""" - if (settings["${uid}"] !== undefined) { - ${js_el_const}.value = settings.${uid} - } else { - settings["${uid}"] = ${js_el_const}.value - } - """) - res = template.substitute(uid=self.uid, js_el_const=self.js_el_const) - - return res - - def get_js_consts(self) -> str: - res = f""" - const {self.js_el_const} = document.getElementById("{self.uid}") - """ - return res diff --git a/streamdeck_sdk/property_inspector/objs/select.py b/streamdeck_sdk/property_inspector/objs/select.py deleted file mode 100644 index ee50524..0000000 --- a/streamdeck_sdk/property_inspector/objs/select.py +++ /dev/null @@ -1,115 +0,0 @@ -from string import Template -from typing import List, Optional - -from .base import BasePIElement - - -def remove_duplicates(strings): - seen = set() - result = [] - for string in strings: - if string not in seen: - seen.add(string) - result.append(string) - return result - - -class Select(BasePIElement): - def __init__( - self, - uid: str, - label: str, - values: List[str], - default_value: Optional[str] = None, - ): - """ - The value in the settings will look like: [["element 1", "element 2", ...], "selected element"] - """ - self.label = label - if default_value is not None and default_value not in values: - raise ValueError("default_value not in values") - self.values = remove_duplicates(values) - self.default_value = default_value - self.uid = uid - self.js_el_const = f"{self.uid}_el" - self.onchange = f"onchange_{self.uid}" - - def get_html_element(self) -> str: - default_exists = False - options = [] - for value in self.values: - if value == self.default_value: - default_exists = True - option = f'' - else: - option = f'' - options.append(option) - if default_exists: - null_option = '' - else: - null_option = '' - - options = "\n".join([null_option, *options]) - res = f""" -
-
{self.label}
- -
- """ - return res - - def get_js_code(self) -> str: - template = Template(""" - const ${onchange} = () => { - console.log(${js_el_const}.value); - let values_and_selected = get_select_values_and_selected( - ${js_el_const}, - ) - settings["${uid}"] = [ - values_and_selected.values, - values_and_selected.selected, - ] - $$PI.setSettings(settings); - } - """) - - res = template.substitute(onchange=self.onchange, uid=self.uid, js_el_const=self.js_el_const) - return res - - def get_on_connect_js(self) -> str: - template = Template(""" - if (settings["${uid}"] !== undefined) { - let update_result = update_select_options( - ${js_el_const}, - settings["${uid}"][0], - settings["${uid}"][1], - ) - if (!update_result) { - let values_and_selected = get_select_values_and_selected( - ${js_el_const}, - ) - settings["${uid}"] = [ - values_and_selected.values, - values_and_selected.selected, - ] - } - } else { - let values_and_selected = get_select_values_and_selected( - ${js_el_const}, - ) - settings["${uid}"] = [ - values_and_selected.values, - values_and_selected.selected, - ] - } - """) - res = template.substitute(uid=self.uid, js_el_const=self.js_el_const) - return res - - def get_js_consts(self) -> str: - res = f""" - const {self.js_el_const} = document.getElementById("{self.uid}") - """ - return res diff --git a/streamdeck_sdk/property_inspector/objs/textarea.py b/streamdeck_sdk/property_inspector/objs/textarea.py deleted file mode 100644 index f6b9c31..0000000 --- a/streamdeck_sdk/property_inspector/objs/textarea.py +++ /dev/null @@ -1,67 +0,0 @@ -from string import Template -from typing import Optional - -from .base import BasePIElement - - -class Textarea(BasePIElement): - def __init__( - self, - label: str, - uid: str, - max_length: Optional[int] = None, - placeholder: str = "", - info_text: str = "", - ): - self.max_length = max_length - self.label = label - self.placeholder = placeholder - self.uid = uid - self.js_el_const = f"{self.uid}_el" - self.onchange = f"onchange_{self.uid}" - self.info_text = info_text - - def get_html_element(self) -> str: - max_length = f'maxlength="{self.max_length}"' if self.max_length is not None else "" - - res = f""" -
-
{self.label}
-
- - -
-
- """ - return res - - def get_js_code(self) -> str: - template = Template(""" - const ${onchange} = () => { - console.log(${js_el_const}.value); - settings["${uid}"] = ${js_el_const}.value; - $$PI.setSettings(settings); - } - """) - - res = template.substitute(onchange=self.onchange, uid=self.uid, js_el_const=self.js_el_const) - return res - - def get_on_connect_js(self) -> str: - template = Template(""" - if (settings["${uid}"] !== undefined) { - ${js_el_const}.value = settings.${uid} - } else { - settings["${uid}"] = ${js_el_const}.value - } - """) - res = template.substitute(uid=self.uid, js_el_const=self.js_el_const) - - return res - - def get_js_consts(self) -> str: - res = f""" - const {self.js_el_const} = document.getElementById("{self.uid}") - """ - return res diff --git a/streamdeck_sdk/property_inspector/objs/textfield.py b/streamdeck_sdk/property_inspector/objs/textfield.py deleted file mode 100644 index c009f2f..0000000 --- a/streamdeck_sdk/property_inspector/objs/textfield.py +++ /dev/null @@ -1,66 +0,0 @@ -from string import Template - -from .base import BasePIElement - - -class Textfield(BasePIElement): - def __init__( - self, - label: str, - uid: str, - required: bool = False, - pattern: str = "", - placeholder: str = "", - default_value: str = "", - ): - self.label = label - self.placeholder = placeholder - self.required = required - self.pattern = pattern - self.default_value = default_value - self.uid = uid - self.js_el_const = f"{self.uid}_el" - self.onchange = f"onchange_{self.uid}" - - def get_html_element(self) -> str: - required = "required" if self.required else "" - pattern = f'pattern="{self.pattern}"' if self.pattern else "" - - res = f""" -
-
{self.label}
- -
- """ - return res - - def get_js_code(self) -> str: - template = Template(""" - const ${onchange} = () => { - console.log(${js_el_const}.value); - settings["${uid}"] = ${js_el_const}.value; - $$PI.setSettings(settings); - } - """) - - res = template.substitute(onchange=self.onchange, uid=self.uid, js_el_const=self.js_el_const) - return res - - def get_on_connect_js(self) -> str: - template = Template(""" - if (settings["${uid}"] !== undefined) { - ${js_el_const}.value = settings.${uid} - } else { - settings["${uid}"] = ${js_el_const}.value - } - """) - res = template.substitute(uid=self.uid, js_el_const=self.js_el_const) - - return res - - def get_js_consts(self) -> str: - res = f""" - const {self.js_el_const} = document.getElementById("{self.uid}") - """ - return res diff --git a/streamdeck_sdk/property_inspector/objs/time_obj.py b/streamdeck_sdk/property_inspector/objs/time_obj.py deleted file mode 100644 index d2fc414..0000000 --- a/streamdeck_sdk/property_inspector/objs/time_obj.py +++ /dev/null @@ -1,59 +0,0 @@ -from string import Template -from typing import Optional - -from .base import BasePIElement - - -class Time(BasePIElement): - def __init__( - self, - label: str, - uid: str, - default_value: Optional[str] = None, - ): - self.label = label - self.default_value = default_value - self.uid = uid - self.js_el_const = f"{self.uid}_el" - self.onchange = f"onchange_{self.uid}" - - def get_html_element(self) -> str: - value = f'value="{self.default_value}"' if {self.default_value} else "" - - res = f""" -
-
{self.label}
- -
- """ - return res - - def get_js_code(self) -> str: - template = Template(""" - const ${onchange} = () => { - console.log(${js_el_const}.value); - settings["${uid}"] = ${js_el_const}.value; - $$PI.setSettings(settings); - } - """) - - res = template.substitute(onchange=self.onchange, uid=self.uid, js_el_const=self.js_el_const) - return res - - def get_on_connect_js(self) -> str: - template = Template(""" - if (settings["${uid}"] !== undefined) { - ${js_el_const}.value = settings.${uid} - } else { - settings["${uid}"] = ${js_el_const}.value - } - """) - res = template.substitute(uid=self.uid, js_el_const=self.js_el_const) - - return res - - def get_js_consts(self) -> str: - res = f""" - const {self.js_el_const} = document.getElementById("{self.uid}") - """ - return res diff --git a/streamdeck_sdk/property_inspector/objs/week.py b/streamdeck_sdk/property_inspector/objs/week.py deleted file mode 100644 index e483853..0000000 --- a/streamdeck_sdk/property_inspector/objs/week.py +++ /dev/null @@ -1,59 +0,0 @@ -from string import Template -from typing import Optional - -from .base import BasePIElement - - -class Week(BasePIElement): - def __init__( - self, - label: str, - uid: str, - default_value: Optional[str] = None, - ): - self.label = label - self.default_value = default_value - self.uid = uid - self.js_el_const = f"{self.uid}_el" - self.onchange = f"onchange_{self.uid}" - - def get_html_element(self) -> str: - value = f'value="{self.default_value}"' if {self.default_value} else "" - - res = f""" -
-
{self.label}
- -
- """ - return res - - def get_js_code(self) -> str: - template = Template(""" - const ${onchange} = () => { - console.log(${js_el_const}.value); - settings["${uid}"] = ${js_el_const}.value; - $$PI.setSettings(settings); - } - """) - - res = template.substitute(onchange=self.onchange, uid=self.uid, js_el_const=self.js_el_const) - return res - - def get_on_connect_js(self) -> str: - template = Template(""" - if (settings["${uid}"] !== undefined) { - ${js_el_const}.value = settings.${uid} - } else { - settings["${uid}"] = ${js_el_const}.value - } - """) - res = template.substitute(uid=self.uid, js_el_const=self.js_el_const) - - return res - - def get_js_consts(self) -> str: - res = f""" - const {self.js_el_const} = document.getElementById("{self.uid}") - """ - return res diff --git a/streamdeck_sdk/property_inspector/property_inspector.py b/streamdeck_sdk/property_inspector/property_inspector.py deleted file mode 100644 index a4c06fc..0000000 --- a/streamdeck_sdk/property_inspector/property_inspector.py +++ /dev/null @@ -1,64 +0,0 @@ -from pathlib import Path -from typing import List - -from .objs.base import BasePIElement - - -class PropertyInspector: - def __init__( - self, - action_uuid: str, - elements: List["BasePIElement"], - ): - self.action_uuid = action_uuid - self.action_name = self.action_uuid.split(".")[-1] - self.elements = elements - - def build(self, output_dir: Path, template: Path): - html_elements = "\n".join([element.get_html_element() for element in self.elements]) - html_elements = "\n".join([line for line in html_elements.splitlines() if line.strip() != ""]) - - js_code = "\n".join([element.get_js_code() for element in self.elements]) - js_code = "\n".join([line for line in js_code.splitlines() if line.strip() != ""]) - - html_element_js_const = "\n".join([element.get_js_consts() for element in self.elements]) - html_element_js_const = "\n".join([line for line in html_element_js_const.splitlines() if line.strip() != ""]) - - on_connect_js = "\n".join([element.get_on_connect_js() for element in self.elements]) - on_connect_js = "\n".join([line for line in on_connect_js.splitlines() if line.strip() != ""]) - - on_did_receive_settings_js = "\n".join([element.get_on_did_receive_settings_js() for element in self.elements]) - on_did_receive_settings_js = "\n".join( - [line for line in on_did_receive_settings_js.splitlines() if line.strip() != ""] - ) - - with open(template, "r") as f: - index_template_text = f.read() - - res_text = index_template_text.replace( - "", - html_elements, - ) - res_text = res_text.replace( - "", - js_code, - ) - res_text = res_text.replace( - "", - html_element_js_const, - ) - res_text = res_text.replace( - "", - on_connect_js, - ) - res_text = res_text.replace( - "YOUR_ACTION_UUID", - self.action_uuid, - ) - res_text = res_text.replace( - "// YOUR_ON_DID_RECEIVE_SETTINGS_JS", - on_did_receive_settings_js - ) - - with open(output_dir / f"{self.action_name}_pi.html", "w") as f: - f.write(res_text) diff --git a/streamdeck_sdk/sd_objs/__init__.py b/streamdeck_sdk/sd_objs/__init__.py deleted file mode 100644 index 8b029ce..0000000 --- a/streamdeck_sdk/sd_objs/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from . import events_received_objs -from . import events_sent_objs -from . import registration_objs diff --git a/streamdeck_sdk/sd_objs/events_received_objs/__init__.py b/streamdeck_sdk/sd_objs/events_received_objs/__init__.py deleted file mode 100644 index e7da765..0000000 --- a/streamdeck_sdk/sd_objs/events_received_objs/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -from .application_did_launch import * -from .application_did_terminate import * -from .assets.controller_enum import * -from .assets.key_coordinates import * -from .device_did_connect import * -from .device_did_disconnect import * -from .dial_down import * -from .dial_rotate import * -from .dial_up import * -from .did_receive_deep_link import * -from .did_receive_global_settings import * -from .did_receive_settings import * -from .key_down import * -from .key_up import * -from .property_inspector_did_appear import * -from .property_inspector_did_disappear import * -from .send_to_plugin import * -from .send_to_property_inspector import * -from .system_did_wake_up import * -from .title_parameters_did_change import * -from .touch_tap import * -from .will_appear import * -from .will_disappear import * diff --git a/streamdeck_sdk/sd_objs/events_received_objs/application_did_launch.py b/streamdeck_sdk/sd_objs/events_received_objs/application_did_launch.py deleted file mode 100644 index 9bc289f..0000000 --- a/streamdeck_sdk/sd_objs/events_received_objs/application_did_launch.py +++ /dev/null @@ -1,25 +0,0 @@ -from pydantic import BaseModel - - -class ApplicationDidLaunchPayload(BaseModel): - """ - application: The identifier of the application that has been launched. - """ - application: str - - -class ApplicationDidLaunch(BaseModel): - """ - A plugin can request in its manifest.json to be notified when some applications are launched or - terminated. The manifest.json should contain an ApplicationsToMonitor object specifying the list of - application identifiers to monitor. On macOS, the application bundle identifier is used while the exe - filename is used on Windows. - For example, the Apple Mail: "application": "com.apple.mail" - - event: applicationDidLaunch - payload: A JSON object - - https://docs.elgato.com/sdk/plugins/events-received#applicationdidlaunch - """ - payload: ApplicationDidLaunchPayload - event: str = "applicationDidLaunch" diff --git a/streamdeck_sdk/sd_objs/events_received_objs/application_did_terminate.py b/streamdeck_sdk/sd_objs/events_received_objs/application_did_terminate.py deleted file mode 100644 index 1fe7d94..0000000 --- a/streamdeck_sdk/sd_objs/events_received_objs/application_did_terminate.py +++ /dev/null @@ -1,25 +0,0 @@ -from pydantic import BaseModel - - -class ApplicationDidTerminatePayload(BaseModel): - """ - application: The identifier of the application that has been terminated. - """ - application: str - - -class ApplicationDidTerminate(BaseModel): - """ - A plugin can request in its manifest.json to be notified when some applications are launched - or terminated. The manifest.json should contain an ApplicationsToMonitor - object specifying the list of application identifiers to monitor. On macOS, the application bundle - identifier is used while the exe filename is used on Windows. - For example, the Apple Mail: "application": "com.apple.mail" - - event: applicationDidTerminate - payload: A JSON object - - https://docs.elgato.com/sdk/plugins/events-received#applicationdidterminate - """ - payload: ApplicationDidTerminatePayload - event: str = "applicationDidTerminate" diff --git a/streamdeck_sdk/sd_objs/events_received_objs/assets/__init__.py b/streamdeck_sdk/sd_objs/events_received_objs/assets/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/streamdeck_sdk/sd_objs/events_received_objs/assets/controller_enum.py b/streamdeck_sdk/sd_objs/events_received_objs/assets/controller_enum.py deleted file mode 100644 index 09d8b5c..0000000 --- a/streamdeck_sdk/sd_objs/events_received_objs/assets/controller_enum.py +++ /dev/null @@ -1,9 +0,0 @@ -from enum import Enum - - -class ControllerEnum(str, Enum): - """ - Types of controller. - """ - KEYPAD = "Keypad" - ENCODER = "Encoder" diff --git a/streamdeck_sdk/sd_objs/events_received_objs/assets/key_coordinates.py b/streamdeck_sdk/sd_objs/events_received_objs/assets/key_coordinates.py deleted file mode 100644 index aa3e1e9..0000000 --- a/streamdeck_sdk/sd_objs/events_received_objs/assets/key_coordinates.py +++ /dev/null @@ -1,9 +0,0 @@ -from pydantic import BaseModel - - -class KeyCoordinates(BaseModel): - """ - The coordinates of the action triggered. - """ - column: int - row: int diff --git a/streamdeck_sdk/sd_objs/events_received_objs/device_did_connect.py b/streamdeck_sdk/sd_objs/events_received_objs/device_did_connect.py deleted file mode 100644 index 6e09514..0000000 --- a/streamdeck_sdk/sd_objs/events_received_objs/device_did_connect.py +++ /dev/null @@ -1,37 +0,0 @@ -from pydantic import BaseModel - - -class DeviceDidConnectDeviceInfoSize(BaseModel): - """ - The number of columns and rows of keys that the device owns. - """ - columns: int - rows: int - - -class DeviceDidConnectDeviceInfo(BaseModel): - """ - type: Type of device. Possible values are kESDSDKDeviceType_StreamDeck (0), - kESDSDKDeviceType_StreamDeckMini (1), kESDSDKDeviceType_StreamDeckXL (2), - kESDSDKDeviceType_StreamDeckMobile (3) and kESDSDKDeviceType_CorsairGKeys (4). - size: The number of columns and rows of keys that the device owns. - name: The name of the device set by the user. - """ - name: str - type: int - size: DeviceDidConnectDeviceInfoSize - - -class DeviceDidConnect(BaseModel): - """ - When a device is plugged into the computer, the plugin will receive a deviceDidConnect event. - - event: deviceDidConnect - device: A value to identify the device. - deviceInfo: A JSON object containing information about the device. - - https://docs.elgato.com/sdk/plugins/events-received#devicedidconnect - """ - device: str - deviceInfo: DeviceDidConnectDeviceInfo - event: str = "deviceDidConnect" diff --git a/streamdeck_sdk/sd_objs/events_received_objs/device_did_disconnect.py b/streamdeck_sdk/sd_objs/events_received_objs/device_did_disconnect.py deleted file mode 100644 index 4bc4c58..0000000 --- a/streamdeck_sdk/sd_objs/events_received_objs/device_did_disconnect.py +++ /dev/null @@ -1,14 +0,0 @@ -from pydantic import BaseModel - - -class DeviceDidDisconnect(BaseModel): - """ - When a device is unplugged from the computer, the plugin will receive a deviceDidDisconnect event. - - event: deviceDidDisconnect - device: A value to identify the device. - - https://docs.elgato.com/sdk/plugins/events-received#devicediddisconnect - """ - device: str - event: str = "deviceDidDisconnect" diff --git a/streamdeck_sdk/sd_objs/events_received_objs/dial_down.py b/streamdeck_sdk/sd_objs/events_received_objs/dial_down.py deleted file mode 100644 index 68c2c93..0000000 --- a/streamdeck_sdk/sd_objs/events_received_objs/dial_down.py +++ /dev/null @@ -1,37 +0,0 @@ -from pydantic import BaseModel - -from .assets.controller_enum import ControllerEnum -from .assets.key_coordinates import KeyCoordinates - - -class DialDownPayload(BaseModel): - """ - settings: This JSON object contains data that you can set and are stored persistently. - coordinates: The coordinates of the action triggered. - controller: Encoder. - """ - settings: dict - coordinates: KeyCoordinates - controller: ControllerEnum = ControllerEnum.ENCODER - - -class DialDown(BaseModel): - """ - (SD+) - When the user presses the encoder down, the plugin will receive the dialDown event (SD+). - - action: The action's unique identifier. If your plugin supports multiple actions, - you should use this value to see which action was triggered. - event: dialDown - context: A value identifying the instance's action. You will need to pass this - opaque value to several APIs like the setTitle API. - device: A value to identify the device. - payload: A JSON object - - https://docs.elgato.com/sdk/plugins/events-received#dialdown-sd - """ - action: str - context: str - device: str - payload: DialDownPayload - event: str = "dialDown" diff --git a/streamdeck_sdk/sd_objs/events_received_objs/dial_rotate.py b/streamdeck_sdk/sd_objs/events_received_objs/dial_rotate.py deleted file mode 100644 index 22b1db0..0000000 --- a/streamdeck_sdk/sd_objs/events_received_objs/dial_rotate.py +++ /dev/null @@ -1,42 +0,0 @@ -from pydantic import BaseModel - -from .assets.controller_enum import ControllerEnum -from .assets.key_coordinates import KeyCoordinates - - -class DialRotatePayload(BaseModel): - """ - settings: This JSON object contains data that you can set and are stored persistently. - controller: Encoder. - coordinates: The coordinates of the action triggered. - ticks: The integer which holds the number of "ticks" on encoder rotation. Positive values are for clockwise - rotation, negative values are for counterclockwise rotation, zero value is never happen. - pressed: Boolean which is true on rotation when encoder pressed. - """ - settings: dict - coordinates: KeyCoordinates - ticks: int - pressed: bool - controller: ControllerEnum = ControllerEnum.ENCODER - - -class DialRotate(BaseModel): - """ - (SD+) - When the user rotates the encoder, the plugin will receive the dialRotate event. - - action: The action's unique identifier. If your plugin supports multiple actions, you should use this value - to see which action was triggered. - event: dialRotate - context: A value identifying the instance's action. You will need to pass this opaque value to - several APIs like the setTitle API. - device: A value to identify the device. - payload: A JSON object. - - https://docs.elgato.com/sdk/plugins/events-received#dialrotate-sd - """ - action: str - context: str - device: str - payload: DialRotatePayload - event: str = "dialRotate" diff --git a/streamdeck_sdk/sd_objs/events_received_objs/dial_up.py b/streamdeck_sdk/sd_objs/events_received_objs/dial_up.py deleted file mode 100644 index 4bae225..0000000 --- a/streamdeck_sdk/sd_objs/events_received_objs/dial_up.py +++ /dev/null @@ -1,37 +0,0 @@ -from pydantic import BaseModel - -from .assets.controller_enum import ControllerEnum -from .assets.key_coordinates import KeyCoordinates - - -class DialUpPayload(BaseModel): - """ - settings: This JSON object contains data that you can set and are stored persistently. - coordinates: The coordinates of the action triggered. - controller: Encoder. - """ - settings: dict - coordinates: KeyCoordinates - controller: ControllerEnum = ControllerEnum.ENCODER - - -class DialUp(BaseModel): - """ - (SD+) - When the user releases a pressed encoder, the plugin will receive the dialUp event (SD+). - - action: The action's unique identifier. If your plugin supports multiple actions, you should use this - value to see which action was triggered. - event: dialUp - context: A value identifying the instance's action. You will need to pass this opaque value to - several APIs like the setTitle API. - device: A value to identify the device. - payload: A JSON object - - https://docs.elgato.com/sdk/plugins/events-received#dialup-sd - """ - action: str - context: str - device: str - payload: DialUpPayload - event: str = "dialUp" diff --git a/streamdeck_sdk/sd_objs/events_received_objs/did_receive_deep_link.py b/streamdeck_sdk/sd_objs/events_received_objs/did_receive_deep_link.py deleted file mode 100644 index 743bb73..0000000 --- a/streamdeck_sdk/sd_objs/events_received_objs/did_receive_deep_link.py +++ /dev/null @@ -1,27 +0,0 @@ -from pydantic import BaseModel - - -class DidReceiveDeepLinkPayload(BaseModel): - """ - url: The deep-link URL, with the prefix omitted. For example - the URL streamdeck://plugins/message/com.elgato.test/hello-world would result in a url of hello-world. - """ - url: str - - -class DidReceiveDeepLink(BaseModel): - """ - ! Available from Stream Deck 6.5 onwards. - - Occurs when Stream Deck receives a deep-link message intended for the plugin. - The message is re-routed to the plugin, and provided as part of the payload. - One-way deep-link message can be routed to the plugin using the URL format: - streamdeck://plugins/message//{MESSAGE} - - event: didReceiveDeepLink - payload: A JSON object - - https://docs.elgato.com/sdk/plugins/events-received#didreceivedeeplink - """ - payload: DidReceiveDeepLinkPayload - event: str = "didReceiveDeepLink" diff --git a/streamdeck_sdk/sd_objs/events_received_objs/did_receive_global_settings.py b/streamdeck_sdk/sd_objs/events_received_objs/did_receive_global_settings.py deleted file mode 100644 index b963858..0000000 --- a/streamdeck_sdk/sd_objs/events_received_objs/did_receive_global_settings.py +++ /dev/null @@ -1,19 +0,0 @@ -from pydantic import BaseModel - - -class DidReceiveGlobalSettingsPayload(BaseModel): - settings: dict - - -class DidReceiveGlobalSettings(BaseModel): - """ - The didReceiveGlobalSettings event is received after calling the getGlobalSettings API - to retrieve the global persistent data stored for the plugin. - - event: didReceiveGlobalSettings - payload: A JSON object - - https://docs.elgato.com/sdk/plugins/events-received#didreceiveglobalsettings - """ - payload: DidReceiveGlobalSettingsPayload - event: str = "didReceiveGlobalSettings" diff --git a/streamdeck_sdk/sd_objs/events_received_objs/did_receive_settings.py b/streamdeck_sdk/sd_objs/events_received_objs/did_receive_settings.py deleted file mode 100644 index 01f67bf..0000000 --- a/streamdeck_sdk/sd_objs/events_received_objs/did_receive_settings.py +++ /dev/null @@ -1,39 +0,0 @@ -from typing import Optional - -from pydantic import BaseModel - -from .assets.key_coordinates import KeyCoordinates - - -class DidReceiveSettingsPayload(BaseModel): - """ - settings: This JSON object contains persistently stored data. - coordinates: The coordinates of the action triggered. - state: Only set when the action has multiple states defined in its manifest.json. The 0-based - value contains the current state of the action. - isInMultiAction: Boolean indicating if the action is inside a Multi-Action. - """ - settings: dict - coordinates: KeyCoordinates - isInMultiAction: bool - state: Optional[int] = None - - -class DidReceiveSettings(BaseModel): - """ - The didReceiveSettings event is received after calling the getSettings API - to retrieve the persistent data stored for the action. - - action: The action's unique identifier. - event: didReceiveSettings - context: A value identifying the instance's action. - device: A value to identify the device. - payload: A JSON object - - https://docs.elgato.com/sdk/plugins/events-received#didreceivesettings - """ - action: str - context: str - device: str - payload: DidReceiveSettingsPayload - event: str = "didReceiveSettings" diff --git a/streamdeck_sdk/sd_objs/events_received_objs/key_down.py b/streamdeck_sdk/sd_objs/events_received_objs/key_down.py deleted file mode 100644 index c935ec0..0000000 --- a/streamdeck_sdk/sd_objs/events_received_objs/key_down.py +++ /dev/null @@ -1,44 +0,0 @@ -from typing import Optional - -from pydantic import BaseModel - -from .assets.key_coordinates import KeyCoordinates - - -class KeyDownPayload(BaseModel): - """ - settings: This JSON object contains data that you can set and are stored persistently. - coordinates: The coordinates of the action triggered. - state: Only set when the action has multiple states defined in its manifest.json. The 0-based value - contains the current state of the action. - userDesiredState: Only set when the action is triggered with a specific value from a - Multi-Action. For example, if the user sets the Game Capture Record action to be disabled in - a Multi-Action, you would see the value 1. 0 and 1 are valid. - isInMultiAction: Boolean indicating if the action is inside a Multi-Action. - """ - settings: dict - isInMultiAction: bool - coordinates: Optional[KeyCoordinates] = None - state: Optional[int] = None - userDesiredState: Optional[int] = None - - -class KeyDown(BaseModel): - """ - When the user presses a key, the plugin will receive the keyDown event. - - action: The action's unique identifier. If your plugin supports multiple actions, you should use this value - to see which action was triggered. - event: keyDown - context: A value identifying the instance's action. You will need to pass this opaque value to - several APIs like the setTitle API. - device: A value to identify the device. - payload: A JSON object. - - https://docs.elgato.com/sdk/plugins/events-received#keydown - """ - action: str - context: str - device: str - payload: KeyDownPayload - event: str = "keyDown" diff --git a/streamdeck_sdk/sd_objs/events_received_objs/key_up.py b/streamdeck_sdk/sd_objs/events_received_objs/key_up.py deleted file mode 100644 index 5c4e71b..0000000 --- a/streamdeck_sdk/sd_objs/events_received_objs/key_up.py +++ /dev/null @@ -1,44 +0,0 @@ -from typing import Optional - -from pydantic import BaseModel - -from .assets.key_coordinates import KeyCoordinates - - -class KeyUpPayload(BaseModel): - """ - settings: This JSON object contains data that you can set and is stored persistently. - coordinates: The coordinates of the action triggered. - state: Only set when the action has multiple states defined in its manifest.json. The 0-based value contains - the current state of the action. - userDesiredState: Only set when the action is triggered with a specific value from a Multi-Action. For - example, if the user sets the Game Capture Record action to be disabled in a Multi-Action, you would see the - value 1. 0 and 1 are valid. - isInMultiAction: Boolean indicating if the action is inside a Multi-Action. - """ - settings: dict - isInMultiAction: bool - state: Optional[int] = None - coordinates: Optional[KeyCoordinates] = None - userDesiredState: Optional[int] = None - - -class KeyUp(BaseModel): - """ - When the user releases a key, the plugin will receive the keyUp event. - - action: The action's unique identifier. If your plugin supports multiple actions, you should use this value - to find out which action was triggered. - event: keyUp - context: A value to identify the instance's action. You will need to pass this opaque value - to several APIs like the setTitle API. - device: A value to identify the device. - payload: A JSON object - - https://docs.elgato.com/sdk/plugins/events-received#keyup - """ - action: str - context: str - device: str - payload: KeyUpPayload - event: str = "keyUp" diff --git a/streamdeck_sdk/sd_objs/events_received_objs/property_inspector_did_appear.py b/streamdeck_sdk/sd_objs/events_received_objs/property_inspector_did_appear.py deleted file mode 100644 index ff1fc40..0000000 --- a/streamdeck_sdk/sd_objs/events_received_objs/property_inspector_did_appear.py +++ /dev/null @@ -1,19 +0,0 @@ -from pydantic import BaseModel - - -class PropertyInspectorDidAppear(BaseModel): - """ - The plugin will receive a propertyInspectorDidAppear event when the Property Inspector appears. - * This API has been introduced in Stream Deck 4.1. - - action: The action's unique identifier. - event: propertyInspectorDidAppear - context: A value to identify the instance's action. - device: A value to identify the device. - - https://docs.elgato.com/sdk/plugins/events-received#propertyinspectordidappear - """ - action: str - context: str - device: str - event: str = "propertyInspectorDidAppear" diff --git a/streamdeck_sdk/sd_objs/events_received_objs/property_inspector_did_disappear.py b/streamdeck_sdk/sd_objs/events_received_objs/property_inspector_did_disappear.py deleted file mode 100644 index 2a56825..0000000 --- a/streamdeck_sdk/sd_objs/events_received_objs/property_inspector_did_disappear.py +++ /dev/null @@ -1,18 +0,0 @@ -from pydantic import BaseModel - - -class PropertyInspectorDidDisappear(BaseModel): - """ - The plugin will receive a propertyInspectorDidDisappear event when the Property Inspector disappears. - - action: The action's unique identifier. - event: propertyInspectorDidDisappear - context: A value to identify the instance's action. - device: A value to identify the device. - - https://docs.elgato.com/sdk/plugins/events-received#propertyinspectordiddisappear - """ - action: str - context: str - device: str - event: str = "propertyInspectorDidDisappear" diff --git a/streamdeck_sdk/sd_objs/events_received_objs/send_to_plugin.py b/streamdeck_sdk/sd_objs/events_received_objs/send_to_plugin.py deleted file mode 100644 index 48c6542..0000000 --- a/streamdeck_sdk/sd_objs/events_received_objs/send_to_plugin.py +++ /dev/null @@ -1,18 +0,0 @@ -from pydantic import BaseModel - - -class SendToPlugin(BaseModel): - """ - The plugin will receive a sendToPlugin event when the Property Inspector sends a sendToPlugin event. - - action: The action's unique identifier. - context: A value to identify the instance's action. - payload: A JSON object - event: sendToPlugin - - https://docs.elgato.com/sdk/plugins/events-received#sendtoplugin - """ - action: str - context: str - payload: dict - event: str = "sendToPlugin" diff --git a/streamdeck_sdk/sd_objs/events_received_objs/send_to_property_inspector.py b/streamdeck_sdk/sd_objs/events_received_objs/send_to_property_inspector.py deleted file mode 100644 index b0f26c1..0000000 --- a/streamdeck_sdk/sd_objs/events_received_objs/send_to_property_inspector.py +++ /dev/null @@ -1,19 +0,0 @@ -from pydantic import BaseModel - - -class SendToPropertyInspector(BaseModel): - """ - The Property Inspector will receive a sendToPropertyInspector event when the plugin - sends a sendToPropertyInspector event. - - action: The action's unique identifier. - context: A value to identify the instance's action. - payload: A JSON object - event: sendToPropertyInspector - - https://docs.elgato.com/sdk/plugins/events-received#sendtopropertyinspector - """ - action: str - context: str - payload: dict - event: str = "sendToPropertyInspector" diff --git a/streamdeck_sdk/sd_objs/events_received_objs/system_did_wake_up.py b/streamdeck_sdk/sd_objs/events_received_objs/system_did_wake_up.py deleted file mode 100644 index c95d064..0000000 --- a/streamdeck_sdk/sd_objs/events_received_objs/system_did_wake_up.py +++ /dev/null @@ -1,16 +0,0 @@ -from pydantic import BaseModel - - -class SystemDidWakeUp(BaseModel): - """ - When the computer wakes up, the plugin will receive the systemDidWakeUp event. - Several important points to note: - * A plugin could get multiple systemDidWakeUp events when waking up the computer - * When the plugin receives the systemDidWakeUp event, there is no guarantee that the devices are available - * This API has been introduced in Stream Deck 4.3. - - event: systemDidWakeUp - - https://docs.elgato.com/sdk/plugins/events-received#systemdidwakeup - """ - event: str = "systemDidWakeUp" diff --git a/streamdeck_sdk/sd_objs/events_received_objs/title_parameters_did_change.py b/streamdeck_sdk/sd_objs/events_received_objs/title_parameters_did_change.py deleted file mode 100644 index 346be12..0000000 --- a/streamdeck_sdk/sd_objs/events_received_objs/title_parameters_did_change.py +++ /dev/null @@ -1,59 +0,0 @@ -from pydantic import BaseModel - -from .assets.key_coordinates import KeyCoordinates - - -class TitleParametersDidChangePayloadTitleParameters(BaseModel): - """ - fontFamily: The font family for the title. - fontSize: The font size for the title. - fontStyle: The font style for the title. - fontUnderline: Boolean indicating an underline under the title. - showTitle: Boolean indicating if the title is visible. - titleAlignment: Vertical alignment of the title. Possible values are "top", "bottom" and "middle". - titleColor: Title color. - """ - fontFamily: str - fontSize: int - fontStyle: str - fontUnderline: bool - showTitle: bool - titleAlignment: str - titleColor: str - - -class TitleParametersDidChangePayload(BaseModel): - """ - settings: This JSON object contains data that you can set and is stored persistently. - coordinates: The coordinates of the action triggered. - state: This value indicates which state of the action the title or title parameters have been changed. - title: The new title. - titleParameters: A JSON object describing the new title parameters. - """ - coordinates: KeyCoordinates - settings: dict - state: int - title: str - titleParameters: TitleParametersDidChangePayloadTitleParameters - - -class TitleParametersDidChange(BaseModel): - """ - When the user changes the title or title parameters of the instance of an action, the plugin will - receive a titleParametersDidChange event. - - action: The action's unique identifier. If your plugin supports multiple actions, you should use this value - to find out which action was triggered. - event: titleParametersDidChange - context: A value to identify the instance's action. You will need to pass this value to several APIs - like the setTitle API. - device: A value to identify the device. - payload: A JSON object - - https://docs.elgato.com/sdk/plugins/events-received#titleparametersdidchange - """ - action: str - context: str - device: str - payload: TitleParametersDidChangePayload - event: str = "titleParametersDidChange" diff --git a/streamdeck_sdk/sd_objs/events_received_objs/touch_tap.py b/streamdeck_sdk/sd_objs/events_received_objs/touch_tap.py deleted file mode 100644 index baac0fe..0000000 --- a/streamdeck_sdk/sd_objs/events_received_objs/touch_tap.py +++ /dev/null @@ -1,43 +0,0 @@ -from typing import Tuple - -from pydantic import BaseModel - -from .assets.controller_enum import ControllerEnum -from .assets.key_coordinates import KeyCoordinates - - -class TouchTapPayload(BaseModel): - """ - settings: This JSON object contains data that you can set and are stored persistently. - controller: Encoder. - coordinates: The coordinates of the action triggered. - tapPos: The array which holds (x, y) coordinates as a position of tap inside of LCD slot associated with action. - hold: Boolean which is true when long tap happened - """ - settings: dict - coordinates: KeyCoordinates - tapPos: Tuple[int, int] - hold: bool - controller: ControllerEnum = ControllerEnum.ENCODER - - -class TouchTap(BaseModel): - """ - (SD+) - When the user touches the display, the plugin will receive the touchTap event. - - action: The action's unique identifier. If your plugin supports multiple actions, - you should use this value to see which action was triggered. - event: touchTap - context: A value identifying the instance's action. You will need to pass this opaque - value to several APIs like the setTitle API. - device: A value to identify the device. - payload: A JSON object - - https://docs.elgato.com/sdk/plugins/events-received#touchtap-sd - """ - action: str - context: str - device: str - payload: TouchTapPayload - event: str = "touchTap" diff --git a/streamdeck_sdk/sd_objs/events_received_objs/will_appear.py b/streamdeck_sdk/sd_objs/events_received_objs/will_appear.py deleted file mode 100644 index adc77ac..0000000 --- a/streamdeck_sdk/sd_objs/events_received_objs/will_appear.py +++ /dev/null @@ -1,50 +0,0 @@ -from typing import Optional - -from pydantic import BaseModel - -from .assets.controller_enum import ControllerEnum -from .assets.key_coordinates import KeyCoordinates - - -class WillAppearPayload(BaseModel): - """ - settings: This JSON object contains data that you can set and are stored persistently. - coordinates: The coordinates of the action triggered. - controller: Defines the controller type the action is applicable to. Keypad refers to a standard action on - a Stream Deck device, e.g. 1 of the 15 buttons on the Stream Deck MK.2, or a pedal on the - Stream Deck Pedal, etc., whereas an Encoder refers to a dial / touchscreen on the Stream Deck+. - state: Only set when the action has multiple states defined in its manifest.json. The 0-based value - contains the current state of the action. - isInMultiAction: Boolean indicating if the action is inside a Multi-Action. - """ - settings: dict - isInMultiAction: bool - coordinates: Optional[KeyCoordinates] = None - state: Optional[int] = None - controller: Optional[ControllerEnum] = None - - -class WillAppear(BaseModel): - """ - When an instance of an action is displayed on Stream Deck, for example, when the hardware is first plugged - in or when a folder containing that action is entered, the plugin will receive a willAppear event. You will see - such an event when: - * the Stream Deck application is started - * the user switches between profiles - * the user sets a key to use your action - - action: The action's unique identifier. If your plugin supports multiple actions, you should use this value to - know which action was triggered. - event: willAppear - context: A value to identify the instance's action. You will need to pass this opaque value to several APIs - like the setTitle API. - device: A value to identify the device. - payload: A JSON object - - https://docs.elgato.com/sdk/plugins/events-received#willappear - """ - action: str - context: str - device: str - payload: WillAppearPayload - event: str = "willAppear" diff --git a/streamdeck_sdk/sd_objs/events_received_objs/will_disappear.py b/streamdeck_sdk/sd_objs/events_received_objs/will_disappear.py deleted file mode 100644 index 4b2619f..0000000 --- a/streamdeck_sdk/sd_objs/events_received_objs/will_disappear.py +++ /dev/null @@ -1,48 +0,0 @@ -from typing import Optional - -from pydantic import BaseModel - -from .assets.controller_enum import ControllerEnum -from .assets.key_coordinates import KeyCoordinates - - -class WillDisappearPayload(BaseModel): - """ - settings: This JSON object contains data that you can set and is stored persistently. - coordinates: The coordinates of the action triggered. - controller: Defines the controller type the action is applicable to. Keypad refers to a standard action - on a Stream Deck device, e.g. 1 of the 15 buttons on the Stream Deck MK.2, or a pedal on the Stream - Deck Pedal, etc., whereas an Encoder refers to a dial / touchscreen on the Stream Deck+. - state: Only set when the action has multiple states defined in its manifest.json. The 0-based value - contains the current state of the action. - isInMultiAction: Boolean indicating if the action is inside a Multi-Action. - """ - settings: dict - isInMultiAction: bool - coordinates: Optional[KeyCoordinates] = None - state: Optional[int] = None - controller: Optional[ControllerEnum] = None - - -class WillDisappear(BaseModel): - """ - When an instance of an action ceases to be displayed on Stream Deck, for example, when switching profiles - or folders, the plugin will receive a willDisappear event. You will see such an event when: - * the user switches between profiles - * the user deletes an action - - action: The action's unique identifier. If your plugin supports multiple actions, you should - use this value to find out which action was triggered. - event: willDisappear - context: A value to identify the instance's action. You will need to pass this opaque value - to several APIs like the setTitle API. - device: A value to identify the device. - payload: A JSON object - - https://docs.elgato.com/sdk/plugins/events-received#willdisappear - """ - action: str - context: str - device: str - payload: WillDisappearPayload - event: str = "willDisappear" diff --git a/streamdeck_sdk/sd_objs/events_sent_objs/__init__.py b/streamdeck_sdk/sd_objs/events_sent_objs/__init__.py deleted file mode 100644 index b5c8f6c..0000000 --- a/streamdeck_sdk/sd_objs/events_sent_objs/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -from .get_global_settings import * -from .get_settings import * -from .log_message import * -from .open_url import * -from .send_to_plugin import * -from .send_to_property_inspector import * -from .set_feedback import * -from .set_feedback_layout import * -from .set_global_settings import * -from .set_image import * -from .set_settings import * -from .set_state import * -from .set_title import * -from .set_trigger_description import * -from .show_alert import * -from .show_ok import * -from .switch_to_profile import * diff --git a/streamdeck_sdk/sd_objs/events_sent_objs/get_global_settings.py b/streamdeck_sdk/sd_objs/events_sent_objs/get_global_settings.py deleted file mode 100644 index bcd09ef..0000000 --- a/streamdeck_sdk/sd_objs/events_sent_objs/get_global_settings.py +++ /dev/null @@ -1,17 +0,0 @@ -from pydantic import BaseModel - - -class GetGlobalSettings(BaseModel): - """ - The plugin and Property Inspector can request the persistent global data using the getGlobalSettings event. - The plugin or Property Inspector will receive asynchronously an event didReceiveGlobalSettings the p - containing the global settings. - - event: getGlobalSettings - context: A value to Identify the plugin (inPluginUUID) or the Property Inspector (inPropertyInspectorUUID). This - value is received during the Registration procedure. - - https://docs.elgato.com/sdk/plugins/events-sent#getglobalsettings - """ - context: str - event: str = "getGlobalSettings" diff --git a/streamdeck_sdk/sd_objs/events_sent_objs/get_settings.py b/streamdeck_sdk/sd_objs/events_sent_objs/get_settings.py deleted file mode 100644 index 6482c7f..0000000 --- a/streamdeck_sdk/sd_objs/events_sent_objs/get_settings.py +++ /dev/null @@ -1,17 +0,0 @@ -from pydantic import BaseModel - - -class GetSettings(BaseModel): - """ - The plugin and Property Inspector can request the persistent data stored for the action's - instance using the getSettings event. - - event: getSettings - context: A value to Identify the instance's action or Property Inspector. In the case of - the Property Inspector, this value is received by the Property Inspector as parameter of - the connectElgatoStreamDeckSocket function. - - https://docs.elgato.com/sdk/plugins/events-sent#getsettings - """ - context: str - event: str = "getSettings" diff --git a/streamdeck_sdk/sd_objs/events_sent_objs/log_message.py b/streamdeck_sdk/sd_objs/events_sent_objs/log_message.py deleted file mode 100644 index 2e3901d..0000000 --- a/streamdeck_sdk/sd_objs/events_sent_objs/log_message.py +++ /dev/null @@ -1,24 +0,0 @@ -from pydantic import BaseModel - - -class LogMessagePayload(BaseModel): - """ - message: A string to write to the logs file. - """ - message: str - - -class LogMessage(BaseModel): - """ - The plugin and Property Inspector can use the logMessage event to write a debug message to the logs file. - * Logs are saved to disk per plugin in the folder ~/Library/Logs/ElgatoStreamDeck/ on macOS - and %appdata%\Elgato\StreamDeck\logs\ on Windows. Note that the log files are rotated each time - the Stream Deck application is relaunched. - - event: logMessage - payload: A JSON object - - https://docs.elgato.com/sdk/plugins/events-sent#logmessage - """ - payload: LogMessagePayload - event: str = "logMessage" diff --git a/streamdeck_sdk/sd_objs/events_sent_objs/open_url.py b/streamdeck_sdk/sd_objs/events_sent_objs/open_url.py deleted file mode 100644 index d769914..0000000 --- a/streamdeck_sdk/sd_objs/events_sent_objs/open_url.py +++ /dev/null @@ -1,22 +0,0 @@ -from pydantic import BaseModel - - -class OpenUrlPayload(BaseModel): - """ - url: An URL to open in the default browser. - """ - url: str - - -class OpenUrl(BaseModel): - """ - The plugin and Property Inspector can tell the Stream Deck application to open URL in the - default browser using the openUrl event. - - event: openUrl - payload: A JSON object - - https://docs.elgato.com/sdk/plugins/events-sent#openurl - """ - payload: OpenUrlPayload - event: str = "openUrl" diff --git a/streamdeck_sdk/sd_objs/events_sent_objs/send_to_plugin.py b/streamdeck_sdk/sd_objs/events_sent_objs/send_to_plugin.py deleted file mode 100644 index d95609d..0000000 --- a/streamdeck_sdk/sd_objs/events_sent_objs/send_to_plugin.py +++ /dev/null @@ -1,21 +0,0 @@ -from pydantic import BaseModel - - -class SendToPlugin(BaseModel): - """ - The Property Inspector can send a payload to the plugin using the sendToPlugin event. - The plugin will receive asynchronously an event sendToPlugin. - - action: The action's unique identifier. If your plugin supports multiple actions, you should use this value to - find out which action was triggered. - event: sendToPlugin - context: A value to Identify the Property Inspector. This value is received by the Property Inspector as parameter - of the connectElgatoStreamDeckSocket function. - payload: A JSON object that will be received by the plugin. - - https://docs.elgato.com/sdk/plugins/events-sent#sendtoplugin - """ - action: str - context: str - payload: dict - event: str = "sendToPlugin" diff --git a/streamdeck_sdk/sd_objs/events_sent_objs/send_to_property_inspector.py b/streamdeck_sdk/sd_objs/events_sent_objs/send_to_property_inspector.py deleted file mode 100644 index 9a51cf0..0000000 --- a/streamdeck_sdk/sd_objs/events_sent_objs/send_to_property_inspector.py +++ /dev/null @@ -1,19 +0,0 @@ -from pydantic import BaseModel - - -class SendToPropertyInspector(BaseModel): - """ - The plugin can send a payload to the Property Inspector using the sendToPropertyInspector event. - The Property Inspector will receive asynchronously an event sendToPropertyInspector. - - action: The action's unique identifier. - event: sendToPropertyInspector - context: A value to identify the instance's action. - payload: A JSON object that will be received by the Property Inspector. - - https://docs.elgato.com/sdk/plugins/events-sent#sendtopropertyinspector - """ - action: str - context: str - payload: dict - event: str = "sendToPropertyInspector" diff --git a/streamdeck_sdk/sd_objs/events_sent_objs/set_feedback.py b/streamdeck_sdk/sd_objs/events_sent_objs/set_feedback.py deleted file mode 100644 index 628f1a3..0000000 --- a/streamdeck_sdk/sd_objs/events_sent_objs/set_feedback.py +++ /dev/null @@ -1,20 +0,0 @@ -from pydantic import BaseModel - - -class SetFeedback(BaseModel): - """ - (SD+) - The plugin can send a setFeedback event to the Stream Deck application to dynamically change properties of - items on the Stream Deck + touch display layout. - - event: setFeedback - context: A value to Identify the instance's action you want to modify. - payload: A JSON object. - key: The key is a name of the element in layout to be changed with given value. - value: The value to be set in key named layout element - - https://docs.elgato.com/sdk/plugins/events-sent#setfeedback-sd - """ - context: str - payload: dict - event: str = "setFeedback" diff --git a/streamdeck_sdk/sd_objs/events_sent_objs/set_feedback_layout.py b/streamdeck_sdk/sd_objs/events_sent_objs/set_feedback_layout.py deleted file mode 100644 index 0596726..0000000 --- a/streamdeck_sdk/sd_objs/events_sent_objs/set_feedback_layout.py +++ /dev/null @@ -1,26 +0,0 @@ -from pydantic import BaseModel - - -class SetFeedbackLayoutPayload(BaseModel): - """ - layout: A predefined layout identifier or the relative path to a json file that contains a custom layout. - """ - layout: str - - -class SetFeedbackLayout(BaseModel): - """ - (SD+) - The plugin can send a setFeedbackLayout event to the Stream Deck application to dynamically change the - current Stream Deck + touch display layout. setFeedbackLayout can use the id of a built-in layout or - a relative path to a custom layout JSON file. See Layouts for more information. - - event: setFeedbackLayout - context: A value to Identify the instance's action you want to modify. - payload: Json - - https://docs.elgato.com/sdk/plugins/events-sent#setfeedbacklayout-sd - """ - context: str - payload: SetFeedbackLayoutPayload - event: str = "setFeedbackLayout" diff --git a/streamdeck_sdk/sd_objs/events_sent_objs/set_global_settings.py b/streamdeck_sdk/sd_objs/events_sent_objs/set_global_settings.py deleted file mode 100644 index 687666a..0000000 --- a/streamdeck_sdk/sd_objs/events_sent_objs/set_global_settings.py +++ /dev/null @@ -1,23 +0,0 @@ -from pydantic import BaseModel - - -class SetGlobalSettings(BaseModel): - """ - The plugin and Property Inspector can save persistent data globally. The data - will be saved securely to the Keychain on macOS and the Credential Store on Windows. This API can - be used to save tokens that should be available to every action in the plugin. - Note that when the plugin uses this API, the Property Inspector will automatically receive - a didReceiveGlobalSettings callback with the new settings. Similarly, when the Property Inspector uses - this API, the plugin will automatically receive a didReceiveGlobalSettings callback with the new settings. - This API has been introduced in Stream Deck 4.1. - - event: setGlobalSettings - context: A value to Identify the plugin (inPluginUUID) or the Property Inspector (inPropertyInspectorUUID). This - value is received during the Registration procedure. - payload: A JSON object which is persistently saved globally. - - https://docs.elgato.com/sdk/plugins/events-sent#setglobalsettings - """ - context: str - payload: dict - event: str = "setGlobalSettings" diff --git a/streamdeck_sdk/sd_objs/events_sent_objs/set_image.py b/streamdeck_sdk/sd_objs/events_sent_objs/set_image.py deleted file mode 100644 index 9145e52..0000000 --- a/streamdeck_sdk/sd_objs/events_sent_objs/set_image.py +++ /dev/null @@ -1,35 +0,0 @@ -from typing import Optional - -from pydantic import BaseModel - - -class SetImagePayload(BaseModel): - """ - image: The image to display encoded in base64 with the image format declared in the mime - type (PNG, JPEG, BMP, ...). svg is also supported. If not provided, the image is - reset to the default image from the manifest. - You can use functions from image_converters.py for convert image in base64. - target: Specify if you want to display the title on the hardware and software (0), - only on the hardware (1), or only on the software (2). Default is 0. - state: A 0-based integer value representing the state of an action with multiple states. If not specified, - the image is set to all states. - """ - image: str # base64 - target: int = 0 - state: Optional[int] = None - - -class SetImage(BaseModel): - """ - The plugin can send a setImage event to the Stream Deck application to dynamically change the image displayed - by an instance of an action. - - event: setImage - context: A value to Identify the instance's action you want to modify. - payload: A JSON object - - https://docs.elgato.com/sdk/plugins/events-sent#setimage - """ - context: str - payload: SetImagePayload - event: str = "setImage" diff --git a/streamdeck_sdk/sd_objs/events_sent_objs/set_settings.py b/streamdeck_sdk/sd_objs/events_sent_objs/set_settings.py deleted file mode 100644 index 1e26074..0000000 --- a/streamdeck_sdk/sd_objs/events_sent_objs/set_settings.py +++ /dev/null @@ -1,22 +0,0 @@ -from pydantic import BaseModel - - -class SetSettings(BaseModel): - """ - The plugin and Property Inspector can save data persistently for the action's instance using the setSettings event. - Note that when the plugin uses this API, the Property Inspector will automatically receive a didReceiveSettings - callback with the new settings. Similarly, when the Property Inspector uses this API, the plugin will - automatically receive a didReceiveSettings callback with the new settings. - The setSettings API is available since Stream Deck 4.0 for the plugin. Starting - with Stream Deck 4.1, this API is available from the Property Inspector. - - event: setSettings - context: A value to Identify the instance's action or Property Inspector. This value is received by - the Property Inspector as a parameter of the connectElgatoStreamDeckSocket function. - payload: A JSON object which is persistently saved for the action's instance. - - https://docs.elgato.com/sdk/plugins/events-sent#setsettings - """ - context: str - payload: dict - event: str = "setSettings" diff --git a/streamdeck_sdk/sd_objs/events_sent_objs/set_state.py b/streamdeck_sdk/sd_objs/events_sent_objs/set_state.py deleted file mode 100644 index 06c8e3b..0000000 --- a/streamdeck_sdk/sd_objs/events_sent_objs/set_state.py +++ /dev/null @@ -1,23 +0,0 @@ -from pydantic import BaseModel - - -class SetStatePayload(BaseModel): - """ - state: A 0-based integer value representing the state requested. - """ - state: int - - -class SetState(BaseModel): - """ - This function can be used by a plugin to dynamically change the state of an action supporting multiple states. - - event: setState - context: A value to identify the instance's action. - payload: A JSON object - - https://docs.elgato.com/sdk/plugins/events-sent#setstate - """ - context: str - payload: SetStatePayload - event: str = "setState" diff --git a/streamdeck_sdk/sd_objs/events_sent_objs/set_title.py b/streamdeck_sdk/sd_objs/events_sent_objs/set_title.py deleted file mode 100644 index 0002d71..0000000 --- a/streamdeck_sdk/sd_objs/events_sent_objs/set_title.py +++ /dev/null @@ -1,33 +0,0 @@ -from typing import Optional - -from pydantic import BaseModel - - -class SetTitlePayload(BaseModel): - """ - title: The title to display. If there is no title parameter, the title is reset to the title set by the user. - target: Specify if you want to display the title on the hardware and software (0), only on the hardware (1), - or only on the software (2). Default is 0. - state: A 0-based integer value representing the state of an action with multiple states. If not specified, - the title is set to all states. - """ - title: str - target: int = 0 - state: Optional[int] = None - - -class SetTitle(BaseModel): - """ - The plugin can send a setTitle event to the Stream Deck application to dynamically change the title - displayed by an instance of an action. - * Note: Show the title on your hardware or software using the Show Title checkbox in the Stream Deck window. - - event: setTitle - context: A value to Identify the instance's action you want to modify. - payload: A JSON object - - https://docs.elgato.com/sdk/plugins/events-sent#settitle - """ - context: str - payload: SetTitlePayload - event: str = "setTitle" diff --git a/streamdeck_sdk/sd_objs/events_sent_objs/set_trigger_description.py b/streamdeck_sdk/sd_objs/events_sent_objs/set_trigger_description.py deleted file mode 100644 index 181fe07..0000000 --- a/streamdeck_sdk/sd_objs/events_sent_objs/set_trigger_description.py +++ /dev/null @@ -1,39 +0,0 @@ -from typing import Optional - -from pydantic import BaseModel - - -class SetTriggerDescriptionPayload(BaseModel): - """ - longTouch: Optional value that describes the long-touch interaction with the touch display. When undefined the - description will be hidden. - push: Optional value that describes the push interaction with the dial. When undefined the description will - be hidden. - rotate: Optional value that describes the rotate interaction with the dial. When undefined the description will - be hidden. - touch: Optional value that describes the touch interaction with the touch display. When undefined the description - will be hidden. - """ - longTouch: Optional[str] = None - push: Optional[str] = None - rotate: Optional[str] = None - touch: Optional[str] = None - - -class SetTriggerDescription(BaseModel): - """ - (SD+) - Sets the trigger descriptions associated with an encoder (touch display + dial) action instance. All descriptions - are optional; when one or more descriptions are defined all descriptions are updated, with undefined values - having their description hidden in Stream Deck. To reset the descriptions to the default values defined - within the manifest, an empty payload can be sent as part of the event. - - event: setTriggerDescription - context: A value to identify the instance's action. - payload: A JSON object - - https://docs.elgato.com/sdk/plugins/events-sent#settriggerdescription-sd - """ - context: str - payload: SetTriggerDescriptionPayload - event: str = "setTriggerDescription" diff --git a/streamdeck_sdk/sd_objs/events_sent_objs/show_alert.py b/streamdeck_sdk/sd_objs/events_sent_objs/show_alert.py deleted file mode 100644 index 34709ca..0000000 --- a/streamdeck_sdk/sd_objs/events_sent_objs/show_alert.py +++ /dev/null @@ -1,15 +0,0 @@ -from pydantic import BaseModel - - -class ShowAlert(BaseModel): - """ - The plugin can send a showAlert event to the Stream Deck application to temporarily show an alert icon on the - image displayed by an instance of an action. - - event: showAlert - context: A value to identify the instance's action. - - https://docs.elgato.com/sdk/plugins/events-sent#showalert - """ - context: str - event: str = "showAlert" diff --git a/streamdeck_sdk/sd_objs/events_sent_objs/show_ok.py b/streamdeck_sdk/sd_objs/events_sent_objs/show_ok.py deleted file mode 100644 index b53478a..0000000 --- a/streamdeck_sdk/sd_objs/events_sent_objs/show_ok.py +++ /dev/null @@ -1,15 +0,0 @@ -from pydantic import BaseModel - - -class ShowOk(BaseModel): - """ - The plugin can send a showOk event to the Stream Deck application to temporarily show an OK checkmark icon on - the image displayed by an instance of an action. - - event: showOk - context: A value to identify the instance's action. - - https://docs.elgato.com/sdk/plugins/events-sent#showok - """ - context: str - event: str = "showOk" diff --git a/streamdeck_sdk/sd_objs/events_sent_objs/switch_to_profile.py b/streamdeck_sdk/sd_objs/events_sent_objs/switch_to_profile.py deleted file mode 100644 index a3e1d1c..0000000 --- a/streamdeck_sdk/sd_objs/events_sent_objs/switch_to_profile.py +++ /dev/null @@ -1,32 +0,0 @@ -from pydantic import BaseModel - - -class SwitchToProfilePayload(BaseModel): - """ - profile: The name of the profile to switch to. The name should be identical to the name provided - in the manifest.json file. - page: Page to show when switching to the profile; indexed from 0. - """ - profile: str - page: int - - -class SwitchToProfile(BaseModel): - """ - The plugin can tell the Stream Deck application to switch to one of his preconfigured read-only profile - using the switchToProfile event. - * Note that a plugin can only switch to read-only profiles declared in its manifest.json file. If the profile - field is missing or empty, the Stream Deck application will switch to the previously selected profile. - - event: switchToProfile - context: A value to Identify the plugin. This value should be set to the PluginUUID received during the - registration procedure. - device: A value to identify the device. - payload: A JSON object - - https://docs.elgato.com/sdk/plugins/events-sent#switchtoprofile - """ - device: str - context: str - payload: SwitchToProfilePayload - event: str = "switchToProfile" diff --git a/streamdeck_sdk/sd_objs/registration_objs.py b/streamdeck_sdk/sd_objs/registration_objs.py deleted file mode 100644 index 2419e1b..0000000 --- a/streamdeck_sdk/sd_objs/registration_objs.py +++ /dev/null @@ -1,87 +0,0 @@ -from typing import List, Optional - -from pydantic import BaseModel - - -# region NestedModels -class InfoApplication(BaseModel): - """ - language: In which language the Stream Deck application is running. Possible values are en, fr, de, es, ja, zh_CN. - platform: On which platform the Stream Deck application is running. Possible values - are kESDSDKApplicationInfoPlatformMac ("mac") and kESDSDKApplicationInfoPlatformWindows ("windows"). - version: The Stream Deck application version. - platformVersion: The operating system version. - """ - font: str - language: str - platform: str - platformVersion: str - version: str - - -class InfoPlugin(BaseModel): - """ - version: The plugin version as written in the manifest.json. - uuid: The unique identifier of the plugin. - """ - uuid: str - version: str - - -class InfoColors(BaseModel): - """ - A JSON object containing information about the preferred user colors. - """ - buttonPressedBackgroundColor: str - buttonPressedBorderColor: str - buttonPressedTextColor: str - highlightColor: str - disabledColor: Optional[str] = None - mouseDownColor: Optional[str] = None - - -class InfoDeviceSize(BaseModel): - """ - The number of columns and rows of keys that the device owns. - """ - columns: int - rows: int - - -class InfoDevice(BaseModel): - """ - id: A value to identify the device. - type: Type of device. Possible values are kESDSDKDeviceType_StreamDeck (0), kESDSDKDeviceType_StreamDeckMini (1), - kESDSDKDeviceType_StreamDeckXL (2), kESDSDKDeviceType_StreamDeckMobile (3), kESDSDKDeviceType_CorsairGKeys (4), - kESDSDKDeviceType_StreamDeckPedal (5), kESDSDKDeviceType_CorsairVoyager (6), - and kESDSDKDeviceType_StreamDeckPlus (7). - size: The number of columns and rows of keys that the device owns. - name: The name of the device set by the user. - """ - id: str - name: str - size: InfoDeviceSize - type: int - - -# endregion NestedModels - -# region Models -class Info(BaseModel): - """ - The info parameter used in the registration process is A JSON object. - - application: A JSON object containing information about the application. - plugin: A JSON object containing information about the plugin. - devices: A JSON array containing information about the devices. - devicePixelRatio: Pixel ratio value to indicate if the Stream Deck application is running on a HiDPI screen. - colors: A JSON object containing information about the preferred user colors. - - https://docs.elgato.com/sdk/plugins/registration-procedure#info-parameter - """ - application: InfoApplication - plugin: InfoPlugin - devicePixelRatio: int - colors: InfoColors - devices: List[InfoDevice] -# endregion Models diff --git a/streamdeck_sdk/sdk.py b/streamdeck_sdk/sdk.py deleted file mode 100644 index d433646..0000000 --- a/streamdeck_sdk/sdk.py +++ /dev/null @@ -1,166 +0,0 @@ -import argparse -import json -import logging -import sys -from os import PathLike -from pathlib import Path -from typing import Optional, List, Dict, Set - -from websockets.sync.server import ( - ServerConnection, -) - -from .logger import ( - init_root_logger, - log_errors, - rename_plugin_logger, -) -from .mixins import Base -from .mixins.event_routing_mixin import EventRoutingMixin -from .mixins.debug_server_mixin import DebugServerMixin -from .sd_objs import registration_objs -from .simple_ws.client import WebSocketClientApp - -logger = logging.getLogger(__name__) - - -class Action(Base): - UUID: str # Required - - def __init__(self): - self.plugin_uuid: Optional[str] = None - self.ws: Optional[WebSocketClientApp] = None - self.info: Optional[registration_objs.Info] = None - - -class StreamDeck( - Base, - EventRoutingMixin, - DebugServerMixin, -): - def __init__( - self, - actions: Optional[List[Action]] = None, - debug: bool = False, - debug_port: int = 5581, - *, - log_file: Optional[PathLike] = None, - log_level: int = logging.INFO, - log_max_bytes: int = 3 * 1024 * 1024, # 3 MB - log_backup_count: int = 2, - ): - if log_file is not None: - if debug: - log_level = logging.DEBUG - log_file: Path = Path(log_file) - init_root_logger( - log_file=log_file, - log_level=log_level, - log_max_bytes=log_max_bytes, - log_backup_count=log_backup_count, - ) - - self.actions_list = actions - self.actions: Dict[str, Action] = {} - - self.debug = debug - self.debug_port = debug_port - self.debug_clients: Set[ServerConnection] = set() - - self.ws: Optional[WebSocketClientApp] = None - self.port: Optional[int] = None - self.plugin_uuid: Optional[str] = None - self.register_event: Optional[str] = None - self.info: Optional[registration_objs.Info] = None - - self.registration_dict: Optional[dict] = None - - @log_errors - def run(self): - logger.debug(f"Plugin has been launched") - - if self.debug: - self.run_debug() - return - - self.__parse_args() - self.ws = WebSocketClientApp( - uri=f'ws://localhost:{self.port}/', - on_message=self.ws_on_message, - on_error=self.ws_on_error, - on_close=self.ws_on_close, - on_open=self.ws_on_open, - ) - self.__init_actions() - self.ws.run_forever() - - @log_errors - def run_debug(self): - logger.warning("Debug mode.") - - if len(sys.argv) == 1: # is client - try: - logger.info("Trying to connect to the debug server.") - self.ws = WebSocketClientApp( - uri=f'ws://localhost:{self.debug_port}/', - on_message=self.ws_on_message, - ) - logger.info(f"Successfully connected to the debug server.") - self.__init_actions() - self.ws.run_forever() - except Exception as err: - logger.exception(err) - logger.debug(f"Failed to connect to debug server.") - return - - logger.info("Trying to create a debug server.") - self.__parse_args() - self._debug_server_run() - logger.debug("Debug server is running.") - self.ws = WebSocketClientApp( - uri=f'ws://localhost:{self.port}/', - on_message=self._debug_server_on_message, - on_open=self.ws_on_open, - ) - logger.debug("Debug server connected to StreamDeck.") - self.ws.run_forever() - logger.info("Debug server stopped.") - - def __init_actions(self) -> None: - if self.actions_list is None: - return - - for action in self.actions_list: - try: - action_uuid = action.UUID - except AttributeError: - action_class = str(action.__class__) - message = f"{action_class} must have attribute UUID." - logger.error(message, exc_info=True) - raise AttributeError(message) - action.ws = self.ws - action.plugin_uuid = self.plugin_uuid - action.info = self.info - self.actions[action_uuid] = action - - def __parse_args(self): - logger.debug("Trying to parse arguments.") - parser = argparse.ArgumentParser(description='StreamDeck Plugin') - parser.add_argument('-port', dest='port', type=int, help="Port", required=True) - parser.add_argument('-pluginUUID', dest='pluginUUID', type=str, help="pluginUUID", required=True) - parser.add_argument('-registerEvent', dest='registerEvent', type=str, help="registerEvent", required=True) - parser.add_argument('-info', dest='info', type=str, help="info", required=True) - args = parser.parse_args() - logger.debug("Trying to parse arguments was successful.") - logger.debug(f"{args=}") - - self.port = args.port - self.plugin_uuid = args.pluginUUID - self.register_event = args.registerEvent - self.info = registration_objs.Info.parse_obj(json.loads(args.info)) - logger.debug(f"{self.info=}") - - rename_plugin_logger(name=self.info.plugin.uuid) - - self.registration_dict = {"event": self.register_event, "uuid": self.plugin_uuid} - logger.debug(f"{self.registration_dict=}") diff --git a/streamdeck_sdk/simple_ws/__init__.py b/streamdeck_sdk/simple_ws/__init__.py deleted file mode 100644 index ba45768..0000000 --- a/streamdeck_sdk/simple_ws/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from . import client diff --git a/streamdeck_sdk/simple_ws/client.py b/streamdeck_sdk/simple_ws/client.py deleted file mode 100644 index 02c5a8e..0000000 --- a/streamdeck_sdk/simple_ws/client.py +++ /dev/null @@ -1,61 +0,0 @@ -import logging -from typing import Callable, Optional - -from websockets.exceptions import ConnectionClosedOK, ConnectionClosedError, ConnectionClosed -from websockets.sync.client import ClientConnection, connect - -logger = logging.getLogger('simple_ws_client') - - -class WebSocketClientApp: - def __init__( - self, - uri: str, - *, - on_open: Callable = None, - on_message: Callable = None, - on_error: Callable = None, - on_close: Callable = None, - ): - self.uri = uri - self.on_open = on_open - self.on_message = on_message - self.on_error = on_error - self.on_close = on_close - self.client: Optional[ClientConnection] = connect(uri=self.uri) - - def send(self, message): - self.client.send(message=message) - - def close(self): - self.client.close() - - def run_forever(self): - self._callback(self.on_open) - while True: - try: - message = self.client.recv() - logger.debug(f"Message received. {message=}") - except ConnectionClosedOK as err: - self._handle_connection_close(err=err) - break - except ConnectionClosedError as err: - self._callback(self.on_error, err) - self._handle_connection_close(err=err) - break - self._callback(self.on_message, message) - - def _handle_connection_close(self, err: ConnectionClosed): - close_status_code = getattr(err.rcvd, "code", None) - close_msg = getattr(err.rcvd, "reason", None) - self._callback(self.on_close, close_status_code, close_msg) - - def _callback(self, callback, *args): - if not callback: - return - try: - callback(self.client, *args) - except Exception as err: - logger.error(f"error from callback {callback}: {err}") - if self.on_error: - self.on_error(self, err) diff --git a/streamdeck_sdk/utils/__init__.py b/streamdeck_sdk/utils/__init__.py deleted file mode 100644 index 160204d..0000000 --- a/streamdeck_sdk/utils/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .image_converters import image_file_to_base64, image_bytes_to_base64 -from .in_separate_thread import in_separate_thread diff --git a/streamdeck_sdk/utils/image_converters.py b/streamdeck_sdk/utils/image_converters.py deleted file mode 100644 index 7e8bcdb..0000000 --- a/streamdeck_sdk/utils/image_converters.py +++ /dev/null @@ -1,22 +0,0 @@ -import base64 -import mimetypes -from pathlib import Path - - -def image_file_to_base64(file_path: Path) -> str: - image_mime = mimetypes.guess_type(file_path, strict=True)[0] - prefix = f"data:{image_mime};base64," - with open(file_path, "rb") as image_file: - image_base64: bytes = base64.b64encode(image_file.read()) - result = prefix + image_base64.decode("UTF-8") - return result - - -def image_bytes_to_base64(obj: bytes, image_mime: str) -> str: - """ - :param image_mime: Example: image/png, image/jpg, image/bmp, image/svg+xml - """ - prefix = f"data:{image_mime};base64," - image_base64: bytes = base64.b64encode(obj) - result = prefix + image_base64.decode("UTF-8") - return result diff --git a/streamdeck_sdk/utils/in_separate_thread.py b/streamdeck_sdk/utils/in_separate_thread.py deleted file mode 100644 index 66ac5b6..0000000 --- a/streamdeck_sdk/utils/in_separate_thread.py +++ /dev/null @@ -1,41 +0,0 @@ -from functools import wraps -from threading import Thread -from typing import Callable, Optional - - -class ThreadingFunc: - def __init__( - self, - func: Callable, - *, - daemon: Optional[bool] = None, - ): - self.func = func - self.daemon = daemon - - def __call__(self, *args, **kwargs) -> Thread: - thread = Thread(target=self.func, args=args, kwargs=kwargs, daemon=self.daemon) - thread.start() - return thread - - -def in_separate_thread(daemon: Optional[bool] = None): - """ - Decorator for executing the decorated function on a separate thread. - - :param daemon: A daemon thread (True) or not (False). If None, then its initial value is inherited - from the creating thread. - """ - - def _decorator(func: Callable): - @wraps(func) - def wrapper(*args, **kwargs): - return ThreadingFunc(func=func, daemon=_daemon)(*args, **kwargs) - - return wrapper - - _daemon: Optional[bool] = None - if callable(daemon): - return _decorator(func=daemon) - _daemon = daemon - return _decorator From e823d60f0475e25ae0d5a0d789df860180d38177 Mon Sep 17 00:00:00 2001 From: Grigoriy Gusev Date: Sun, 22 Sep 2024 13:38:30 +0300 Subject: [PATCH 3/5] dev7 --- pyproject.toml | 2 +- src/streamdeck_sdk/mixins/debug_server_mixin.py | 6 +++--- src/streamdeck_sdk/mixins/event_routing_mixin.py | 8 ++++---- src/streamdeck_sdk/sdk.py | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index fd2c999..7196ecd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "streamdeck_sdk" -version = "1.2.0.dev6" +version = "1.2.0.dev7" authors = [ { name = "Grigoriy Gusev", email = "thegrigus@gmail.com" }, ] diff --git a/src/streamdeck_sdk/mixins/debug_server_mixin.py b/src/streamdeck_sdk/mixins/debug_server_mixin.py index 06ba65d..a574183 100644 --- a/src/streamdeck_sdk/mixins/debug_server_mixin.py +++ b/src/streamdeck_sdk/mixins/debug_server_mixin.py @@ -7,9 +7,9 @@ serve, ) -from src.streamdeck_sdk.mixins import SendMixin -from src.streamdeck_sdk.simple_ws.client import WebSocketClientApp -from src.streamdeck_sdk.utils.in_separate_thread import in_separate_thread +from .send_event_mixins import SendMixin +from ..simple_ws.client import WebSocketClientApp +from ..utils.in_separate_thread import in_separate_thread logger = logging.getLogger(__name__) diff --git a/src/streamdeck_sdk/mixins/event_routing_mixin.py b/src/streamdeck_sdk/mixins/event_routing_mixin.py index dbfbf78..abcd0d6 100644 --- a/src/streamdeck_sdk/mixins/event_routing_mixin.py +++ b/src/streamdeck_sdk/mixins/event_routing_mixin.py @@ -4,12 +4,12 @@ import pydantic -from src.streamdeck_sdk import event_routings -from src.streamdeck_sdk.logger import ( +from .. import event_routings +from ..logger import ( log_errors, ) -from src.streamdeck_sdk.mixins import EventsSendMixin -from src.streamdeck_sdk.simple_ws.client import WebSocketClientApp +from ..mixins.send_event_mixins import EventsSendMixin +from ..simple_ws.client import WebSocketClientApp logger = logging.getLogger(__name__) diff --git a/src/streamdeck_sdk/sdk.py b/src/streamdeck_sdk/sdk.py index d433646..2d2a46f 100644 --- a/src/streamdeck_sdk/sdk.py +++ b/src/streamdeck_sdk/sdk.py @@ -16,8 +16,8 @@ rename_plugin_logger, ) from .mixins import Base -from .mixins.event_routing_mixin import EventRoutingMixin from .mixins.debug_server_mixin import DebugServerMixin +from .mixins.event_routing_mixin import EventRoutingMixin from .sd_objs import registration_objs from .simple_ws.client import WebSocketClientApp From 6bddb5e5461f7712282311c89dc471c5697abe65 Mon Sep 17 00:00:00 2001 From: Grigoriy Gusev Date: Sun, 22 Sep 2024 13:47:55 +0300 Subject: [PATCH 4/5] dev8 --- README-PYPI.md | 4 ++++ README.md | 4 ++++ README.ru.md | 4 ++++ pyproject.toml | 2 +- 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/README-PYPI.md b/README-PYPI.md index 2b6634f..41676b7 100644 --- a/README-PYPI.md +++ b/README-PYPI.md @@ -38,6 +38,10 @@ Library for creating Stream Deck plugins in Python. ## Installation +> ⚠️ For correct operation on Windows, it is recommended to enable `LongPaths` support in +> the system: [manual](https://www.backupery.com/how-to-enable-ntfs-long-paths-in-windows/). +> Without this setting, problems with installation and use may occur! + ```shell pip install streamdeck-sdk[dev] ``` diff --git a/README.md b/README.md index 18ae53b..3453c5f 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,10 @@ Library for creating Stream Deck plugins in Python. ## Installation +> ⚠️ For correct operation on Windows, it is recommended to enable `LongPaths` support in +> the system: [manual](https://www.backupery.com/how-to-enable-ntfs-long-paths-in-windows/). +> Without this setting, problems with installation and use may occur! + ```shell pip install streamdeck-sdk[dev] ``` diff --git a/README.ru.md b/README.ru.md index 5941ccf..1e5d8db 100644 --- a/README.ru.md +++ b/README.ru.md @@ -45,6 +45,10 @@ ## Установка +> ⚠️ Для корректной работы на Windows рекомендуется включить поддержку `LongPaths` в +> системе: [manual](https://www.backupery.com/how-to-enable-ntfs-long-paths-in-windows/). +> Без этой настройки возможны проблемы с установкой и использованием! + ```shell pip install streamdeck-sdk[dev] ``` diff --git a/pyproject.toml b/pyproject.toml index 7196ecd..3d5d4be 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "streamdeck_sdk" -version = "1.2.0.dev7" +version = "1.2.0.dev8" authors = [ { name = "Grigoriy Gusev", email = "thegrigus@gmail.com" }, ] From c09275ce913b5acbe7d508c6ce98427475879d55 Mon Sep 17 00:00:00 2001 From: Grigoriy Gusev Date: Sun, 22 Sep 2024 13:56:18 +0300 Subject: [PATCH 5/5] delete requirements.txt --- requirements.txt | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index d0542a7..0000000 --- a/requirements.txt +++ /dev/null @@ -1,6 +0,0 @@ -annotated-types==0.7.0 -decohints==1.0.9 -pydantic==2.8.2 -pydantic_core==2.20.1 -typing_extensions==4.12.2 -websockets==13.0.1