fastled 1.2.49__tar.gz → 1.2.59__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. {fastled-1.2.49 → fastled-1.2.59}/.github/workflows/test_macos.yml +1 -1
  2. {fastled-1.2.49 → fastled-1.2.59}/.github/workflows/test_ubuntu.yml +1 -1
  3. {fastled-1.2.49 → fastled-1.2.59}/.github/workflows/test_win.yml +1 -1
  4. {fastled-1.2.49 → fastled-1.2.59}/.gitignore +1 -1
  5. {fastled-1.2.49 → fastled-1.2.59}/Dockerfile +2 -2
  6. {fastled-1.2.49 → fastled-1.2.59}/PKG-INFO +19 -5
  7. {fastled-1.2.49 → fastled-1.2.59}/README.md +13 -1
  8. {fastled-1.2.49 → fastled-1.2.59}/compiler/compile.py +29 -16
  9. fastled-1.2.59/compiler/entrypoint.sh +16 -0
  10. fastled-1.2.59/compiler/extra/micdemo.html +136 -0
  11. fastled-1.2.59/compiler/process_extended.py +109 -0
  12. fastled-1.2.59/compiler/pyproject.toml +22 -0
  13. {fastled-1.2.49 → fastled-1.2.59}/compiler/server.py +3 -0
  14. {fastled-1.2.49 → fastled-1.2.59}/lint +1 -3
  15. {fastled-1.2.49 → fastled-1.2.59}/pyproject.toml +3 -2
  16. {fastled-1.2.49 → fastled-1.2.59}/src/fastled/__init__.py +1 -1
  17. {fastled-1.2.49 → fastled-1.2.59}/src/fastled/app.py +1 -2
  18. fastled-1.2.59/src/fastled/assets/localhost-key.pem +28 -0
  19. fastled-1.2.59/src/fastled/assets/localhost.pem +27 -0
  20. fastled-1.2.59/src/fastled/cli_test.py +20 -0
  21. {fastled-1.2.49 → fastled-1.2.59}/src/fastled/client_server.py +8 -7
  22. {fastled-1.2.49 → fastled-1.2.59}/src/fastled/docker_manager.py +2 -1
  23. {fastled-1.2.49 → fastled-1.2.59}/src/fastled/filewatcher.py +78 -1
  24. {fastled-1.2.49 → fastled-1.2.59}/src/fastled/keyboard.py +1 -0
  25. fastled-1.2.59/src/fastled/keyz.py +30 -0
  26. {fastled-1.2.49 → fastled-1.2.59}/src/fastled/open_browser.py +55 -65
  27. fastled-1.2.59/src/fastled/open_browser2.py +108 -0
  28. fastled-1.2.59/src/fastled/server_fastapi.py +60 -0
  29. fastled-1.2.59/src/fastled/server_fastapi_cli.py +60 -0
  30. {fastled-1.2.49 → fastled-1.2.59}/src/fastled/settings.py +1 -0
  31. {fastled-1.2.49 → fastled-1.2.59}/src/fastled/site/build.py +2 -10
  32. fastled-1.2.59/src/fastled/site/examples.py +10 -0
  33. {fastled-1.2.49 → fastled-1.2.59}/src/fastled/string_diff.py +23 -5
  34. {fastled-1.2.49 → fastled-1.2.59}/src/fastled.egg-info/PKG-INFO +19 -5
  35. {fastled-1.2.49 → fastled-1.2.59}/src/fastled.egg-info/SOURCES.txt +31 -21
  36. {fastled-1.2.49 → fastled-1.2.59}/src/fastled.egg-info/requires.txt +3 -2
  37. {fastled-1.2.49 → fastled-1.2.59}/test +2 -2
  38. {fastled-1.2.49/tests → fastled-1.2.59/tests/integration}/test_build_examples.py +12 -1
  39. {fastled-1.2.49/tests → fastled-1.2.59/tests/integration}/test_examples.py +1 -1
  40. {fastled-1.2.49/tests → fastled-1.2.59/tests/unit}/test_embedded_data.py +8 -2
  41. {fastled-1.2.49/tests → fastled-1.2.59/tests/unit}/test_http_server.py +2 -2
  42. fastled-1.2.59/tests/unit/test_string_diff.py +80 -0
  43. fastled-1.2.49/compiler/entrypoint.sh +0 -7
  44. fastled-1.2.49/compiler/requirements.txt +0 -12
  45. fastled-1.2.49/src/fastled/open_browser2.py +0 -111
  46. {fastled-1.2.49 → fastled-1.2.59}/.aiderignore +0 -0
  47. {fastled-1.2.49 → fastled-1.2.59}/.dockerignore +0 -0
  48. {fastled-1.2.49 → fastled-1.2.59}/.github/workflows/build_multi_docker_image.yml +0 -0
  49. {fastled-1.2.49 → fastled-1.2.59}/.github/workflows/build_webpage.yml +0 -0
  50. {fastled-1.2.49 → fastled-1.2.59}/.github/workflows/lint.yml +0 -0
  51. {fastled-1.2.49 → fastled-1.2.59}/.github/workflows/publish_release.yml +0 -0
  52. {fastled-1.2.49 → fastled-1.2.59}/.github/workflows/template_build_docker_image.yml +0 -0
  53. {fastled-1.2.49 → fastled-1.2.59}/.github/workflows/test_build_exe.yml +0 -0
  54. {fastled-1.2.49 → fastled-1.2.59}/.pylintrc +0 -0
  55. {fastled-1.2.49 → fastled-1.2.59}/.vscode/launch.json +0 -0
  56. {fastled-1.2.49 → fastled-1.2.59}/.vscode/settings.json +0 -0
  57. {fastled-1.2.49 → fastled-1.2.59}/.vscode/tasks.json +0 -0
  58. {fastled-1.2.49 → fastled-1.2.59}/LICENSE +0 -0
  59. {fastled-1.2.49 → fastled-1.2.59}/MANIFEST.in +0 -0
  60. {fastled-1.2.49 → fastled-1.2.59}/RELEASE.md +0 -0
  61. {fastled-1.2.49 → fastled-1.2.59}/TODO.md +0 -0
  62. {fastled-1.2.49 → fastled-1.2.59}/build_exe.py +0 -0
  63. {fastled-1.2.49 → fastled-1.2.59}/build_site.py +0 -0
  64. {fastled-1.2.49 → fastled-1.2.59}/clean +0 -0
  65. {fastled-1.2.49 → fastled-1.2.59}/compiler/CMakeLists.txt +0 -0
  66. {fastled-1.2.49 → fastled-1.2.59}/compiler/__init__.py +0 -0
  67. {fastled-1.2.49 → fastled-1.2.59}/compiler/arduino-pre-process.sh +0 -0
  68. {fastled-1.2.49 → fastled-1.2.59}/compiler/build.sh +0 -0
  69. {fastled-1.2.49 → fastled-1.2.59}/compiler/build_archive.sh +0 -0
  70. {fastled-1.2.49 → fastled-1.2.59}/compiler/build_fast.sh +0 -0
  71. {fastled-1.2.49 → fastled-1.2.59}/compiler/code_sync.py +0 -0
  72. {fastled-1.2.49 → fastled-1.2.59}/compiler/compile_lock.py +0 -0
  73. {fastled-1.2.49 → fastled-1.2.59}/compiler/extra/100dots.html +0 -0
  74. {fastled-1.2.49 → fastled-1.2.59}/compiler/extra/demo_threejs.html +0 -0
  75. {fastled-1.2.49 → fastled-1.2.59}/compiler/extra/webgl_postprocessing_unreal_bloom.html +0 -0
  76. {fastled-1.2.49 → fastled-1.2.59}/compiler/final_prewarm.sh +0 -0
  77. {fastled-1.2.49 → fastled-1.2.59}/compiler/init_runtime.py +0 -0
  78. {fastled-1.2.49 → fastled-1.2.59}/compiler/install-arduino-cli.sh +0 -0
  79. {fastled-1.2.49 → fastled-1.2.59}/compiler/libcompile/CMakeLists.txt +0 -0
  80. {fastled-1.2.49 → fastled-1.2.59}/compiler/paths.py +0 -0
  81. {fastled-1.2.49 → fastled-1.2.59}/compiler/pre-process.sh +0 -0
  82. {fastled-1.2.49 → fastled-1.2.59}/compiler/prewarm.sh +0 -0
  83. {fastled-1.2.49 → fastled-1.2.59}/compiler/process-ino.py +0 -0
  84. {fastled-1.2.49 → fastled-1.2.59}/compiler/run.py +0 -0
  85. {fastled-1.2.49 → fastled-1.2.59}/compiler/sketch_hasher.py +0 -0
  86. {fastled-1.2.49 → fastled-1.2.59}/compiler/wasm_compiler_flags.py +0 -0
  87. {fastled-1.2.49 → fastled-1.2.59}/docker-compose.yml +0 -0
  88. {fastled-1.2.49 → fastled-1.2.59}/install +0 -0
  89. {fastled-1.2.49 → fastled-1.2.59}/install_linux.sh +0 -0
  90. {fastled-1.2.49 → fastled-1.2.59}/requirements.testing.txt +0 -0
  91. {fastled-1.2.49 → fastled-1.2.59}/setup.cfg +0 -0
  92. {fastled-1.2.49 → fastled-1.2.59}/setup.py +0 -0
  93. {fastled-1.2.49 → fastled-1.2.59}/src/fastled/assets/example.txt +0 -0
  94. {fastled-1.2.49 → fastled-1.2.59}/src/fastled/cli.py +0 -0
  95. {fastled-1.2.49 → fastled-1.2.59}/src/fastled/compile_server.py +0 -0
  96. {fastled-1.2.49 → fastled-1.2.59}/src/fastled/compile_server_impl.py +0 -0
  97. {fastled-1.2.49 → fastled-1.2.59}/src/fastled/interactive_srcs.py +0 -0
  98. {fastled-1.2.49 → fastled-1.2.59}/src/fastled/live_client.py +0 -0
  99. {fastled-1.2.49 → fastled-1.2.59}/src/fastled/parse_args.py +0 -0
  100. {fastled-1.2.49 → fastled-1.2.59}/src/fastled/paths.py +0 -0
  101. {fastled-1.2.49 → fastled-1.2.59}/src/fastled/project_init.py +0 -0
  102. {fastled-1.2.49 → fastled-1.2.59}/src/fastled/select_sketch_directory.py +0 -0
  103. {fastled-1.2.49 → fastled-1.2.59}/src/fastled/sketch.py +0 -0
  104. {fastled-1.2.49 → fastled-1.2.59}/src/fastled/spinner.py +0 -0
  105. {fastled-1.2.49 → fastled-1.2.59}/src/fastled/test/can_run_local_docker_tests.py +0 -0
  106. {fastled-1.2.49 → fastled-1.2.59}/src/fastled/test/examples.py +0 -0
  107. {fastled-1.2.49 → fastled-1.2.59}/src/fastled/types.py +0 -0
  108. {fastled-1.2.49 → fastled-1.2.59}/src/fastled/util.py +0 -0
  109. {fastled-1.2.49 → fastled-1.2.59}/src/fastled/web_compile.py +0 -0
  110. {fastled-1.2.49 → fastled-1.2.59}/src/fastled.egg-info/dependency_links.txt +0 -0
  111. {fastled-1.2.49 → fastled-1.2.59}/src/fastled.egg-info/entry_points.txt +0 -0
  112. {fastled-1.2.49 → fastled-1.2.59}/src/fastled.egg-info/top_level.txt +0 -0
  113. {fastled-1.2.49/tests → fastled-1.2.59/tests/unit}/html/index.html +0 -0
  114. {fastled-1.2.49/tests → fastled-1.2.59/tests/unit}/test_api.py +0 -0
  115. {fastled-1.2.49/tests → fastled-1.2.59/tests/unit}/test_bad_ino.py +0 -0
  116. {fastled-1.2.49/tests → fastled-1.2.59/tests/unit}/test_cli.py +0 -0
  117. {fastled-1.2.49/tests → fastled-1.2.59/tests/unit}/test_compile_server.py +0 -0
  118. {fastled-1.2.49/tests → fastled-1.2.59/tests/unit}/test_docker_linux_on_windows.py +0 -0
  119. {fastled-1.2.49/tests → fastled-1.2.59/tests/unit}/test_filechanger.py +0 -0
  120. {fastled-1.2.49/tests → fastled-1.2.59/tests/unit}/test_ino/bad/bad.ino +0 -0
  121. {fastled-1.2.49/tests → fastled-1.2.59/tests/unit}/test_ino/bad_platformio/bad_platformio.ino +0 -0
  122. {fastled-1.2.49/tests → fastled-1.2.59/tests/unit}/test_ino/bad_platformio/platformio.ini +0 -0
  123. {fastled-1.2.49/tests → fastled-1.2.59/tests/unit}/test_ino/embedded/data/bigdata.dat +0 -0
  124. {fastled-1.2.49/tests → fastled-1.2.59/tests/unit}/test_ino/embedded/wasm.ino +0 -0
  125. {fastled-1.2.49/tests → fastled-1.2.59/tests/unit}/test_ino/wasm/wasm.ino +0 -0
  126. {fastled-1.2.49/tests → fastled-1.2.59/tests/unit}/test_project_init.py +0 -0
  127. {fastled-1.2.49/tests → fastled-1.2.59/tests/unit}/test_server_and_client_seperatly.py +0 -0
  128. {fastled-1.2.49/tests → fastled-1.2.59/tests/unit}/test_webcompile.py +0 -0
  129. {fastled-1.2.49 → fastled-1.2.59}/upload_package.sh +0 -0
