IS-Matrix-Forge 1.0.0.dev5__tar.gz → 1.0.0.dev7__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.
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/PKG-INFO +3 -1
- is_matrix_forge-1.0.0.dev7/is_matrix_forge/common/decorators/__init__.py +12 -0
- is_matrix_forge-1.0.0.dev5/is_matrix_forge/common/decorators/__init__.py → is_matrix_forge-1.0.0.dev7/is_matrix_forge/common/decorators/freeze_setter.py +2 -12
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/controller/controller.py +79 -30
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/animations/__init__.py +9 -0
- is_matrix_forge-1.0.0.dev7/is_matrix_forge/led_matrix/display/animations/audio_visualizer.py +124 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/effects/breather.py +1 -1
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/grid/grid.py +43 -8
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/helpers/device.py +1 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/pyproject.toml +5 -2
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/LICENSE.md +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/README.md +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/assets/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/assets/audio/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/assets/audio/files/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/assets/audio/files/plugged.wav +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/assets/audio/files/unplugged.wav +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/assets/char_map.json +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/assets/font_map.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/common/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/common/dirs.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/common/helpers/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/common/helpers/github_api.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/designer_gui/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/designer_gui/main_window/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/designer_gui/main_window/layout/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/designer_gui/main_window/layout/button_grid/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/designer_gui/main_window/layout/button_grid/column.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/designer_gui/main_window/layout/button_grid/grid.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/designer_gui/main_window/streamlit_app.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/dev_tools/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/dev_tools/debug.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/dev_tools/presets.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/inputmodule/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/inputmodule/b1display.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/inputmodule/c1minimal.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/inputmodule/font.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/inputmodule/helpers/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/inputmodule/ledmatrix.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/Scripts/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/Scripts/battery_monitor.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/Scripts/identify_matrices.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/Scripts/install_presets/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/Scripts/install_presets/arguments.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/Scripts/install_presets/main.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/commands/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/commands/map.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/constants.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/controller/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/controller/helpers/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/controller/helpers/threading.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/controller/multiton.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/controller/threaded.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/animations/animation.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/animations/effects/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/animations/errors.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/animations/font/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/animations/font/font.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/animations/font/map_builder.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/animations/frame/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/animations/frame/base.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/animations/frame/helpers.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/animations/keep_awake.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/animations/plugged.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/animations/text_scroller.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/effects/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/effects/fade.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/effects/scroller/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/effects/scroller/base.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/effects/scroller/helpers.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/grid/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/grid/helpers.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/grid/presets/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/grid/presets/manifest.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/helpers/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/helpers/columns.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/media.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/patterns/built_in/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/patterns/built_in/commands.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/patterns/built_in/constants.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/patterns/built_in/stencils/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/patterns/built_in/stencils/res.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/text/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/display/text/scroller.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/errors/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/errors/base.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/errors/grid.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/errors/matrix.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/errors/misc.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/fonts.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/hardware.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/helpers/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/helpers/core/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/helpers/core/lazy_mod_load.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/helpers/status_handler.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/helpers/stream/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/helpers/stream/errors.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/led_matrix.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/status.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/tools/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/tools/identify.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/utils/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/log_engine.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/monitor/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/monitor/errors.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/monitor/events.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/monitor/gui/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/monitor/gui/errors.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/monitor/gui/event/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/monitor/gui/event/collection.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/monitor/gui/event/errors.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/monitor/gui/event/event.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/monitor/gui/layout/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/monitor/gui/layout/base.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/monitor/gui/metaclasses/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/monitor/gui/windows/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/monitor/gui/windows/base.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/monitor/gui/windows/main/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/monitor/gui/windows/main/layout.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/monitor/helpers.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/monitor/monitor.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/notify/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/notify/sounds/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/notify/sounds/base.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/progress.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/scripts/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/scripts/preset_installer.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/serial_com/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/serial_com/base/__init__.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/serial_com/base/answer.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/serial_com/base/message.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/serial_com/base/request.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/serial_com/exchange.py +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/presets/blank.json +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/presets/manifest.json +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/presets/shock_face.json +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/presets/test1.json +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/presets/test2.json +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/presets/test3.json +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/presets/test4.json +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/presets/test5.json +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/presets/test6.json +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/presets/test7.json +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/presets/x_animation II.json +0 -0
- {is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/presets/x_animation.json +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: IS-Matrix-Forge
|
|
3
|
-
Version: 1.0.0.
|
|
3
|
+
Version: 1.0.0.dev7
|
|
4
4
|
Summary:
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: led,matrix,framework,hardware
|
|
@@ -12,6 +12,7 @@ Classifier: Programming Language :: Python :: 3
|
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.12
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.13
|
|
14
14
|
Provides-Extra: clipboard-support
|
|
15
|
+
Requires-Dist: aliaser (>=1.0.0.dev4,<2.0.0)
|
|
15
16
|
Requires-Dist: chime (>=0.7.0,<0.8.0)
|
|
16
17
|
Requires-Dist: clipboard (>=0.0.4,<0.0.5) ; extra == "clipboard-support"
|
|
17
18
|
Requires-Dist: easy-exit-calls (>=1.0.0.dev1,<2.0.0)
|
|
@@ -23,6 +24,7 @@ Requires-Dist: pillow (>=11.2.1,<12.0.0)
|
|
|
23
24
|
Requires-Dist: pyserial (>=3.5,<4.0)
|
|
24
25
|
Requires-Dist: pysimplegui-4-foss (==4.60.4.1)
|
|
25
26
|
Requires-Dist: pysimpleguiweb (==0.39.0)
|
|
27
|
+
Requires-Dist: requests (>=2.32.4,<3.0.0)
|
|
26
28
|
Project-URL: Homepage, https://github.com/Inspyre-Softworks/IS-Matrix-Forge
|
|
27
29
|
Project-URL: Repository, https://github.com/Inspyre-Softworks/IS-Matrix-Forge
|
|
28
30
|
Description-Content-Type: text/markdown
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from inspyre_toolbox.syntactic_sweets.classes.decorators import validate_type
|
|
2
|
+
from is_matrix_forge.common.decorators.freeze_setter import freeze_setter
|
|
3
|
+
from is_matrix_forge.led_matrix.errors.misc import ImplicitNameDerivationError
|
|
4
|
+
from aliaser import Aliases
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
'Aliases',
|
|
9
|
+
'ImplicitNameDerivationError',
|
|
10
|
+
'freeze_setter',
|
|
11
|
+
'validate_type',
|
|
12
|
+
]
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import functools
|
|
2
2
|
from typing import Optional, Type, Callable, Any
|
|
3
3
|
|
|
4
|
-
import functools
|
|
5
|
-
from typing import Optional, Type, Callable, Any
|
|
6
|
-
from inspyre_toolbox.syntactic_sweets.classes.decorators import validate_type
|
|
7
|
-
from is_matrix_forge.led_matrix.errors.misc import ImplicitNameDerivationError
|
|
8
|
-
|
|
9
4
|
|
|
10
5
|
def freeze_setter(
|
|
11
6
|
attr_name: Optional[str] = None,
|
|
@@ -94,6 +89,8 @@ def freeze_setter(
|
|
|
94
89
|
- `ImplicitNameDerivationError`: Raised for configuration issues with underscore-prefixed setters.
|
|
95
90
|
- `AttributeError`: Default exception for reassigning a frozen attribute.
|
|
96
91
|
"""
|
|
92
|
+
from is_matrix_forge.led_matrix.errors.misc import ImplicitNameDerivationError
|
|
93
|
+
|
|
97
94
|
def decorator(setter: Callable) -> Callable:
|
|
98
95
|
setter_name = setter.__name__
|
|
99
96
|
|
|
@@ -143,10 +140,3 @@ def freeze_setter(
|
|
|
143
140
|
return wrapper
|
|
144
141
|
|
|
145
142
|
return decorator
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
__all__ = [
|
|
149
|
-
'ImplicitNameDerivationError',
|
|
150
|
-
'freeze_setter',
|
|
151
|
-
'validate_type',
|
|
152
|
-
]
|
|
@@ -26,20 +26,20 @@ from inspyre_toolbox.syntactic_sweets.classes.decorators.aliases import add_alia
|
|
|
26
26
|
from serial.tools.list_ports_common import ListPortInfo
|
|
27
27
|
|
|
28
28
|
from is_matrix_forge.common.helpers import coerce_to_int
|
|
29
|
+
from aliaser.metaclass import AliasMeta
|
|
29
30
|
from is_matrix_forge.led_matrix.constants import SLOT_MAP
|
|
30
31
|
from is_matrix_forge.led_matrix.display.text import show_string as _show_string_raw
|
|
31
32
|
from is_matrix_forge.led_matrix.controller import MultitonMeta
|
|
32
33
|
from is_matrix_forge.led_matrix.controller.helpers.threading import synchronized
|
|
33
34
|
from is_matrix_forge.led_matrix.commands.map import CommandVals
|
|
34
|
-
from is_matrix_forge.led_matrix.hardware import
|
|
35
|
+
from is_matrix_forge.led_matrix.hardware import send_command
|
|
35
36
|
from is_matrix_forge.led_matrix.display.effects.breather import Breather
|
|
36
37
|
from is_matrix_forge.led_matrix.display.text import show_string
|
|
37
38
|
|
|
38
39
|
COMMANDS = CommandVals
|
|
39
40
|
|
|
40
41
|
|
|
41
|
-
|
|
42
|
-
class LEDMatrixController(metaclass=MultitonMeta):
|
|
42
|
+
class LEDMatrixController(metaclass=AliasMeta):
|
|
43
43
|
"""
|
|
44
44
|
Controller class for LED Matrix devices.
|
|
45
45
|
|
|
@@ -115,6 +115,8 @@ class LEDMatrixController(metaclass=MultitonMeta):
|
|
|
115
115
|
self.__show_grid_on_init = None
|
|
116
116
|
self._thread_safe = None
|
|
117
117
|
self._cmd_lock = None
|
|
118
|
+
self._keep_alive = False
|
|
119
|
+
self._KEEP_ALIVE_INTERVAL = 50
|
|
118
120
|
|
|
119
121
|
self.hold_all = hold_all or False
|
|
120
122
|
|
|
@@ -129,6 +131,7 @@ class LEDMatrixController(metaclass=MultitonMeta):
|
|
|
129
131
|
self.__init_clear = not skip_init_clear
|
|
130
132
|
|
|
131
133
|
if init_grid is not None:
|
|
134
|
+
from is_matrix_forge.led_matrix.display.grid import Grid
|
|
132
135
|
if not isinstance(init_grid, Grid):
|
|
133
136
|
raise TypeError(f'init_grid must be of type `Grid`, not {type(init_grid)}')
|
|
134
137
|
|
|
@@ -145,13 +148,75 @@ class LEDMatrixController(metaclass=MultitonMeta):
|
|
|
145
148
|
|
|
146
149
|
self.__post_init__()
|
|
147
150
|
|
|
151
|
+
# ---------------------------------------------------------------------
|
|
152
|
+
# Keep‑alive internal worker
|
|
153
|
+
# ---------------------------------------------------------------------
|
|
154
|
+
|
|
155
|
+
@synchronized
|
|
156
|
+
def __keep_alive_worker(self):
|
|
157
|
+
"""Loop until signalled, polling :pyattr:`animating` every 50 s."""
|
|
158
|
+
# Lazily create the stop event (should already exist, but be safe)
|
|
159
|
+
stop_evt = self._keep_alive_stop_evt or threading.Event()
|
|
160
|
+
self._keep_alive_stop_evt = stop_evt
|
|
161
|
+
|
|
162
|
+
while not stop_evt.is_set():
|
|
163
|
+
try:
|
|
164
|
+
_ = self.animating # A simple query is enough to keep FW awake
|
|
165
|
+
except Exception: # pragma: no cover – we don't crash the thread
|
|
166
|
+
pass
|
|
167
|
+
|
|
168
|
+
# Wait with timeout so the thread can exit early when stop_evt is set
|
|
169
|
+
stop_evt.wait(self._KEEP_ALIVE_INTERVAL)
|
|
170
|
+
|
|
171
|
+
# ---------------------------------------------------------------------
|
|
172
|
+
# Property controlling the keep‑alive thread
|
|
173
|
+
# ---------------------------------------------------------------------
|
|
174
|
+
|
|
175
|
+
@property
|
|
176
|
+
def keep_alive(self) -> bool:
|
|
177
|
+
"""Whether the background keep‑alive thread is active."""
|
|
178
|
+
return self._keep_alive
|
|
179
|
+
|
|
180
|
+
@keep_alive.setter
|
|
181
|
+
def keep_alive(self, enable: bool):
|
|
182
|
+
if not isinstance(enable, bool):
|
|
183
|
+
raise TypeError('keep_alive must be a boolean.')
|
|
184
|
+
|
|
185
|
+
# No change ➜ nothing to do
|
|
186
|
+
if enable == self._keep_alive:
|
|
187
|
+
return
|
|
188
|
+
|
|
189
|
+
if enable:
|
|
190
|
+
# Start background thread
|
|
191
|
+
self._keep_alive_stop_evt = threading.Event()
|
|
192
|
+
self._keep_alive_thread = threading.Thread(
|
|
193
|
+
target=self.__keep_alive_worker,
|
|
194
|
+
name=f"{self.__class__.__name__}-KeepAlive-{self.device.name}",
|
|
195
|
+
daemon=True,
|
|
196
|
+
)
|
|
197
|
+
self._keep_alive_thread.start()
|
|
198
|
+
self._keep_alive = True
|
|
199
|
+
else:
|
|
200
|
+
# Signal thread to exit and wait (briefly) for it
|
|
201
|
+
if self._keep_alive_stop_evt is not None:
|
|
202
|
+
self._keep_alive_stop_evt.set()
|
|
203
|
+
if (
|
|
204
|
+
self._keep_alive_thread is not None
|
|
205
|
+
and self._keep_alive_thread.is_alive()
|
|
206
|
+
):
|
|
207
|
+
self._keep_alive_thread.join(timeout=self._KEEP_ALIVE_INTERVAL + 1)
|
|
208
|
+
self._keep_alive_thread = None
|
|
209
|
+
self._keep_alive_stop_evt = None
|
|
210
|
+
self._keep_alive = False
|
|
211
|
+
self.__post_init__()
|
|
212
|
+
|
|
148
213
|
def __post_init__(self):
|
|
149
214
|
from is_matrix_forge.led_matrix.display.effects.breather import Breather
|
|
150
215
|
|
|
151
216
|
self.__breather = Breather(self)
|
|
152
217
|
|
|
153
218
|
if self.clear_on_init:
|
|
154
|
-
self.
|
|
219
|
+
self.clear_matrix()
|
|
155
220
|
|
|
156
221
|
if self.set_brightness_on_init:
|
|
157
222
|
self.set_brightness(self.__default_brightness)
|
|
@@ -184,7 +249,6 @@ class LEDMatrixController(metaclass=MultitonMeta):
|
|
|
184
249
|
bool: True if the device is animating, False otherwise.
|
|
185
250
|
"""
|
|
186
251
|
return bool(send_command(self.device, COMMANDS.Animate, with_response=True)[0])
|
|
187
|
-
# return animate(self.device)
|
|
188
252
|
|
|
189
253
|
@property
|
|
190
254
|
def breather(self) -> Breather:
|
|
@@ -320,8 +384,12 @@ class LEDMatrixController(metaclass=MultitonMeta):
|
|
|
320
384
|
return self.location['abbrev']
|
|
321
385
|
|
|
322
386
|
@property
|
|
387
|
+
@alias('serial_port', 'port_name')
|
|
323
388
|
def name(self) -> str:
|
|
324
|
-
|
|
389
|
+
if self.__name is None:
|
|
390
|
+
self.__name = self.device.name
|
|
391
|
+
|
|
392
|
+
return self.__name
|
|
325
393
|
|
|
326
394
|
def play_animation(self, animation):
|
|
327
395
|
from is_matrix_forge.led_matrix.display.animations.animation import Animation
|
|
@@ -344,9 +412,6 @@ class LEDMatrixController(metaclass=MultitonMeta):
|
|
|
344
412
|
text_animation.loop = True
|
|
345
413
|
return self.play_animation(text_animation)
|
|
346
414
|
|
|
347
|
-
def show_text(self, text: str):
|
|
348
|
-
self.draw_text(text)
|
|
349
|
-
|
|
350
415
|
@property
|
|
351
416
|
def set_brightness_on_init(self):
|
|
352
417
|
"""
|
|
@@ -404,6 +469,7 @@ class LEDMatrixController(metaclass=MultitonMeta):
|
|
|
404
469
|
# The animate function also sets the status to 'animate' when enabled
|
|
405
470
|
animate(self.device, enable)
|
|
406
471
|
|
|
472
|
+
@alias('clear')
|
|
407
473
|
@synchronized
|
|
408
474
|
def clear_matrix(self) -> None:
|
|
409
475
|
"""
|
|
@@ -419,12 +485,7 @@ class LEDMatrixController(metaclass=MultitonMeta):
|
|
|
419
485
|
grid = Grid(init_grid=data)
|
|
420
486
|
self.draw_grid(grid)
|
|
421
487
|
|
|
422
|
-
|
|
423
|
-
self.clear_matrix()
|
|
424
|
-
|
|
425
|
-
def draw(self, grid: 'Grid' = None) -> None:
|
|
426
|
-
return self.draw_grid(grid)
|
|
427
|
-
|
|
488
|
+
@alias('draw')
|
|
428
489
|
@synchronized
|
|
429
490
|
def draw_grid(self, grid: 'Grid' = None) -> None:
|
|
430
491
|
"""
|
|
@@ -442,8 +503,8 @@ class LEDMatrixController(metaclass=MultitonMeta):
|
|
|
442
503
|
grid = Grid(init_grid=grid)
|
|
443
504
|
render_matrix(self.device, grid.grid)
|
|
444
505
|
|
|
506
|
+
@alias('pattern', 'show_pattern')
|
|
445
507
|
@synchronized
|
|
446
|
-
@method_alias('pattern')
|
|
447
508
|
def draw_pattern(self, pattern: str) -> None:
|
|
448
509
|
"""
|
|
449
510
|
Draw a pattern on the LED matrix.
|
|
@@ -459,6 +520,7 @@ class LEDMatrixController(metaclass=MultitonMeta):
|
|
|
459
520
|
pattern_pen = BuiltInPatterns(self)
|
|
460
521
|
pattern_pen.render(pattern)
|
|
461
522
|
|
|
523
|
+
@alias('display_percentage', 'show_percentage')
|
|
462
524
|
@synchronized
|
|
463
525
|
def draw_percentage(self, percentage: int, clear_first: bool = False):
|
|
464
526
|
from is_matrix_forge.led_matrix.hardware import percentage as _show_percentage_raw
|
|
@@ -476,12 +538,6 @@ class LEDMatrixController(metaclass=MultitonMeta):
|
|
|
476
538
|
|
|
477
539
|
_show_percentage_raw(self.device, percentage)
|
|
478
540
|
|
|
479
|
-
def draw_string(self, text: str):
|
|
480
|
-
self.show_text(text)
|
|
481
|
-
|
|
482
|
-
def draw_text(self, text: str):
|
|
483
|
-
self.show_text(text)
|
|
484
|
-
|
|
485
541
|
@synchronized
|
|
486
542
|
def display_location(self):
|
|
487
543
|
"""
|
|
@@ -613,15 +669,8 @@ class LEDMatrixController(metaclass=MultitonMeta):
|
|
|
613
669
|
if not __from_setter:
|
|
614
670
|
self.__brightness = brightness
|
|
615
671
|
|
|
616
|
-
def show_string(self, text: str) -> None:
|
|
617
|
-
"""
|
|
618
|
-
Alias for LEDMatrixController.show_text.
|
|
619
|
-
|
|
620
|
-
See Also:
|
|
621
|
-
LEDMatrixController.show_text
|
|
622
|
-
"""
|
|
623
|
-
self.show_text(text)
|
|
624
672
|
|
|
673
|
+
@method_alias('draw_text', 'show_string', 'draw_string')
|
|
625
674
|
@synchronized
|
|
626
675
|
def show_text(self, text: str) -> None:
|
|
627
676
|
"""
|
|
@@ -2,6 +2,7 @@ from time import sleep
|
|
|
2
2
|
|
|
3
3
|
from is_matrix_forge.led_matrix.hardware import brightness
|
|
4
4
|
from is_matrix_forge.led_matrix.display.text import show_string
|
|
5
|
+
from .audio_visualizer import AudioVisualizer
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
def clear(dev):
|
|
@@ -26,3 +27,11 @@ def goodbye_animation(dev):
|
|
|
26
27
|
checkerboard_cycle(dev)
|
|
27
28
|
sleep(.5)
|
|
28
29
|
show_string(dev, 'Bye')
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
__all__ = [
|
|
33
|
+
'AudioVisualizer',
|
|
34
|
+
'clear',
|
|
35
|
+
'checkerboard_cycle',
|
|
36
|
+
'goodbye_animation',
|
|
37
|
+
]
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"""Real-time audio visualizer for the LED matrix.
|
|
2
|
+
|
|
3
|
+
This module provides a small utility that streams audio data and renders simple
|
|
4
|
+
bar style visualizations on one or more LED matrix controllers. By default it
|
|
5
|
+
uses the system microphone for input, however an audio file may also be used as
|
|
6
|
+
the source allowing "regular" audio to be visualized. ``sounddevice`` and
|
|
7
|
+
``soundfile`` are optional dependencies and the visualiser gracefully degrades
|
|
8
|
+
if they are unavailable.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import threading
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import Iterable, List, Optional, Union
|
|
16
|
+
|
|
17
|
+
import numpy as np
|
|
18
|
+
|
|
19
|
+
try: # ``sounddevice`` is an optional dependency
|
|
20
|
+
import sounddevice as sd
|
|
21
|
+
except Exception: # pragma: no cover - optional dependency missing
|
|
22
|
+
sd = None # type: ignore
|
|
23
|
+
|
|
24
|
+
try: # ``soundfile`` is also optional
|
|
25
|
+
import soundfile as sf
|
|
26
|
+
except Exception: # pragma: no cover - optional dependency missing
|
|
27
|
+
sf = None # type: ignore
|
|
28
|
+
|
|
29
|
+
from is_matrix_forge.led_matrix.controller.controller import LEDMatrixController
|
|
30
|
+
from is_matrix_forge.led_matrix.display.animations.frame.base import Frame
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class AudioVisualizer:
|
|
34
|
+
"""Stream audio data and render a simple bar visualisation."""
|
|
35
|
+
|
|
36
|
+
def __init__(
|
|
37
|
+
self,
|
|
38
|
+
controllers: Iterable[LEDMatrixController],
|
|
39
|
+
sample_rate: int = 44_100,
|
|
40
|
+
chunk_size: int = 1_024,
|
|
41
|
+
audio_source: Union[str, Path, None] = None,
|
|
42
|
+
loop_file: bool = True,
|
|
43
|
+
) -> None:
|
|
44
|
+
self.controllers: List[LEDMatrixController] = list(controllers)
|
|
45
|
+
self.sample_rate = sample_rate
|
|
46
|
+
self.chunk_size = chunk_size
|
|
47
|
+
self._stream: Optional[sd.InputStream] = None # type: ignore[var-annotated]
|
|
48
|
+
self._thread: Optional[threading.Thread] = None
|
|
49
|
+
self._running = False
|
|
50
|
+
self._audio_source: Optional[Path] = Path(audio_source) if audio_source else None
|
|
51
|
+
self._loop_file = loop_file
|
|
52
|
+
|
|
53
|
+
# ------------------------------------------------------------------ utils --
|
|
54
|
+
def _process_chunk(self, data: np.ndarray) -> None: # pragma: no cover - real time
|
|
55
|
+
"""Render a frame based on ``data`` samples."""
|
|
56
|
+
amplitude = float(np.linalg.norm(data) / len(data))
|
|
57
|
+
bar_height = min(int(amplitude * 34), 34)
|
|
58
|
+
|
|
59
|
+
grid = [[0 for _ in range(34)] for _ in range(9)]
|
|
60
|
+
for x in range(9):
|
|
61
|
+
for y in range(bar_height):
|
|
62
|
+
grid[x][33 - y] = 1
|
|
63
|
+
|
|
64
|
+
frame = Frame(grid=grid, duration=0.01)
|
|
65
|
+
|
|
66
|
+
for ctrl in self.controllers:
|
|
67
|
+
ctrl.draw_grid(frame.grid)
|
|
68
|
+
|
|
69
|
+
def _audio_callback(self, indata, frames, time, status) -> None: # pragma: no cover - real time
|
|
70
|
+
if not self._running:
|
|
71
|
+
return
|
|
72
|
+
self._process_chunk(indata[:, 0])
|
|
73
|
+
|
|
74
|
+
def _file_loop(self) -> None: # pragma: no cover - requires soundfile
|
|
75
|
+
assert sf is not None and self._audio_source is not None
|
|
76
|
+
while self._running:
|
|
77
|
+
with sf.SoundFile(self._audio_source) as f:
|
|
78
|
+
while self._running:
|
|
79
|
+
data = f.read(self.chunk_size, dtype='float32')
|
|
80
|
+
if len(data) == 0:
|
|
81
|
+
break
|
|
82
|
+
self._process_chunk(data)
|
|
83
|
+
if not self._loop_file:
|
|
84
|
+
break
|
|
85
|
+
|
|
86
|
+
# ------------------------------------------------------------------- API --
|
|
87
|
+
def start(self) -> None:
|
|
88
|
+
if sd is None: # pragma: no cover - environment without sounddevice
|
|
89
|
+
raise RuntimeError("sounddevice is required for AudioVisualizer")
|
|
90
|
+
|
|
91
|
+
if self._running:
|
|
92
|
+
return
|
|
93
|
+
|
|
94
|
+
self._running = True
|
|
95
|
+
if self._audio_source is not None:
|
|
96
|
+
if sf is None:
|
|
97
|
+
raise RuntimeError("soundfile is required for file playback")
|
|
98
|
+
self._thread = threading.Thread(target=self._file_loop, daemon=True)
|
|
99
|
+
self._thread.start()
|
|
100
|
+
else:
|
|
101
|
+
self._stream = sd.InputStream(
|
|
102
|
+
channels=1,
|
|
103
|
+
samplerate=self.sample_rate,
|
|
104
|
+
blocksize=self.chunk_size,
|
|
105
|
+
callback=self._audio_callback,
|
|
106
|
+
)
|
|
107
|
+
self._stream.start()
|
|
108
|
+
|
|
109
|
+
def stop(self) -> None:
|
|
110
|
+
if not self._running:
|
|
111
|
+
return
|
|
112
|
+
|
|
113
|
+
self._running = False
|
|
114
|
+
if self._stream is not None:
|
|
115
|
+
self._stream.stop()
|
|
116
|
+
self._stream.close()
|
|
117
|
+
self._stream = None
|
|
118
|
+
if self._thread is not None:
|
|
119
|
+
self._thread.join(timeout=1)
|
|
120
|
+
self._thread = None
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
__all__ = ["AudioVisualizer"]
|
|
124
|
+
|
|
@@ -22,6 +22,7 @@ from pathlib import Path
|
|
|
22
22
|
from typing import List, Optional, Union, ClassVar, Type, Any, Dict # Added Any, Dict
|
|
23
23
|
from ...constants import WIDTH as __WIDTH, HEIGHT as __HEIGHT, PRESETS_DIR
|
|
24
24
|
from .helpers import is_valid_grid, generate_blank_grid
|
|
25
|
+
from ...helpers import load_from_file as _helpers_load_from_file
|
|
25
26
|
from is_matrix_forge.common.helpers import coerce_to_int
|
|
26
27
|
|
|
27
28
|
MATRIX_HEIGHT = __HEIGHT
|
|
@@ -35,6 +36,24 @@ This constant defines the default width for new Grid instances and for loading o
|
|
|
35
36
|
"""
|
|
36
37
|
|
|
37
38
|
|
|
39
|
+
def load_from_file(
|
|
40
|
+
path: Union[str, Path],
|
|
41
|
+
expected_width: Optional[int] | None = None,
|
|
42
|
+
expected_height: Optional[int] | None = None,
|
|
43
|
+
fallback_duration: Optional[Union[int, float]] = None,
|
|
44
|
+
) -> Any:
|
|
45
|
+
"""Wrapper around :func:`is_matrix_forge.led_matrix.helpers.load_from_file`.
|
|
46
|
+
|
|
47
|
+
Exists primarily for unit tests which monkeypatch this function directly.
|
|
48
|
+
"""
|
|
49
|
+
return _helpers_load_from_file(
|
|
50
|
+
path,
|
|
51
|
+
expected_width,
|
|
52
|
+
expected_height,
|
|
53
|
+
fallback_duration,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
|
|
38
57
|
class Grid:
|
|
39
58
|
"""
|
|
40
59
|
Represents a 2D column-major grid for the LED display (grid[x][y], 9×34).
|
|
@@ -127,8 +146,18 @@ class Grid:
|
|
|
127
146
|
cls,
|
|
128
147
|
spec: List[List[int]]
|
|
129
148
|
) -> 'Grid':
|
|
130
|
-
"""Instantiate directly from a column-major spec list.
|
|
131
|
-
|
|
149
|
+
"""Instantiate directly from a column-major spec list.
|
|
150
|
+
|
|
151
|
+
The dimensions of the grid are inferred from ``spec`` so tests can
|
|
152
|
+
provide arbitrary sized grids.
|
|
153
|
+
"""
|
|
154
|
+
width = len(spec)
|
|
155
|
+
height = len(spec[0]) if spec else 0
|
|
156
|
+
if not is_valid_grid(spec, width, height):
|
|
157
|
+
raise ValueError(
|
|
158
|
+
f"init_grid must be {width}×{height} column-major 0/1 list"
|
|
159
|
+
)
|
|
160
|
+
return cls(width=width, height=height, init_grid=spec)
|
|
132
161
|
|
|
133
162
|
@classmethod
|
|
134
163
|
def from_file(
|
|
@@ -141,10 +170,16 @@ class Grid:
|
|
|
141
170
|
"""
|
|
142
171
|
Load a column-major grid from file (single grid or frames of grids).
|
|
143
172
|
"""
|
|
144
|
-
from ...helpers import load_from_file
|
|
145
173
|
raw = load_from_file(str(filename))
|
|
146
174
|
# Single-grid JSON: list of lists
|
|
147
|
-
if
|
|
175
|
+
if (
|
|
176
|
+
isinstance(raw, list)
|
|
177
|
+
and raw
|
|
178
|
+
and isinstance(raw[0], list)
|
|
179
|
+
and is_valid_grid(raw[0], width, height)
|
|
180
|
+
):
|
|
181
|
+
grid_data = raw[0]
|
|
182
|
+
elif isinstance(raw, list) and raw and isinstance(raw[0], list):
|
|
148
183
|
grid_data = raw
|
|
149
184
|
# Frame-list JSON: list of dicts
|
|
150
185
|
elif isinstance(raw, list) and all(isinstance(f, dict) for f in raw):
|
|
@@ -187,11 +222,11 @@ class Grid:
|
|
|
187
222
|
new = generate_blank_grid(self._width, self._height, self._fill_value)
|
|
188
223
|
|
|
189
224
|
for c, r in itertools.product(range(self._width), range(self._height)):
|
|
190
|
-
|
|
191
|
-
|
|
225
|
+
dest_c = (c + dx) % self._width if wrap else c + dx
|
|
226
|
+
dest_r = (r + dy) % self._height if wrap else r + dy
|
|
192
227
|
|
|
193
|
-
if 0 <=
|
|
194
|
-
new[
|
|
228
|
+
if 0 <= dest_c < self._width and 0 <= dest_r < self._height:
|
|
229
|
+
new[dest_c][dest_r] = self._grid[c][r]
|
|
195
230
|
|
|
196
231
|
return Grid(width=self._width, height=self._height, fill_value=self._fill_value, init_grid=new)
|
|
197
232
|
|
|
@@ -7,6 +7,7 @@ including functions to convert between different device location formats.
|
|
|
7
7
|
from serial import Serial, SerialException
|
|
8
8
|
from serial.tools import list_ports
|
|
9
9
|
from is_matrix_forge.log_engine import ROOT_LOGGER
|
|
10
|
+
from is_matrix_forge.led_matrix.constants import VID as EXPECTED_VID, PID as EXPECTED_PID
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
MOD_LOGGER = ROOT_LOGGER.get_child('led_matrix.helpers.device')
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "IS-Matrix-Forge"
|
|
3
|
-
version = "1.0.0-dev.
|
|
3
|
+
version = "1.0.0-dev.7"
|
|
4
4
|
description = ""
|
|
5
5
|
authors = ["Taylor B. <t.blackstone@inspyre.tech>"]
|
|
6
6
|
readme = "README.md"
|
|
@@ -31,6 +31,8 @@ clipboard = { version = "^0.0.4", optional = true }
|
|
|
31
31
|
pysimplegui-4-foss = "==4.60.4.1"
|
|
32
32
|
pysimpleguiweb = "==0.39.0"
|
|
33
33
|
imapclient = "==3.0.1"
|
|
34
|
+
requests = "^2.32.4"
|
|
35
|
+
aliaser = "^1.0.0.dev4"
|
|
34
36
|
|
|
35
37
|
[tool.poetry.extras]
|
|
36
38
|
clipboard_support = ["clipboard"]
|
|
@@ -44,7 +46,8 @@ ipyboost = { version = "1.0.0.a3", source = "testpypi" }
|
|
|
44
46
|
[tool.poetry.scripts]
|
|
45
47
|
python-path = "Scripts.python_path:main"
|
|
46
48
|
led-matrix-identify = "is_matrix_forge.led_matrix.Scripts.identify_matrices:main"
|
|
47
|
-
install-presets = "Scripts.install_presets:main"
|
|
49
|
+
install-presets = "is_matrix_forge.led_matrix.Scripts.install_presets.main:main"
|
|
50
|
+
pixel-grid = "is_matrix_forge.designer_gui.main_window:main"
|
|
48
51
|
|
|
49
52
|
[[tool.poetry.include]]
|
|
50
53
|
path = "presets/**"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/assets/__init__.py
RENAMED
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/assets/audio/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/assets/char_map.json
RENAMED
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/assets/font_map.py
RENAMED
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/common/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/common/helpers/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/designer_gui/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/dev_tools/__init__.py
RENAMED
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/dev_tools/debug.py
RENAMED
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/dev_tools/presets.py
RENAMED
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/inputmodule/__init__.py
RENAMED
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/inputmodule/b1display.py
RENAMED
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/inputmodule/c1minimal.py
RENAMED
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/inputmodule/font.py
RENAMED
|
File without changes
|
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/inputmodule/ledmatrix.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/commands/map.py
RENAMED
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/constants.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/errors/base.py
RENAMED
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/errors/grid.py
RENAMED
|
File without changes
|
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/errors/misc.py
RENAMED
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/fonts.py
RENAMED
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/hardware.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/led_matrix.py
RENAMED
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/led_matrix/status.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/monitor/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/monitor/gui/__init__.py
RENAMED
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/monitor/gui/errors.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/monitor/gui/event/event.py
RENAMED
|
File without changes
|
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/monitor/gui/layout/base.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/monitor/helpers.py
RENAMED
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/monitor/monitor.py
RENAMED
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/notify/__init__.py
RENAMED
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/notify/sounds/__init__.py
RENAMED
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/notify/sounds/base.py
RENAMED
|
File without changes
|
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/scripts/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/serial_com/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/serial_com/base/answer.py
RENAMED
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/serial_com/base/message.py
RENAMED
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/serial_com/base/request.py
RENAMED
|
File without changes
|
{is_matrix_forge-1.0.0.dev5 → is_matrix_forge-1.0.0.dev7}/is_matrix_forge/serial_com/exchange.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|