mirror of https://github.com/LedFx/LedFx.git
Merge branch 'main' into led-strips/zengge-magichome
This commit is contained in:
commit
fbc1204f4a
|
@ -13,14 +13,14 @@ jobs:
|
|||
python: [3.8,3.9,3.10.x]
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3.4.0
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
sudo apt-get update && sudo apt-get install -y \
|
||||
gcc libatlas3-base portaudio19-dev
|
||||
- name: Setup Python ${{ matrix.python }}
|
||||
id: python
|
||||
uses: actions/setup-python@v2.2.1
|
||||
uses: actions/setup-python@v4.5.0
|
||||
with:
|
||||
python-version: ${{ matrix.python }}
|
||||
- name: Build a binary wheel
|
||||
|
@ -39,10 +39,10 @@ jobs:
|
|||
python: [3.8,3.9,3.10.x]
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3.4.0
|
||||
- name: Setup Python ${{ matrix.python }}
|
||||
id: python
|
||||
uses: actions/setup-python@v2.2.1
|
||||
uses: actions/setup-python@v4.5.0
|
||||
with:
|
||||
python-version: ${{ matrix.python }}
|
||||
- name: Build a binary wheel
|
||||
|
@ -61,13 +61,13 @@ jobs:
|
|||
python: [3.8,3.9,3.10.x]
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3.4.0
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
brew install portaudio
|
||||
- name: Setup Python ${{ matrix.python }}
|
||||
id: python
|
||||
uses: actions/setup-python@v2.2.1
|
||||
uses: actions/setup-python@v4.5.0
|
||||
with:
|
||||
python-version: ${{ matrix.python }}
|
||||
- name: Build a binary wheel
|
||||
|
@ -86,7 +86,7 @@ jobs:
|
|||
# node-version: [10, 12, 14]
|
||||
# steps:
|
||||
# - name: Check out code from GitHub
|
||||
# uses: actions/checkout@v2
|
||||
# uses: actions/checkout@v3.4.0
|
||||
# - name: Use Node.js ${{ matrix.node-version }}
|
||||
# uses: actions/setup-node@v2
|
||||
# with:
|
||||
|
|
|
@ -44,3 +44,11 @@ jobs:
|
|||
with:
|
||||
user: __token__
|
||||
password: ${{ secrets.PYPI_API_TOKEN }}
|
||||
- name: Trigger HomeAssistant Add-on
|
||||
uses: benc-uk/workflow-dispatch@v1
|
||||
with:
|
||||
workflow: Builder
|
||||
repo: YeonV/home-assistant-addons
|
||||
ref: refs/heads/master
|
||||
token: ${{ secrets.LEDFX_HOMEASSISTANT_ADDON }}
|
||||
inputs: '{ "version": "${{ github.ref_name }}" }'
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
hiddenimports = [
|
||||
"sacn",
|
||||
"aubio",
|
||||
"numpy",
|
||||
"notifypy",
|
||||
"math",
|
||||
"voluptuous",
|
||||
"numpy",
|
||||
"notifypy",
|
||||
"aiohttp",
|
||||
"mido",
|
||||
"mido.frozen",
|
||||
"paho",
|
||||
"paho.mqtt",
|
||||
"openrgb-python",
|
||||
"openrgb",
|
||||
"python-rtmidi",
|
||||
"rtmidi",
|
||||
"mido.backends.rtmidi",
|
||||
"paho.mqtt.client",
|
||||
"samplerate",
|
||||
"samplerate._src",
|
||||
"samplerate._samplerate_data",
|
||||
"sounddevice",
|
||||
"sentry_sdk",
|
||||
"sentry_sdk.integrations.django",
|
||||
"sentry_sdk.integrations.flask",
|
||||
"sentry_sdk.integrations.bottle",
|
||||
"sentry_sdk.integrations.falcon",
|
||||
"sentry_sdk.integrations.sanic",
|
||||
"sentry_sdk.integrations.celery",
|
||||
"sentry_sdk.integrations.aiohttp",
|
||||
"sentry_sdk.integrations.rq",
|
||||
"sentry_sdk.integrations.tornado",
|
||||
"sentry_sdk.integrations.sqlalchemy",
|
||||
"sentry_sdk.integrations.boto3",
|
||||
"_cffi_backend",
|
||||
"serial",
|
||||
"pystray._win32",
|
||||
"serial.tools.list_ports",
|
||||
"tcp_latency",
|
||||
"aiohttp_cors",
|
||||
"psutil",
|
||||
"yappi",
|
||||
]
|
|
@ -44,7 +44,7 @@ from ledfx.consts import (
|
|||
REQUIRED_PYTHON_VERSION,
|
||||
)
|
||||
from ledfx.core import LedFxCore
|
||||
from ledfx.utils import currently_frozen
|
||||
from ledfx.utils import currently_frozen, get_icon_path
|
||||
|
||||
# Logger Variables
|
||||
PYUPDATERLOGLEVEL = 35
|
||||
|
@ -193,12 +193,23 @@ def parse_args():
|
|||
default=None,
|
||||
type=str,
|
||||
)
|
||||
parser.add_argument(
|
||||
|
||||
group = parser.add_mutually_exclusive_group()
|
||||
|
||||
group.add_argument(
|
||||
"--tray",
|
||||
dest="tray",
|
||||
action="store_true",
|
||||
help="Hide LedFx console to the system tray",
|
||||
help="Force LedFx system tray icon",
|
||||
)
|
||||
|
||||
group.add_argument(
|
||||
"--no-tray",
|
||||
dest="no_tray",
|
||||
action="store_true",
|
||||
help="Force no LedFx system tray icon",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--offline",
|
||||
dest="offline_mode",
|
||||
|
@ -290,6 +301,29 @@ def update_ledfx(icon=None):
|
|||
)
|
||||
|
||||
|
||||
def log_packages():
|
||||
from platform import (
|
||||
processor,
|
||||
python_build,
|
||||
python_implementation,
|
||||
python_version,
|
||||
release,
|
||||
system,
|
||||
)
|
||||
|
||||
from pkg_resources import working_set
|
||||
|
||||
_LOGGER.debug(f"{system()} : {release()} : {processor()}")
|
||||
_LOGGER.debug(
|
||||
f"{python_version()} : {python_build()} : {python_implementation()}"
|
||||
)
|
||||
_LOGGER.debug("Packages")
|
||||
dists = [d for d in working_set]
|
||||
dists.sort(key=lambda x: x.project_name)
|
||||
for dist in dists:
|
||||
_LOGGER.debug(f"{dist.project_name} : {dist.version}")
|
||||
|
||||
|
||||
def main():
|
||||
"""Main entry point allowing external calls"""
|
||||
args = parse_args()
|
||||
|
@ -331,7 +365,7 @@ def main():
|
|||
_LOGGER.warning("Steering LedFx into a brick wall")
|
||||
div_by_zero = 1 / 0
|
||||
|
||||
if args.tray or currently_frozen():
|
||||
if (args.tray or currently_frozen()) and not args.no_tray:
|
||||
# If pystray is imported on a device that can't display it, it explodes. Catch it
|
||||
try:
|
||||
import pystray
|
||||
|
@ -343,22 +377,18 @@ def main():
|
|||
|
||||
from PIL import Image
|
||||
|
||||
if currently_frozen():
|
||||
current_directory = os.path.dirname(__file__)
|
||||
icon_location = os.path.join(current_directory, "tray.png")
|
||||
else:
|
||||
current_directory = os.path.dirname(__file__)
|
||||
icon_location = os.path.join(
|
||||
current_directory, "..", "icons/" "tray.png"
|
||||
)
|
||||
icon_location = get_icon_path("tray.png")
|
||||
|
||||
icon = pystray.Icon(
|
||||
"LedFx", icon=Image.open(icon_location), title="LedFx"
|
||||
)
|
||||
icon.visible = True
|
||||
else:
|
||||
icon = None
|
||||
# icon = None
|
||||
|
||||
if _LOGGER.isEnabledFor(logging.DEBUG):
|
||||
log_packages()
|
||||
|
||||
# if have_updater and not args.offline_mode and currently_frozen():
|
||||
# update_ledfx(icon)
|
||||
|
||||
|
@ -372,6 +402,9 @@ def entry_point(icon=None):
|
|||
# have to re-parse args here :/ no way to pass them through pysicon's setup
|
||||
args = parse_args()
|
||||
|
||||
if icon:
|
||||
icon.visible = True
|
||||
|
||||
exit_code = 4
|
||||
while exit_code == 4:
|
||||
_LOGGER.info("LedFx Core is initializing")
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
import logging
|
||||
from json import JSONDecodeError
|
||||
|
||||
from aiohttp import web
|
||||
from notifypy import Notify
|
||||
|
||||
from ledfx.api import RestEndpoint
|
||||
from ledfx.utils import get_icon_path
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class NotifyEndpoint(RestEndpoint):
|
||||
"""REST end-point that exposes a notification api"""
|
||||
|
||||
ENDPOINT_PATH = "/api/notify"
|
||||
|
||||
def __init__(self, ledfx):
|
||||
self.icon = ledfx.icon
|
||||
|
||||
async def put(self, request) -> web.Response:
|
||||
try:
|
||||
data = await request.json()
|
||||
except JSONDecodeError:
|
||||
response = {
|
||||
"status": "failed",
|
||||
"reason": "JSON Decoding failed",
|
||||
}
|
||||
return web.json_response(data=response, status=400)
|
||||
|
||||
title = data.get("title")
|
||||
if title is None:
|
||||
response = {
|
||||
"status": "failed",
|
||||
"reason": 'Required attribute "title" was not provided',
|
||||
}
|
||||
return web.json_response(data=response, status=400)
|
||||
|
||||
text = data.get("text")
|
||||
if text is None:
|
||||
response = {
|
||||
"status": "failed",
|
||||
"reason": 'Required attribute "text" was not provided',
|
||||
}
|
||||
return web.json_response(data=response, status=400)
|
||||
|
||||
_LOGGER.info(f"notify: {title} --- {text}")
|
||||
if self.icon is not None:
|
||||
if self.icon.HAS_NOTIFICATION:
|
||||
self.icon.notify(f"{title}:\n{text}")
|
||||
else:
|
||||
icon_location = get_icon_path("tray.png")
|
||||
notification = Notify()
|
||||
notification.application_name = "LedFx"
|
||||
notification.title = title
|
||||
notification.message = text
|
||||
notification.icon = icon_location
|
||||
notification.send(block=False)
|
||||
|
||||
response = {
|
||||
"status": "success",
|
||||
}
|
||||
|
||||
return web.json_response(data=response, status=200)
|
|
@ -39,7 +39,7 @@ class ScenesEndpoint(RestEndpoint):
|
|||
if scene_id is None:
|
||||
response = {
|
||||
"status": "failed",
|
||||
"reason": 'Required attribute "scene_id" was not provided',
|
||||
"reason": 'Required attribute "id" was not provided',
|
||||
}
|
||||
return web.json_response(data=response, status=400)
|
||||
|
||||
|
@ -92,7 +92,7 @@ class ScenesEndpoint(RestEndpoint):
|
|||
if scene_id is None:
|
||||
response = {
|
||||
"status": "failed",
|
||||
"reason": 'Required attribute "scene_id" was not provided',
|
||||
"reason": 'Required attribute "id" was not provided',
|
||||
}
|
||||
return web.json_response(data=response, status=400)
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ REQUIRED_PYTHON_STRING = ">={}.{}.{}".format(
|
|||
|
||||
MAJOR_VERSION = 2
|
||||
MINOR_VERSION = 0
|
||||
MICRO_VERSION = 60
|
||||
MICRO_VERSION = 62
|
||||
POST = 0
|
||||
DEV = 0
|
||||
PROJECT_VERSION = "{}.{}.{}".format(
|
||||
|
|
|
@ -618,12 +618,14 @@ class Devices(RegistryLoader):
|
|||
if hasattr(device, "async_initialize"):
|
||||
await device.async_initialize()
|
||||
|
||||
device_config = device.config
|
||||
device_config["name"] = wled_name
|
||||
# Update and save the configuration
|
||||
self._ledfx.config["devices"].append(
|
||||
{
|
||||
"id": device.id,
|
||||
"type": device.type,
|
||||
"config": device.config,
|
||||
"config": device_config,
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -717,3 +719,7 @@ class WLEDListener(zeroconf.ServiceBrowser):
|
|||
loop=self._ledfx.loop,
|
||||
exc_handler=handle_exception,
|
||||
)
|
||||
|
||||
def update_service(self, zeroconf_obj, type, name):
|
||||
"""Callback when a service is updated."""
|
||||
pass
|
||||
|
|
|
@ -0,0 +1,182 @@
|
|||
import logging
|
||||
import socket
|
||||
import struct
|
||||
from typing import Dict, Optional, Tuple
|
||||
|
||||
import requests
|
||||
import voluptuous as vol
|
||||
|
||||
from ledfx.devices import NetworkedDevice
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class NanoleafDevice(NetworkedDevice):
|
||||
"""
|
||||
Dedicated WLED device support
|
||||
This class fetches its config (px count, etc) from the WLED device
|
||||
at launch, and lets the user choose a sync mode to use.
|
||||
"""
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required(
|
||||
"ip_address",
|
||||
description="Hostname or IP address of the device",
|
||||
): str,
|
||||
vol.Optional("port", description="port", default=16021): int,
|
||||
vol.Optional("udp_port", description="port", default=60222): int,
|
||||
vol.Optional(
|
||||
"auth_token",
|
||||
description="Auth token",
|
||||
): str,
|
||||
vol.Optional(
|
||||
"sync_mode",
|
||||
description="Streaming protocol to Nanoleaf device",
|
||||
default="UDP",
|
||||
): vol.In(["TCP", "UDP"]),
|
||||
}
|
||||
)
|
||||
|
||||
status: Dict[int, Tuple[int, int, int]]
|
||||
_sock: Optional[socket.socket] = None
|
||||
|
||||
def __init__(self, ledfx, config):
|
||||
super().__init__(ledfx, config)
|
||||
|
||||
self.status = {}
|
||||
|
||||
def config_updated(self, config):
|
||||
self.setup_subdevice()
|
||||
|
||||
def url(self, token: str) -> str:
|
||||
return "http://%s:%i/api/v1/%s" % (
|
||||
self._config["ip_address"],
|
||||
self._config["port"],
|
||||
token,
|
||||
)
|
||||
|
||||
def setup_subdevice(self):
|
||||
self.status = {}
|
||||
self.deactivate()
|
||||
self.activate()
|
||||
|
||||
def activate(self):
|
||||
if self.config["sync_mode"] == "UDP":
|
||||
response = requests.put(
|
||||
self.url(self._config["auth_token"]) + "/effects",
|
||||
json={
|
||||
"write": {
|
||||
"command": "display",
|
||||
"animType": "extControl",
|
||||
"extControlVersion": "v2",
|
||||
}
|
||||
},
|
||||
)
|
||||
if response.status_code == 400:
|
||||
raise Exception("Invalid effect dictionary")
|
||||
|
||||
self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
self._sock.connect(
|
||||
(self._config["ip_address"], self._config["udp_port"])
|
||||
)
|
||||
|
||||
super().activate()
|
||||
|
||||
def deactivate(self):
|
||||
if self._sock is not None:
|
||||
self._sock.close()
|
||||
self._sock = None
|
||||
|
||||
super().deactivate()
|
||||
|
||||
def write_udp(self):
|
||||
send_data = struct.pack(">H", len(self.status))
|
||||
w = 0
|
||||
transition = 0
|
||||
|
||||
for panel_id, (r, g, b) in self.status.items():
|
||||
send_data += struct.pack(
|
||||
">HBBBBH", panel_id, r, g, b, w, transition
|
||||
)
|
||||
|
||||
self._sock.send(send_data)
|
||||
|
||||
def write_tcp(self):
|
||||
"""Syncs the digital twin's changes to the real Nanoleaf device.
|
||||
|
||||
:returns: True if success, otherwise False
|
||||
"""
|
||||
anim_data = str(len(self.status))
|
||||
|
||||
for key, (r, g, b) in self.status.items():
|
||||
anim_data += f" {str(key)} 1 {r} {g} {b} 0 0"
|
||||
|
||||
response = requests.put(
|
||||
self.url(self._config["auth_token"]) + "/effects",
|
||||
json={
|
||||
"write": {
|
||||
"command": "display",
|
||||
"animType": "custom",
|
||||
"loop": True,
|
||||
"palette": [],
|
||||
"animData": anim_data,
|
||||
}
|
||||
},
|
||||
)
|
||||
if response.status_code == 400:
|
||||
raise Exception("Invalid effect dictionary")
|
||||
|
||||
def flush(self, data):
|
||||
for panel, col in zip(
|
||||
self.config["pixel_layout"], data.astype(int).clip(0, 255)
|
||||
):
|
||||
self.status[panel["panelId"]] = col.tolist()
|
||||
|
||||
if self.config["sync_mode"] == "TCP":
|
||||
self.write_tcp()
|
||||
elif self.config["sync_mode"] == "UDP":
|
||||
self.write_udp()
|
||||
|
||||
def get_token(self):
|
||||
response = requests.post(self.url("new"))
|
||||
|
||||
if response and response.status_code == 200:
|
||||
data = response.json()
|
||||
if "auth_token" in data:
|
||||
return data["auth_token"]
|
||||
|
||||
raise Exception("No token, press sync button first")
|
||||
|
||||
async def async_initialize(self):
|
||||
await super().async_initialize()
|
||||
|
||||
auth_token = self.config.get("auth_token")
|
||||
|
||||
if not auth_token:
|
||||
auth_token = self.get_token()
|
||||
self.update_config({"auth_token": auth_token})
|
||||
|
||||
self.setup_subdevice()
|
||||
|
||||
nanoleaf_config = requests.get(
|
||||
self.url(self.config["auth_token"])
|
||||
).json()
|
||||
|
||||
panels = [
|
||||
{"x": i["x"], "y": i["y"], "panelId": i["panelId"]}
|
||||
for i in sorted(
|
||||
nanoleaf_config["panelLayout"]["layout"]["positionData"],
|
||||
key=lambda x: (x["x"], x["y"]),
|
||||
)
|
||||
if i["panelId"] != 0
|
||||
]
|
||||
|
||||
config = {
|
||||
"name": nanoleaf_config["name"],
|
||||
"pixel_count": len(panels),
|
||||
"pixel_layout": panels,
|
||||
"refresh_rate": 30, # problems with too fast udp packets
|
||||
}
|
||||
|
||||
self.update_config(config)
|
|
@ -58,6 +58,7 @@ class WLEDDevice(NetworkedDevice):
|
|||
},
|
||||
"DDP": {
|
||||
"name": None,
|
||||
"port": 4048,
|
||||
"ip_address": None,
|
||||
"pixel_count": None,
|
||||
},
|
||||
|
|
|
@ -91,6 +91,8 @@ def _gaussian_kernel1d(sigma, order, array_len):
|
|||
# Choose a radius for the filter kernel large enough to include all significant elements. Using
|
||||
# a radius of 4 standard deviations (rounded to int) will only truncate tail values that are of
|
||||
# the order of 1e-5 or smaller. For very small sigma values, just use a minimal radius.
|
||||
# trapping very small values of sigma to arbitarily 0.00001 to preven div zero crash
|
||||
sigma = max(0.00001, sigma)
|
||||
radius = max(1, int(round(4.0 * sigma)))
|
||||
radius = min(int((array_len - 1) / 2), radius)
|
||||
radius = max(radius, 1)
|
||||
|
|
|
@ -46,6 +46,11 @@ class Strobe(AudioReactiveEffect, GradientEffect):
|
|||
description="Percussive strobe decay rate. Higher -> decays faster.",
|
||||
default=0.5,
|
||||
): vol.All(vol.Coerce(float), vol.Range(min=0, max=1)),
|
||||
vol.Optional(
|
||||
"color_shift_delay",
|
||||
description="color shift delay for percussive strobes. Lower -> more shifts",
|
||||
default=1,
|
||||
): vol.All(vol.Coerce(float), vol.Range(min=0, max=1)),
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -67,7 +72,7 @@ class Strobe(AudioReactiveEffect, GradientEffect):
|
|||
)
|
||||
self.last_color_shift_time = 0
|
||||
self.strobe_width = self._config["strobe_width"]
|
||||
self.color_shift_delay_in_seconds = 1
|
||||
self.color_shift_delay_in_seconds = self._config["color_shift_delay"]
|
||||
self.color_idx = 0
|
||||
|
||||
self.last_strobe_time = 0
|
||||
|
|
|
@ -86,6 +86,8 @@ class Water(AudioReactiveEffect, HSVEffect):
|
|||
# Just bail out with uselessly-small pixel counts.
|
||||
if self.pixel_count < 5:
|
||||
return
|
||||
if self.drops_queue is None:
|
||||
return
|
||||
|
||||
intensities = np.fromiter(
|
||||
(i.max() ** 2 for i in self.melbank_thirds()), float
|
||||
|
|
|
@ -1413,6 +1413,25 @@ ledfx_presets = {
|
|||
},
|
||||
"name": "Glitter",
|
||||
},
|
||||
"color-shift": {
|
||||
"config": {
|
||||
"background_brightness": 1.0,
|
||||
"background_color": "black",
|
||||
"bass_strobe_decay_rate": 0,
|
||||
"blur": 0.0,
|
||||
"brightness": 1.0,
|
||||
"color_shift_delay": 0.1,
|
||||
"color_step": 0.0625,
|
||||
"flip": False,
|
||||
"gradient": "linear-gradient(90deg, rgb(255, 0, 0) 0%, rgb(255, 120, 0) 14%, rgb(255, 200, 0) 28%, rgb(0, 255, 0) 42%, rgb(0, 199, 140) 56%, rgb(0, 0, 255) 70%, rgb(128, 0, 128) 84%, rgb(255, 0, 178) 98%)",
|
||||
"gradient_roll": 0.0,
|
||||
"mirror": False,
|
||||
"strobe_color": "black",
|
||||
"strobe_decay_rate": 1,
|
||||
"strobe_width": 0,
|
||||
},
|
||||
"name": "Color shift",
|
||||
},
|
||||
},
|
||||
"blade_power_plus": {
|
||||
"reset": {"config": {}, "name": "Reset"},
|
||||
|
|
|
@ -540,6 +540,27 @@ def currently_frozen():
|
|||
return getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS")
|
||||
|
||||
|
||||
def get_icon_path(icon_filename) -> str:
|
||||
"""returns fully qualified path for icon, tests for frozen
|
||||
and logs error if does not exist
|
||||
|
||||
Parameters:
|
||||
icon_filename(str): the filename of the icon to be pathed
|
||||
|
||||
Returns:
|
||||
icon_location(str): fully qualified path
|
||||
"""
|
||||
current_directory = os.path.dirname(__file__)
|
||||
|
||||
icon_location = os.path.normpath(
|
||||
os.path.join(current_directory, "..", "icons", icon_filename)
|
||||
)
|
||||
|
||||
if not os.path.isfile(icon_location):
|
||||
_LOGGER.error(f"No icon found at {icon_location}")
|
||||
return icon_location
|
||||
|
||||
|
||||
def generate_id(name):
|
||||
"""Converts a name to a id"""
|
||||
part1 = re.sub("[^a-zA-Z0-9]", " ", name).lower()
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"files": {
|
||||
"main.css": "/static/css/main.4f91d95d.css",
|
||||
"main.js": "/static/js/main.6548a54d.js",
|
||||
"main.css": "/static/css/main.7161fcbe.css",
|
||||
"main.js": "/static/js/main.d11734a7.js",
|
||||
"static/js/729.58abe218.chunk.js": "/static/js/729.58abe218.chunk.js",
|
||||
"static/media/xmas.png": "/static/media/xmas.c633287113d46706b711.png",
|
||||
"static/media/fireworks.jpg": "/static/media/fireworks.81f25863cf1ec0b30fa2.jpg",
|
||||
|
@ -13,12 +13,12 @@
|
|||
"static/media/ring.png": "/static/media/ring.1faea45b576b5380bde1.png",
|
||||
"static/media/blademod.svg": "/static/media/blademod.f939f478785a84b3edcc820eef654556.svg",
|
||||
"index.html": "/index.html",
|
||||
"main.4f91d95d.css.map": "/static/css/main.4f91d95d.css.map",
|
||||
"main.6548a54d.js.map": "/static/js/main.6548a54d.js.map",
|
||||
"main.7161fcbe.css.map": "/static/css/main.7161fcbe.css.map",
|
||||
"main.d11734a7.js.map": "/static/js/main.d11734a7.js.map",
|
||||
"729.58abe218.chunk.js.map": "/static/js/729.58abe218.chunk.js.map"
|
||||
},
|
||||
"entrypoints": [
|
||||
"static/css/main.4f91d95d.css",
|
||||
"static/js/main.6548a54d.js"
|
||||
"static/css/main.7161fcbe.css",
|
||||
"static/js/main.d11734a7.js"
|
||||
]
|
||||
}
|
|
@ -10,7 +10,7 @@ const {
|
|||
app,
|
||||
Menu,
|
||||
Tray,
|
||||
// Notification,
|
||||
// Notification,
|
||||
nativeTheme,
|
||||
BrowserWindow,
|
||||
ipcMain,
|
||||
|
@ -83,11 +83,21 @@ function createWindow(args = {}) {
|
|||
// const NOTIFICATION_TITLE = 'LedFx Client - by Blade';
|
||||
// const NOTIFICATION_BODY = 'Testing Notification from the Main process';
|
||||
|
||||
// function showNotification() {
|
||||
// // function showNotification(title = NOTIFICATION_TITLE, body = NOTIFICATION_BODY) {
|
||||
// function showNotification(title = NOTIFICATION_TITLE, body = NOTIFICATION_BODY) {
|
||||
// new Notification({
|
||||
// title: NOTIFICATION_TITLE,
|
||||
// body: NOTIFICATION_BODY,
|
||||
// }).show();
|
||||
// toastXml: `<toast>
|
||||
// <visual>
|
||||
// <binding template="ToastText02">
|
||||
// <text id="1">LedFx Update available</text>
|
||||
// <text id="2">Click the button to see more informations.</text>
|
||||
// </binding>
|
||||
// </visual>
|
||||
// <actions>
|
||||
// <action content="Goto Release" activationType="protocol" arguments="https://github.com/YeonV/LedFx-Builds/releases/latest" />
|
||||
// </actions>
|
||||
// </toast>`,
|
||||
// }).show();
|
||||
// }
|
||||
|
||||
let tray = null;
|
||||
|
@ -160,7 +170,7 @@ const ready = () => (
|
|||
if (process.platform === 'darwin') app.dock.hide()
|
||||
wind.hide()
|
||||
}},
|
||||
// { label: 'Test Notifiation', click: () => showNotification() },
|
||||
// { label: 'Test Notifiation', click: () => showNotification('Update Available', 'v2.0.62') },
|
||||
{ label: 'seperator', type: 'separator' },
|
||||
{ label: 'Dev', click: () => wind.webContents.openDevTools() },
|
||||
{ label: 'seperator', type: 'separator' },
|
||||
|
@ -197,7 +207,7 @@ const ready = () => (
|
|||
if (process.platform === 'darwin') app.dock.hide()
|
||||
wind.hide()
|
||||
}},
|
||||
// { label: 'Test Notifiation', click: () => showNotification() },
|
||||
// { label: 'Test Notifiation', click: () => showNotification('Update Available', 'v2.0.62') },
|
||||
{ label: 'seperator', type: 'separator' },
|
||||
{ label: 'Dev', click: () => wind.webContents.openDevTools() },
|
||||
{ label: 'seperator', type: 'separator' },
|
||||
|
|
|
@ -1 +1 @@
|
|||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="description" content="LedFx Client - by Blade"/><link rel="apple-touch-icon" sizes="57x57" href="/favicon/apple-icon-57x57.png"><link rel="apple-touch-icon" sizes="60x60" href="/favicon/apple-icon-60x60.png"><link rel="apple-touch-icon" sizes="72x72" href="/favicon/apple-icon-72x72.png"><link rel="apple-touch-icon" sizes="76x76" href="/favicon/apple-icon-76x76.png"><link rel="apple-touch-icon" sizes="114x114" href="/favicon/apple-icon-114x114.png"><link rel="apple-touch-icon" sizes="120x120" href="/favicon/apple-icon-120x120.png"><link rel="apple-touch-icon" sizes="144x144" href="/favicon/apple-icon-144x144.png"><link rel="apple-touch-icon" sizes="152x152" href="/favicon/apple-icon-152x152.png"><link rel="apple-touch-icon" sizes="180x180" href="/favicon/apple-icon-180x180.png"><link rel="icon" type="image/png" sizes="192x192" href="/favicon/android-icon-192x192.png"><link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png"><link rel="icon" type="image/png" sizes="96x96" href="/favicon/favicon-96x96.png"><link rel="icon" type="image/png" sizes="16x16" href="/favicon/favicon-16x16.png"><meta name="msapplication-TileColor" content="#333333"><meta name="msapplication-TileImage" content="/favicon/ms-icon-144x144.png"><meta name="theme-color" content="#333333"><meta name="background-color" content="#020202"><link rel="manifest" href="/manifest.json"/><title>LedFx</title><script defer="defer" src="/static/js/main.6548a54d.js"></script><link href="/static/css/main.4f91d95d.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><script type="application/javascript">"serviceWorker"in navigator&&window.addEventListener("load",(function(){navigator.serviceWorker.register("serviceWorker.js",{scope:"."}).then((function(e){console.debug("ServiceWorker registration successful with scope: ",e.scope)}),(function(e){console.debug("ServiceWorker registration failed: ",e)}))}))</script><div id="root"></div></body></html>
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="description" content="LedFx Client - by Blade"/><link rel="apple-touch-icon" sizes="57x57" href="/favicon/apple-icon-57x57.png"><link rel="apple-touch-icon" sizes="60x60" href="/favicon/apple-icon-60x60.png"><link rel="apple-touch-icon" sizes="72x72" href="/favicon/apple-icon-72x72.png"><link rel="apple-touch-icon" sizes="76x76" href="/favicon/apple-icon-76x76.png"><link rel="apple-touch-icon" sizes="114x114" href="/favicon/apple-icon-114x114.png"><link rel="apple-touch-icon" sizes="120x120" href="/favicon/apple-icon-120x120.png"><link rel="apple-touch-icon" sizes="144x144" href="/favicon/apple-icon-144x144.png"><link rel="apple-touch-icon" sizes="152x152" href="/favicon/apple-icon-152x152.png"><link rel="apple-touch-icon" sizes="180x180" href="/favicon/apple-icon-180x180.png"><link rel="icon" type="image/png" sizes="192x192" href="/favicon/android-icon-192x192.png"><link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png"><link rel="icon" type="image/png" sizes="96x96" href="/favicon/favicon-96x96.png"><link rel="icon" type="image/png" sizes="16x16" href="/favicon/favicon-16x16.png"><meta name="msapplication-TileColor" content="#333333"><meta name="msapplication-TileImage" content="/favicon/ms-icon-144x144.png"><meta name="theme-color" content="#333333"><meta name="background-color" content="#020202"><link rel="manifest" href="/manifest.json"/><title>LedFx</title><script defer="defer" src="/static/js/main.d11734a7.js"></script><link href="/static/css/main.7161fcbe.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><script type="application/javascript">"serviceWorker"in navigator&&window.addEventListener("load",(function(){navigator.serviceWorker.register("serviceWorker.js",{scope:"."}).then((function(e){console.debug("ServiceWorker registration successful with scope: ",e.scope)}),(function(e){console.debug("ServiceWorker registration failed: ",e)}))}))</script><div id="root"></div></body></html>
|
|
@ -1,4 +0,0 @@
|
|||
+ Release 2.0.60
|
||||
+ Merge branch 'main' of https://github.com/YeonV/LedFx-Frontend-v2
|
||||
+ Release 2.0.60
|
||||
+ Release 2.0.58
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -12,6 +12,7 @@
|
|||
certifi~=2020.12.5
|
||||
multidict~=5.0.0
|
||||
numpy~=1.23
|
||||
notify-py>=0.3.42
|
||||
openrgb-python~=0.2.10
|
||||
paho-mqtt~=1.5.1
|
||||
psutil>=5.8.0
|
||||
|
@ -25,5 +26,5 @@
|
|||
tcp-latency~=0.0.10
|
||||
voluptuous~=0.12.1
|
||||
yappi~=1.3.3
|
||||
zeroconf==0.39.4
|
||||
flux_led==0.28.35
|
||||
zeroconf~=0.39.4
|
||||
|
|
3
setup.py
3
setup.py
|
@ -29,6 +29,7 @@ INSTALL_REQUIRES = [
|
|||
"cython>=0.29.21",
|
||||
"certifi>=2020.12.5",
|
||||
"multidict~=5.0.0",
|
||||
"notify-py>=0.3.42",
|
||||
"openrgb-python~=0.2.10",
|
||||
"paho-mqtt>=1.5.1",
|
||||
"psutil>=5.8.0",
|
||||
|
@ -42,7 +43,7 @@ INSTALL_REQUIRES = [
|
|||
"samplerate>=0.1.0",
|
||||
"tcp-latency>=0.0.10",
|
||||
"voluptuous~=0.12.1",
|
||||
"zeroconf==0.39.4",
|
||||
"zeroconf~=0.39.4",
|
||||
"pillow>=8.4.0",
|
||||
# Conditional Requirement
|
||||
# We need pywin32 for Windows
|
||||
|
|
9
win.spec
9
win.spec
|
@ -1,6 +1,6 @@
|
|||
# -*- mode: python ; coding: utf-8 -*-
|
||||
import os
|
||||
|
||||
from hiddenimports import hiddenimports
|
||||
spec_root = os.path.abspath(SPECPATH)
|
||||
|
||||
venv_root = os.path.abspath(os.path.join(SPECPATH, '..'))
|
||||
|
@ -12,10 +12,7 @@ a = Analysis([f'{spec_root}\\ledfx\\__main__.py'],
|
|||
pathex=[f'{spec_root}', f'{spec_root}\\ledfx'],
|
||||
binaries=[],
|
||||
datas=[(f'{spec_root}/ledfx_frontend', 'ledfx_frontend/'), (f'{spec_root}/ledfx/', 'ledfx/'), (f'{spec_root}/icons', 'icons/'),(f'{spec_root}/icons/tray.png','.')],
|
||||
hiddenimports=['sacn', 'aubio', 'numpy', 'math', 'voluptuous', 'numpy', 'aiohttp', 'mido','mido.frozen', 'paho', 'paho.mqtt', 'openrgb-python', 'openrgb', 'python-rtmidi','rtmidi', 'mido.backends.rtmidi', 'paho.mqtt.client','samplerate','_samplerate_data', 'sounddevice',
|
||||
'sentry_sdk', 'sentry_sdk.integrations.django','sentry_sdk.integrations.flask','sentry_sdk.integrations.bottle','sentry_sdk.integrations.falcon','sentry_sdk.integrations.sanic',
|
||||
'sentry_sdk.integrations.celery','sentry_sdk.integrations.aiohttp','sentry_sdk.integrations.rq','sentry_sdk.integrations.tornado','sentry_sdk.integrations.sqlalchemy',
|
||||
'sentry_sdk.integrations.boto3','_cffi_backend','serial','pystray._win32','serial.tools.list_ports','tcp_latency','aiohttp_cors','psutil','yappi'],
|
||||
hiddenimports=hiddenimports,
|
||||
hookspath=[f'{venv_root}\\lib\\site-packages\\pyupdater\\hooks'],
|
||||
runtime_hooks=[],
|
||||
excludes=[],
|
||||
|
@ -43,4 +40,4 @@ coll = COLLECT(exe,
|
|||
strip=False,
|
||||
upx=True,
|
||||
upx_exclude=[],
|
||||
name='LedFx')
|
||||
name='LedFx')
|
Loading…
Reference in New Issue