@@ -26,4 +26,4 @@ jobs:
26
26
  run: ./test
27
27
 
28
28
  - name: live run
29
- run: pip install . && cd tests/test_ino/wasm && sudo rm -rf fastled_js && time fastled-wasm --just-compile && find fastled_js | sort
29
+ run: pip install . && cd tests/unit/test_ino/wasm && sudo rm -rf fastled_js && time fastled-wasm --just-compile && find fastled_js | sort
@@ -26,4 +26,4 @@ jobs:
26
26
  run: ./test
27
27
 
28
28
  - name: live run
29
- run: pip install . && cd tests/test_ino/wasm && sudo rm -rf fastled_js && time fastled-wasm --just-compile && find fastled_js | sort
29
+ run: pip install . && cd tests/unit/test_ino/wasm && sudo rm -rf fastled_js && time fastled-wasm --just-compile && find fastled_js | sort
@@ -28,5 +28,5 @@ jobs:
28
28
  shell: bash -l {0}
29
29
 
30
30
  - name: live run
31
- run: pip install . && cd tests/test_ino/wasm && rm -rf fastled_js && time fastled-wasm --web --just-compile && find fastled_js | sort
31
+ run: pip install . && cd tests/unit/test_ino/wasm && rm -rf fastled_js && time fastled-wasm --web --just-compile && find fastled_js | sort
32
32
  shell: bash -l {0}
@@ -14,7 +14,7 @@ __pycache__/
14
14
  .Python
15
15
  prod_env/
16
16
  data/
17
- !tests/test_ino/embedded/data
17
+ !tests/**/embedded/data
18
18
  build/
19
19
  develop-eggs/
20
20
  dist/
@@ -124,8 +124,8 @@ RUN echo 'export LANG=en_US.UTF-8' >> /etc/profile && \
124
124
  RUN pip install uv==0.6.5
125
125
 
126
126
  # Get the compiler requirements and install them.
127
- COPY compiler/requirements.txt /install/requirements.txt
128
- RUN uv pip install --system -r /install/requirements.txt
127
+ COPY compiler/pyproject.toml /install/pyproject.toml
128
+ RUN uv pip install --system -r /install/pyproject.toml
129
129
 
130
130
  RUN pio settings set check_platformio_interval 9999
131
131
  RUN pio settings set enable_telemetry 0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: fastled
3
- Version: 1.2.49
3
+ Version: 1.2.59
4
4
  Summary: FastLED Wasm Compiler
5
5
  Home-page: https://github.com/zackees/fastled-wasm
6
6
  Maintainer: Zachary Vorhies
@@ -19,9 +19,11 @@ Requires-Dist: disklru>=2.0.1
19
19
  Requires-Dist: appdirs>=1.4.4
20
20
  Requires-Dist: rapidfuzz>=3.10.1
21
21
  Requires-Dist: progress>=1.6
22
- Requires-Dist: Flask>=3.0.0
23
- Requires-Dist: livereload
22
+ Requires-Dist: fastapi>=0.115.12
23
+ Requires-Dist: uvicorn>=0.34.2
24
+ Requires-Dist: pywebview>=5.4
24
25
  Dynamic: home-page
26
+ Dynamic: license-file
25
27
  Dynamic: maintainer
26
28
 
27
29
  # FastLED Wasm compiler
@@ -294,8 +296,8 @@ A: `delay()` will block `loop()` which blocks the main thread of the browser. Th
294
296
  Q: How can I get the compiled size of my FastLED sketch smaller?
295
297
  A: A big chunk of space is being used by unnecessary javascript `emscripten` bundling. The wasm_compiler_settings.py file in the FastLED repo can tweak this.
296
298
 
297
- # Revisions
298
299
 
300
+ # Revisions
299
301
  * 1.2.31 - Bunch of fixes and ease of use while compiling code in the repo.
300
302
  * 1.2.22 - Prefer to use `live-server` from npm. If npm exists on the system then do a background install of `live-server` for next run.
301
303
  * 1.2.20 - Fixed up path issue for web browser launch for hot reload.
@@ -381,3 +383,15 @@ A: A big chunk of space is being used by unnecessary javascript `emscripten` bun
381
383
  * 1.0.2 - Small bug with new installs.
382
384
  * 1.0.1 - Re-use is no longer the default, due to problems.
383
385
  * 1.0.0 - Initial release.
386
+
387
+
388
+ # TODO
389
+ * `live-server --https --cert=localhost.pem --key=localhost-key.pem --port=5500`
390
+ * `live-server --port=8416 --host=localhost . --https --cert=C:/Users/niteris/dev/fastled-wasm/src/fastled/assets/localhost-key.pem --key=C:/Users/niteris/dev/fastled-wasm/src/fastled/assets/localhost.pem --no-browser`
391
+
392
+
393
+
394
+ live-server --https --port=8416 --host=localhost . --cert=C:/Users/niteris/dev/fastled-wasm/src/fastled/assets/localhost-key.pem --key=C:/Users/niteris/dev/fastled-wasm/src/fastled/assets/localhost.pem --no-browser
395
+
396
+
397
+ live-server --https --cert=src/fastled/assets/localhost.pem --key=src/fastled/assets/localhost-key.pem --port=5500
@@ -268,8 +268,8 @@ A: `delay()` will block `loop()` which blocks the main thread of the browser. Th
268
268
  Q: How can I get the compiled size of my FastLED sketch smaller?
269
269
  A: A big chunk of space is being used by unnecessary javascript `emscripten` bundling. The wasm_compiler_settings.py file in the FastLED repo can tweak this.
270
270
 
271
- # Revisions
272
271
 
272
+ # Revisions
273
273
  * 1.2.31 - Bunch of fixes and ease of use while compiling code in the repo.
274
274
  * 1.2.22 - Prefer to use `live-server` from npm. If npm exists on the system then do a background install of `live-server` for next run.
275
275
  * 1.2.20 - Fixed up path issue for web browser launch for hot reload.
@@ -355,3 +355,15 @@ A: A big chunk of space is being used by unnecessary javascript `emscripten` bun
355
355
  * 1.0.2 - Small bug with new installs.
356
356
  * 1.0.1 - Re-use is no longer the default, due to problems.
357
357
  * 1.0.0 - Initial release.
358
+
359
+
360
+ # TODO
361
+ * `live-server --https --cert=localhost.pem --key=localhost-key.pem --port=5500`
362
+ * `live-server --port=8416 --host=localhost . --https --cert=C:/Users/niteris/dev/fastled-wasm/src/fastled/assets/localhost-key.pem --key=C:/Users/niteris/dev/fastled-wasm/src/fastled/assets/localhost.pem --no-browser`
363
+
364
+
365
+
366
+ live-server --https --port=8416 --host=localhost . --cert=C:/Users/niteris/dev/fastled-wasm/src/fastled/assets/localhost-key.pem --key=C:/Users/niteris/dev/fastled-wasm/src/fastled/assets/localhost.pem --no-browser
367
+
368
+
369
+ live-server --https --cert=src/fastled/assets/localhost.pem --key=src/fastled/assets/localhost-key.pem --port=5500
@@ -9,27 +9,38 @@
9
9
  # enforced by the script that sets up the docker container.
10
10
  # 2. The docker container has installed compiler dependencies in the /js directory.
11
11
 
12
- import argparse
13
- import hashlib
14
- import json
15
- import os
16
- import re
17
- import shutil
18
- import subprocess
19
- import sys
20
- import traceback
21
- from dataclasses import dataclass
22
- from datetime import datetime
23
- from enum import Enum
24
- from pathlib import Path
25
- from typing import List
26
-
27
- from paths import COMPILER_ROOT, FASTLED_COMPILER_DIR, PIO_BUILD_DIR, SKETCH_SRC
12
+
13
+ print("Compiler script starting...")
14
+
15
+ import argparse # noqa: E402
16
+ import hashlib # noqa: E402
17
+ import json # noqa: E402
18
+ import os # noqa: E402
19
+ import re # noqa: E402
20
+ import shutil # noqa: E402
21
+ import subprocess # noqa: E402
22
+ import sys # noqa: E402
23
+ import traceback # noqa: E402
24
+ from dataclasses import dataclass # noqa: E402
25
+ from datetime import datetime # noqa: E402
26
+ from enum import Enum # noqa: E402
27
+ from pathlib import Path # noqa: E402
28
+ from typing import List # noqa: E402
29
+
30
+ from paths import ( # noqa: E402
31
+ COMPILER_ROOT,
32
+ FASTLED_COMPILER_DIR,
33
+ PIO_BUILD_DIR,
34
+ SKETCH_SRC,
35
+ )
36
+
37
+ print("Finished imports...")
28
38
 
29
39
  _FASTLED_MODULES_DIR = FASTLED_COMPILER_DIR / "modules"
30
40
  _INDEX_HTML_SRC = FASTLED_COMPILER_DIR / "index.html"
31
41
  _INDEX_CSS_SRC = FASTLED_COMPILER_DIR / "index.css"
32
42
  _INDEX_JS_SRC = FASTLED_COMPILER_DIR / "index.js"
43
+ _PIO_VERBOSE = True
33
44
 
34
45
 
35
46
  _WASM_COMPILER_SETTTINGS = FASTLED_COMPILER_DIR / "wasm_compiler_flags.py"
@@ -98,6 +109,8 @@ def compile(
98
109
  cmd_list.extend(["pio", "run"])
99
110
  if not auto_clean:
100
111
  cmd_list.append("--disable-auto-clean")
112
+ if _PIO_VERBOSE:
113
+ cmd_list.append("-v")
101
114
 
102
115
  def _open_process(cmd_list: list[str] = cmd_list) -> subprocess.Popen:
103
116
  out = subprocess.Popen(
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # load emsdk environment
4
+ source /emsdk/emsdk_env.sh
5
+ export PATH="$PATH:/emsdk/upstream/bin"
6
+
7
+ # initialize runtime
8
+ python init_runtime.py
9
+
10
+ # only do the final prewarm if RUNTIME_PREWARM is set to "1"
11
+ if [[ "${RUNTIME_PREWARM:-0}" == "1" ]]; then
12
+ ./final_prewarm.sh
13
+ fi
14
+
15
+ # hand off to the main command
16
+ exec "$@"
@@ -0,0 +1,136 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Mic & System Audio Demo</title>
7
+ <style>
8
+ body { font-family: sans-serif; text-align: center; padding: 2rem; }
9
+ #controls { margin-bottom: 1rem; }
10
+ #volume { font-size: 2rem; margin-bottom: 1rem; }
11
+ #bar {
12
+ width: 300px;
13
+ height: 30px;
14
+ background: #eee;
15
+ margin: 0 auto;
16
+ border: 1px solid #ccc;
17
+ border-radius: 4px;
18
+ overflow: hidden;
19
+ }
20
+ #fill {
21
+ height: 100%;
22
+ width: 0%;
23
+ background: #76ce60;
24
+ transition: width 0.1s ease;
25
+ }
26
+ #mic-select { margin-left: 0.5rem; }
27
+ </style>
28
+ </head>
29
+ <body>
30
+ <h1>Audio Volume Demo</h1>
31
+ <div id="controls">
32
+ <label><input type="radio" name="source" value="mic" checked> Microphone</label>
33
+ <label><input type="radio" name="source" value="tab"> Tab/Screen Audio</label>
34
+ <select id="mic-select"></select>
35
+ </div>
36
+ <div id="volume">-∞ dBFS</div>
37
+ <div id="bar"><div id="fill"></div></div>
38
+
39
+ <script>
40
+ let audioCtx, analyser, dataArray;
41
+ let currentStream;
42
+
43
+ async function listAudioInputs() {
44
+ const devices = await navigator.mediaDevices.enumerateDevices();
45
+ const mics = devices.filter(d => d.kind === 'audioinput');
46
+ const select = document.getElementById('mic-select');
47
+ select.innerHTML = '';
48
+ mics.forEach((mic, i) => {
49
+ const option = document.createElement('option');
50
+ option.value = mic.deviceId;
51
+ option.text = mic.label || `Microphone ${i+1}`;
52
+ select.appendChild(option);
53
+ });
54
+ select.onchange = () => startMic(select.value);
55
+ if (mics.length) startMic(mics[0].deviceId);
56
+ }
57
+
58
+ async function startMic(deviceId) {
59
+ stopStream();
60
+ try {
61
+ currentStream = await navigator.mediaDevices.getUserMedia({ audio: { deviceId: { exact: deviceId } } });
62
+ setupAudioGraph(currentStream);
63
+ } catch (err) {
64
+ alert('Error accessing microphone: ' + err.message);
65
+ }
66
+ }
67
+
68
+ async function startTabAudio() {
69
+ stopStream();
70
+ try {
71
+ currentStream = await navigator.mediaDevices.getDisplayMedia({ audio: true, video: false });
72
+ setupAudioGraph(currentStream);
73
+ } catch (err) {
74
+ alert('Error capturing tab/screen audio: ' + err.message);
75
+ }
76
+ }
77
+
78
+ function stopStream() {
79
+ if (currentStream) {
80
+ currentStream.getTracks().forEach(track => track.stop());
81
+ }
82
+ }
83
+
84
+ function setupAudioGraph(stream) {
85
+ if (!audioCtx) {
86
+ audioCtx = new (window.AudioContext || window.webkitAudioContext)();
87
+ }
88
+ const source = audioCtx.createMediaStreamSource(stream);
89
+ analyser = audioCtx.createAnalyser();
90
+ analyser.fftSize = 2048;
91
+ source.connect(analyser);
92
+ dataArray = new Float32Array(analyser.fftSize);
93
+ updateVolume();
94
+ }
95
+
96
+ function updateVolume() {
97
+ analyser.getFloatTimeDomainData(dataArray);
98
+ let max = 0;
99
+ for (let i = 0; i < dataArray.length; i++) {
100
+ const v = Math.abs(dataArray[i]);
101
+ if (v > max) max = v;
102
+ }
103
+
104
+ const db = max > 0 ? 20 * Math.log10(max) : -Infinity;
105
+ const dbDisplay = db === -Infinity ? '-∞' : db.toFixed(1);
106
+ document.getElementById('volume').textContent = `${dbDisplay} dBFS`;
107
+
108
+ const percent = Math.min(max * 100, 100);
109
+ document.getElementById('fill').style.width = percent + '%';
110
+
111
+ requestAnimationFrame(updateVolume);
112
+ }
113
+
114
+ // Switcher
115
+ document.querySelectorAll('input[name="source"]').forEach(radio => {
116
+ radio.addEventListener('change', e => {
117
+ const mode = e.target.value;
118
+ if (mode === 'mic') {
119
+ document.getElementById('mic-select').style.display = '';
120
+ listAudioInputs();
121
+ } else {
122
+ document.getElementById('mic-select').style.display = 'none';
123
+ startTabAudio();
124
+ }
125
+ });
126
+ });
127
+
128
+ // Initialize
129
+ if (navigator.mediaDevices && navigator.mediaDevices.enumerateDevices) {
130
+ listAudioInputs();
131
+ } else {
132
+ alert('enumerateDevices() not supported.');
133
+ }
134
+ </script>
135
+ </body>
136
+ </html>
@@ -0,0 +1,109 @@
1
+ """
2
+ Experimental module that extends the multiprocessing.Process class to redirect
3
+ stdout and stderr to pipes that can be read line-by-line in real time.
4
+
5
+ """
6
+
7
+ import multiprocessing
8
+ import os
9
+ import sys
10
+ import time
11
+
12
+
13
+ class ProcessExtended(multiprocessing.Process):
14
+ def __init__(self, target, args=(), kwargs=None):
15
+ if kwargs is None:
16
+ kwargs = {}
17
+ # Store the target function and its arguments.
18
+ self._target_func = target
19
+ self._target_args = args
20
+ self._target_kwargs = kwargs
21
+ # Create OS pipes for stdout and stderr.
22
+ self._stdout_pipe_read, self._stdout_pipe_write = os.pipe()
23
+ self._stderr_pipe_read, self._stderr_pipe_write = os.pipe()
24
+ super().__init__()
25
+
26
+ def run(self):
27
+ """
28
+ In the child process, close the parent's copy of the read ends,
29
+ duplicate the write ends to stdout and stderr, and execute the target function.
30
+ """
31
+ # In child: close the parent's read ends.
32
+ os.close(self._stdout_pipe_read)
33
+ os.close(self._stderr_pipe_read)
34
+
35
+ # Redirect stdout and stderr to the write ends of the pipes.
36
+ os.dup2(self._stdout_pipe_write, sys.stdout.fileno())
37
+ os.dup2(self._stderr_pipe_write, sys.stderr.fileno())
38
+
39
+ # Reassign the Python-level streams with line buffering.
40
+ sys.stdout = os.fdopen(sys.stdout.fileno(), "w", buffering=1)
41
+ sys.stderr = os.fdopen(sys.stderr.fileno(), "w", buffering=1)
42
+
43
+ try:
44
+ self._target_func(*self._target_args, **self._target_kwargs)
45
+ finally:
46
+ # Flush and close the write ends so the parent can detect EOF.
47
+ sys.stdout.flush()
48
+ sys.stderr.flush()
49
+ os.close(self._stdout_pipe_write)
50
+ os.close(self._stderr_pipe_write)
51
+
52
+ def start(self):
53
+ """
54
+ Start the child process and, in the parent process, close the write ends
55
+ of the pipes so that reading from the read ends will end once the child closes them.
56
+ """
57
+ super().start()
58
+ # In the parent process, close the write ends.
59
+ os.close(self._stdout_pipe_write)
60
+ os.close(self._stderr_pipe_write)
61
+
62
+ @property
63
+ def stdout(self):
64
+ """
65
+ Returns a file object that can be iterated line-by-line to read the child's stdout.
66
+ """
67
+ if not hasattr(self, "_stdout_file"):
68
+ self._stdout_file = os.fdopen(self._stdout_pipe_read, "r", buffering=1)
69
+ return self._stdout_file
70
+
71
+ @property
72
+ def stderr(self):
73
+ """
74
+ Returns a file object that can be iterated line-by-line to read the child's stderr.
75
+ """
76
+ if not hasattr(self, "_stderr_file"):
77
+ self._stderr_file = os.fdopen(self._stderr_pipe_read, "r", buffering=1)
78
+ return self._stderr_file
79
+
80
+
81
+ # -------------------------------
82
+ # Example usage:
83
+ # -------------------------------
84
+ def worker():
85
+ for i in range(5):
86
+ print(f"stdout line {i}")
87
+ print(f"stderr line {i}", file=sys.stderr)
88
+ time.sleep(1)
89
+
90
+
91
+ if __name__ == "__main__":
92
+ proc = ProcessExtended(target=worker)
93
+ proc.start()
94
+
95
+ # Iterate over stdout in real time.
96
+ # Note: In a real-world scenario you might want to use threads or select/poll to
97
+ # concurrently process stdout and stderr if both are needed in real time.
98
+ try:
99
+ for line in proc.stdout:
100
+ print("Streamed stdout:", line, end="")
101
+ except KeyboardInterrupt:
102
+ pass
103
+
104
+ # Wait for the process to finish.
105
+ proc.join()
106
+
107
+ # Optionally, process any remaining stderr output.
108
+ for line in proc.stderr:
109
+ print("Streamed stderr:", line, end="")
@@ -0,0 +1,22 @@
1
+ [build-system]
2
+ requires = ["setuptools>=42", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "fastled_server"
7
+ version = "0.1.0"
8
+ description = "FastLED Server"
9
+ requires-python = ">=3.10"
10
+
11
+ dependencies = [
12
+ "platformio==6.1.17",
13
+ "fastapi==0.115.11",
14
+ "uvicorn[standard]==0.34.0",
15
+ "python-multipart==0.0.20",
16
+ "disklru==2.0.0",
17
+ "psutil==6.1.1",
18
+ "wormhole-tx",
19
+ ]
20
+
21
+ [tool.setuptools]
22
+ package-dir = {"" = "."}
@@ -55,6 +55,9 @@ _EXAMPLES: list[str] = [
55
55
  "FxNoiseRing",
56
56
  "FxSdCard",
57
57
  "FxWater",
58
+ "Wave2d",
59
+ "FxWave2d",
60
+ "FireCylinder",
58
61
  ]
59
62
 
60
63
 
@@ -11,9 +11,7 @@ echo Running black src tests compiler
11
11
  black src tests compiler
12
12
  echo Running isort src tests compiler
13
13
  isort --profile black src tests compiler
14
- echo Running mypy src compiler
15
- mypy src tests compiler
16
14
  echo Running pyright src tests compiler
17
- pyright src compiler tests
15
+ uv run pyright src compiler tests
18
16
  echo Linting complete!
19
17
  exit 0
@@ -20,8 +20,9 @@ dependencies = [
20
20
  "appdirs>=1.4.4",
21
21
  "rapidfuzz>=3.10.1",
22
22
  "progress>=1.6",
23
- "Flask>=3.0.0",
24
- "livereload",
23
+ "fastapi>=0.115.12",
24
+ "uvicorn>=0.34.2",
25
+ "pywebview>=5.4",
25
26
  ]
26
27
 
27
28
  dynamic = ["version"]
@@ -13,7 +13,7 @@ from .types import BuildMode, CompileResult, CompileServerError
13
13
  # IMPORTANT! There's a bug in github which will REJECT any version update
14
14
  # that has any other change in the repo. Please bump the version as the
15
15
  # ONLY change in a commit, or else the pypi update and the release will fail.
16
- __version__ = "1.2.49"
16
+ __version__ = "1.2.59"
17
17
 
18
18
  DOCKER_FILE = (
19
19
  "https://raw.githubusercontent.com/zackees/fastled-wasm/refs/heads/main/Dockerfile"
@@ -122,8 +122,7 @@ if __name__ == "__main__":
122
122
  import os
123
123
 
124
124
  os.chdir("../fastled")
125
- sys.argv.append("examples/wasm")
126
- sys.argv.append("--just-compile")
125
+ sys.argv.append("examples/FxWave2d")
127
126
  sys.exit(main())
128
127
  except KeyboardInterrupt:
129
128
  print("\nExiting from main...")
@@ -0,0 +1,28 @@
1
+ -----BEGIN PRIVATE KEY-----
2
+ MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDlxbWcpUXPpjqs
3
+ DJPgFF1FsXPZqq0JPJqssHh4ZLfN0h4yJmj+kRcHS+pkgXnG46g6bUcL/AK5Ba08
4
+ vwnUUGkPH0v4ShKiAGYwvOcbWaqTmvvJuIoaDBXh2jSCeOTagNoaHLYEugARkkEu
5
+ 0/FEW5P/79wU5vJ5G+SyZ8rBCVdxlU57pL1hKWBU7K+BLWsCiZ308NMpzHF5APZ6
6
+ YxVjhFosJPr4TjN6yXr+whrsAjSTHamD5690MbXWyyPG0jwPQyjBot/cNtt8GrsN
7
+ gcjA1E+8VKFvxO8RvZanMZLb0CGEpt7u3oaJ/jprHEsw+/UhnG6Qhksm8C/DN9kP
8
+ hselewffAgMBAAECggEARjQ6YTo+Mkvf8WGGbRjLxteJRiBX7lKOD+V7aY2ce06P
9
+ 21LREbbTCm+vljXZN2OnqvJomsjNLCsH21+jaTOIZg5x79LyDn2Au7N8CWdELwVT
10
+ mTbBO2Ql63P4R0UY54onGYNcOeV6z+OX9u7a8L/qYHCxFdHalBZpsfj0gjaQeStJ
11
+ JSnvGjo6tKkwC/nUmX01qEVQgUO1+39WYqCaIWjijZNXt6XiKclEuu1AkL0u6Mpt
12
+ CzvzEDrEA66D0Lvl3Tek9B4O16Oie5anNnNMHigwU9yVc6dI8vDCRSEiz7laPTFK
13
+ xzOCQmqPGClKXkX3U+OvZp/Ss9U26Wpu0AbRKTvzAQKBgQDsMR9NjMpOmUaWkAwl
14
+ 1wlUxsZ9YkRuTy7R3RfIdYWj6Lcoc4/iN0qILFM7xidkHhYTFqnsnP1SQkV6lEHV
15
+ OalYxZu9F2l1rHPc8G5YWh/KOg1rAEI47MVT4iwhA2fw6JLti/rm25AeSTMjSTqu
16
+ ht3146036opcIF3v86oGUrSXDwKBgQD5CsNcwLeUDGXozjq62T8/mTYwd2Tw3aiY
17
+ KaGp+exAW321vYm5SKsMitBMGU2tGFlv5eptSI48h7SCpgnszaexw7yj30KuvqjG
18
+ bBqq/MsKuXHyn2sG0A7MJ6zfk+4l46B45blDJZ+x7xL0dyS4UCU3zUeesgSGo4zK
19
+ ZOspPIQCMQKBgQCk35VuWP1P6IbxyxPvxi/pUeh01gfWyMdyD9fuQrtLM8PHJQQn
20
+ cVlBvU9MxoHwzV+za3qqhNwAc+p0KtHZuiqQoUCZuqIPVpZ6gAtG+YJ/dA6xxrhz
21
+ bDRC3frYALyp2m/WCoTWaiYsPgTIePHRqqt+XbQo+DwlGyL3wSvKxijx2QKBgCb0
22
+ OwioEE70/X/DukX9szn0chh0pHJUiYl7gZD/yadraCdkRUWZC0BD+j7c+lxn4Z1y
23
+ HhAH+E+Zfm+tHwJOTLuufTQ4uMpygh2/TRCPyAaeaSdlLi17n8TpM84o6mg8yZ3/
24
+ eNH68Za4aYOZm0HFL30h++DjwXd534zM6keh8pgRAoGBAKUrsjDGjuSo8l1fi4Cq
25
+ INu/rQop2h/db02zyJP5q7NKhE1nqogeLwwn+2M/LtHQ1nIzZR+rvrLNgt6oWY31
26
+ sPsv8JUfVT8GmdhU9KKmizK6eUu3rWdj2+rJARmuEaPmHcD5O6oJaGU0qadqQP34
27
+ H+enwWmpyZXAIbEu/q63DFhV
28
+ -----END PRIVATE KEY-----
@@ -0,0 +1,27 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIEfTCCAuWgAwIBAgIRAPb7jkLrCuqToG+s3AQYeuUwDQYJKoZIhvcNAQELBQAw
3
+ gakxHjAcBgNVBAoTFW1rY2VydCBkZXZlbG9wbWVudCBDQTE/MD0GA1UECww2REVT
4
+ S1RPUC1JMzcxOERPXFphY2ggVm9yaGllc0BERVNLVE9QLUkzNzE4RE8gKG5pdGVy
5
+ aXMpMUYwRAYDVQQDDD1ta2NlcnQgREVTS1RPUC1JMzcxOERPXFphY2ggVm9yaGll
6
+ c0BERVNLVE9QLUkzNzE4RE8gKG5pdGVyaXMpMB4XDTI1MDQyODAwMzk1MFoXDTI3
7
+ MDcyODAwMzk1MFowajEnMCUGA1UEChMebWtjZXJ0IGRldmVsb3BtZW50IGNlcnRp
8
+ ZmljYXRlMT8wPQYDVQQLDDZERVNLVE9QLUkzNzE4RE9cWmFjaCBWb3JoaWVzQERF
9
+ U0tUT1AtSTM3MThETyAobml0ZXJpcykwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
10
+ ggEKAoIBAQDlxbWcpUXPpjqsDJPgFF1FsXPZqq0JPJqssHh4ZLfN0h4yJmj+kRcH
11
+ S+pkgXnG46g6bUcL/AK5Ba08vwnUUGkPH0v4ShKiAGYwvOcbWaqTmvvJuIoaDBXh
12
+ 2jSCeOTagNoaHLYEugARkkEu0/FEW5P/79wU5vJ5G+SyZ8rBCVdxlU57pL1hKWBU
13
+ 7K+BLWsCiZ308NMpzHF5APZ6YxVjhFosJPr4TjN6yXr+whrsAjSTHamD5690MbXW
14
+ yyPG0jwPQyjBot/cNtt8GrsNgcjA1E+8VKFvxO8RvZanMZLb0CGEpt7u3oaJ/jpr
15
+ HEsw+/UhnG6Qhksm8C/DN9kPhselewffAgMBAAGjXjBcMA4GA1UdDwEB/wQEAwIF
16
+ oDATBgNVHSUEDDAKBggrBgEFBQcDATAfBgNVHSMEGDAWgBSPBydvhr9wI+FsoW/H
17
+ WK3DbS8IUDAUBgNVHREEDTALgglsb2NhbGhvc3QwDQYJKoZIhvcNAQELBQADggGB
18
+ AJVrF1yczZaxt+A2AhdeFbJQUR6NzGBTc20YeWF1YzLV5sV3QVumwZLP2M9ggRgd
19
+ xWV0xfwUHobFQk6RIPTADcLKctiurql0cgF4DPnpWVvto9RM00U3AkQcMj3xtKBV
20
+ wUqo83TcbqgL+euudFZ09gGTs9u9AENaZPcMh+rW8DDO92t+EwMI/IfopxVOJGUB
21
+ RSM3yTwV93BMYBuddt8mclzLzPK/1WONfsHU2xEascaHR1tYMOmJN9Vq4o0fzWxo
22
+ a2vI6K0aJqZV/ztdXq3akwLc6/e9hyptHWa0i/022xVCyNWIlnuEhT7ENMPxh6rX
23
+ ZCQCZVnhcSWAyFjggLJql3aSID5fPF8rmN7wWsB/I5pl9qwMR1/THMPrm5aWn1Xj
24
+ xW6PxkSGm73kd57DH7tqm5HTd8eYCbnsFofI9rC7xI6HCfwchKp+YHvIEu/LJ56E
25
+ FLnCZW/orYkHCzWntzxv1bddrw1BwaNR8Q+mu3imRP8fuyXb2UkFkINVVyOOWHuW
26
+ Kw==
27
+ -----END CERTIFICATE-----
@@ -0,0 +1,20 @@
1
+ import sys
2
+
3
+ from fastled.app import main as app_main
4
+
5
+ if __name__ == "__main__":
6
+ # Note that the entry point for the exe is in cli.py
7
+ try:
8
+ import os
9
+
10
+ os.chdir("../fastled")
11
+ # sys.argv.append("--server")
12
+ # sys.argv.append("--local")
13
+ sys.argv.append("examples/FxWave2d")
14
+ sys.exit(app_main())
15
+ except KeyboardInterrupt:
16
+ print("\nExiting from main...")
17
+ sys.exit(1)
18
+ except Exception as e:
19
+ print(f"Error: {e}")
20
+ sys.exit(1)
@@ -7,7 +7,7 @@ from pathlib import Path
7
7
 
8
8
  from fastled.compile_server import CompileServer
9
9
  from fastled.docker_manager import DockerManager
10
- from fastled.filewatcher import FileWatcherProcess
10
+ from fastled.filewatcher import DebouncedFileWatcherProcess, FileWatcherProcess
11
11
  from fastled.keyboard import SpaceBarWatcher
12
12
  from fastled.open_browser import open_browser_process
13
13
  from fastled.parse_args import Args
@@ -231,9 +231,8 @@ def run_client(
231
231
  return 1
232
232
 
233
233
  excluded_patterns = ["fastled_js"]
234
-
235
- sketch_filewatcher = FileWatcherProcess(
236
- directory, excluded_patterns=excluded_patterns
234
+ debounced_sketch_watcher = DebouncedFileWatcherProcess(
235
+ FileWatcherProcess(directory, excluded_patterns=excluded_patterns),
237
236
  )
238
237
 
239
238
  source_code_watcher: FileWatcherProcess | None = None
@@ -246,7 +245,7 @@ def run_client(
246
245
  def trigger_rebuild_if_sketch_changed(
247
246
  last_compiled_result: CompileResult,
248
247
  ) -> tuple[bool, CompileResult]:
249
- changed_files = sketch_filewatcher.get_all_changes()
248
+ changed_files = debounced_sketch_watcher.get_all_changes()
250
249
  if changed_files:
251
250
  print(f"\nChanges detected in {changed_files}")
252
251
  last_hash_value = last_compiled_result.hash_value
@@ -301,7 +300,9 @@ def run_client(
301
300
  timeout=1.0
302
301
  )
303
302
  file_changes = source_code_watcher.get_all_changes()
304
- sketch_files_changed = sketch_filewatcher.get_all_changes()
303
+ sketch_files_changed = (
304
+ debounced_sketch_watcher.get_all_changes()
305
+ )
305
306
 
306
307
  if file_changes:
307
308
  print(
@@ -331,7 +332,7 @@ def run_client(
331
332
  print(f"Error: {e}")
332
333
  return 1
333
334
  finally:
334
- sketch_filewatcher.stop()
335
+ debounced_sketch_watcher.stop()
335
336
  if compile_server:
336
337
  compile_server.stop()
337
338
  if browser_proc: