Compare commits

...

57 Commits

Author SHA1 Message Date
LordGrey cd22d4454d
Philips Hue APIv2 support (#1637)
* Support Philips Hue APIv2 and refactoring

* Fix MDNSBrower - if timeout during host resolvment occurs

* Hue API v2 - Migrate database

* Fix macOS build

* Handle network timeout before any other error

* Address CodeQL findings

* Clean-up and Fixes

* Only getProperties, if username is available

* Option to layout by entertainment area center

* Fix Wizard

---------

Co-authored-by: Paulchen-Panther <16664240+Paulchen-Panther@users.noreply.github.com>
2023-10-03 20:33:11 +02:00
dependabot[bot] 33722c9a09
Bump crazy-max/ghaction-import-gpg from 5.3.0 to 6.0.0 (#1644)
Bumps [crazy-max/ghaction-import-gpg](https://github.com/crazy-max/ghaction-import-gpg) from 5.3.0 to 6.0.0.
- [Release notes](https://github.com/crazy-max/ghaction-import-gpg/releases)
- [Commits](https://github.com/crazy-max/ghaction-import-gpg/compare/v5.3.0...v6.0.0)

---
updated-dependencies:
- dependency-name: crazy-max/ghaction-import-gpg
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-02 18:06:39 +02:00
dependabot[bot] 41bffecc0b
Bump peter-evans/repository-dispatch from 2.1.1 to 2.1.2 (#1645)
Bumps [peter-evans/repository-dispatch](https://github.com/peter-evans/repository-dispatch) from 2.1.1 to 2.1.2.
- [Release notes](https://github.com/peter-evans/repository-dispatch/releases)
- [Commits](https://github.com/peter-evans/repository-dispatch/compare/v2.1.1...v2.1.2)

---
updated-dependencies:
- dependency-name: peter-evans/repository-dispatch
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-02 18:04:26 +02:00
dependabot[bot] f49e1a2c0b
Bump actions/checkout from 3 to 4 (#1646)
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-02 18:03:57 +02:00
LordGrey 08dc59c885
Fix #1630 - Audio Capture settings are ignored (#1640)
* Fix macOS build

* Update minimum cmake version

* Correct compile errorswith Qt6.7

* Update minimum cmake version (2)

* Use C++17

* Correct compile errors with Qt6.7

* Replace unsupported Lambda UniqueConnection

* Support UTF-8 Output on console

* Fix #1630
2023-10-01 21:56:53 +02:00
LordGrey 48cea4ad9b
Focus on relevant PRs 2023-09-30 18:00:38 +02:00
LordGrey 7909997398
Update install_pr.sh
Only run named  'Hyperion PR Build' have artifacts
2023-09-06 20:08:20 +02:00
LordGrey a5bb7e905b
Fix non image updates ignore blacklisted leds (#1635)
* Fix #1634

* Refactor to process blacklisted LEDs with less resources
2023-08-26 11:12:43 +02:00
LordGrey d1879c2e39
ws281x - Update logic to identify is user is admin (#1623) 2023-08-03 22:40:25 +02:00
LordGrey c0dc08b0c0
Update to Protobuf 23.4.0 (#1626)
* Update to protobuf v23.4.0

* Add defines for 3rd party sub-modules used by protobuf

* Check out sub-modules recursively
2023-07-29 19:28:51 +02:00
LordGrey 5bf25c98ad
Update mbedTLS to v3.4.0 (#1625) 2023-07-29 19:28:39 +02:00
LordGrey da275dd448
Update flatbuffers to v23.5.26 (#1624) 2023-07-29 19:28:28 +02:00
Paulchen-Panther 1257cfff70 Set OpenSSL to 1.1.1 (Windows) 2023-07-21 18:59:23 +00:00
LordGrey 42c98da470
Update platforms (#1617)
* Remove stretch, bionic, add lunar

* Fix CEC CMakeList for Ubuntu 23.04

* Fix git version identification when run in docker and local code

* Update SYSTEM_LIBS_SKIP list

* Updates after Ubuntu Server 20.04, latest PI OS Light and CoreElec 20

* Update year

* Skip List working with Fedora38 Server (x86) and libreElec 11 (x86)

* Update platform tag handling

* Show error, if ssl lib cannot be found

* Update supported platforms

* Script to install selected Pull Requests

* Fix misspelled explanation + improve description

* Correct run-id evaluation

* Support python3 and python2

* Support to copy existing config for PR testing
2023-07-21 16:45:37 +02:00
LordGrey 64642a4457
Fix WLED UI handling non supported segment streaming (#1610) 2023-07-10 20:39:35 +02:00
Christoph Pohl af1a31b842
Update dependencies for Debian Bookworm (#1613) 2023-06-25 10:34:47 +02:00
dependabot[bot] a7ce0f8a4c
Bump crazy-max/ghaction-import-gpg from 5.2.0 to 5.3.0 (#1608)
Bumps [crazy-max/ghaction-import-gpg](https://github.com/crazy-max/ghaction-import-gpg) from 5.2.0 to 5.3.0.
- [Release notes](https://github.com/crazy-max/ghaction-import-gpg/releases)
- [Commits](https://github.com/crazy-max/ghaction-import-gpg/compare/v5.2.0...v5.3.0)

---
updated-dependencies:
- dependency-name: crazy-max/ghaction-import-gpg
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-11 20:42:35 +02:00
Paulchen-Panther 00ce3ff089
Update Discord Invite 2023-05-29 21:43:28 +02:00
Paulchen-Panther 54d03b8065 added workflow_dispatch
to allow the bot to create the APT repository itself
2023-05-14 16:29:57 +02:00
lsellens 2a17de37f1
fix for matrix effect (#1602) 2023-05-11 21:11:33 +02:00
LordGrey 5535b884bf
Fixes (#1605)
* Correct misleading Error messages

* Fix that Audio Capture is not shown when there is no screen nor video grabber

* Fix - Audio Capture enabled after reboot automatically (#1581)
2023-05-07 14:04:45 +02:00
Hyperion-Bot 79b31e16e0 Update submodule rpi_ws281x 2023-04-26 00:22:19 +00:00
dependabot[bot] e3496eb4dc
Bump SamKirkland/FTP-Deploy-Action from 4.3.3 to 4.3.4 (#1598)
Bumps [SamKirkland/FTP-Deploy-Action](https://github.com/SamKirkland/FTP-Deploy-Action) from 4.3.3 to 4.3.4.
- [Release notes](https://github.com/SamKirkland/FTP-Deploy-Action/releases)
- [Commits](https://github.com/SamKirkland/FTP-Deploy-Action/compare/4.3.3...v4.3.4)

---
updated-dependencies:
- dependency-name: SamKirkland/FTP-Deploy-Action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-05 17:25:49 +02:00
Paulchen-Panther 08e7c7d8c2 [HotFix] Supplement to the PR #1570 - Fix Issue #1596 2023-03-27 20:54:34 +02:00
Paulchen-Panther e0060eb406 cleanup 2023-03-26 15:22:06 +02:00
dependabot[bot] 2f09f9a0b8
Bump actions/upload-artifact from 2.2.0 to 3.1.2 (#1583)
GitHub Actions Update
2023-03-16 21:38:08 +01:00
Portisch 85eb62f314
Fix missing Include (#1585)
'std::numeric_limits' do need '#include <limits>'
2023-03-09 08:38:05 +01:00
Hyperion-Bot c73f8623b8 Update submodule rpi_ws281x 2023-03-07 00:26:14 +00:00
Harald e59e456b00
fix python version on Debian bookworm (fix #1579) (#1580)
the package wanted the dependency libpython3.9
but the executable expects libpython3.10
2023-02-27 17:04:34 +01:00
Rastafabisch a393f6211c
Update Info.plist.in (#1575)
Hide Hyperion from the Dock.
2023-02-21 17:39:18 +01:00
LordGrey b2fcea3bbd Rollover to 2.0.16-beta.1 2023-02-20 07:38:01 +01:00
LordGrey 24a00e3b0b
Prep Release 2.0.15 (#1571)
* Readd import Collections to show JSON validation failures details

* Editorial update

* Audiograbber - Remove config for not implemented feature

* Smoothing - Update defaults and range

* Version 2.0.15
2023-02-19 13:24:43 +01:00
Hyperion-Bot bfba0d6137 Update de.json (POEditor.com) 2023-02-19 11:41:47 +01:00
Hyperion-Bot fd82f58269 Update de.json (POEditor.com) 2023-02-19 11:05:25 +01:00
Michael Rochelle acdf733936
Audio Grabber Feature (#1570)
* Creating Audio Grabber

Creating Audio Grabber

Creating Audio Grabber.

Successfully began capturing audio in windows. Starting to implement a hard-coded UV Visualizer.

Got Windows DirectSound Implementation working.
Hardcoded basic VU Meter.

Begin working on linux audio grabber implementation.

Finished Linux Draft Implementation.
Minor Mods to windows implementation.

Windows:
 - Free memory used by device id.
 - Prevent starting audio if the grabber is disabled
 - More debug logging

Linux:
 - Prevent starting audio if the grabber is disabled

Added strings to english
Removed "custom" from device selection
Made hard-coded visualizer values configurable.
wrote values to imageData with BGR priority to enable configurable values to be set in RGB format.
created logic to support "Automatic" to enable the API to select the default device.

Add language key for audio in "Remote Control" section.
Removed audio configuration for number of channels. This was causing an error with some devices.

Fixed logic to update capture while its active.
Optimizing code .

UI Tweaks
Destructuring.

Fixed build error on linux.

Custom Effects - Clean-ups and Enhancements (#1163)

* Cleanup EffectFileHandler

* Support Custom Effect Schemas and align EffectFileHandler

* Change back to colon prefix for system effects

* WebSockets - Fix error in handling fragmented frames

* Correct missing colon updates

* Update json with image file location for custom gif effects

* Image effect deletion - considere full filename is stored in JSON

* Correct selection lists indentions

Creating Audio Grabber

Creating Audio Grabber

Creating Audio Grabber.

Successfully began capturing audio in windows. Starting to implement a hard-coded UV Visualizer.

Got Windows DirectSound Implementation working.
Hardcoded basic VU Meter.

Begin working on linux audio grabber implementation.

Finished Linux Draft Implementation.
Minor Mods to windows implementation.

Windows:
 - Free memory used by device id.
 - Prevent starting audio if the grabber is disabled
 - More debug logging

Linux:
 - Prevent starting audio if the grabber is disabled

Added strings to english
Removed "custom" from device selection
Made hard-coded visualizer values configurable.
wrote values to imageData with BGR priority to enable configurable values to be set in RGB format.
created logic to support "Automatic" to enable the API to select the default device.

Add language key for audio in "Remote Control" section.
Removed audio configuration for number of channels. This was causing an error with some devices.

Fixed logic to update capture while its active.
Optimizing code .

UI Tweaks
Destructuring.

Fixed build error on linux.

Commented setVideoMode from AudioGrabber.

Linux Threading changes.

Implementing new API

Continuing to implement audio into new APIs

Fixed Audio Grabber for DirectSound on Windows
Fixed UI for Audio Grabber Configuration
Default AUDIO to off unless specified.

fixed missing #ifdef for audio grabber.

Added logic to calculate a dynamic multiplier from the signal input.

Updating linux api for discovering devices.

Fixed HTML/JS issues with view.
Fixed NPE in Windows.
Disabled setting thread priority in linux.

updated the schema options check to pass through hidden states and commented the change.

Updated grabber start conditions
Updated Audio grabber to instantiate similar to video grabber

Updated windows grabber to set "started" flag to false when shutting down.
Removed "tryStart" to prevent enabling audio capture unnecessarily.

Fixing instance audio grabber device configuration

Added configurable resolution
Reduced tolerance to 5%
Fixed issue where grabber failed for additional instances when "start" was called multiple times.

Fixed resolution calculation

Change averaging algorithm to prevent overflowing the sum.

Updated logic to stop audio grabber when disabled.

Fix integer casting and rounding.

Restart grabber on configuration change.
Fix missing include/grabber/AudioGrabber.
Disable tolerance.

Added configurable tolerance.
Fixed tolerance algorithm.
reset multiplier on configuration change.

Line Endings

Proposed change and questions/request to fix

implementing more of LordGrey's suggestions.

Fix mode for snd_pcm_open. Latest ALSA uses SND_PCM_NONBLOCK instead of SND_PCM_OPEN_NONBLOCK
defaulted multiplier to 0 "auto"
defaulted tolerance to 20%

changed 100 to 100.0 for pixel value percentage calculation to fix value from being 0.

missed a 100 as a double so precision isn't lost during math operation.

Fix Windows grabber and further cleanups

Enable Audio grabbing in standard build

Remove empty methods

Fix audio capture priority setting

Remove unused code

Clean-up default config

Allow additional json-editor attributes

Allow multiple effects and resetting to defaults

Correct default values

Allow to build for Qt < 5.14

Update CodeQL build dependency

Update build dependencies

Remove effect1 placeholder

* Renamed uvMeter to VU Meter (Volume Unit)
- Fixed issues flagged by code scanning bot.

* Moved stop call into destructor of implementing class.

* Removed commented linux audio channel configuration logic.

---------

Co-authored-by: Michael Rochelle <michael@j2inn.com>
2023-02-19 09:36:39 +01:00
LordGrey a1bfa63343
Update schema-webConfig.json 2023-02-17 17:09:12 +01:00
Hyperion-Bot 21c5c6a122 Update de.json (POEditor.com) 2023-02-17 16:12:11 +01:00
LordGrey 1ae37d151e
Dominant Color support (#1569)
* Dominant Color and Mean Color Squared

* Workaround - Suppress empty LED updates

* Add missing text

* Dominant Colors advanced

* Test with fixed initial colors

* Test with fixed initial colors

* Support new processing values via API

* ImageToLED - Add reduced pixel processing, make dominant color advanced configurable

* Updates on Grabber fps setting

* ImageToLedMap - Remove maptype and update test

* Update dynamic cluster array allocation
2023-02-17 16:02:51 +01:00
Hyperion-Bot 093361d3e4 Update sv.json (POEditor.com) 2023-02-17 15:19:10 +01:00
Hyperion-Bot f4391a512b Update es.json (POEditor.com) 2023-02-17 15:19:09 +01:00
Hyperion-Bot f062aa71c5 Update ru.json (POEditor.com) 2023-02-17 15:19:07 +01:00
Hyperion-Bot 6251b58ff9 Update pl.json (POEditor.com) 2023-02-17 15:19:06 +01:00
Hyperion-Bot dea0a17df4 Update it.json (POEditor.com) 2023-02-17 15:19:04 +01:00
Hyperion-Bot 22fa008c4b Update fr.json (POEditor.com) 2023-02-17 15:19:03 +01:00
LordGrey bf418686e3
Fix WLED & Smoothing (#1567)
* WLED - Fix empty segment element in DB

* WLED - Fix to not overwrite on state when not isStayOnAfterStreaming

* Refactor ProviderRestApi, increase default timeout

* Fix Smoothing - Fix empty updates, consider smoothing configs for effects

* UI - Fix not removed priority

* Add missing header and code updates

* setRedirectPolicy was only introduced in Qt 5.9

* Adalight - Align to HyperSerial v9.0.0

* HyperSerial Hyperion with awa protocol v8.0.0

* Correct line-endings
2023-02-12 21:20:50 +01:00
LordGrey a57bcbc2b8
WLED segment streaming support (#1556)
* WLED segment streaming support

* Address CodeQL findings

* WLED - Remove that interim color is shown when WLED is powered off

* Allow LEDDevice to stay on after streaming

* Apply stayOn on segment streamed to

* Fix LED-Matrix Layout: Add Cabling direction selection element again
2023-02-07 08:15:22 +01:00
LordGrey ef7ceb0bbf
Update to Mbed TLS 3.3.0 (#1558)
* Convert mbedtls to subproject

* Align cmake to subproject and mbedtls 3.3.0

* mdebtls 3.3.0

* Add cxx_std_20 for Windows build
2023-02-05 15:19:25 +01:00
dependabot[bot] f327b5063e
Bump actions/download-artifact from 3.0.1 to 3.0.2 (#1562)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 3.0.1 to 3.0.2.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v3.0.1...v3.0.2)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-02 19:15:29 +01:00
LordGrey fa7a5b6b56
Various Fixes/Updates (#1549)
* Update FindWindowsSDK.cmake

* cmake support libcec without version

* Ensure Light-Ids are strings

* Fix type - do not have dbus as requried

* Fixing #1544

* Cleanup

* CleanupFix #1551

* Consistently return instance number with JSON replies (#1504)

* hyperion-remote- Fix extracting reply for configGet request

* Qt 6.6 - Fix iterator finds

* Fix test_image2ledsmap

* Ensure window.currentHyperionInstanceName is set, cleanup system/log clipboard report

* Address protobuf cmake warning

* Update License

* Update ChangeLog

* Address CodeQL and clang findings
2023-01-16 12:01:28 +01:00
LordGrey f665f1e1b6
Update to Protocol Buffers 3.21.12 (#1557) 2023-01-15 22:25:39 +01:00
dependabot[bot] e3a82b2890
Bump peter-evans/repository-dispatch from 2.1.0 to 2.1.1 (#1553)
Bumps [peter-evans/repository-dispatch](https://github.com/peter-evans/repository-dispatch) from 2.1.0 to 2.1.1.
- [Release notes](https://github.com/peter-evans/repository-dispatch/releases)
- [Commits](https://github.com/peter-evans/repository-dispatch/compare/v2.1.0...v2.1.1)

---
updated-dependencies:
- dependency-name: peter-evans/repository-dispatch
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-06 11:26:58 +01:00
dependabot[bot] 09d1ef4883
Bump SamKirkland/FTP-Deploy-Action from 4.3.2 to 4.3.3 (#1552)
Bumps [SamKirkland/FTP-Deploy-Action](https://github.com/SamKirkland/FTP-Deploy-Action) from 4.3.2 to 4.3.3.
- [Release notes](https://github.com/SamKirkland/FTP-Deploy-Action/releases)
- [Commits](https://github.com/SamKirkland/FTP-Deploy-Action/compare/4.3.2...4.3.3)

---
updated-dependencies:
- dependency-name: SamKirkland/FTP-Deploy-Action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-06 11:26:47 +01:00
LordGrey 6fa7bab6f7
Add CodeQL for GitHub code scanning (#1548)
* Create codeql.yml

* Addressing codeql findings
2022-12-27 08:36:10 +01:00
LordGrey 1189f86c1a
Add Suspend/Resume support (#1535)
* Add Suspend/Resume support

* Support Suspend/Resume/Restart via API, UI and Systray

* Support screen lock/unlock scenario

* Handle idle scenario

* Align with fix for #1368

* Update Windows build

* Refactor SuspendHandler to maintain state

* Do not start BG-Effect, if system goes into suspend mode

* Correct Idle and Resume interaction
2022-12-22 12:40:39 +01:00
LordGrey 2217135336
Fixing outstanding issues (#1537)
* Correct stopEnableAttemptsTimer thread affinity

* Restart correctly, if running as service

* Add instance# in API response

* Qt6 updates

* Update fallthrough guide

* Update Compile warning
2022-12-19 14:04:35 +01:00
LordGrey 10b755b2ec
Refactor for Python 3.11 deprecated functions (#1538) 2022-12-19 13:14:35 +01:00
LordGrey c4e681f6b3
Rollover version 2022-12-03 22:22:24 +01:00
245 changed files with 11310 additions and 3188 deletions

View File

@ -1,76 +0,0 @@
# Hyperion.NG .codedocs Configuration File
#---------------------------------------------------------------------------
# CodeDocs Configuration
#---------------------------------------------------------------------------
# Include the Doxygen configuration from another file.
# The file must be a relative path with respect to the root of the repository.
DOXYFILE =
# Specify external repository to link documentation with.
# This is similar to Doxygen's TAGFILES option, but will automatically link to
# tags of other repositories already using CodeDocs. List each repository to
# link with by giving its location in the form of owner/repository.
# For example:
# TAGLINKS = doxygen/doxygen CodeDocs/osg
# Note: these repositories must already be built on CodeDocs.
TAGLINKS =
#---------------------------------------------------------------------------
# Doxygen Configuration
#---------------------------------------------------------------------------
# Doxygen configuration may also be placed in this file.
# Currently, the following Doxygen configuration options are available. Refer
# to http://doxygen.org/manual/config.html for detailed explanation of the
# options. To request support for more options, contact support@codedocs.xyz.
#
# ABBREVIATE_BRIEF =
# ALIASES =
# ALPHABETICAL_INDEX =
# ALWAYS_DETAILED_SEC =
# CASE_SENSE_NAMES =
# CLASS_DIAGRAMS =
# DISABLE_INDEX =
# DISTRIBUTE_GROUP_DOC =
# EXAMPLE_PATH =
EXCLUDE = .ci/ \
assets/ \
bin/
config/ \
effects/ \
test/ \
# EXCLUDE_PATTERNS =
# EXCLUDE_SYMBOLS =
# EXTENSION_MAPPING =
# EXTRACT_LOCAL_CLASSES =
# FILE_PATTERNS =
# GENERATE_TAGFILE =
# GENERATE_TREEVIEW =
# HIDE_COMPOUND_REFERENCE =
# HIDE_SCOPE_NAMES =
# HIDE_UNDOC_CLASSES =
# HIDE_UNDOC_MEMBERS =
# HTML_TIMESTAMP =
# INLINE_GROUPED_CLASSES =
# INPUT_ENCODING =
# INTERNAL_DOCS =
# OPTIMIZE_OUTPUT_FOR_C =
PROJECT_BRIEF = "The successor to Hyperion aka Hyperion Next Generation"
PROJECT_NAME = "Hyperion.NG"
# PROJECT_NUMBER =
# SHORT_NAMES =
# SHOW_FILES =
# SHOW_INCLUDE_FILES =
# SHOW_NAMESPACES =
# SORT_BRIEF_DOCS =
# SORT_BY_SCOPE_NAME =
# SORT_MEMBER_DOCS =
# STRICT_PROTO_MATCHING =
# TYPEDEF_HIDES_STRUCT =
USE_MDFILE_AS_MAINPAGE = README.md
# VERBATIM_HEADERS =
#

4
.github/config/codeql.yml vendored Normal file
View File

@ -0,0 +1,4 @@
name: "CodeQL config"
paths-ignore:
- 'dependencies/external/'
- 'assets/webconfig/js/lib'

View File

@ -1,6 +1,26 @@
name: Hyperion APT Build
on:
workflow_call:
inputs:
head_sha:
type: string
description: The branch, tag or SHA to checkout
required: true
secrets:
APT_GPG:
required: true
APT_USER:
required: true
APT_PASSWORD:
required: true
APT_DRAFT:
required: true
workflow_dispatch:
inputs:
head_sha:
type: string
description: The branch, tag or SHA to checkout
required: true
secrets:
APT_GPG:
required: true
@ -16,7 +36,7 @@ jobs:
name: Setup APT build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set APT matrix
id: apt-ppa
run: |
@ -34,8 +54,9 @@ jobs:
matrix: ${{ fromJson(needs.setup.outputs.apt-matrix) }}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
ref: ${{ github.event.inputs.head_sha || github.event.client_payload.head_sha }}
submodules: true
- name: Generate environment variables
@ -73,7 +94,7 @@ jobs:
cp ../hyperion_*.deb /deploy"
- name: Upload package artifact
if: startsWith(github.event.ref, 'refs/tags')
if: ${{ startsWith(github.event.ref, 'refs/tags') || github.event_name == 'workflow_dispatch' }}
uses: actions/upload-artifact@v3
with:
path: deploy
@ -81,15 +102,17 @@ jobs:
publish:
name: Publish APT packages
if: startsWith(github.event.ref, 'refs/tags')
if: ${{ startsWith(github.event.ref, 'refs/tags') || github.event_name == 'workflow_dispatch' }}
needs: [setup, build]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
ref: ${{ github.event.inputs.head_sha || github.event.client_payload.head_sha }}
- name: Import GPG key
uses: crazy-max/ghaction-import-gpg@v5.2.0
uses: crazy-max/ghaction-import-gpg@v6.0.0
with:
gpg_private_key: ${{ secrets.APT_GPG }}
@ -108,7 +131,7 @@ jobs:
reprepro -Vb apt export
- name: Download artifacts
uses: actions/download-artifact@v3.0.1
uses: actions/download-artifact@v3.0.2
- name: Include artifacts into the package source
run: |
@ -121,7 +144,7 @@ jobs:
done
- name: Upload packages to APT server (DRAFT)
uses: SamKirkland/FTP-Deploy-Action@4.3.2
uses: SamKirkland/FTP-Deploy-Action@v4.3.4
with:
server: apt.hyperion-project.org
username: ${{ secrets.APT_USER }}

View File

@ -1,65 +1,57 @@
[
{
"distribution": "Bionic",
"architecture": "amd64",
"build-depends": "git, cmake, build-essential, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, libqt5x11extras5-dev, libusb-1.0-0-dev, python3-dev, libcec-dev, libxcb-image0-dev, libxcb-util0-dev, libxcb-shm0-dev, libxcb-render0-dev, libxcb-randr0-dev, libxrandr-dev, libxrender-dev, libturbojpeg0-dev, libjpeg-dev, libssl1.0-dev, libmbedtls-dev",
"package-depends": "libpython3.6, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls10, libturbojpeg, libcec4",
"cmake-environment": "-DUSE_SYSTEM_MBEDTLS_LIBS=ON -DENABLE_DEPLOY_DEPENDENCIES=OFF -DCMAKE_BUILD_TYPE=Release",
"description": "Ubuntu 18.04 (Bionic Beaver) (amd64)"
},
{
"distribution": "Focal",
"architecture": "amd64",
"build-depends": "git, cmake, build-essential, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, libqt5x11extras5-dev, libusb-1.0-0-dev, python3-dev, libcec-dev, libxcb-image0-dev, libxcb-util0-dev, libxcb-shm0-dev, libxcb-render0-dev, libxcb-randr0-dev, libxrandr-dev, libxrender-dev, libturbojpeg0-dev, libjpeg-dev, libssl-dev, libmbedtls-dev",
"package-depends": "libpython3.8, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls12, libturbojpeg, libcec4",
"build-depends": "git, cmake, build-essential, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, libqt5x11extras5-dev, libusb-1.0-0-dev, python3-dev, libcec-dev, libxcb-image0-dev, libxcb-util0-dev, libxcb-shm0-dev, libxcb-render0-dev, libxcb-randr0-dev, libxrandr-dev, libxrender-dev, libasound2-dev, libturbojpeg0-dev, libjpeg-dev, libssl-dev, libmbedtls-dev",
"package-depends": "libpython3.8, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls12, libasound2, libturbojpeg, libcec4",
"cmake-environment": "-DUSE_SYSTEM_MBEDTLS_LIBS=ON -DENABLE_DEPLOY_DEPENDENCIES=OFF -DCMAKE_BUILD_TYPE=Release",
"description": "Ubuntu 20.04 (Focal Fossa) (amd64)"
},
{
"distribution": "Jammy",
"architecture": "amd64",
"build-depends": "git, cmake, build-essential, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, libqt5x11extras5-dev, libusb-1.0-0-dev, python3-dev, libcec-dev, libxcb-image0-dev, libxcb-util0-dev, libxcb-shm0-dev, libxcb-render0-dev, libxcb-randr0-dev, libxrandr-dev, libxrender-dev, libturbojpeg0-dev, libjpeg-dev, libssl-dev, libmbedtls-dev",
"package-depends": "libpython3.10, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls14, libturbojpeg, libcec6",
"build-depends": "git, cmake, build-essential, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, libqt5x11extras5-dev, libusb-1.0-0-dev, python3-dev, libcec-dev, libxcb-image0-dev, libxcb-util0-dev, libxcb-shm0-dev, libxcb-render0-dev, libxcb-randr0-dev, libxrandr-dev, libxrender-dev, libasound2-dev, libturbojpeg0-dev, libjpeg-dev, libssl-dev, libmbedtls-dev",
"package-depends": "libpython3.10, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls14, libasound2, libturbojpeg, libcec6",
"cmake-environment": "-DUSE_SYSTEM_MBEDTLS_LIBS=ON -DENABLE_DEPLOY_DEPENDENCIES=OFF -DCMAKE_BUILD_TYPE=Release",
"description": "Ubuntu 22.04 (Jammy Jellyfish) (amd64)"
},
{
"distribution": "Kinetic",
"architecture": "amd64",
"build-depends": "git, cmake, build-essential, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, libqt5x11extras5-dev, libusb-1.0-0-dev, python3-dev, libcec-dev, libxcb-image0-dev, libxcb-util0-dev, libxcb-shm0-dev, libxcb-render0-dev, libxcb-randr0-dev, libxrandr-dev, libxrender-dev, libturbojpeg0-dev, libjpeg-dev, libssl-dev, libmbedtls-dev",
"package-depends": "libpython3.10, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls14, libturbojpeg, libcec6",
"build-depends": "git, cmake, build-essential, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, libqt5x11extras5-dev, libusb-1.0-0-dev, python3-dev, libcec-dev, libxcb-image0-dev, libxcb-util0-dev, libxcb-shm0-dev, libxcb-render0-dev, libxcb-randr0-dev, libxrandr-dev, libxrender-dev, libasound2-dev, libturbojpeg0-dev, libjpeg-dev, libssl-dev, libmbedtls-dev",
"package-depends": "libpython3.10, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls14, libasound2, libturbojpeg, libcec6",
"cmake-environment": "-DUSE_SYSTEM_MBEDTLS_LIBS=ON -DENABLE_DEPLOY_DEPENDENCIES=OFF -DCMAKE_BUILD_TYPE=Release",
"description": "Ubuntu 22.10 (Kinetic Kudu) (amd64)"
},
{
"distribution": "Stretch",
"distribution": "Lunar",
"architecture": "amd64",
"build-depends": "git, cmake, build-essential, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, libqt5x11extras5-dev, libusb-1.0-0-dev, python3-dev, libcec-dev, libxcb-image0-dev, libxcb-util0-dev, libxcb-shm0-dev, libxcb-render0-dev, libxcb-randr0-dev, libxrandr-dev, libxrender-dev, libturbojpeg0-dev, libjpeg-dev, libssl1.0-dev, libmbedtls-dev",
"package-depends": "libpython3.5, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls10, libturbojpeg0, libcec4",
"build-depends": "git, cmake, build-essential, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, libqt5x11extras5-dev, libusb-1.0-0-dev, python3-dev, libcec-dev, libxcb-image0-dev, libxcb-util0-dev, libxcb-shm0-dev, libxcb-render0-dev, libxcb-randr0-dev, libxrandr-dev, libxrender-dev, libasound2-dev, libturbojpeg0-dev, libjpeg-dev, libssl-dev, libmbedtls-dev",
"package-depends": "libpython3.11, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls14, libasound2, libturbojpeg, libcec6",
"cmake-environment": "-DUSE_SYSTEM_MBEDTLS_LIBS=ON -DENABLE_DEPLOY_DEPENDENCIES=OFF -DCMAKE_BUILD_TYPE=Release",
"description": "Debian 9.x (Stretch) (amd64)"
"description": "Ubuntu 23.04 (Lunar Lobster) (amd64)"
},
{
"distribution": "Buster",
"architecture": "amd64",
"build-depends": "git, cmake, build-essential, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, libqt5x11extras5-dev, libusb-1.0-0-dev, python3-dev, libcec-dev, libxcb-image0-dev, libxcb-util0-dev, libxcb-shm0-dev, libxcb-render0-dev, libxcb-randr0-dev, libxrandr-dev, libxrender-dev, libturbojpeg0-dev, libjpeg-dev, libssl-dev, libmbedtls-dev",
"package-depends": "libpython3.7, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls12, libturbojpeg0, libcec4",
"build-depends": "git, cmake, build-essential, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, libqt5x11extras5-dev, libusb-1.0-0-dev, python3-dev, libcec-dev, libxcb-image0-dev, libxcb-util0-dev, libxcb-shm0-dev, libxcb-render0-dev, libxcb-randr0-dev, libxrandr-dev, libxrender-dev, libasound2-dev, libturbojpeg0-dev, libjpeg-dev, libssl-dev, libmbedtls-dev",
"package-depends": "libpython3.7, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls12, libasound2, libturbojpeg0, libcec4",
"cmake-environment": "-DUSE_SYSTEM_MBEDTLS_LIBS=ON -DENABLE_DEPLOY_DEPENDENCIES=OFF -DCMAKE_BUILD_TYPE=Release",
"description": "Debian 10.x (Buster) (amd64)"
},
{
"distribution": "Bullseye",
"architecture": "amd64",
"build-depends": "git, cmake, build-essential, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, libqt5x11extras5-dev, libusb-1.0-0-dev, python3-dev, libcec-dev, libxcb-image0-dev, libxcb-util0-dev, libxcb-shm0-dev, libxcb-render0-dev, libxcb-randr0-dev, libxrandr-dev, libxrender-dev, libturbojpeg0-dev, libjpeg-dev, libssl-dev, libmbedtls-dev",
"package-depends": "libpython3.9, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls12, libturbojpeg0, libcec6",
"build-depends": "git, cmake, build-essential, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, libqt5x11extras5-dev, libusb-1.0-0-dev, python3-dev, libcec-dev, libxcb-image0-dev, libxcb-util0-dev, libxcb-shm0-dev, libxcb-render0-dev, libxcb-randr0-dev, libxrandr-dev, libxrender-dev, libasound2-dev, libturbojpeg0-dev, libjpeg-dev, libssl-dev, libmbedtls-dev",
"package-depends": "libpython3.9, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls12, libasound2, libturbojpeg0, libcec6",
"cmake-environment": "-DUSE_SYSTEM_MBEDTLS_LIBS=ON -DENABLE_DEPLOY_DEPENDENCIES=OFF -DCMAKE_BUILD_TYPE=Release",
"description": "Debian 11.x (Bullseye) (amd64)"
},
{
"distribution": "Bookworm",
"architecture": "amd64",
"build-depends": "git, cmake, build-essential, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, libqt5x11extras5-dev, libusb-1.0-0-dev, python3-dev, libcec-dev, libxcb-image0-dev, libxcb-util0-dev, libxcb-shm0-dev, libxcb-render0-dev, libxcb-randr0-dev, libxrandr-dev, libxrender-dev, libturbojpeg0-dev, libjpeg-dev, libssl-dev, libmbedtls-dev",
"package-depends": "libpython3.9, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls12, libturbojpeg0, libcec6",
"build-depends": "git, cmake, build-essential, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, libqt5x11extras5-dev, libusb-1.0-0-dev, python3-dev, libcec-dev, libxcb-image0-dev, libxcb-util0-dev, libxcb-shm0-dev, libxcb-render0-dev, libxcb-randr0-dev, libxrandr-dev, libxrender-dev, libasound2-dev, libturbojpeg0-dev, libjpeg-dev, libssl-dev, libmbedtls-dev",
"package-depends": "libpython3.11, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls14, libasound2, libturbojpeg0, libcec6",
"cmake-environment": "-DUSE_SYSTEM_MBEDTLS_LIBS=ON -DENABLE_DEPLOY_DEPENDENCIES=OFF -DCMAKE_BUILD_TYPE=Release",
"description": "Debian 12.x (Bookworm) (amd64)"
}

View File

@ -1,57 +1,49 @@
[
{
"distribution": "Bionic",
"architecture": "arm64",
"build-depends": "git, cmake, build-essential, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, libqt5x11extras5-dev, libusb-1.0-0-dev, python3-dev, libcec-dev, libxcb-image0-dev, libxcb-util0-dev, libxcb-shm0-dev, libxcb-render0-dev, libxcb-randr0-dev, libxrandr-dev, libxrender-dev, libturbojpeg0-dev, libjpeg-dev, libssl1.0-dev, libmbedtls-dev",
"package-depends": "libpython3.6, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls10, libturbojpeg, libcec4",
"cmake-environment": "-DENABLE_DISPMANX=OFF -DENABLE_X11=ON -DENABLE_XCB=ON -DUSE_SYSTEM_MBEDTLS_LIBS=ON -DENABLE_DEPLOY_DEPENDENCIES=OFF -DCMAKE_BUILD_TYPE=Release",
"description": "Ubuntu 18.04 (Bionic Beaver) (arm64)"
},
{
"distribution": "Focal",
"architecture": "arm64",
"build-depends": "git, cmake, build-essential, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, libqt5x11extras5-dev, libusb-1.0-0-dev, python3-dev, libcec-dev, libxcb-image0-dev, libxcb-util0-dev, libxcb-shm0-dev, libxcb-render0-dev, libxcb-randr0-dev, libxrandr-dev, libxrender-dev, libturbojpeg0-dev, libjpeg-dev, libssl-dev, libmbedtls-dev",
"package-depends": "libpython3.8, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls12, libturbojpeg, libcec4",
"build-depends": "git, cmake, build-essential, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, libqt5x11extras5-dev, libusb-1.0-0-dev, python3-dev, libcec-dev, libxcb-image0-dev, libxcb-util0-dev, libxcb-shm0-dev, libxcb-render0-dev, libxcb-randr0-dev, libxrandr-dev, libxrender-dev, libasound2-dev, libturbojpeg0-dev, libjpeg-dev, libssl-dev, libmbedtls-dev",
"package-depends": "libpython3.8, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls12, libasound2, libturbojpeg, libcec4",
"cmake-environment": "-DENABLE_DISPMANX=OFF -DENABLE_X11=ON -DENABLE_XCB=ON -DUSE_SYSTEM_MBEDTLS_LIBS=ON -DENABLE_DEPLOY_DEPENDENCIES=OFF -DCMAKE_BUILD_TYPE=Release",
"description": "Ubuntu 20.04 (Focal Fossa) (arm64)"
},
{
"distribution": "Jammy",
"architecture": "arm64",
"build-depends": "git, cmake, build-essential, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, libqt5x11extras5-dev, libusb-1.0-0-dev, python3-dev, libcec-dev, libxcb-image0-dev, libxcb-util0-dev, libxcb-shm0-dev, libxcb-render0-dev, libxcb-randr0-dev, libxrandr-dev, libxrender-dev, libturbojpeg0-dev, libjpeg-dev, libssl-dev, libmbedtls-dev",
"package-depends": "libpython3.10, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls14, libturbojpeg, libcec6",
"build-depends": "git, cmake, build-essential, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, libqt5x11extras5-dev, libusb-1.0-0-dev, python3-dev, libcec-dev, libxcb-image0-dev, libxcb-util0-dev, libxcb-shm0-dev, libxcb-render0-dev, libxcb-randr0-dev, libxrandr-dev, libxrender-dev, libasound2-dev, libturbojpeg0-dev, libjpeg-dev, libssl-dev, libmbedtls-dev",
"package-depends": "libpython3.10, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls14, libasound2, libturbojpeg, libcec6",
"cmake-environment": "-DENABLE_DISPMANX=OFF -DENABLE_X11=ON -DENABLE_XCB=ON -DUSE_SYSTEM_MBEDTLS_LIBS=ON -DENABLE_DEPLOY_DEPENDENCIES=OFF -DCMAKE_BUILD_TYPE=Release",
"description": "Ubuntu 22.04 (Jammy Jellyfish) (arm64)"
},
{
"distribution": "Kinetic",
"architecture": "arm64",
"build-depends": "git, cmake, build-essential, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, libqt5x11extras5-dev, libusb-1.0-0-dev, python3-dev, libcec-dev, libxcb-image0-dev, libxcb-util0-dev, libxcb-shm0-dev, libxcb-render0-dev, libxcb-randr0-dev, libxrandr-dev, libxrender-dev, libturbojpeg0-dev, libjpeg-dev, libssl-dev, libmbedtls-dev",
"package-depends": "libpython3.10, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls14, libturbojpeg, libcec6",
"build-depends": "git, cmake, build-essential, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, libqt5x11extras5-dev, libusb-1.0-0-dev, python3-dev, libcec-dev, libxcb-image0-dev, libxcb-util0-dev, libxcb-shm0-dev, libxcb-render0-dev, libxcb-randr0-dev, libxrandr-dev, libxrender-dev, libasound2-dev, libturbojpeg0-dev, libjpeg-dev, libssl-dev, libmbedtls-dev",
"package-depends": "libpython3.10, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls14, libasound2, libturbojpeg, libcec6",
"cmake-environment": "-DENABLE_DISPMANX=OFF -DENABLE_X11=ON -DENABLE_XCB=ON -DUSE_SYSTEM_MBEDTLS_LIBS=ON -DENABLE_DEPLOY_DEPENDENCIES=OFF -DCMAKE_BUILD_TYPE=Release",
"description": "Ubuntu 22.10 (Kinetic Kudu) (arm64)"
},
{
"distribution": "Buster",
"architecture": "arm64",
"build-depends": "git, cmake, python3-dev, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, build-essential, libusb-1.0-0-dev, libcec-dev, libssl-dev, libraspberrypi-dev, libturbojpeg0-dev, libjpeg-dev, libmbedtls-dev",
"package-depends": "libpython3.7, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls12, libturbojpeg0, libcec4",
"build-depends": "git, cmake, python3-dev, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, build-essential, libusb-1.0-0-dev, libcec-dev, libssl-dev, libraspberrypi-dev, libasound2-dev, libturbojpeg0-dev, libjpeg-dev, libmbedtls-dev",
"package-depends": "libpython3.7, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls12, libasound2, libturbojpeg0, libcec4",
"cmake-environment": "-DUSE_SYSTEM_MBEDTLS_LIBS=ON -DENABLE_DEPLOY_DEPENDENCIES=OFF -DCMAKE_BUILD_TYPE=Release",
"description": "Debian 10.x (Buster) (arm64)"
},
{
"distribution": "Bullseye",
"architecture": "arm64",
"build-depends": "git, cmake, python3-dev, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, build-essential, libusb-1.0-0-dev, libcec-dev, libssl-dev, libraspberrypi-dev, libturbojpeg0-dev, libjpeg-dev, libmbedtls-dev",
"package-depends": "libpython3.9, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls12, libturbojpeg0, libcec6",
"build-depends": "git, cmake, python3-dev, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, build-essential, libusb-1.0-0-dev, libcec-dev, libssl-dev, libraspberrypi-dev, libasound2-dev, libturbojpeg0-dev, libjpeg-dev, libmbedtls-dev",
"package-depends": "libpython3.9, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls12, libasound2, libturbojpeg0, libcec6",
"cmake-environment": "-DUSE_SYSTEM_MBEDTLS_LIBS=ON -DENABLE_DEPLOY_DEPENDENCIES=OFF -DCMAKE_BUILD_TYPE=Release",
"description": "Debian 11.x (Bullseye) (arm64)"
},
{
"distribution": "Bookworm",
"architecture": "arm64",
"build-depends": "git, cmake, python3-dev, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, build-essential, libusb-1.0-0-dev, libcec-dev, libssl-dev, libraspberrypi-dev, libturbojpeg0-dev, libjpeg-dev, libmbedtls-dev",
"package-depends": "libpython3.9, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls12, libturbojpeg0, libcec6",
"build-depends": "git, cmake, python3-dev, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, build-essential, libusb-1.0-0-dev, libcec-dev, libssl-dev, libraspberrypi-dev, libasound2-dev, libturbojpeg0-dev, libjpeg-dev, libmbedtls-dev",
"package-depends": "libpython3.11, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls14, libasound2, libturbojpeg0, libcec6",
"cmake-environment": "-DUSE_SYSTEM_MBEDTLS_LIBS=ON -DENABLE_DEPLOY_DEPENDENCIES=OFF -DCMAKE_BUILD_TYPE=Release",
"description": "Debian 12.x (Bookworm) (arm64)",
"exclude" : true

View File

@ -1,65 +1,49 @@
[
{
"distribution": "Bionic",
"architecture": "armhf",
"build-depends": "git, cmake, build-essential, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, libqt5x11extras5-dev, libusb-1.0-0-dev, python3-dev, libcec-dev, libxcb-image0-dev, libxcb-util0-dev, libxcb-shm0-dev, libxcb-render0-dev, libxcb-randr0-dev, libxrandr-dev, libxrender-dev, libturbojpeg0-dev, libjpeg-dev, libssl1.0-dev, libmbedtls-dev",
"package-depends": "libpython3.6, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls10, libturbojpeg, libcec4",
"cmake-environment": "-DENABLE_DISPMANX=OFF -DENABLE_X11=ON -DENABLE_XCB=ON -DUSE_SYSTEM_MBEDTLS_LIBS=ON -DENABLE_DEPLOY_DEPENDENCIES=OFF -DCMAKE_BUILD_TYPE=Release",
"description": "Ubuntu 18.04 (Bionic Beaver) (armhf)"
},
{
"distribution": "Focal",
"architecture": "armhf",
"build-depends": "git, cmake, build-essential, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, libqt5x11extras5-dev, libusb-1.0-0-dev, python3-dev, libcec-dev, libxcb-image0-dev, libxcb-util0-dev, libxcb-shm0-dev, libxcb-render0-dev, libxcb-randr0-dev, libxrandr-dev, libxrender-dev, libturbojpeg0-dev, libjpeg-dev, libssl-dev, libmbedtls-dev",
"package-depends": "libpython3.8, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls12, libturbojpeg, libcec4",
"build-depends": "git, cmake, build-essential, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, libqt5x11extras5-dev, libusb-1.0-0-dev, python3-dev, libcec-dev, libxcb-image0-dev, libxcb-util0-dev, libxcb-shm0-dev, libxcb-render0-dev, libxcb-randr0-dev, libxrandr-dev, libxrender-dev, libasound2-dev, libturbojpeg0-dev, libjpeg-dev, libssl-dev, libmbedtls-dev",
"package-depends": "libpython3.8, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls12, libasound2, libturbojpeg, libcec4",
"cmake-environment": "-DENABLE_DISPMANX=OFF -DENABLE_X11=ON -DENABLE_XCB=ON -DUSE_SYSTEM_MBEDTLS_LIBS=ON -DENABLE_DEPLOY_DEPENDENCIES=OFF -DCMAKE_BUILD_TYPE=Release",
"description": "Ubuntu 20.04 (Focal Fossa) (armhf)"
},
{
"distribution": "Jammy",
"architecture": "armhf",
"build-depends": "git, cmake, build-essential, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, libqt5x11extras5-dev, libusb-1.0-0-dev, python3-dev, libcec-dev, libxcb-image0-dev, libxcb-util0-dev, libxcb-shm0-dev, libxcb-render0-dev, libxcb-randr0-dev, libxrandr-dev, libxrender-dev, libturbojpeg0-dev, libjpeg-dev, libssl-dev, libmbedtls-dev",
"package-depends": "libpython3.10, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls14, libturbojpeg, libcec6",
"build-depends": "git, cmake, build-essential, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, libqt5x11extras5-dev, libusb-1.0-0-dev, python3-dev, libcec-dev, libxcb-image0-dev, libxcb-util0-dev, libxcb-shm0-dev, libxcb-render0-dev, libxcb-randr0-dev, libxrandr-dev, libxrender-dev, libasound2-dev, libturbojpeg0-dev, libjpeg-dev, libssl-dev, libmbedtls-dev",
"package-depends": "libpython3.10, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls14, libasound2, libturbojpeg, libcec6",
"cmake-environment": "-DENABLE_DISPMANX=OFF -DENABLE_X11=ON -DENABLE_XCB=ON -DUSE_SYSTEM_MBEDTLS_LIBS=ON -DENABLE_DEPLOY_DEPENDENCIES=OFF -DCMAKE_BUILD_TYPE=Release",
"description": "Ubuntu 22.04 (Jammy Jellyfish) (armhf)"
},
{
"distribution": "Kinetic",
"architecture": "armhf",
"build-depends": "git, cmake, build-essential, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, libqt5x11extras5-dev, libusb-1.0-0-dev, python3-dev, libcec-dev, libxcb-image0-dev, libxcb-util0-dev, libxcb-shm0-dev, libxcb-render0-dev, libxcb-randr0-dev, libxrandr-dev, libxrender-dev, libturbojpeg0-dev, libjpeg-dev, libssl-dev, libmbedtls-dev",
"package-depends": "libpython3.10, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls14, libturbojpeg, libcec6",
"build-depends": "git, cmake, build-essential, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, libqt5x11extras5-dev, libusb-1.0-0-dev, python3-dev, libcec-dev, libxcb-image0-dev, libxcb-util0-dev, libxcb-shm0-dev, libxcb-render0-dev, libxcb-randr0-dev, libxrandr-dev, libxrender-dev, libasound2-dev, libturbojpeg0-dev, libjpeg-dev, libssl-dev, libmbedtls-dev",
"package-depends": "libpython3.10, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls14, libasound2, libturbojpeg, libcec6",
"cmake-environment": "-DENABLE_DISPMANX=OFF -DENABLE_X11=ON -DENABLE_XCB=ON -DUSE_SYSTEM_MBEDTLS_LIBS=ON -DENABLE_DEPLOY_DEPENDENCIES=OFF -DCMAKE_BUILD_TYPE=Release",
"description": "Ubuntu 22.10 (Kinetic Kudu) (armhf)"
},
{
"distribution": "Stretch",
"architecture": "armhf",
"build-depends": "git, cmake, python3-dev, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, build-essential, libusb-1.0-0-dev, libcec-dev, libssl1.0-dev, libraspberrypi-dev, libturbojpeg0-dev, libjpeg-dev, libmbedtls-dev",
"package-depends": "libpython3.5, libusb-1.0-0, libqt5widgets5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls10, libturbojpeg0, libcec4",
"cmake-environment": "-DUSE_SYSTEM_MBEDTLS_LIBS=ON -DENABLE_DEPLOY_DEPENDENCIES=OFF -DCMAKE_BUILD_TYPE=Release",
"description":"Debian 9.x (Stretch) (armhf)"
},
{
"distribution": "Buster",
"architecture": "armhf",
"build-depends": "git, cmake, python3-dev, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, build-essential, libusb-1.0-0-dev, libcec-dev, libssl1.0-dev, libraspberrypi-dev, libturbojpeg0-dev, libjpeg-dev, libmbedtls-dev",
"package-depends": "libpython3.7, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls12, libturbojpeg0, libcec4",
"build-depends": "git, cmake, python3-dev, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, build-essential, libusb-1.0-0-dev, libcec-dev, libssl1.0-dev, libraspberrypi-dev, libasound2-dev, libturbojpeg0-dev, libjpeg-dev, libmbedtls-dev",
"package-depends": "libpython3.7, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls12, libasound2, libturbojpeg0, libcec4",
"cmake-environment": "-DUSE_SYSTEM_MBEDTLS_LIBS=ON -DENABLE_DEPLOY_DEPENDENCIES=OFF -DCMAKE_BUILD_TYPE=Release",
"description": "Debian 10.x (Buster) (armhf)"
},
{
"distribution": "Bullseye",
"architecture": "armhf",
"build-depends": "git, cmake, python3-dev, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, build-essential, libusb-1.0-0-dev, libcec-dev, libssl-dev, libraspberrypi-dev, libturbojpeg0-dev, libjpeg-dev, libmbedtls-dev",
"package-depends": "libpython3.9, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls12, libturbojpeg0, libcec6",
"build-depends": "git, cmake, python3-dev, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, build-essential, libusb-1.0-0-dev, libcec-dev, libssl-dev, libraspberrypi-dev, libasound2-dev, libturbojpeg0-dev, libjpeg-dev, libmbedtls-dev",
"package-depends": "libpython3.9, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls12, libasound2, libturbojpeg0, libcec6",
"cmake-environment": "-DUSE_SYSTEM_MBEDTLS_LIBS=ON -DENABLE_DEPLOY_DEPENDENCIES=OFF -DCMAKE_BUILD_TYPE=Release",
"description": "Debian 11.x (Bullseye) (armhf)"
},
{
"distribution": "Bookworm",
"architecture": "armhf",
"build-depends": "git, cmake, python3-dev, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, build-essential, libusb-1.0-0-dev, libcec-dev, libssl-dev, libraspberrypi-dev, libturbojpeg0-dev, libjpeg-dev, libmbedtls-dev",
"package-depends": "libpython3.9, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls12, libturbojpeg0, libcec6",
"build-depends": "git, cmake, python3-dev, qtbase5-dev, libqt5serialport5-dev, libqt5sql5-sqlite, libqt5svg5-dev, build-essential, libusb-1.0-0-dev, libcec-dev, libssl-dev, libraspberrypi-dev, libasound2-dev, libturbojpeg0-dev, libjpeg-dev, libmbedtls-dev",
"package-depends": "libpython3.11, libusb-1.0-0, libqt5widgets5, libqt5x11extras5, libqt5sql5, libqt5sql5-sqlite, libqt5serialport5, libmbedtls14, libasound2, libturbojpeg0, libcec6",
"cmake-environment": "-DUSE_SYSTEM_MBEDTLS_LIBS=ON -DENABLE_DEPLOY_DEPENDENCIES=OFF -DCMAKE_BUILD_TYPE=Release",
"description": "Debian 12.x (Bookworm) (armhf)",
"exclude" : true

76
.github/workflows/codeql.yml vendored Normal file
View File

@ -0,0 +1,76 @@
name: "CodeQL"
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
schedule:
- cron: "36 18 * * 4"
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ python, javascript, cpp ]
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Packages (cpp)
if: ${{ matrix.language == 'cpp' }}
run: |
sudo apt-get update
sudo apt-get install --yes git cmake build-essential qtbase5-dev libqt5serialport5-dev libqt5sql5-sqlite libqt5svg5-dev libqt5x11extras5-dev libusb-1.0-0-dev python3-dev libcec-dev libxcb-image0-dev libxcb-util0-dev libxcb-shm0-dev libxcb-render0-dev libxcb-randr0-dev libxrandr-dev libxrender-dev libavahi-core-dev libavahi-compat-libdnssd-dev libasound2-dev libturbojpeg0-dev libjpeg-dev libssl-dev
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
queries: +security-and-quality
config-file: ./.github/config/codeql.yml
- name: Autobuild
uses: github/codeql-action/autobuild@v2
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{ matrix.language }}"
upload: False
output: sarif-results
- name: Filter SARIF
uses: advanced-security/filter-sarif@v1
with:
patterns: |
-**/dependencies/**
-**/moc_*.cpp
-**/libsrc/flatbufserver/hyperion_request_generated.h
-**/libsrc/protoserver/message.pb.cc
-**/libsrc/protoserver/message.pb.h
input: sarif-results/${{ matrix.language }}.sarif
output: sarif-results/${{ matrix.language }}.sarif
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: sarif-results/${{ matrix.language }}.sarif
- name: Upload loc as a Build Artifact
uses: actions/upload-artifact@v3
with:
name: sarif-results
path: sarif-results
retention-days: 1

View File

@ -13,7 +13,7 @@ jobs:
if: github.repository_owner == 'hyperion-project'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
persist-credentials: false
fetch-depth: 0
@ -48,7 +48,7 @@ jobs:
if: github.repository_owner == 'hyperion-project'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Check if commit has changed
id: build-necessary
run: |
@ -66,7 +66,7 @@ jobs:
if: ${{ needs.check.outputs.build-nightly == 'true' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set nightly matrix
id: nightly-ppa
run: |
@ -84,9 +84,9 @@ jobs:
matrix: ${{ fromJson(needs.setup.outputs.nightly-matrix) }}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
submodules: true
submodules: recursive
- name: Generate environment variables
run: |
@ -135,10 +135,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Import GPG key
uses: crazy-max/ghaction-import-gpg@v5.2.0
uses: crazy-max/ghaction-import-gpg@v6.0.0
with:
gpg_private_key: ${{ secrets.APT_GPG }}
@ -158,7 +158,7 @@ jobs:
reprepro -Vb nightly export
- name: Download artifacts
uses: actions/download-artifact@v3.0.1
uses: actions/download-artifact@v3.0.2
- name: Include artifacts into the package source
run: |
@ -171,7 +171,7 @@ jobs:
done
- name: Upload packages to nightly server
uses: SamKirkland/FTP-Deploy-Action@4.3.2
uses: SamKirkland/FTP-Deploy-Action@v4.3.4
with:
server: nightly.apt.hyperion-project.org
username: ${{ secrets.NIGHTLY_USER }}

View File

@ -18,23 +18,23 @@ jobs:
dockerImage: [ x86_64, armv6l, armv7l, aarch64 ]
include:
- dockerImage: x86_64
dockerName: Debian Stretch (x86_64)
dockerName: Debian Buster (x86_64)
platform: x11
- dockerImage: armv6l
dockerName: Debian Stretch (Raspberry Pi v1 & ZERO)
dockerName: Debian Buster (Raspberry Pi v1 & ZERO)
platform: rpi
- dockerImage: armv7l
dockerName: Debian Stretch (Raspberry Pi 2 & 3)
dockerName: Debian Buster (Raspberry Pi 2 & 3)
platform: rpi
- dockerImage: aarch64
dockerName: Debian Stretch (Generic AARCH64)
dockerName: Debian Buster (Generic AARCH64)
platform: amlogic
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: true
submodules: recursive
# Append PR number to .version
- name: Append PR number to version
@ -47,7 +47,7 @@ jobs:
- name: Build packages
env:
DOCKER_IMAGE: ${{ matrix.dockerImage }}
DOCKER_TAG: stretch
DOCKER_TAG: buster
DOCKER_NAME: ${{ matrix.dockerName }}
PLATFORM: ${{ matrix.platform }}
shell: bash
@ -76,9 +76,9 @@ jobs:
runs-on: macos-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: true
submodules: recursive
# Append PR number to .version
- name: Append PR number to version
@ -125,9 +125,9 @@ jobs:
QT_VERSION: 5.15.2
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: true
submodules: recursive
# Append PR number to .version
- name: Append PR number to version
@ -151,10 +151,16 @@ jobs:
path: C:\Users\runneradmin\AppData\Local\Temp\chocolatey
key: ${{ runner.os }}-chocolatey
- name: Install Python, OpenSSL, DirectX SDK
# - name: Install Python
# shell: powershell
# run: |
# choco install --no-progress python -y
- name: Install OpenSSL, DirectX SDK
shell: powershell
run: |
choco install --no-progress python openssl directx-sdk -y
choco install --no-progress openssl --version=1.1.1.2100 -y
choco install --no-progress directx-sdk -y
- name: Install libjpeg-turbo
run: |

View File

@ -20,28 +20,28 @@ jobs:
dockerImage: [ x86_64, armv6l, armv7l, aarch64 ]
include:
- dockerImage: x86_64
dockerName: Debian Stretch (x86_64)
dockerName: Debian Buster (x86_64)
platform: x11
- dockerImage: armv6l
dockerName: Debian Stretch (Raspberry Pi v1 & ZERO)
dockerName: Debian Buster (Raspberry Pi v1 & ZERO)
platform: rpi
- dockerImage: armv7l
dockerName: Debian Stretch (Raspberry Pi 2 & 3)
dockerName: Debian Buster (Raspberry Pi 2 & 3)
platform: rpi
- dockerImage: aarch64
dockerName: Debian Stretch (Generic AARCH64)
dockerName: Debian Buster (Generic AARCH64)
platform: amlogic
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
submodules: true
submodules: recursive
# Build process
- name: Build packages
env:
DOCKER_IMAGE: ${{ matrix.dockerImage }}
DOCKER_TAG: stretch
DOCKER_TAG: buster
DOCKER_NAME: ${{ matrix.dockerName }}
PLATFORM: ${{ matrix.platform }}
shell: bash
@ -62,9 +62,9 @@ jobs:
name: macOS
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
submodules: true
submodules: recursive
# Install dependencies
- name: Install dependencies
@ -97,9 +97,9 @@ jobs:
QT_VERSION: 5.15.2
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: true
submodules: recursive
- name: Install Qt
uses: jurplel/install-qt-action@v3
@ -116,10 +116,16 @@ jobs:
path: C:\Users\runneradmin\AppData\Local\Temp\chocolatey
key: ${{ runner.os }}-chocolatey
- name: Install Python, OpenSSL, DirectX SDK
# - name: Install Python
# shell: powershell
# run: |
# choco install --no-progress python -y
- name: Install OpenSSL, DirectX SDK
shell: powershell
run: |
choco install --no-progress python openssl directx-sdk -y
choco install --no-progress openssl --version=1.1.1.2100 -y
choco install --no-progress directx-sdk -y
- name: Install libjpeg-turbo
run: |
@ -156,7 +162,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
# Generate environment variables
- name: Generate environment variables from .version and tag
@ -166,7 +172,7 @@ jobs:
# Download artifacts from previous build process
- name: Download artifacts
uses: actions/download-artifact@v3.0.1
uses: actions/download-artifact@v3.0.2
with:
path: artifacts
@ -190,8 +196,6 @@ jobs:
if: startsWith(github.event.ref, 'refs/tags')
needs: [Linux, macOS, windows]
uses: ./.github/workflows/apt.yml
secrets:
APT_GPG: ${{ secrets.APT_GPG }}
APT_USER: ${{ secrets.APT_USER }}
APT_PASSWORD: ${{ secrets.APT_PASSWORD }}
APT_DRAFT: ${{ secrets.APT_DRAFT }}
secrets: inherit
with:
head_sha: master

View File

@ -10,7 +10,7 @@ jobs:
steps:
# Dispatch event to build new HyperBian image
- name: Dispatch HyperBian build
uses: peter-evans/repository-dispatch@v2.1.0
uses: peter-evans/repository-dispatch@v2.1.2
if: ${{ github.repository_owner == 'hyperion-project'}}
with:
repository: hyperion-project/HyperBian

1
.gitignore vendored
View File

@ -30,6 +30,7 @@ libsrc/flatbufserver/hyperion_request_generated.h
# Ignore
.vs/*
CMakeSettings.json
/out
# Allow
!.vs/launch.vs.json

3
.gitmodules vendored
View File

@ -12,3 +12,6 @@
[submodule "dependencies/external/qmdnsengine"]
path = dependencies/external/qmdnsengine
url = https://github.com/nitroshare/qmdnsengine.git
[submodule "dependencies/external/mbedtls"]
path = dependencies/external/mbedtls
url = ../../Mbed-TLS/mbedtls.git

View File

@ -1,27 +0,0 @@
extraction:
cpp:
prepare:
packages:
- "git"
- "cmake"
- "build-essential"
- "qtbase5-dev"
- "libqt5serialport5-dev"
- "libqt5sql5-sqlite"
- "libqt5svg5-dev"
- "libqt5x11extras5-dev"
- "libusb-1.0-0-dev"
- "python3-dev"
- "libcec-dev"
- "libxcb-image0-dev"
- "libxcb-util0-dev"
- "libxcb-shm0-dev"
- "libxcb-render0-dev"
- "libxcb-randr0-dev"
- "libxrandr-dev"
- "libxrender-dev"
- "libavahi-core-dev"
- "libavahi-compat-libdnssd-dev"
- "libturbojpeg0-dev"
- "libjpeg-dev"
- "libssl-dev"

View File

@ -1 +1 @@
2.0.14
2.0.16-beta.1

View File

@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased](https://github.com/hyperion-project/hyperion.ng/compare/2.0.14...HEAD)
## [Unreleased](https://github.com/hyperion-project/hyperion.ng/compare/2.0.15...HEAD)
### Breaking
@ -13,6 +13,57 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
### Fixed
- Fixed missing Include limits in QJsonSchemaChecker
- Fixed dependencies for deb packages in Debian Bookworm
## Removed
## [2.0.15](https://github.com/hyperion-project/hyperion.ng/releases/tag/2.0.15) - 2023-02
### Added
- Audio Grabber to add audio visualization support for both Windows and Linux.
- Support streaming to individual WLED segments (requires WLED 0.13.3+).
To allow segment streaming, enable "Realtime - Use main segment only" in WLED's Sync Interfaces setup screen
- Allow to keep WLED powered on after streaming and restoring state
- Allow to Disable / Enable all instances (#970) by
- Suspend/Resume support for Linux and Windows (#1493,#1282, #978).
Suspend/Resume/Restart is supported via API, UI, Systray and hyperion-remote
- Idle scenario via Screen Locking (Linux/Windows), Screensaver invokation (Linux), hyperion-remote or API
In Idle, all instances, components will be disabled besides the output processing (LED-Devices, smoothing).
The current priorities will be cleared and the background effect per instance will be executed, if enabled.
- Commands toogleSuspend and toggleIdle allow to flip between modes, e.g. might be used to trigger modes by a remote
- Reduced pixel processing to reduce resources on big assignment areas
- Support for squared mean color processing
- Support for dominant color processing on assigned LED areas (#1382). A simple and advanced way is provided. Advanced and high accuracy might be combined with reduced pixel processing to lower CPU usage.
- Add instance# in API response (#1504)
### Changed
- REST API - Increased default timeout to address "Operation cancelled" errors
- LED Devices: Allow to differentiate between recoverable/unrecoverable errors
- Renamed LED area assignment naming to provide clarity on the processing algorithms
### Fixed
- Effects/Smoothing: Effects with dedicated smoothing settings will now run with those settings (even if general smoothing is off)
- No interim color update after streaming and turning off WLED
- LED-Matrix Layout: Add Cabling direction selection element again (#1566)
- Restart correctly, if running as service (#1368)
- Hue-Wizard: In case auto discovery failed, port 80 was not used as default (#1544)
- Send only one reply per Start Instance request (#1551)
- Add instance# in JSON-API replies (aligning to Add instance in websocket response to a subscription #1504 behaviour)
- hyperion-remote: Extracting reply for a configGet request correctly (#1555)
- Grabber fps setting was not applied correctly
- Smoothing: No empty updates
### Technical
- Add CodeQL for GitHub code scanning
- Update to Protocol Buffers 3.21.12
- Update to Mbed TLS 3.3.0
- Qt6 alignments
- cmake support of libcec without version in lib-name
- Refactor for Python 3.11 deprecated functions
## Removed

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.1.0)
cmake_minimum_required(VERSION 3.5.0)
message( STATUS "CMake Version: ${CMAKE_VERSION}" )
@ -38,26 +38,24 @@ if ( CCACHE_FOUND )
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
endif(CCACHE_FOUND)
# enable C++14; MSVC doesn't have c++14 feature switch
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
if(APPLE)
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("Werror=unguarded-availability" REQUIRED_UNGUARDED_AVAILABILITY)
if(REQUIRED_UNGUARDED_AVAILABILITY)
list(APPEND CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} "Werror=unguarded-availability")
endif()
# enable C++17
if(APPLE)
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("Werror=unguarded-availability" REQUIRED_UNGUARDED_AVAILABILITY)
if(REQUIRED_UNGUARDED_AVAILABILITY)
list(APPEND CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} "Werror=unguarded-availability")
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-psabi")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-psabi")
endif()
set(CMAKE_CXX_STANDARD 14)
set(CXX_STANDARD_REQUIRED ON)
set(CXX_EXTENSIONS OFF)
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-psabi")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-psabi")
endif()
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# Set build variables
# Grabber
SET ( DEFAULT_AMLOGIC OFF )
@ -67,6 +65,7 @@ SET ( DEFAULT_MF OFF )
SET ( DEFAULT_OSX OFF )
SET ( DEFAULT_QT ON )
SET ( DEFAULT_V4L2 OFF )
SET ( DEFAULT_AUDIO ON )
SET ( DEFAULT_X11 OFF )
SET ( DEFAULT_XCB OFF )
@ -172,24 +171,25 @@ if ( "${PLATFORM}" MATCHES "osx" )
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${SUBDIRPY})
include_directories("/opt/X11/include/")
SET ( DEFAULT_OSX ON )
SET ( DEFAULT_DEV_USB_HID ON )
SET ( DEFAULT_OSX ON )
SET ( DEFAULT_AUDIO OFF )
SET ( DEFAULT_DEV_USB_HID ON )
elseif ( "${PLATFORM}" MATCHES "rpi" )
SET ( DEFAULT_DISPMANX ON )
SET ( DEFAULT_DEV_WS281XPWM ON )
elseif ( "${PLATFORM}" STREQUAL "amlogic" )
elseif ( "${PLATFORM}" MATCHES "^amlogic" )
SET ( DEFAULT_AMLOGIC ON )
elseif ( "${PLATFORM}" STREQUAL "amlogic-dev" )
SET ( DEFAULT_AMLOGIC ON )
SET ( DEFAULT_DISPMANX OFF )
SET ( DEFAULT_QT OFF )
SET ( DEFAULT_CEC OFF )
elseif ( "${PLATFORM}" STREQUAL "amlogic64" )
SET ( DEFAULT_AMLOGIC ON )
elseif ( "${PLATFORM}" MATCHES "x11" )
if ( "${PLATFORM}" MATCHES "-dev$" )
SET ( DEFAULT_AMLOGIC ON )
SET ( DEFAULT_DISPMANX OFF )
SET ( DEFAULT_QT OFF )
SET ( DEFAULT_CEC OFF )
endif()
elseif ( "${PLATFORM}" MATCHES "^x11" )
SET ( DEFAULT_X11 ON )
SET ( DEFAULT_XCB ON )
if ( "${PLATFORM}" STREQUAL "x11-dev" )
if ( "${PLATFORM}" MATCHES "-dev$" )
SET ( DEFAULT_AMLOGIC ON)
SET ( DEFAULT_DEV_WS281XPWM ON )
endif()
@ -198,7 +198,7 @@ elseif ( "${PLATFORM}" STREQUAL "imx6" )
endif()
# enable tests for -dev builds
if ( "${PLATFORM}" MATCHES "-dev" )
if ( "${PLATFORM}" MATCHES "-dev$" )
SET ( DEFAULT_TESTS ON )
endif()
@ -222,6 +222,7 @@ if (HYPERION_LIGHT)
SET ( DEFAULT_OSX OFF )
SET ( DEFAULT_QT OFF )
SET ( DEFAULT_V4L2 OFF )
SET ( DEFAULT_AUDIO OFF )
SET ( DEFAULT_X11 OFF )
SET ( DEFAULT_XCB OFF )
@ -273,6 +274,11 @@ message(STATUS "ENABLE_V4L2 = ${ENABLE_V4L2}")
option(ENABLE_X11 "Enable the X11 grabber" ${DEFAULT_X11})
message(STATUS "ENABLE_X11 = ${ENABLE_X11}")
option(ENABLE_AUDIO "Enable the AUDIO grabber" ${DEFAULT_AUDIO})
message(STATUS "ENABLE_AUDIO = ${ENABLE_AUDIO}")
option(ENABLE_WS281XPWM "Enable the WS281x-PWM device" ${DEFAULT_WS281XPWM} )
message(STATUS "ENABLE_WS281XPWM = ${ENABLE_WS281XPWM}")
option(ENABLE_XCB "Enable the XCB grabber" ${DEFAULT_XCB})
message(STATUS "ENABLE_XCB = ${ENABLE_XCB}")

View File

@ -9,6 +9,10 @@
// Define to enable the DirectX grabber
#cmakedefine ENABLE_DX
// Define to enable the framebuffer grabber
// Define to enable the Audio grabber
#cmakedefine ENABLE_AUDIO
// Define to enable the Framebuffer grabber
#cmakedefine ENABLE_FB

View File

@ -7,9 +7,9 @@ For Windows and macOS is an installation file available on our [Release page](ht
## Linux:
On the following operating systems, Hyperion can currently be installed/updated using the method listed below:
- Raspbian Stretch/Raspberry Pi OS and later (armhf/arm64)
- Debian Stretch (9) and later (armhf/arm64/x86_64)
- Ubuntu 18.04 and later (armhf/arm64/x86_64)
- Raspbian Buster/Raspberry Pi OS and later (armhf/arm64)
- Debian Buster(10) and later (armhf/arm64/x86_64)
- Ubuntu 20.04 and later (armhf/arm64/x86_64)
***

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2014-2022 Hyperion Project
Copyright (c) 2014-2023 Hyperion Project
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -6,10 +6,10 @@
[![Latest-Release](https://img.shields.io/github/v/release/hyperion-project/hyperion.ng?include_prereleases&label=Latest%20Release&logo=github&logoColor=white&color=0f83e7)](https://github.com/hyperion-project/hyperion.ng/releases)
[![GitHub Actions](https://github.com/hyperion-project/hyperion.ng/workflows/Hyperion%20CI%20Build/badge.svg?branch=master)](https://github.com/hyperion-project/hyperion.ng/actions)
[![LGTM](https://img.shields.io/lgtm/grade/cpp/github/hyperion-project/hyperion.ng?label=Code%20Quality&logo=lgtm&logoColor=white&color=4bc51d)](https://lgtm.com/projects/g/hyperion-project/hyperion.ng/context:cpp)
[![CodeQL Analysis](https://github.com/hyperion-project/hyperion.ng/actions/workflows/codeql.yml/badge.svg)](https://github.com/hyperion-project/hyperion.ng/actions/workflows/codeql.yml)
[![Forum](https://img.shields.io/website/https/hyperion-project.org.svg?label=Forum&down_color=red&down_message=offline&up_color=4bc51d&up_message=online&logo=homeadvisor&logoColor=white)](https://www.hyperion-project.org)
[![Documentation](https://img.shields.io/website/https/docs.hyperion-project.org.svg?label=Documentation&down_color=red&down_message=offline&up_color=4bc51d&up_message=online&logo=read-the-docs)](https://docs.hyperion-project.org)
[![Discord](https://img.shields.io/discord/785578322167463937?label=Discord&logo=discord&logoColor=white&color=4bc51d)](https://discord.gg/khkR8Vx3ff)
[![Discord](https://img.shields.io/discord/785578322167463937?label=Discord&logo=discord&logoColor=white&color=4bc51d)](https://discord.gg/XtVTb3HEKS)
![made-with-love](https://img.shields.io/badge/Made%20With-&#9829;-ff0000.svg)
## About Hyperion

View File

@ -0,0 +1,655 @@
#include <NeoPixelBus.h>
////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////// CONFIG SECTION STARTS /////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
#define THIS_IS_RGBW // RGBW SK6812, otherwise comment it
#define COLD_WHITE // for RGBW (THIS_IS_RGBW enabled) select COLD version, comment it if NEUTRAL
const bool skipFirstLed = false; // if set the first led in the strip will be set to black (for level shifters using sacrifice LED)
const int serialSpeed = 2000000; // serial port speed
#define DATA_PIN 2 // PIN: data output for LED strip
const bool reportStats = false; // Send back processing statistics
const int reportStatInterval_s = 10; // Send back processing every interval in seconds
/* Statistics breakdown:
FPS: Updates to the LEDs per second
F-FPS: Frames identified per second
S: Shown (Done) updates to the LEDs per given interval
F: Frames identified per interval (garbled grames cannot be counted)
G: Good frames identified per interval
B: Total bad frames of all types identified per interval
BF: Bad frames identified per interval
BS: Skipped incomplete frames
BC: Frames failing CRC check per interval
BFL Frames failing Fletcher content validation per interval
*/
//Developer configs
#define ENABLE_STRIP
#define ENABLE_CHECK_FLETCHER
const int SERIAL_SIZE_RX = 4096;
#ifndef ENABLE_STRIP
const int serial2Speed = 460800;
const bool reportInput = false;
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////// CONFIG SECTION ENDS /////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
const String version = "8.0";
#ifdef THIS_IS_RGBW
float whiteLimit = 1.0f;
#ifdef COLD_WHITE
uint8_t rCorrection = 0xA0; // adjust red -> white in 0-0xFF range
uint8_t gCorrection = 0xA0; // adjust green -> white in 0-0xFF range
uint8_t bCorrection = 0xA0; // adjust blue -> white in 0-0xFF range
#else
uint8_t rCorrection = 0xB0; // adjust red -> white in 0-0xFF range
uint8_t gCorrection = 0xB0; // adjust green -> white in 0-0xFF range
uint8_t bCorrection = 0x70; // adjust blue -> white in 0-0xFF range
#endif
#endif
int ledCount = 0; // This is dynamic, don't change it
int pixelCount = 0; // This is dynamic, don't change it
#ifdef THIS_IS_RGBW
#define LED_TYPE NeoGrbwFeature
#if defined(ARDUINO_LOLIN_S2_MINI)
#define LED_METHOD NeoEsp32I2s0Sk6812Method
#else
#define LED_METHOD NeoEsp32I2s1Sk6812Method
#endif
#else
#define LED_TYPE NeoGrbFeature
#if defined(ARDUINO_LOLIN_S2_MINI)
#define LED_METHOD NeoEsp32I2s0Ws2812xMethod
#else
#define LED_METHOD NeoEsp32I2s1Ws2812xMethod
#endif
#endif
#define LED_DRIVER NeoPixelBus<LED_TYPE, LED_METHOD>
uint8_t* ledBuffer;
int ledBufferSize;
#ifdef ENABLE_STRIP
LED_DRIVER* strip = NULL;
#endif
enum class AwaProtocol
{
HEADER_A,
HEADER_w,
HEADER_a,
HEADER_HI,
HEADER_LO,
HEADER_CRC,
CHANNELCALIB_GAIN,
CHANNELCALIB_RED,
CHANNELCALIB_GREEN,
CHANNELCALIB_BLUE,
PIXEL,
FLETCHER1,
FLETCHER2,
FLETCHER_EXT
};
AwaProtocol state = AwaProtocol::HEADER_A;
const int headerSize = 6;
const int trailerSize = 3;
const int calibInfoSize = 4;
int bytesRead = 0;
bool isVersion2 = false;
bool isChannelCalib = false;
uint8_t CRC = 0;
int count = 0;
int currentPixel = 0;
uint16_t fletcher1 = 0;
uint16_t fletcher2 = 0;
uint16_t fletcherExt = 0;
#ifdef THIS_IS_RGBW
RgbwColor inputColor;
uint8_t wChannel[256];
uint8_t rChannel[256];
uint8_t gChannel[256];
uint8_t bChannel[256];
#else
RgbColor inputColor;
#endif
bool ledsComplete = false;
// statistics
const int reportStatInterval_ms = reportStatInterval_s * 1000;
unsigned long curTime;
unsigned long stat_start = 0;
uint16_t stat_shown = 0;
uint16_t stat_frames = 0;
uint16_t stat_good = 0;
uint16_t stat_bad = 0;
uint16_t stat_bad_frame = 0;
uint16_t stat_bad_skip = 0;
uint16_t stat_bad_crc = 0;
uint16_t stat_bad_fletcher = 0;
uint16_t stat_final_shown = 0;
uint16_t stat_final_frames = 0;
uint16_t stat_final_good = 0;
uint16_t stat_final_bad = 0;
uint16_t stat_final_bad_frame = 0;
uint16_t stat_final_bad_skip = 0;
uint16_t stat_final_bad_crc = 0;
uint16_t stat_final_bad_fletcher = 0;
//Debugging
String inputString;
String inputErrorString;
String debugString;
void printStringHex(String string)
{
#ifndef ENABLE_STRIP
Serial2.println(string.length());
for (int i = 0; i < string.length(); ++i)
{
if (i % 36 == 0)
{
Serial2.println();
Serial2.print("[");
Serial2.print(i);
Serial2.print("] ");
}
if (string[i] < 16)
Serial2.print("0");
Serial2.print(string[i], HEX);
Serial2.print(":");
}
#endif
}
inline void showMe()
{
#ifdef ENABLE_STRIP
if (strip != NULL && strip->CanShow())
{
stat_shown++;
strip->Show();
}
#endif
}
// statistics
inline void showStats()
{
if (reportStats)
{
if (stat_frames > 0)
{
stat_final_shown = stat_shown;
stat_final_frames = stat_frames;
stat_final_good = stat_good;
stat_final_bad = stat_bad;
stat_final_bad_frame = stat_bad_frame;
stat_final_bad_skip = stat_bad_skip;
stat_final_bad_crc = stat_bad_crc;
stat_final_bad_fletcher = stat_bad_fletcher;
}
stat_start = curTime;
stat_shown = 0;
stat_frames = 0;
stat_good = 0;
stat_bad = 0;
stat_bad_frame = 0;
stat_bad_skip = 0;
stat_bad_crc = 0;
stat_bad_fletcher = 0;
String summary = String("FPS: ") + (stat_final_shown / reportStatInterval_s) +
" F-FPS: " + (stat_final_frames / reportStatInterval_s) +
" S: " + stat_final_shown +
" F: " + stat_final_frames +
" G: " + stat_final_good +
" B: " + stat_final_bad +
" (BF: " + stat_final_bad_frame +
" BS: " + stat_final_bad_skip +
" BC: " + stat_final_bad_crc +
" BFL: " + stat_final_bad_fletcher +
")";
#ifdef ENABLE_STRIP
Serial.println(summary);
#else
Serial2.println(summary);
#endif
}
}
void InitLeds(uint16_t ledCount, int pixelCount, bool channelCalibration = false)
{
if (ledBuffer != NULL)
delete ledBuffer;
ledBufferSize = pixelCount + (channelCalibration ? calibInfoSize : 0);
ledBuffer = new uint8_t[ledBufferSize];
#ifdef ENABLE_STRIP
if (strip != NULL)
delete strip;
strip = new LED_DRIVER(ledCount, DATA_PIN);
strip->Begin();
#endif
}
inline void processSerialData()
{
while (Serial.available()) {
char input = Serial.read();
++bytesRead;
#ifndef ENABLE_STRIP
if (reportInput)
inputString += input;
#endif
switch (state)
{
case AwaProtocol::HEADER_A:
if (input == 'A')
{
state = AwaProtocol::HEADER_w;
}
break;
case AwaProtocol::HEADER_w:
if (input == 'w')
state = AwaProtocol::HEADER_a;
else
{
state = AwaProtocol::HEADER_A;
}
break;
case AwaProtocol::HEADER_a:
if (input == 'a')
{
isVersion2 = false;
state = AwaProtocol::HEADER_HI;
}
else if (input == 'A')
{
state = AwaProtocol::HEADER_HI;
isVersion2 = true;
}
else
{
state = AwaProtocol::HEADER_A;
}
break;
case AwaProtocol::HEADER_HI:
stat_frames++;
count = input << 8;
CRC = input;
fletcher1 = 0;
fletcher2 = 0;
fletcherExt = 0;
state = AwaProtocol::HEADER_LO;
break;
case AwaProtocol::HEADER_LO:
count += input + 1;
if (ledCount != count || isChannelCalib != isVersion2)
{
ledCount = count;
isChannelCalib = isVersion2;
pixelCount = ledCount * 3;
if (isChannelCalib)
prepareCalibration();
InitLeds(ledCount, pixelCount, isChannelCalib);
}
CRC = CRC ^ input ^ 0x55;
state = AwaProtocol::HEADER_CRC;
break;
case AwaProtocol::HEADER_CRC:
// Check, if incomplete package information was skipped, set bytesread to headersize and skip wrong input
if (bytesRead != headerSize)
{
stat_bad_skip++;
bytesRead = headerSize;
}
currentPixel = 0;
if (CRC == input)
{
state = AwaProtocol::PIXEL;
}
else
{
// CRC failure
stat_bad++;
stat_bad_crc++;
state = AwaProtocol::HEADER_A;
}
break;
case AwaProtocol::PIXEL:
ledBuffer[currentPixel++] = input;
if (currentPixel == pixelCount)
{
if (isChannelCalib)
state = AwaProtocol::CHANNELCALIB_GAIN;
else
state = AwaProtocol::FLETCHER1;
}
break;
case AwaProtocol::CHANNELCALIB_GAIN:
ledBuffer[currentPixel++] = input;
state = AwaProtocol::CHANNELCALIB_RED;
break;
case AwaProtocol::CHANNELCALIB_RED:
ledBuffer[currentPixel++] = input;
state = AwaProtocol::CHANNELCALIB_GREEN;
break;
case AwaProtocol::CHANNELCALIB_GREEN:
ledBuffer[currentPixel++] = input;
state = AwaProtocol::CHANNELCALIB_BLUE;
break;
case AwaProtocol::CHANNELCALIB_BLUE:
ledBuffer[currentPixel++] = input;
state = AwaProtocol::FLETCHER1;
break;
case AwaProtocol::FLETCHER1:
fletcher1 = input;
state = AwaProtocol::FLETCHER2;
break;
case AwaProtocol::FLETCHER2:
fletcher2 = input;
state = AwaProtocol::FLETCHER_EXT;
break;
case AwaProtocol::FLETCHER_EXT:
fletcherExt = input;
ledsComplete = true;
state = AwaProtocol::HEADER_A;
break;
}
}
}
void setup()
{
// Init serial port
int bufSize = Serial.setRxBufferSize(SERIAL_SIZE_RX);
Serial.begin(serialSpeed);
Serial.setTimeout(50);
#ifndef ENABLE_STRIP
Serial2.begin(serial2Speed);
Serial2.println();
Serial2.println("Welcome!");
Serial2.println("Hyperion Awa driver " + version);
Serial2.println("!!! Debug Output !!!");
#endif
// Display config
Serial.println();
Serial.println("Welcome!");
Serial.println("Hyperion Awa driver " + version);
Serial.print("(Build: ");
Serial.print(__DATE__);
Serial.print(" ");
Serial.print(__TIME__);
Serial.println(")");
// first LED info
if (skipFirstLed)
Serial.println("First LED: disabled");
else
Serial.println("First LED: enabled");
// RGBW claibration info
#ifdef THIS_IS_RGBW
#ifdef COLD_WHITE
Serial.println("Default color mode: RGBW cold");
#else
Serial.println("Default color mode: RGBW neutral");
#endif
prepareCalibration();
#else
Serial.println("Color mode: RGB");
#endif
InitLeds(ledCount, pixelCount);
}
void prepareCalibration()
{
#ifdef THIS_IS_RGBW
// prepare LUT calibration table, cold white is much better than "neutral" white
for (uint32_t i = 0; i < 256; i++)
{
// color calibration
float red = rCorrection * i; // adjust red
float green = gCorrection * i; // adjust green
float blue = bCorrection * i; // adjust blue
wChannel[i] = (uint8_t)round(min(whiteLimit * i, 255.0f));
rChannel[i] = (uint8_t)round(min(red / 0xFF, 255.0f));
gChannel[i] = (uint8_t)round(min(green / 0xFF, 255.0f));
bChannel[i] = (uint8_t)round(min(blue / 0xFF, 255.0f));
}
Serial.write("RGBW calibration. White limit(%): ");
Serial.print(whiteLimit * 100.0f);
Serial.write(" %, red: ");
Serial.print(rCorrection);
Serial.write(" , green: ");
Serial.print(gCorrection);
Serial.write(" , blue: ");
Serial.print(bCorrection);
Serial.println();
#endif
}
void loop()
{
curTime = millis();
#ifdef __AVR__
// nothing , USART Interrupt is implemented
ESPserialEvent();
#else
// ESP8266 polling
ESPserialEvent();
#endif
if (ledsComplete)
{
#ifndef ENABLE_STRIP
if (reportInput)
{
Serial2.println();
Serial2.print("<input> L: ");
printStringHex(inputString);
Serial2.println("<\input>");
inputString = "";
Serial2.print("bytesRead: ");
Serial2.print(bytesRead);
Serial2.print(" , currentPixel: ");
Serial2.print(currentPixel);
Serial2.print(" ,pixelCount: ");
Serial2.print(pixelCount);
Serial2.println();
}
#endif
int frameSize = headerSize + ledBufferSize + trailerSize;
if (bytesRead > frameSize)
{
//Add number of frames ignored on top of frame
int frames = bytesRead / frameSize;
stat_frames += frames;
//Count frame plus frames ignored as bad frames
int badFrames = frames + 1;
stat_bad += badFrames;
stat_bad_frame += badFrames;
}
else
{
#ifdef ENABLE_CHECK_FLETCHER
//Test if content is valid
uint16_t item = 0;
uint16_t fletch1 = 0;
uint16_t fletch2 = 0;
uint16_t fletchExt = 0;
while (item < ledBufferSize)
{
fletch1 = (fletch1 + (uint16_t)ledBuffer[item]) % 255;
fletch2 = (fletch2 + fletch1) % 255;
fletcherExt = (fletcherExt + ((uint16_t)ledBuffer[item] ^ (item))) % 255;
++item;
}
if ((fletch1 == fletcher1) && (fletch2 == fletcher2) && (ledBuffer[item-1] == (fletcherExt != 0x41) ? fletcherExt : 0xaa))
{
#endif
stat_good++;
uint16_t startLed = 0;
if (skipFirstLed)
{
#ifdef ENABLE_STRIP
#ifdef THIS_IS_RGBW
strip->SetPixelColor(startLed, RgbwColor(0, 0, 0, 0));
#else
strip->SetPixelColor(startLed, RgbColor(0, 0, 0));
#endif
#endif
startLed = 1;
}
for (uint16_t led = startLed; led < ledCount; ++led)
{
inputColor.R = ledBuffer[led * 3];
inputColor.G = ledBuffer[led * 3 + 1];
inputColor.B = ledBuffer[led * 3 + 2];
#ifdef THIS_IS_RGBW
inputColor.W = min(rChannel[inputColor.R],
min(gChannel[inputColor.G],
bChannel[inputColor.B]));
inputColor.R -= rChannel[inputColor.W];
inputColor.G -= gChannel[inputColor.W];
inputColor.B -= bChannel[inputColor.W];
inputColor.W = wChannel[inputColor.W];
#endif
#ifdef ENABLE_STRIP
strip->SetPixelColor(led, inputColor);
#endif
}
showMe();
yield();
#ifdef THIS_IS_RGBW
if (isChannelCalib)
{
uint8_t incoming_gain = ledBuffer[pixelCount];
uint8_t incoming_red = ledBuffer[pixelCount + 1];
uint8_t incoming_green = ledBuffer[pixelCount + 2];
uint8_t incoming_blue = ledBuffer[pixelCount + 3];
float final_limit = (incoming_gain != 255) ? incoming_gain / 255.0f : 1.0f;
if (rCorrection != incoming_red || gCorrection != incoming_green || bCorrection != incoming_blue || whiteLimit != final_limit)
{
rCorrection = incoming_red;
gCorrection = incoming_green;
bCorrection = incoming_blue;
whiteLimit = final_limit;
prepareCalibration();
}
}
#endif
#ifdef ENABLE_CHECK_FLETCHER
}
else
{
stat_bad++;
stat_bad_fletcher++;
}
#endif
}
bytesRead = 0;
state = AwaProtocol::HEADER_A;
ledsComplete = false;
}
if ((curTime - stat_start > reportStatInterval_ms))
{
if (stat_frames > 0)
{
showStats();
}
}
}
#ifdef __AVR__
void serialEvent()
{
processSerialData();
}
#elif defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
void ESPserialEvent()
{
processSerialData();
}
#endif

View File

@ -0,0 +1,646 @@
#include <NeoPixelBus.h>
////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////// CONFIG SECTION STARTS /////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
#define THIS_IS_RGBW // RGBW SK6812, otherwise comment it
#define COLD_WHITE // for RGBW (THIS_IS_RGBW enabled) select COLD version, comment it if NEUTRAL
const bool skipFirstLed = false; // if set the first led in the strip will be set to black (for level shifters using sacrifice LED)
const int serialSpeed = 2000000; // serial port speed
const bool reportStats = false; // Send back processing statistics
const int reportStatInterval_s = 10; // Send back processing every interval in seconds
/* Statistics breakdown:
FPS: Updates to the LEDs per second
F-FPS: Frames identified per second
S: Shown (Done) updates to the LEDs per given interval
F: Frames identified per interval (garbled grames cannot be counted)
G: Good frames identified per interval
B: Total bad frames of all types identified per interval
BF: Bad frames identified per interval
BS: Skipped incomplete frames
BC: Frames failing CRC check per interval
BFL Frames failing Fletcher content validation per interval
*/
//Developer configs
#define ENABLE_STRIP
#define ENABLE_CHECK_FLETCHER
const int SERIAL_SIZE_RX = 4096;
#ifndef ENABLE_STRIP
const int serial2Speed = 460800;
const bool reportInput = false;
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////// CONFIG SECTION ENDS /////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
const String version = "8.0";
#ifdef THIS_IS_RGBW
float whiteLimit = 1.0f;
#ifdef COLD_WHITE
uint8_t rCorrection = 0xA0; // adjust red -> white in 0-0xFF range
uint8_t gCorrection = 0xA0; // adjust green -> white in 0-0xFF range
uint8_t bCorrection = 0xA0; // adjust blue -> white in 0-0xFF range
#else
uint8_t rCorrection = 0xB0; // adjust red -> white in 0-0xFF range
uint8_t gCorrection = 0xB0; // adjust green -> white in 0-0xFF range
uint8_t bCorrection = 0x70; // adjust blue -> white in 0-0xFF range
#endif
#endif
int ledCount = 0; // This is dynamic, don't change it
int pixelCount = 0; // This is dynamic, don't change it
#ifdef THIS_IS_RGBW
#define LED_TYPE NeoGrbwFeature
#define LED_METHOD NeoEsp8266Uart1Sk6812Method
#else
#define LED_TYPE NeoGrbFeature
#define LED_METHOD NeoEsp8266Uart1Ws2812xMethod
#endif
#define LED_DRIVER NeoPixelBus<LED_TYPE, LED_METHOD>
uint8_t* ledBuffer;
int ledBufferSize;
#ifdef ENABLE_STRIP
LED_DRIVER* strip = NULL;
#endif
enum class AwaProtocol
{
HEADER_A,
HEADER_w,
HEADER_a,
HEADER_HI,
HEADER_LO,
HEADER_CRC,
CHANNELCALIB_GAIN,
CHANNELCALIB_RED,
CHANNELCALIB_GREEN,
CHANNELCALIB_BLUE,
PIXEL,
FLETCHER1,
FLETCHER2,
FLETCHER_EXT
};
AwaProtocol state = AwaProtocol::HEADER_A;
const int headerSize = 6;
const int trailerSize = 3;
const int calibInfoSize = 4;
int bytesRead = 0;
bool isVersion2 = false;
bool isChannelCalib = false;
uint8_t CRC = 0;
int count = 0;
int currentPixel = 0;
uint16_t fletcher1 = 0;
uint16_t fletcher2 = 0;
uint16_t fletcherExt = 0;
#ifdef THIS_IS_RGBW
RgbwColor inputColor;
uint8_t wChannel[256];
uint8_t rChannel[256];
uint8_t gChannel[256];
uint8_t bChannel[256];
#else
RgbColor inputColor;
#endif
bool ledsComplete = false;
// statistics
const int reportStatInterval_ms = reportStatInterval_s * 1000;
unsigned long curTime;
unsigned long stat_start = 0;
uint16_t stat_shown = 0;
uint16_t stat_frames = 0;
uint16_t stat_good = 0;
uint16_t stat_bad = 0;
uint16_t stat_bad_frame = 0;
uint16_t stat_bad_skip = 0;
uint16_t stat_bad_crc = 0;
uint16_t stat_bad_fletcher = 0;
uint16_t stat_final_shown = 0;
uint16_t stat_final_frames = 0;
uint16_t stat_final_good = 0;
uint16_t stat_final_bad = 0;
uint16_t stat_final_bad_frame = 0;
uint16_t stat_final_bad_skip = 0;
uint16_t stat_final_bad_crc = 0;
uint16_t stat_final_bad_fletcher = 0;
//Debugging
String inputString;
String inputErrorString;
String debugString;
void printStringHex(String string)
{
#ifndef ENABLE_STRIP
Serial2.println(string.length());
for (int i = 0; i < string.length(); ++i)
{
if (i % 36 == 0)
{
Serial2.println();
Serial2.print("[");
Serial2.print(i);
Serial2.print("] ");
}
if (string[i] < 16)
Serial2.print("0");
Serial2.print(string[i], HEX);
Serial2.print(":");
}
#endif
}
inline void showMe()
{
#ifdef ENABLE_STRIP
if (strip != NULL && strip->CanShow())
{
stat_shown++;
strip->Show();
}
#endif
}
// statistics
inline void showStats()
{
if (reportStats)
{
if (stat_frames > 0)
{
stat_final_shown = stat_shown;
stat_final_frames = stat_frames;
stat_final_good = stat_good;
stat_final_bad = stat_bad;
stat_final_bad_frame = stat_bad_frame;
stat_final_bad_skip = stat_bad_skip;
stat_final_bad_crc = stat_bad_crc;
stat_final_bad_fletcher = stat_bad_fletcher;
}
stat_start = curTime;
stat_shown = 0;
stat_frames = 0;
stat_good = 0;
stat_bad = 0;
stat_bad_frame = 0;
stat_bad_skip = 0;
stat_bad_crc = 0;
stat_bad_fletcher = 0;
String summary = String("FPS: ") + (stat_final_shown / reportStatInterval_s) +
" F-FPS: " + (stat_final_frames / reportStatInterval_s) +
" S: " + stat_final_shown +
" F: " + stat_final_frames +
" G: " + stat_final_good +
" B: " + stat_final_bad +
" (BF: " + stat_final_bad_frame +
" BS: " + stat_final_bad_skip +
" BC: " + stat_final_bad_crc +
" BFL: " + stat_final_bad_fletcher +
")";
#ifdef ENABLE_STRIP
Serial.println(summary);
#else
Serial2.println(summary);
#endif
}
}
void InitLeds(uint16_t ledCount, int pixelCount, bool channelCalibration = false)
{
if (ledBuffer != NULL)
delete ledBuffer;
ledBufferSize = pixelCount + (channelCalibration ? calibInfoSize : 0);
ledBuffer = new uint8_t[ledBufferSize];
#ifdef ENABLE_STRIP
if (strip != NULL)
delete strip;
strip = new LED_DRIVER(ledCount);
strip->Begin();
#endif
}
inline void processSerialData()
{
while (Serial.available()) {
char input = Serial.read();
++bytesRead;
#ifndef ENABLE_STRIP
if (reportInput)
inputString += input;
#endif
switch (state)
{
case AwaProtocol::HEADER_A:
if (input == 'A')
{
state = AwaProtocol::HEADER_w;
}
break;
case AwaProtocol::HEADER_w:
if (input == 'w')
state = AwaProtocol::HEADER_a;
else
{
state = AwaProtocol::HEADER_A;
}
break;
case AwaProtocol::HEADER_a:
if (input == 'a')
{
isVersion2 = false;
state = AwaProtocol::HEADER_HI;
}
else if (input == 'A')
{
state = AwaProtocol::HEADER_HI;
isVersion2 = true;
}
else
{
state = AwaProtocol::HEADER_A;
}
break;
case AwaProtocol::HEADER_HI:
stat_frames++;
count = input << 8;
CRC = input;
fletcher1 = 0;
fletcher2 = 0;
fletcherExt = 0;
state = AwaProtocol::HEADER_LO;
break;
case AwaProtocol::HEADER_LO:
count += input + 1;
if (ledCount != count || isChannelCalib != isVersion2)
{
ledCount = count;
isChannelCalib = isVersion2;
pixelCount = ledCount * 3;
if (isChannelCalib)
prepareCalibration();
InitLeds(ledCount, pixelCount, isChannelCalib);
}
CRC = CRC ^ input ^ 0x55;
state = AwaProtocol::HEADER_CRC;
break;
case AwaProtocol::HEADER_CRC:
// Check, if incomplete package information was skipped, set bytesread to headersize and skip wrong input
if (bytesRead != headerSize)
{
stat_bad_skip++;
bytesRead = headerSize;
}
currentPixel = 0;
if (CRC == input)
{
state = AwaProtocol::PIXEL;
}
else
{
// CRC failure
stat_bad++;
stat_bad_crc++;
state = AwaProtocol::HEADER_A;
}
break;
case AwaProtocol::PIXEL:
ledBuffer[currentPixel++] = input;
if (currentPixel == pixelCount)
{
if (isChannelCalib)
state = AwaProtocol::CHANNELCALIB_GAIN;
else
state = AwaProtocol::FLETCHER1;
}
break;
case AwaProtocol::CHANNELCALIB_GAIN:
ledBuffer[currentPixel++] = input;
state = AwaProtocol::CHANNELCALIB_RED;
break;
case AwaProtocol::CHANNELCALIB_RED:
ledBuffer[currentPixel++] = input;
state = AwaProtocol::CHANNELCALIB_GREEN;
break;
case AwaProtocol::CHANNELCALIB_GREEN:
ledBuffer[currentPixel++] = input;
state = AwaProtocol::CHANNELCALIB_BLUE;
break;
case AwaProtocol::CHANNELCALIB_BLUE:
ledBuffer[currentPixel++] = input;
state = AwaProtocol::FLETCHER1;
break;
case AwaProtocol::FLETCHER1:
fletcher1 = input;
state = AwaProtocol::FLETCHER2;
break;
case AwaProtocol::FLETCHER2:
fletcher2 = input;
state = AwaProtocol::FLETCHER_EXT;
break;
case AwaProtocol::FLETCHER_EXT:
fletcherExt = input;
ledsComplete = true;
state = AwaProtocol::HEADER_A;
break;
}
}
}
void setup()
{
// Init serial port
int bufSize = Serial.setRxBufferSize(SERIAL_SIZE_RX);
Serial.begin(serialSpeed);
Serial.setTimeout(50);
#ifndef ENABLE_STRIP
Serial2.begin(serial2Speed);
Serial2.println();
Serial2.println("Welcome!");
Serial2.println("Hyperion Awa driver " + version);
Serial2.println("!!! Debug Output !!!");
#endif
// Display config
Serial.println();
Serial.println("Welcome!");
Serial.println("Hyperion Awa driver " + version);
Serial.print("(Build: ");
Serial.print(__DATE__);
Serial.print(" ");
Serial.print(__TIME__);
Serial.println(")");
// first LED info
if (skipFirstLed)
Serial.println("First LED: disabled");
else
Serial.println("First LED: enabled");
// RGBW claibration info
#ifdef THIS_IS_RGBW
#ifdef COLD_WHITE
Serial.println("Default color mode: RGBW cold");
#else
Serial.println("Default color mode: RGBW neutral");
#endif
prepareCalibration();
#else
Serial.println("Color mode: RGB");
#endif
InitLeds(ledCount, pixelCount);
}
void prepareCalibration()
{
#ifdef THIS_IS_RGBW
// prepare LUT calibration table, cold white is much better than "neutral" white
for (uint32_t i = 0; i < 256; i++)
{
// color calibration
float red = rCorrection * i; // adjust red
float green = gCorrection * i; // adjust green
float blue = bCorrection * i; // adjust blue
wChannel[i] = (uint8_t)round(min(whiteLimit * i, 255.0f));
rChannel[i] = (uint8_t)round(min(red / 0xFF, 255.0f));
gChannel[i] = (uint8_t)round(min(green / 0xFF, 255.0f));
bChannel[i] = (uint8_t)round(min(blue / 0xFF, 255.0f));
}
Serial.write("RGBW calibration. White limit(%): ");
Serial.print(whiteLimit * 100.0f);
Serial.write(" %, red: ");
Serial.print(rCorrection);
Serial.write(" , green: ");
Serial.print(gCorrection);
Serial.write(" , blue: ");
Serial.print(bCorrection);
Serial.println();
#endif
}
void loop()
{
curTime = millis();
#ifdef __AVR__
// nothing , USART Interrupt is implemented
ESPserialEvent();
#else
// ESP8266 polling
ESPserialEvent();
#endif
if (ledsComplete)
{
#ifndef ENABLE_STRIP
if (reportInput)
{
Serial2.println();
Serial2.print("<input> L: ");
printStringHex(inputString);
Serial2.println("<\input>");
inputString = "";
Serial2.print("bytesRead: ");
Serial2.print(bytesRead);
Serial2.print(" , currentPixel: ");
Serial2.print(currentPixel);
Serial2.print(" ,pixelCount: ");
Serial2.print(pixelCount);
Serial2.println();
}
#endif
int frameSize = headerSize + ledBufferSize + trailerSize;
if (bytesRead > frameSize)
{
//Add number of frames ignored on top of frame
int frames = bytesRead / frameSize;
stat_frames += frames;
//Count frame plus frames ignored as bad frames
int badFrames = frames + 1;
stat_bad += badFrames;
stat_bad_frame += badFrames;
}
else
{
#ifdef ENABLE_CHECK_FLETCHER
//Test if content is valid
uint16_t item = 0;
uint16_t fletch1 = 0;
uint16_t fletch2 = 0;
uint16_t fletchExt = 0;
while (item < ledBufferSize)
{
fletch1 = (fletch1 + (uint16_t)ledBuffer[item]) % 255;
fletch2 = (fletch2 + fletch1) % 255;
fletcherExt = (fletcherExt + ((uint16_t)ledBuffer[item] ^ (item))) % 255;
++item;
}
if ((fletch1 == fletcher1) && (fletch2 == fletcher2) && (ledBuffer[item-1] == (fletcherExt != 0x41) ? fletcherExt : 0xaa))
{
#endif
stat_good++;
uint16_t startLed = 0;
if (skipFirstLed)
{
#ifdef ENABLE_STRIP
#ifdef THIS_IS_RGBW
strip->SetPixelColor(startLed, RgbwColor(0, 0, 0, 0));
#else
strip->SetPixelColor(startLed, RgbColor(0, 0, 0));
#endif
#endif
startLed = 1;
}
for (uint16_t led = startLed; led < ledCount; ++led)
{
inputColor.R = ledBuffer[led * 3];
inputColor.G = ledBuffer[led * 3 + 1];
inputColor.B = ledBuffer[led * 3 + 2];
#ifdef THIS_IS_RGBW
inputColor.W = min(rChannel[inputColor.R],
min(gChannel[inputColor.G],
bChannel[inputColor.B]));
inputColor.R -= rChannel[inputColor.W];
inputColor.G -= gChannel[inputColor.W];
inputColor.B -= bChannel[inputColor.W];
inputColor.W = wChannel[inputColor.W];
#endif
#ifdef ENABLE_STRIP
strip->SetPixelColor(led, inputColor);
#endif
}
showMe();
yield();
#ifdef THIS_IS_RGBW
if (isChannelCalib)
{
uint8_t incoming_gain = ledBuffer[pixelCount];
uint8_t incoming_red = ledBuffer[pixelCount + 1];
uint8_t incoming_green = ledBuffer[pixelCount + 2];
uint8_t incoming_blue = ledBuffer[pixelCount + 3];
float final_limit = (incoming_gain != 255) ? incoming_gain / 255.0f : 1.0f;
if (rCorrection != incoming_red || gCorrection != incoming_green || bCorrection != incoming_blue || whiteLimit != final_limit)
{
rCorrection = incoming_red;
gCorrection = incoming_green;
bCorrection = incoming_blue;
whiteLimit = final_limit;
prepareCalibration();
}
}
#endif
#ifdef ENABLE_CHECK_FLETCHER
}
else
{
stat_bad++;
stat_bad_fletcher++;
}
#endif
}
bytesRead = 0;
state = AwaProtocol::HEADER_A;
ledsComplete = false;
}
if ((curTime - stat_start > reportStatInterval_ms))
{
if (stat_frames > 0)
{
showStats();
}
}
}
#ifdef __AVR__
void serialEvent()
{
processSerialData();
}
#elif defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
void ESPserialEvent()
{
processSerialData();
}
#endif

View File

@ -153,10 +153,9 @@ to this service over the network.
srv = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
srv.bind(('0.0.0.0', args.localport)) # lgtm [py/bind-socket-all-network-interfaces]
srv.bind(('0.0.0.0', args.localport))
try:
intentional_exit = False
while True:
try:
while True:
@ -180,7 +179,7 @@ to this service over the network.
# probably got disconnected
break
except KeyboardInterrupt:
intentional_exit = True
# intentional_exit
raise
except socket.error as msg:
if args.develop:
@ -190,6 +189,7 @@ to this service over the network.
ser_to_net.socket = None
sys.stderr.write('Disconnected\n')
except KeyboardInterrupt:
# do not handle exceptions
pass
sys.stderr.write('\n--- exit ---\n')

View File

@ -322,6 +322,17 @@
</select>
</td>
</tr>
<tr>
<td class="ltd">
<label class="ltdlabel" for="ip_ma_direction" data-i18n="conf_leds_layout_ma_direction">Cabling</label>
</td>
<td class="itd">
<select class="form-control ledMAconstr" id="ip_ma_direction">
<option value="horizontal" data-i18n="conf_leds_layout_ma_opthoriz">Horizontal</option>
<option value="vertical" data-i18n="conf_leds_layout_ma_optvert">Vertical</option>
</select>
</td>
</tr>
<tr>
<td class="ltd">
<label class="ltdlabel" for="ip_ma_start" data-i18n="conf_leds_layout_ma_position">Input</label>

View File

@ -42,6 +42,14 @@
<a class="fa fa-cog fa-fw" onclick="SwitchToMenuItem('MenuItemGrabber', 'editor_container_videograbber')" style="text-decoration: none; cursor: pointer"></a>
</td>
</tr>
<tr id="dash_audio_grabber_row">
<td></td>
<td data-i18n="edt_conf_audio_heading_title">Audio-Grabber</td>
<td style="text-align: right; padding-right: 0">
<span id="dash_audio_grabber">disabled</span>
<a class="fa fa-cog fa-fw" onclick="SwitchToMenuItem('MenuItemGrabber', 'editor_container_audiograbber')" style="text-decoration: none; cursor: pointer"></a>
</td>
</tr>
</tbody>
</table>
<table id="dash_ports" class="table borderless">
@ -135,6 +143,7 @@
</div>
<!-- /.row -->
</div>
</div>
<!-- /.container-fluid -->
<script src="/js/content_dashboard.js"></script>

View File

@ -10,6 +10,9 @@
"InfoDialog_nowrite_foottext": "Die Webkonfiguration wird automatisch wieder freigegeben, sobald das Problem behoben wurde!",
"InfoDialog_nowrite_text": "Hyperion hat keinen Schreibzugriff auf die aktuell geladene Konfiguration. Bitte korrigiere die Dateizugriffsrechte, um fortzufahren.",
"InfoDialog_nowrite_title": "Fehler beim Schreibzugriff!",
"InfoDialog_systemRestart_title": "Neustart",
"InfoDialog_systemResume_title": "Aktivieren",
"InfoDialog_systemSuspend_title": "Ruhezustand",
"about_3rd_party_licenses": "Drittanbieter Lizenzen",
"about_3rd_party_licenses_error": "Wir hatten Probleme beim Laden der Drittanbieter Lizenzen aus dem Internet. <br />Klicke hier, um die Datei auf GitHub aufzurufen.",
"about_build": "Build",
@ -41,6 +44,7 @@
"conf_general_inst_title": "LED-Hardware Instanzverwaltung",
"conf_general_intro": "Grundsätzliche Einstellungen zu Hyperion oder WebUI, die in keine andere Kategorie passen.",
"conf_general_label_title": "Allgemeine Einstellungen",
"conf_grabber_audio_intro": "Bei der Audioerfassung wird ein Audioeingabegerät als Quelle für die Visualisierung verwendet.",
"conf_grabber_fg_intro": "Bildschirm Aufnahme ist das lokale System auf dem Hyperion installiert wurde, welches als Bildquelle dient.",
"conf_grabber_inst_grabber_config_info": "Konfiguriere deine Aufnahmegeräte bevor du sie in einer LED-Instanz benutzt.",
"conf_grabber_v4l_intro": "USB-Aufnahme ist ein Gerät, welches via USB angeschlossen ist und als Bildquelle dient.",
@ -55,7 +59,9 @@
"conf_leds_error_get_properties_title": "Geräteeigenschaften",
"conf_leds_error_hwled_gt_layout": "Die Zahl der gegebenen Hardware LEDs ($1) ist größer, als die Anzahl der im LED-Layout definierten ($2), $3 {{plural:$3|LED wird|LEDs werden}} schwarz bleiben.",
"conf_leds_error_hwled_gt_maxled": "Die Zahl der gegebenen Hardware LEDs ($1) ist größer, als die Anzahl der durch den LED-Steuerungstyp unterstützen ($2). <br>Die Anzahl Hardware LEDs wird auf ($3) gesetzt.",
"conf_leds_error_hwled_gt_maxled_protocol": "Die Anzahl der Hardware-LEDs ($1) ist größer als die maximale Anzahl der vom Streaming-Protokoll unterstützten LEDs ($2).<br> Das Streaming-Protokoll wird auf ($3) geändert.",
"conf_leds_error_hwled_lt_layout": "Die Zahl der gegebenen Hardware LEDs ($1) ist kleiner, als die Anzahl der im LED-Layout definierten ($2). <br> Im LED-Layout dürfen nicht mehr LEDs konfiguriert sein, als vorhanden.",
"conf_leds_error_wled_segment_missing": "Das aktuell konfigurierte Segment ($1) ist in WLED-Gerät nicht konfiguriert.<br> Überprüfe die WLED-Konfiguration!<br>Die Konfigurationsseite zeigt die aktuelle WLED-Einstellung.",
"conf_leds_info_ws281x": "Hyperion muss mit 'root' Rechten für diesen LED-Steuerungstyp laufen!",
"conf_leds_layout_advanced": "Erweiterte Optionen",
"conf_leds_layout_blacklist_num_title": "LED-Anzahl",
@ -229,6 +235,27 @@
"edt_append_pixel": "Pixel",
"edt_append_s": "s",
"edt_append_sdegree": "s/grad",
"edt_conf_audio_device_expl": "Ausgewähltes Audio-Eingabegerät",
"edt_conf_audio_device_title": "Audio-Eingabegerät",
"edt_conf_audio_effect_enum_vumeter": "VU-Meter",
"edt_conf_audio_effect_hotcolor_expl": "Farbe die einen hohen Pegel anzeigt.",
"edt_conf_audio_effect_hotcolor_title": "Farbe hoher Pegel",
"edt_conf_audio_effect_multiplier_expl": "Multiplikator zur Verstärkung des Audiosignals.",
"edt_conf_audio_effect_multiplier_title": "Multiplikator",
"edt_conf_audio_effect_safecolor_expl": "Farbe die einen niedrigen Pegel anzeigt.",
"edt_conf_audio_effect_safecolor_title": "Farbe niedriger Pegel",
"edt_conf_audio_effect_safevalue_expl": "Schwellwert bis zu dem ein niedriger Pegel gegeben ist.",
"edt_conf_audio_effect_safevalue_title": "Schwellwert niedriger Pegel",
"edt_conf_audio_effect_set_defaults": "Zurücksetzen auf Standardwerte",
"edt_conf_audio_effect_tolerance_expl": "Toleranz für die automatische Berechnung eines Signalmultiplikators von 0-100",
"edt_conf_audio_effect_tolerance_title": "Toleranz",
"edt_conf_audio_effect_warncolor_expl": "Farbe die einen mittleren Pegel anzeigt.",
"edt_conf_audio_effect_warncolor_title": "Farbe mittlerer Pegel",
"edt_conf_audio_effect_warnvalue_expl": "Schwellwert bis zu dem ein mittlerer Pegel gegeben ist.",
"edt_conf_audio_effect_warnvalue_title": "Schwellwert mittlerer Pegel",
"edt_conf_audio_effects_expl": "Wähle einen Effekt für die Umwandlung des Audiosignals.",
"edt_conf_audio_effects_title": "Audio-Effekte",
"edt_conf_audio_heading_title": "Audio Aufnahme",
"edt_conf_bb_blurRemoveCnt_expl": "Anzahl an Pixeln, die zusätzlich vom Rand abgeschnitten werden.",
"edt_conf_bb_blurRemoveCnt_title": "Unscharfe Pixel",
"edt_conf_bb_borderFrameCnt_expl": "Anzahl an Bildern bis ein neuer Rand festgelegt wird.",
@ -244,6 +271,8 @@
"edt_conf_bb_unknownFrameCnt_title": "Unbekannte Bilder",
"edt_conf_bge_heading_title": "Hintergrund Effekt/Farbe",
"edt_conf_bobls_heading_title": "Boblight Server",
"edt_conf_color_accuracyLevel_expl": "Stufe, wie genau dominante Farben ausgewertet werden. Eine höhere Stufe erzeugt genauere Ergebnisse, erfordert aber auch mehr Rechenleistung. Sollte mit reduzierter Pixelverarbeitung kombiniert werden.",
"edt_conf_color_accuracyLevel_title": "Genauigkeitsstufe",
"edt_conf_color_backlightColored_expl": "Die Hintergrundbeleuchtung kann mit oder ohne Farbanteile genutzt werden.",
"edt_conf_color_backlightColored_title": "Farbige Hintergrundbeleuchtung",
"edt_conf_color_backlightThreshold_expl": "Eine Beleuchtung die dauerhaft aktiv ist. (Automatisch deaktiviert bei Effekten, Farben oder im Zustand \"Aus\")",
@ -274,7 +303,7 @@
"edt_conf_color_heading_title": "Farbkalibrierung",
"edt_conf_color_id_expl": "Eine vom Benutzer frei angegebene ID.",
"edt_conf_color_id_title": "ID",
"edt_conf_color_imageToLedMappingType_expl": "Sofern nicht \"Mehrfarbig\", wird dein LED-Layout mit einer anderen Bildzuweisung überschrieben",
"edt_conf_color_imageToLedMappingType_expl": "Sofern nicht \"Durchschnittsfarbe einfach \", wird dein LED-Layout mit einer anderen Bildzuweisung überschrieben",
"edt_conf_color_imageToLedMappingType_title": "LED-Bereich Zuordnungstyp",
"edt_conf_color_leds_expl": "Zugewiesen zu allen (*) LEDs oder nur zu bestimmten LED Nummern (0-17).",
"edt_conf_color_leds_title": "LED-Iindex",
@ -282,6 +311,8 @@
"edt_conf_color_magenta_title": "Magenta",
"edt_conf_color_red_expl": "Kalibrierter Rotwert.",
"edt_conf_color_red_title": "Rot",
"edt_conf_color_reducedPixelSetFactorFactor_expl": "Es wird nur eine reduzierte Menge von Pixeln pro definiertem LED-Bereich ausgewertet, Niedrig ~25%, Mittel ~10%, Hoch ~6%",
"edt_conf_color_reducedPixelSetFactorFactor_title": "Reduzierte Pixelverarbeitung",
"edt_conf_color_saturationGain_expl": "Anpassung der Farbsättigung. 1,0 bedeutet keine Änderung, Werte größer 1,0 erhöhen die Sättigung, kleiner 1,0 verringern diese.",
"edt_conf_color_saturationGain_title": "Sättigungsverstärkung",
"edt_conf_color_white_expl": "Kalibrierter Weißwert.",
@ -313,6 +344,8 @@
"edt_conf_enum_color": "Farbe",
"edt_conf_enum_custom": "Benutzerdefiniert",
"edt_conf_enum_decay": "Dämpfung",
"edt_conf_enum_delay": "Nur Verzögerung",
"edt_conf_enum_disabled": "Deaktiviert",
"edt_conf_enum_dl_error": "nur Fehler",
"edt_conf_enum_dl_informational": "informativ",
"edt_conf_enum_dl_nodebug": "keine Debugausgabe",
@ -321,9 +354,12 @@
"edt_conf_enum_dl_verbose1": "Stufe 1",
"edt_conf_enum_dl_verbose2": "Stufe 2",
"edt_conf_enum_dl_verbose3": "Stufe 3",
"edt_conf_enum_dominant_color": "Dominante Farbe - pro LED",
"edt_conf_enum_dominant_color_advanced": "Dominante Farbe fortgeschritten - pro LED",
"edt_conf_enum_effect": "Effekt",
"edt_conf_enum_gbr": "GBR",
"edt_conf_enum_grb": "GRB",
"edt_conf_enum_high": "Hoch",
"edt_conf_enum_hsv": "HSV",
"edt_conf_enum_left_right": "von links nach rechts",
"edt_conf_enum_linear": "Linear",
@ -331,7 +367,10 @@
"edt_conf_enum_logsilent": "Stille",
"edt_conf_enum_logverbose": "Ausführlich",
"edt_conf_enum_logwarn": "Warnung",
"edt_conf_enum_multicolor_mean": "Mehrfarbig",
"edt_conf_enum_low": "Niedrig",
"edt_conf_enum_medium": "Mittel",
"edt_conf_enum_multicolor_mean": "Durchschnittsfarbe einfach - pro LED",
"edt_conf_enum_multicolor_mean_squared": "Durchschnittsfarbe zum Quadrat - pro LED",
"edt_conf_enum_please_select": "Bitte auswählen",
"edt_conf_enum_rbg": "RBG",
"edt_conf_enum_rgb": "RGB",
@ -341,7 +380,7 @@
"edt_conf_enum_transeffect_sudden": "Sofort",
"edt_conf_enum_udp_ddp": "DDP",
"edt_conf_enum_udp_raw": "RAW",
"edt_conf_enum_unicolor_mean": "Einfarbig",
"edt_conf_enum_unicolor_mean": "Durchschnittsfarbe Gesamtbild - auf alle LED angewandt",
"edt_conf_fbs_heading_title": "Flatbuffers Server",
"edt_conf_fbs_timeout_expl": "Wenn für die angegebene Zeit keine Daten empfangen werden, wird die Komponente (vorübergehend) deaktiviert",
"edt_conf_fbs_timeout_title": "Zeitüberschreitung",
@ -400,11 +439,13 @@
"edt_conf_grabber_discovered_title": "Gefundenes Aufnahmegerät",
"edt_conf_grabber_discovered_title_info": "Wähle dein gefundenes Aufnahmegerät aus.",
"edt_conf_grabber_discovery_inprogress": "Suche Aufnahmegeräte",
"edt_conf_instC_audioEnable_expl": "Aktiviert die Audioaufnahme für diese LED Hardware Instanz.",
"edt_conf_instC_audioEnable_title": "Aktivieren der Audioaufnahme",
"edt_conf_instC_screen_grabber_device_expl": "Das verwendet Bildschirmaufnahmegerät",
"edt_conf_instC_screen_grabber_device_title": "Bildschirmaufnahmegerät",
"edt_conf_instC_systemEnable_expl": "Aktiviert die Bildschirm Aufnahme für diese LED Hardware Instanz.",
"edt_conf_instC_systemEnable_title": "Aktiviere Bildschirm Aufnahme",
"edt_conf_instC_v4lEnable_expl": "Aktiviert die USB Aufnahme für diese LED -Hardware Instanz.",
"edt_conf_instC_v4lEnable_expl": "Aktiviert die USB Aufnahme für diese LED Hardware Instanz.",
"edt_conf_instC_v4lEnable_title": "Aktiviere USB-Aufnahme",
"edt_conf_instC_video_grabber_device_expl": "Das verwendete Videoaufnahmegerät.",
"edt_conf_instC_video_grabber_device_title": "Videoaufnahmegerät",
@ -439,8 +480,6 @@
"edt_conf_smooth_heading_title": "Glättung",
"edt_conf_smooth_interpolationRate_expl": "Frequenz in der Zwischenschritte zur Glättung berechnet werden.",
"edt_conf_smooth_interpolationRate_title": "Interpolationsfrequenz",
"edt_conf_smooth_outputRate_expl": "Die Ausgangfrequenz zum LED-Gerät",
"edt_conf_smooth_outputRate_title": "Ausgabefrequenz",
"edt_conf_smooth_time_ms_expl": "Wie lange soll die Glättung Bilder sammeln?",
"edt_conf_smooth_time_ms_title": "Zeit",
"edt_conf_smooth_type_expl": "Algorithmus der Glättung.",
@ -614,10 +653,17 @@
"edt_dev_spec_rgbw_calibration_green": "Grün/Weiß-Kanal Aspekt",
"edt_dev_spec_rgbw_calibration_limit": "Grenzwert für Weißkanal",
"edt_dev_spec_rgbw_calibration_red": "Rot/Weiß-Kanal Aspekt",
"edt_dev_spec_segmentId_title": "Segment-ID",
"edt_dev_spec_segmentsOverlapValidation_error": "Korrigiere die WLED-Konfiguration! Das Segment darf sich nicht mit {{Plural:$1|Segment|Segmenten}} überschneiden: \"$2\".",
"edt_dev_spec_segmentsSwitchOffOthers_title": "Abschalten anderer Segmente",
"edt_dev_spec_segments_disabled_title": "Segment-Streaming ist in WLED deaktiviert.",
"edt_dev_spec_segments_title": "Stream zum Segment",
"edt_dev_spec_serial_title": "Seriennummer",
"edt_dev_spec_spipath_title": "SPI Pfad",
"edt_dev_spec_sslHSTimeoutMax_title": "Streamer Handshake maximum Timeout",
"edt_dev_spec_sslHSTimeoutMin_title": "Streamer Handshake minimum Timeout",
"edt_dev_spec_stayOnAfterStreaming_title": "LED bleiben nach dem Stream an",
"edt_dev_spec_stayOnAfterStreaming_title_info": "Die LEDs bleiben nach dem Streaming oder der Wiederherstellung des Status eingeschaltet.",
"edt_dev_spec_stream_protocol_title": "Streaming-Protokoll",
"edt_dev_spec_switchOffOnBlack_title": "Aus bei schwarz",
"edt_dev_spec_switchOffOnbelowMinBrightness_title": "Aus bei Minimum",
@ -841,6 +887,7 @@
"general_col_blue": "blau",
"general_col_green": "grün",
"general_col_red": "rot",
"general_comp_AUDIO": "Audioaufnahme",
"general_comp_BLACKBORDER": "Schwarze Balken Erkennung",
"general_comp_BOBLIGHTSERVER": "Boblight Server",
"general_comp_FLATBUFSERVER": "Flatbuffers Server",
@ -964,8 +1011,11 @@
"remote_losthint": "Notiz: Alle Änderungen gehen nach einem Neustart verloren.",
"remote_maptype_intro": "Für gewöhnlich entscheidet dein LED-Layout welcher Bildbereich welche LED zugewiesen bekommt, dies kann hier geändert werden. $1",
"remote_maptype_label": "LED-Bereich Zuordnung",
"remote_maptype_label_multicolor_mean": "Mehrfarbig",
"remote_maptype_label_unicolor_mean": "Einfarbig",
"remote_maptype_label_dominant_color": "Dominante Farbe",
"remote_maptype_label_dominant_color_advanced": "Dominante Farbe fortgeschritten",
"remote_maptype_label_multicolor_mean": "Durchschnittsfarbe einfach",
"remote_maptype_label_multicolor_mean_squared": "Durchschnittsfarbe zum Quadrat",
"remote_maptype_label_unicolor_mean": "Durchschnittsfarbe Gesamtbild",
"remote_optgroup_syseffets": "Mitgelieferte Effekte",
"remote_optgroup_templates_custom": "Nutzer Vorlage",
"remote_optgroup_templates_system": "System Vorlage",

View File

@ -13,6 +13,9 @@
"infoDialog_password_current_text": "Current password",
"infoDialog_password_minimum_length": "Passwords must be minimum 8 characters.",
"infoDialog_password_new_text": "New password",
"InfoDialog_systemSuspend_title": "Suspend",
"InfoDialog_systemResume_title": "Resume",
"InfoDialog_systemRestart_title": "Restart",
"infoDialog_username_text": "Username",
"about_3rd_party_licenses": "3rd party licenses",
"about_3rd_party_licenses_error": "We had trouble collecting 3rd party licenses information from web. <br />Please follow this link to the GitHub Resource.",
@ -48,6 +51,7 @@
"conf_grabber_fg_intro": "Screen capture is your local system capture as input source, Hyperion is installed on.",
"conf_grabber_inst_grabber_config_info": "Configure your capturing hardware devices to be used by the instance in advance",
"conf_grabber_v4l_intro": "USB capture is a (capture) device connected via USB which is used to input source pictures for processing.",
"conf_grabber_audio_intro": "Audio capture utilizes an audio input device as the source for visualization.",
"conf_helptable_expl": "Explanation",
"conf_helptable_option": "Option",
"conf_leds_config_error": "Error in LED/LED layout configuration",
@ -55,11 +59,13 @@
"conf_leds_contr_label_contrtype": "Controller type:",
"conf_leds_device_info_log": "In case your LEDs do not work, check here for errors:",
"conf_leds_device_intro": "Hyperion supports a lot of controllers to transmit data to your target device. Select a LED controller out of the sorted list and configure it. We have chosen the best default settings for each device.",
"conf_leds_error_get_properties_text" : "Failed to get the device's properties. Please check the configuration items.",
"conf_leds_error_get_properties_title" : "Device properties",
"conf_leds_error_get_properties_text": "Failed to get the device's properties. Please check the configuration items.",
"conf_leds_error_get_properties_title": "Device properties",
"conf_leds_error_hwled_gt_layout": "The hardware LED count ($1) is greater than LEDs configured via layout ($2),<br>$3 {{plural:$3|LED|LEDs}} will stay black if you continue.",
"conf_leds_error_hwled_lt_layout": "The hardware LED count ($1) is less than LEDs configured via layout ($2). <br> The number of LEDs configured in the layout must not exceed the available LEDs",
"conf_leds_error_hwled_gt_maxled": "The hardware LED count ($1) is greater than the maximum number of LEDs supported by the device ($2). <br> The hardware LED count is set to ($3).",
"conf_leds_error_hwled_gt_maxled_protocol": "The hardware LED count ($1) is greater than the maximum number of LEDs supported by the streaming protocol ($2). <br> The streaming protocol will be changed to ($3).",
"conf_leds_error_wled_segment_missing": "The currently configured segment ($1) is not configured at your WLED device.<br>You might need to check the WLED configuration!<br>The configuration page represents the current WLED setup.",
"conf_leds_info_ws281x": "Hyperion must run with 'root' privileges for this controller type!",
"conf_leds_layout_advanced": "Advanced Settings",
"conf_leds_layout_blacklist_num_title": "Number of LEDs",
@ -80,6 +86,8 @@
"conf_leds_layout_cl_bottomright": "Bottom Right (Corner)",
"conf_leds_layout_cl_cornergap": "Corner Gap",
"conf_leds_layout_cl_edgegap": "Edge Gap",
"conf_leds_layout_cl_entertainment": "Entertainment Area",
"conf_leds_layout_cl_entertainment_center": "Entertainment Area Center",
"conf_leds_layout_cl_gaglength": "Gap length",
"conf_leds_layout_cl_gappos": "gap position",
"conf_leds_layout_cl_hleddepth": "Horizontal LED depth",
@ -248,6 +256,8 @@
"edt_conf_bb_unknownFrameCnt_title": "Unknown frames",
"edt_conf_bge_heading_title": "Background Effect/Color",
"edt_conf_bobls_heading_title": "Boblight Server",
"edt_conf_color_accuracyLevel_expl": "Level how accurate dominat colors are evaluated. A higher level creates more accurate results, but also requries more processing power. Should to be combined with reduced pixel processing.",
"edt_conf_color_accuracyLevel_title": "Accuracy level",
"edt_conf_color_backlightColored_expl": "Add some color to your backlight.",
"edt_conf_color_backlightColored_title": "Colored backlight",
"edt_conf_color_backlightThreshold_expl": "The minimum amount of brightness (backlight). Disabled during effects, colors and in status \"Off\"",
@ -276,7 +286,7 @@
"edt_conf_color_heading_title": "Color Calibration",
"edt_conf_color_id_expl": "User given name",
"edt_conf_color_id_title": "ID",
"edt_conf_color_imageToLedMappingType_expl": "Overwrites the LED area assignment of your LED layout if it's not \"multicolor\"",
"edt_conf_color_imageToLedMappingType_expl": "Overwrites the LED area assignment of your LED layout if it's not \"Mean Color Simple\"",
"edt_conf_color_imageToLedMappingType_title": "LED area assignment",
"edt_conf_color_leds_expl": "Assign this adjustment to all LEDs (*) or just some (0-24).",
"edt_conf_color_leds_title": "LED index",
@ -288,6 +298,8 @@
"edt_conf_color_saturationGain_title": "Saturation gain",
"edt_conf_color_brightnessGain_expl": "Adjusts the brightness of colors. 1.0 means no change, over 1.0 increases brightness, under 1.0 decreases brightness.",
"edt_conf_color_brightnessGain_title": "Brightness gain",
"edt_conf_color_reducedPixelSetFactorFactor_expl": "Evaluate only a set of pixels per LED area defined, Low ~25%, Medium ~10%, High ~6%",
"edt_conf_color_reducedPixelSetFactorFactor_title": "Reduced pixel processing",
"edt_conf_color_white_expl": "The calibrated white value.",
"edt_conf_color_white_title": "White",
"edt_conf_color_yellow_expl": "The calibrated yellow value.",
@ -317,6 +329,8 @@
"edt_conf_enum_color": "Color",
"edt_conf_enum_custom": "Custom",
"edt_conf_enum_decay": "Decay",
"edt_conf_enum_delay": "Delay only",
"edt_conf_enum_disabled": "Disabled",
"edt_conf_enum_dl_error": "Error",
"edt_conf_enum_dl_informational": "Informational",
"edt_conf_enum_dl_nodebug": "No Debug output",
@ -325,9 +339,12 @@
"edt_conf_enum_dl_verbose1": "Verbosity level 1",
"edt_conf_enum_dl_verbose2": "Verbosity level 2",
"edt_conf_enum_dl_verbose3": "Verbosity level 3",
"edt_conf_enum_dominant_color": "Dominant Color - per LED",
"edt_conf_enum_dominant_color_advanced": "Dominant Color Advanced - per LED",
"edt_conf_enum_effect": "Effect",
"edt_conf_enum_gbr": "GBR",
"edt_conf_enum_grb": "GRB",
"edt_conf_enum_high": "High",
"edt_conf_enum_hsv": "HSV",
"edt_conf_enum_left_right": "Left to right",
"edt_conf_enum_linear": "Linear",
@ -335,7 +352,10 @@
"edt_conf_enum_logsilent": "Silent",
"edt_conf_enum_logverbose": "Verbose",
"edt_conf_enum_logwarn": "Warning",
"edt_conf_enum_multicolor_mean": "Multicolor",
"edt_conf_enum_low": "Low",
"edt_conf_enum_medium": "Medium",
"edt_conf_enum_multicolor_mean": "Mean Color Simple - per LED",
"edt_conf_enum_multicolor_mean_squared": "Mean Color Squared - per LED",
"edt_conf_enum_please_select": "Please Select",
"edt_conf_enum_rbg": "RBG",
"edt_conf_enum_rgb": "RGB",
@ -345,7 +365,7 @@
"edt_conf_enum_transeffect_sudden": "Sudden",
"edt_conf_enum_udp_ddp": "DDP",
"edt_conf_enum_udp_raw": "RAW",
"edt_conf_enum_unicolor_mean": "Unicolor",
"edt_conf_enum_unicolor_mean": "Mean Color Image - applied to all LEDs",
"edt_conf_fbs_heading_title": "Flatbuffers Server",
"edt_conf_fbs_timeout_expl": "If no data is received for the given period, the component will be (soft) disabled.",
"edt_conf_fbs_timeout_title": "Timeout",
@ -410,6 +430,8 @@
"edt_conf_instC_systemEnable_title": "Enable screen capture",
"edt_conf_instC_v4lEnable_expl": "Enables the USB capture for this LED hardware instance",
"edt_conf_instC_v4lEnable_title": "Enable USB capture",
"edt_conf_instC_audioEnable_expl": "Enables the Audio capture for this LED hardware instance",
"edt_conf_instC_audioEnable_title": "Enable Audio capture",
"edt_conf_instC_video_grabber_device_expl": "The video capture device used",
"edt_conf_instC_video_grabber_device_title": "Video capture device",
"edt_conf_instCapture_heading_title": "Capture Devices",
@ -510,6 +532,27 @@
"edt_conf_v4l2_hardware_set_defaults_tip": "Set device's default values for brightness, contrast, hue and saturation",
"edt_conf_v4l2_noSignalCounterThreshold_title": "Signal Counter Threshold",
"edt_conf_v4l2_noSignalCounterThreshold_expl": "Count of frames (check that with grabber's current FPS mode) after which the no signal is triggered",
"edt_conf_audio_device_expl": "Selected audio input device",
"edt_conf_audio_device_title": "Audio Device",
"edt_conf_audio_effects_expl": "Select an effect on how the audio signal is transformed to",
"edt_conf_audio_effects_title": "Audio Effects",
"edt_conf_audio_effect_enum_vumeter": "VU-Meter",
"edt_conf_audio_effect_hotcolor_expl": "Hot Color",
"edt_conf_audio_effect_hotcolor_title": "Hot Color",
"edt_conf_audio_effect_multiplier_expl": "Audio Signal Value multiplier",
"edt_conf_audio_effect_multiplier_title": "Multiplier",
"edt_conf_audio_effect_safecolor_expl": "Safe Color",
"edt_conf_audio_effect_safecolor_title": "Safe Color",
"edt_conf_audio_effect_safevalue_expl": "Safe Threshold",
"edt_conf_audio_effect_safevalue_title": "Safe Threshold",
"edt_conf_audio_effect_set_defaults": "Reset to default values",
"edt_conf_audio_effect_tolerance_expl": "Tolerance used when auto calculating a signal multipler from 0-100",
"edt_conf_audio_effect_tolerance_title": "Tolerance",
"edt_conf_audio_effect_warncolor_expl": "Warning Color",
"edt_conf_audio_effect_warncolor_title": "Warning Color",
"edt_conf_audio_effect_warnvalue_expl": "Warning Threshold",
"edt_conf_audio_effect_warnvalue_title": "Warning Threshold",
"edt_conf_audio_heading_title": "Audio Capture",
"edt_conf_webc_crtPath_expl": "Path to the certification file (format should be PEM)",
"edt_conf_webc_crtPath_title": "Certificate path",
"edt_conf_webc_docroot_expl": "Local webinterface root path (just for webui developer)",
@ -519,7 +562,9 @@
"edt_conf_webc_keyPassPhrase_title": "Key password",
"edt_conf_webc_keyPath_expl": "Path to the key file (format PEM, encrypted with RSA)",
"edt_conf_webc_keyPath_title": "Private key path",
"edt_conf_webc_sslport_expl": "Port oft the HTTPS-Webserver",
"edt_conf_webc_port_expl": "Port for the WebServer, RPC and WebSocket HTTP connections",
"edt_conf_webc_port_title": "HTTP Port",
"edt_conf_webc_sslport_expl": "Port for the WebServer, RPC and WebSocket HTTPS connections",
"edt_conf_webc_sslport_title": "HTTPS Port",
"edt_dev_auth_key_title": "Authentication Token",
"edt_dev_auth_key_title_info": "Authentication Token required to acccess the device",
@ -555,7 +600,7 @@
"edt_dev_spec_brightnessOverwrite_title": "Overwrite brightness",
"edt_dev_spec_brightnessThreshold_title": "Signal detection brightness minimum",
"edt_dev_spec_brightness_title": "Brightness",
"edt_dev_spec_candyGamma_title" : "'Candy' mode (double gamma correction)",
"edt_dev_spec_candyGamma_title": "'Candy' mode (double gamma correction)",
"edt_dev_spec_chanperfixture_title": "Channels per Fixture",
"edt_dev_spec_cid_title": "CID",
"edt_dev_spec_clientKey_title": "Clientkey",
@ -575,7 +620,7 @@
"edt_dev_spec_gpioBcm_title": "GPIO Pin",
"edt_dev_spec_gpioMap_title": "GPIO mapping",
"edt_dev_spec_gpioNumber_title": "GPIO number",
"edt_dev_spec_groupId_title": "Group ID",
"edt_dev_spec_groupId_title": "Group",
"edt_dev_spec_header_title": "Specific Settings",
"edt_dev_spec_interpolation_title": "Interpolation",
"edt_dev_spec_intervall_title": "Interval",
@ -612,15 +657,22 @@
"edt_dev_spec_razer_device_title": "Razer Chroma Device",
"edt_dev_spec_restoreOriginalState_title": "Restore lights' state",
"edt_dev_spec_restoreOriginalState_title_info": "Restore the device's original state when device is disabled",
"edt_dev_spec_rgbw_calibration_enable" : "White channel calibration (RGBW only)",
"edt_dev_spec_rgbw_calibration_limit" : "White channel limit",
"edt_dev_spec_rgbw_calibration_red" : "Red/White channel aspect",
"edt_dev_spec_rgbw_calibration_green" : "Green/White channel aspect",
"edt_dev_spec_rgbw_calibration_blue" : "Blue/White channel aspect",
"edt_dev_spec_rgbw_calibration_enable": "White channel calibration (RGBW only)",
"edt_dev_spec_rgbw_calibration_limit": "White channel limit",
"edt_dev_spec_rgbw_calibration_red": "Red/White channel aspect",
"edt_dev_spec_rgbw_calibration_green": "Green/White channel aspect",
"edt_dev_spec_rgbw_calibration_blue": "Blue/White channel aspect",
"edt_dev_spec_segments_disabled_title": "Segment streaming disabled at WLED.",
"edt_dev_spec_segments_title": "Stream to segment",
"edt_dev_spec_segmentId_title": "Segment-ID",
"edt_dev_spec_segmentsSwitchOffOthers_title": "Switch-off other segments",
"edt_dev_spec_segmentsOverlapValidation_error": "Correct the WLED setup! The segment must not overlap with {{plural:$1| segment|segments}}: \"$2\".",
"edt_dev_spec_serial_title": "Serial number",
"edt_dev_spec_spipath_title": "SPI Device",
"edt_dev_spec_sslHSTimeoutMax_title": "Streamer handshake timeout maximum",
"edt_dev_spec_sslHSTimeoutMin_title": "Streamer handshake timeout minimum",
"edt_dev_spec_stayOnAfterStreaming_title": "Stay on after streaming",
"edt_dev_spec_stayOnAfterStreaming_title_info": "The device will stay on after streaming or restoring state.",
"edt_dev_spec_switchOffOnBlack_title": "Switch off on black",
"edt_dev_spec_switchOffOnbelowMinBrightness_title": "Switch-off, below minimum",
"edt_dev_spec_syncOverwrite_title": "Disable synchronisation",
@ -633,6 +685,7 @@
"edt_dev_spec_transistionTime_title": "Transition time",
"edt_dev_spec_uid_title": "UID",
"edt_dev_spec_universe_title": "Universe",
"edt_dev_spec_useAPIv2_title": "Use API v2",
"edt_dev_spec_useEntertainmentAPI_title": "Use Hue Entertainment API",
"edt_dev_spec_useOrbSmoothing_title": "Use orb smoothing",
"edt_dev_spec_useRgbwProtocol_title": "Use RGBW protocol",
@ -852,6 +905,7 @@
"general_comp_PROTOSERVER": "Protocol Buffers Server",
"general_comp_SMOOTHING": "Smoothing",
"general_comp_V4L": "Capture USB-Input",
"general_comp_AUDIO": "Audio Capture",
"general_country_cn": "China",
"general_country_de": "Germany",
"general_country_es": "Spain",
@ -863,11 +917,11 @@
"general_country_us": "United States",
"general_disabled": "disabled",
"general_enabled": "enabled",
"general_speech_ca": "Catalan",
"general_speech_ca": "Catalan",
"general_speech_cs": "Czech",
"general_speech_da": "Danish",
"general_speech_de": "German",
"general_speech_el": "Greek",
"general_speech_el": "Greek",
"general_speech_en": "English",
"general_speech_es": "Spanish",
"general_speech_fr": "French",
@ -962,8 +1016,11 @@
"remote_losthint": "Note: All changes will be lost after a restart.",
"remote_maptype_intro": "Usually the LED layout defines which LED covers a specific picture area. You can change it here: $1.",
"remote_maptype_label": "Mapping type",
"remote_maptype_label_multicolor_mean": "Multicolor",
"remote_maptype_label_unicolor_mean": "Unicolor",
"remote_maptype_label_dominant_color": "Dominant Color",
"remote_maptype_label_dominant_color_advanced": "Dominant Color Advanced",
"remote_maptype_label_multicolor_mean": "Mean Color Simple",
"remote_maptype_label_multicolor_mean_squared": "Mean Color Squared",
"remote_maptype_label_unicolor_mean": "Mean Color Image",
"remote_optgroup_syseffets": "System Effects",
"remote_optgroup_templates_custom": "User Templates",
"remote_optgroup_templates_system": "System Templates",
@ -1033,7 +1090,7 @@
"wiz_cololight_noprops": "Not able to get device properties - Define Hardware LED count manually",
"wiz_cololight_title": "Cololight Wizard",
"wiz_guideyou": "The $1 will guide you through the settings. Just press the button!",
"wiz_hue_blinkblue": "Let ID $1 light up blue",
"wiz_hue_blinkblue": "Let it light up",
"wiz_hue_clientkey": "Clientkey",
"wiz_hue_create_user": "Create new User",
"wiz_hue_desc1": "1. Hyperion searches automatically for a Hue-Bridge, in case it cannot find one you need to provide the hostname or IP-address and push the reload button. <br> 2. Provide a user ID, if you do not have one create a new one.",

View File

@ -10,6 +10,9 @@
"InfoDialog_nowrite_foottext": "¡El WebUI se desbloqueará automáticamente después de haber resuelto el problema!",
"InfoDialog_nowrite_text": "Hyperion no puede escribir en el archivo de configuración cargado actual. Repara los permisos de archivo para continuar.",
"InfoDialog_nowrite_title": "¡Error de permiso de escritura!",
"InfoDialog_systemRestart_title": "Reiniciar",
"InfoDialog_systemResume_title": "Retomar",
"InfoDialog_systemSuspend_title": "Suspender",
"about_3rd_party_licenses": "Licencias de terceros",
"about_3rd_party_licenses_error": "Tuvimos problemas para recopilar información de licencias de terceros a través de la Web. <br />Por favor, sigue este enlace para acceder al Recurso GitHub.",
"about_build": "Build",
@ -55,7 +58,9 @@
"conf_leds_error_get_properties_title": "Propiedades del dispositivo",
"conf_leds_error_hwled_gt_layout": "El recuento de LEDs por hardware ($1) es mayor que los LEDs configurados a través de la disposición ($2),<br>$3 {{plural:$1|LED|LEDs}} se quedará en negro si continúas.",
"conf_leds_error_hwled_gt_maxled": "El recuento de LEDs por hardware ($1) es mayor que el número máximo de LEDs soportado por el dispositivo ($2). <br> El recuento de LEDs de hardware se establece en ($3).",
"conf_leds_error_hwled_gt_maxled_protocol": "El recuento de LEDs por hardware ($1) es mayor que el número máximo de LEDs soportado por el protocolo de streaming ($2). <br> El protocolo de streaming cambiará a ($3).",
"conf_leds_error_hwled_lt_layout": "El recuento de LEDs por hardware ($1) es menor que los LEDs configurados a través del diseño ($2). <br> El número de LEDs configurados en el esquema no debe superar los LEDs disponibles.",
"conf_leds_error_wled_segment_missing": "El segmento configurado actualmente ($1) no está configurado en tu dispositivo WLED.<br>¡Es posible que tengas que comprobar la configuración del WLED!<br>La página de configuración representa la configuración actual del WLED.",
"conf_leds_info_ws281x": "Hyperion debe ejecutarse con privilegios 'root' para este tipo de controlador.",
"conf_leds_layout_advanced": "Ajustes Avanzados",
"conf_leds_layout_blacklist_num_title": "Número de LEDs",
@ -439,8 +444,6 @@
"edt_conf_smooth_heading_title": "Suavizado",
"edt_conf_smooth_interpolationRate_expl": "Velocidad de cálculo de los fotogramas intermedios suaves.",
"edt_conf_smooth_interpolationRate_title": "Tasa de interpolación",
"edt_conf_smooth_outputRate_expl": "La velocidad de salida a tu controlador de leds.",
"edt_conf_smooth_outputRate_title": "Tasa de salida",
"edt_conf_smooth_time_ms_expl": "¿Cuánto tiempo debe recoger las imágenes el suavizado?",
"edt_conf_smooth_time_ms_title": "Tiempo",
"edt_conf_smooth_type_expl": "Tipo de suavizado",
@ -614,10 +617,17 @@
"edt_dev_spec_rgbw_calibration_green": "Aspecto del canal Verde/Blanco",
"edt_dev_spec_rgbw_calibration_limit": "Límite del canal blanco",
"edt_dev_spec_rgbw_calibration_red": "Aspecto del canal Rojo/Blanco",
"edt_dev_spec_segmentId_title": "Segmento-ID",
"edt_dev_spec_segmentsOverlapValidation_error": "¡Corrige la configuración de WLED! El segmento no debe solaparse con {{plural:$1| segmento|segmentos}}: \"$2\".",
"edt_dev_spec_segmentsSwitchOffOthers_title": "Desconectar otros segmentos",
"edt_dev_spec_segments_disabled_title": "Transmisión de segmentos desactivada en WLED.",
"edt_dev_spec_segments_title": "Transmisión a segmento",
"edt_dev_spec_serial_title": "Número de serie",
"edt_dev_spec_spipath_title": "Dispositivo SPI",
"edt_dev_spec_sslHSTimeoutMax_title": "Máximo tiempo de espera para el contacto con el Streamer",
"edt_dev_spec_sslHSTimeoutMin_title": "Tiempo mínimo de espera para el contacto con el Streamer",
"edt_dev_spec_stayOnAfterStreaming_title": "Permanecer encendido después del streaming",
"edt_dev_spec_stayOnAfterStreaming_title_info": "El dispositivo permanecerá encendido después de transmitir o restaurar el estado.",
"edt_dev_spec_stream_protocol_title": "Protocolo de streaming",
"edt_dev_spec_switchOffOnBlack_title": "Apagar en negro",
"edt_dev_spec_switchOffOnbelowMinBrightness_title": "Apagado, por debajo del mínimo",
@ -861,9 +871,11 @@
"general_country_us": "Estados Unidos",
"general_disabled": "Deshabilitado",
"general_enabled": "Habilitado",
"general_speech_ca": "Catalán",
"general_speech_cs": "Czech",
"general_speech_da": "Danés",
"general_speech_de": "Alemán",
"general_speech_el": "Griego",
"general_speech_en": "Inglés",
"general_speech_es": "Español",
"general_speech_fr": "Francés",

View File

@ -398,9 +398,11 @@
"edt_conf_v4l2_greenSignalThreshold_expl": "Assombrie les valeurs vertes faibles (reconnues comme noires)",
"edt_conf_v4l2_greenSignalThreshold_title": "Seuil de signal vert",
"edt_conf_v4l2_hardware_brightness_expl": "Définie la luminosité matérielle",
"edt_conf_v4l2_hardware_brightness_title": "Contrôle matériel de la luminosité",
"edt_conf_v4l2_hardware_contrast_expl": "Définie le contraste matériel",
"edt_conf_v4l2_hardware_contrast_title": "Contrôle le contraste matériel",
"edt_conf_v4l2_hardware_hue_expl": "Définie le hue matériel",
"edt_conf_v4l2_hardware_hue_title": "Contrôle matériel de la teinte",
"edt_conf_v4l2_hardware_saturation_expl": "Définie la saturation matérielle",
"edt_conf_v4l2_hardware_saturation_title": "Contrôle la saturation matériel",
"edt_conf_v4l2_heading_title": "Capture USB",

View File

@ -5,6 +5,8 @@
"InfoDialog_changePassword_title": "Cambia Password",
"InfoDialog_iswitch_text": "Se esegui più di un Hyperion nella tua rete locale puoi passare tra configurazioni web. Seleziona l'istanza di Hyperion qui sotto e cambia!",
"InfoDialog_iswitch_title": "Cambia Hyperion",
"InfoDialog_nostorage_text": "Il tuo browser non supporta localStorage. Non è possibile salvare un'impostazione di lingua specifica (fallback su \"rilevamento automatico\") e livello di accesso (fallback su \"predefinito\"). Alcuni maghi potrebbero essere nascosti. Puoi ancora utilizzare l'interfaccia web senza ulteriori problemi",
"InfoDialog_nostorage_title": "Impossibile memorizzare le impostazioni",
"InfoDialog_nowrite_foottext": "WebUI sarà sbloccata automaticamente appena avrai risolto il problema!",
"InfoDialog_nowrite_text": "Hyperion non può scrivere sull'attuale file di configurazione caricato. Riparare i permessi del file per procedere",
"InfoDialog_nowrite_title": "errore dei permessi di scrittura!",
@ -40,14 +42,29 @@
"conf_general_intro": "Impostazioni base di Hyperion e WebUI che non rientrano in altre categorie.",
"conf_general_label_title": "Impostazioni generali",
"conf_grabber_fg_intro": "Cattura di sistema usa la cattura locale del sistema su cui è installato Hyperion come sorgente di input.",
"conf_grabber_inst_grabber_config_info": "Configura in anticipo i dispositivi hardware di acquisizione in modo che vengano utilizzati dall'istanza",
"conf_grabber_v4l_intro": "Cattura USB è un dispositivo (di cattura) connesso via USB usato come sorgente di immagini per l'elaborazione.",
"conf_helptable_expl": "Spiegazione",
"conf_helptable_option": "Opzioni",
"conf_leds_config_error": "Errore nella configurazione del layout LED/LED",
"conf_leds_config_warning": "Controlla la configurazione del layout LED/LED",
"conf_leds_contr_label_contrtype": "Tipo di Controller",
"conf_leds_device_info_log": "Nel caso in cui i tuoi LED non funzionino, controlla qui per gli errori:",
"conf_leds_device_intro": "Hyperion supporta molti controller per trasmettere dati al tuo dispositivo. Seleziona un controller LED dalla lista e configuralo. Abbiamo scelto le impostazioni di default migliori per ogni dispositivo.",
"conf_leds_error_get_properties_text": "Impossibile ottenere le proprietà del dispositivo. Si prega di controllare gli elementi di configurazione.",
"conf_leds_error_get_properties_title": "Proprietà del dispositivo",
"conf_leds_error_hwled_gt_layout": "Il conteggio dei LED hardware ($1) è maggiore dei LED configurati tramite layout ($2),<br>$3 {{plural:$3|LED|LED}} rimarranno neri se continui.",
"conf_leds_error_hwled_gt_maxled": "Il numero di LED hardware ($ 1) è superiore al numero massimo di LED supportati dal dispositivo ($ 2). <br> Il conteggio dei LED hardware è impostato su ($ 3)",
"conf_leds_error_hwled_lt_layout": "Il numero di LED hardware ($ 1) è inferiore ai LED configurati tramite layout ($ 2). <br> Il numero di LED configurati nel layout non deve superare i LED disponibili",
"conf_leds_info_ws281x": "Hyperion deve essere eseguito con privilegi di 'root' per questo tipo di controller!",
"conf_leds_layout_advanced": "Impostazioni Avanzate",
"conf_leds_layout_blacklist_num_title": "Numero di LEDs",
"conf_leds_layout_blacklist_rule_title": "Regole della lista nera",
"conf_leds_layout_blacklist_rules_title": "Regole delle liste nere",
"conf_leds_layout_blacklist_start_title": "LED Iniziale",
"conf_leds_layout_blacklistleds_title": "I LED della lista nera",
"conf_leds_layout_btn_checklist": "Mostra lista",
"conf_leds_layout_btn_keystone": "Correzione trapezoidale",
"conf_leds_layout_button_savelay": "Salva Layout",
"conf_leds_layout_button_updsim": "Aggiorna Anteprima",
"conf_leds_layout_checkp1": "Il led nero è il tuo primo led, il primo led è il punto in cui c'è l'input del segnale dati",
@ -67,6 +84,16 @@
"conf_leds_layout_cl_leftbottom": "Sinistra 0% - 100% Sotto",
"conf_leds_layout_cl_leftmiddle": "Sinistra 0% - 75% Centro",
"conf_leds_layout_cl_lefttop": "Sinistra 0% - 50% Sopra",
"conf_leds_layout_cl_lightPosBottomLeft11": "In basso: 75 - 100% da sinistra",
"conf_leds_layout_cl_lightPosBottomLeft112": "In basso: 0 - 50% da sinistra",
"conf_leds_layout_cl_lightPosBottomLeft12": "In basso: 25 - 50% da sinistra",
"conf_leds_layout_cl_lightPosBottomLeft121": "In basso: 50 - 100% da sinistra",
"conf_leds_layout_cl_lightPosBottomLeft14": "In basso: 0 - 25% da sinistra",
"conf_leds_layout_cl_lightPosBottomLeft34": "In basso: 50 - 75% da sinistra",
"conf_leds_layout_cl_lightPosBottomLeftNewMid": "In basso: 25 - 75% da sinistra",
"conf_leds_layout_cl_lightPosTopLeft112": "In alto: 0 - 50% da sinistra",
"conf_leds_layout_cl_lightPosTopLeft121": "In alto: 50 - 100% da sinistra",
"conf_leds_layout_cl_lightPosTopLeftNewMid": "In alto: 25 - 75% da sinistra",
"conf_leds_layout_cl_overlap": "Overlap",
"conf_leds_layout_cl_reversdir": "Inverti direzione",
"conf_leds_layout_cl_right": "Destra",
@ -81,6 +108,7 @@
"conf_leds_layout_generatedconf": "Configurazione LED Generata/Attuale",
"conf_leds_layout_intro": "è necessario anche un layout dei led che rifletta la disposizione dei tuoi led. Il layout classico è il comune bordo della tv, ma supportiamo anche la creazione di matrici led (parete led). La visuale sul layout è SEMPRE DI FRONTE alla TV.",
"conf_leds_layout_ma_cabling": "Cablaggio",
"conf_leds_layout_ma_direction": "Direzione",
"conf_leds_layout_ma_horiz": "Orizzontale",
"conf_leds_layout_ma_optbottomleft": "Basso a sinistra",
"conf_leds_layout_ma_optbottomright": "Basso a destra",
@ -112,17 +140,21 @@
"conf_leds_layout_textf1": "Questo campo testo mostra di default il layout attualmente caricato e viene sovrascritto se ne generi uno nuovo con le opzioni sopra. Se vuoi puoi fare ulteriori modifiche.",
"conf_leds_nav_label_ledcontroller": "Controller LED",
"conf_leds_nav_label_ledlayout": "Layout LED",
"conf_leds_note_layout_overwrite": "Nota: Overwrite crea un layout predefinito per {{plural:$1| un LED| tutti i LED $1}} dati dal conteggio dei LED hardware",
"conf_leds_optgroup_RPiGPIO": "RPi GPIO",
"conf_leds_optgroup_RPiPWM": "RPi PWM",
"conf_leds_optgroup_RPiSPI": "RPi SPI",
"conf_leds_optgroup_debug": "Debug",
"conf_leds_optgroup_network": "Rete",
"conf_leds_optgroup_other": "Altro",
"conf_leds_optgroup_usb": "USB/Seriale",
"conf_logging_btn_autoscroll": "Auto scrolling",
"conf_logging_btn_clipboard": "Copia nel registro Appunti",
"conf_logging_btn_pbupload": "Invia segnalazione per richieste di supporto",
"conf_logging_contpolicy": "Policy per la Privacy delle segnalazioni",
"conf_logging_label_intro": "Area per controllare i messaggi di log, a seconda dell'impostazione di loglevel vedrai più o meno informazioni.",
"conf_logging_lastreports": "Segnalazioni precedenti",
"conf_logging_logoutput": "Log output",
"conf_logging_nomessage": "Nessun messaggio di log disponibile.",
"conf_logging_report": "Segnala",
"conf_logging_uplfailed": "Upload fallito! Controlla la tua connessione a internet!",
@ -163,7 +195,12 @@
"dashboard_infobox_label_instance": "Istanza:",
"dashboard_infobox_label_latesthyp": "L'ultima versione di Hyperion:",
"dashboard_infobox_label_platform": "Piattaforma:",
"dashboard_infobox_label_port_boblight": "Server Boblight:",
"dashboard_infobox_label_port_flat": "Flatbuffer:",
"dashboard_infobox_label_port_json": "JSON-Server:",
"dashboard_infobox_label_port_proto": "Protobuffer:",
"dashboard_infobox_label_ports": "Porte",
"dashboard_infobox_label_ports_websocket": "WebSocket (ws|wss):",
"dashboard_infobox_label_smartacc": "Accesso Smart",
"dashboard_infobox_label_statush": "Status Hyperion:",
"dashboard_infobox_label_title": "Informazioni",
@ -181,6 +218,7 @@
"dashboard_newsbox_readmore": "Leggi ancora",
"dashboard_newsbox_visitblog": "Visita Hyperion-Blog",
"edt_append_degree": "°",
"edt_append_frames": "frames",
"edt_append_hz": "Hz",
"edt_append_leds": "LEDs",
"edt_append_ms": "ms",
@ -216,6 +254,8 @@
"edt_conf_color_blue_title": "Blu",
"edt_conf_color_brightnessComp_expl": "Compensa la differenza di luminosità tra rosso verde blu, ciano magneta giallo e bianco. 100 significa massima compensazione, 0 nessuna compensazione",
"edt_conf_color_brightnessComp_title": "Compensazione luminosità",
"edt_conf_color_brightnessGain_expl": "Regola la luminosità dei colori. 1.0 significa nessun cambiamento, oltre 1.0 aumenta la luminosità, sotto 1.0 diminuisce la luminosità",
"edt_conf_color_brightnessGain_title": "Intensità della luminosità",
"edt_conf_color_brightness_expl": "Imposta la luminosità complessiva dei leds",
"edt_conf_color_brightness_title": "Luminosità",
"edt_conf_color_channelAdjustment_header_expl": "Crea profilo di colore che può essere assegnato a un componente specifico. Regola colore, gamma, luminosità, compensazione e altro.",
@ -242,6 +282,8 @@
"edt_conf_color_magenta_title": "Magenta",
"edt_conf_color_red_expl": "Il valore calibrato del rosso.",
"edt_conf_color_red_title": "Rosso",
"edt_conf_color_saturationGain_expl": "Regola la saturazione dei colori. 1.0 significa nessun cambiamento, oltre 1.0 aumenta la saturazione, sotto 1.0 desatura.",
"edt_conf_color_saturationGain_title": "Intensità della saturazione",
"edt_conf_color_white_expl": "Il valore calibrato del bianco.",
"edt_conf_color_white_title": "Bianco",
"edt_conf_color_yellow_expl": "Il valore calibrato del giallo.",
@ -253,10 +295,13 @@
"edt_conf_effp_paths_expl": "Puoi definire altre cartelle che contengono effetti aggiuntivi. Il configuratore di effetti salva sempre all'interno della prima cartella.",
"edt_conf_effp_paths_itemtitle": "Percorso",
"edt_conf_effp_paths_title": "Percorso Effetti",
"edt_conf_enum_BOTH": "Orizzontale e Verticale",
"edt_conf_enum_HORIZONTAL": "Orizzontale",
"edt_conf_enum_NO_CHANGE": "Auto",
"edt_conf_enum_NTSC": "NTSC",
"edt_conf_enum_PAL": "PAL",
"edt_conf_enum_SECAM": "SECAM",
"edt_conf_enum_VERTICAL": "Verticale",
"edt_conf_enum_automatic": "Automatico",
"edt_conf_enum_bbclassic": "Classico",
"edt_conf_enum_bbdefault": "Default",
@ -287,12 +332,15 @@
"edt_conf_enum_logverbose": "Verboso",
"edt_conf_enum_logwarn": "Avvertimento",
"edt_conf_enum_multicolor_mean": "Multicolore",
"edt_conf_enum_please_select": "Seleziona",
"edt_conf_enum_rbg": "RBG",
"edt_conf_enum_rgb": "RGB",
"edt_conf_enum_right_left": "Da destra a sinistra",
"edt_conf_enum_top_down": "Dall'alto verso il basso",
"edt_conf_enum_transeffect_smooth": "Dolce",
"edt_conf_enum_transeffect_sudden": "Repentina",
"edt_conf_enum_udp_ddp": "DDP",
"edt_conf_enum_udp_raw": "RAW",
"edt_conf_enum_unicolor_mean": "Monocromatico",
"edt_conf_fbs_heading_title": "Server Flatbuffers",
"edt_conf_fbs_timeout_expl": "Se nessuna informazione viene ricevuta per un dato periodo, il componente verrà disabilitato (soft).",
@ -321,11 +369,19 @@
"edt_conf_fge_type_title": "Tipo",
"edt_conf_fw_flat_expl": "Una destinazione flatbuffer per riga. Contiene IP:PORTA:(Esempio: 127.0.0.1:19401)",
"edt_conf_fw_flat_itemtitle": "Destinatario flatbuffer",
"edt_conf_fw_flat_services_discovered_expl": "Obiettivi flatbuffer scoperti",
"edt_conf_fw_flat_services_discovered_title": "Obiettivi flatbuffer scoperti",
"edt_conf_fw_flat_title": "Lista dei client flatbuffer",
"edt_conf_fw_heading_title": "Forwarder",
"edt_conf_fw_json_expl": "Una destinazione json per riga. Contiene IP:PORTA:(Esempio: 127.0.0.1:19446)",
"edt_conf_fw_json_itemtitle": "Destinatario json",
"edt_conf_fw_json_services_discovered_expl": "Server Hyperion scoperti che forniscono servizi JSON-API",
"edt_conf_fw_json_services_discovered_title": "Target JSON rilevati",
"edt_conf_fw_json_title": "Lista dei client json",
"edt_conf_fw_remote_service_discovered_none": "Nessun servizio remoto rilevato",
"edt_conf_fw_service_name_expl": "Nome del fornitore di servizi",
"edt_conf_fw_service_name_title": "Nome di Servizio",
"edt_conf_gen_configVersion_title": "Versione di configurazione",
"edt_conf_gen_heading_title": "impostazioni Generali",
"edt_conf_gen_name_expl": "Un nome definito dall'utente che viene utilizzato per riconoscere Hyperion. (Utile con più di un'istanza di Hyperion)",
"edt_conf_gen_name_title": "Nome configurazione",
@ -339,10 +395,19 @@
"edt_conf_general_port_title": "Porta",
"edt_conf_general_priority_expl": "Priorità di questo componente",
"edt_conf_general_priority_title": "Priorità canale.",
"edt_conf_grabber_discovered_expl": "Seleziona il tuo dispositivo di acquisizione scoperto",
"edt_conf_grabber_discovered_none": "Nessun dispositivo di acquisizione rilevato",
"edt_conf_grabber_discovered_title": "Dispositivo scoperto",
"edt_conf_grabber_discovered_title_info": "Seleziona il tuo dispositivo di acquisizione scoperto",
"edt_conf_grabber_discovery_inprogress": "ricerca in corso",
"edt_conf_instC_screen_grabber_device_expl": "l dispositivo di cattura dello schermo utilizzato",
"edt_conf_instC_screen_grabber_device_title": "Dispositivo di cattura dello schermo",
"edt_conf_instC_systemEnable_expl": "Abilita la cattura della piattaforma per questa istanza di hardware led",
"edt_conf_instC_systemEnable_title": "Abilita cattura piattaforma",
"edt_conf_instC_v4lEnable_expl": "Abilita la cattura USB per questa istanza di hardware led",
"edt_conf_instC_v4lEnable_title": "Abilita cattura USB",
"edt_conf_instC_video_grabber_device_expl": "Il dispositivo di acquisizione video utilizzato",
"edt_conf_instC_video_grabber_device_title": "Dispositivo di acquisizione video",
"edt_conf_instCapture_heading_title": "Cattura Istanza",
"edt_conf_js_heading_title": "Server JSON",
"edt_conf_log_heading_title": "Logging",
@ -374,8 +439,6 @@
"edt_conf_smooth_heading_title": "Sfumatura",
"edt_conf_smooth_interpolationRate_expl": "Velocità di calcolo dei regolari frame intermedi",
"edt_conf_smooth_interpolationRate_title": "Tasso di interpolazione",
"edt_conf_smooth_outputRate_expl": "Velocità di uscita al tuo controller LED.",
"edt_conf_smooth_outputRate_title": "Velocità di uscita",
"edt_conf_smooth_time_ms_expl": "Quanto a lungo la sfumatura dovrebbe raggiungere le immagini?",
"edt_conf_smooth_time_ms_title": "Durata",
"edt_conf_smooth_type_expl": "Tipo di sfumatura.",
@ -390,21 +453,41 @@
"edt_conf_v4l2_cecDetection_title": "Rilevamento CEC",
"edt_conf_v4l2_cropBottom_expl": "Numero di pixels in basso che vengono rimossi dall'immagine.",
"edt_conf_v4l2_cropBottom_title": "Ritaglia in basso",
"edt_conf_v4l2_cropHeightValidation_error": "Ritaglia in alto + Ritaglia in basso non può essere maggiore di Altezza ($ 1)",
"edt_conf_v4l2_cropLeft_expl": "Numero di pixels sulla sinistra che vengono rimossi dall'immagine.",
"edt_conf_v4l2_cropLeft_title": "Ritaglia sinistra",
"edt_conf_v4l2_cropRight_expl": "Numero di pixels sulla destra che vengono rimossi dall'immagine.",
"edt_conf_v4l2_cropRight_title": "Ritaglia destra",
"edt_conf_v4l2_cropTop_expl": "Numero di pixels in alto che vengono rimossi dall'immagine.",
"edt_conf_v4l2_cropTop_title": "Ritaglia in alto",
"edt_conf_v4l2_cropWidthValidation_error": "Ritaglia a sinistra + Ritaglia a destra non può essere maggiore di Larghezza ($1)",
"edt_conf_v4l2_device_expl": "Percorso del dispositivo di cattura USB. Imposta su 'Automatico' per riconoscimento automatico. Esempio: '/dev/video0'",
"edt_conf_v4l2_device_title": "Dispositivo",
"edt_conf_v4l2_encoding_expl": "Forza la codifica video per i grabber multiformato",
"edt_conf_v4l2_encoding_title": "Formato di codifica",
"edt_conf_v4l2_flip_expl": "Ciò consente di capovolgere l'immagine orizzontalmente, verticalmente o entrambi.",
"edt_conf_v4l2_flip_title": "Capovolgimento dell'immagine",
"edt_conf_v4l2_fpsSoftwareDecimation_expl": "Per risparmiare risorse verrà elaborato solo ogni n-esimo frame. Per es. se il grabber è impostato a 30fps con questa opzione impostata a 5 il risultato finale sarà di circa 6fps",
"edt_conf_v4l2_fpsSoftwareDecimation_title": "Salto del frame del software",
"edt_conf_v4l2_framerate_expl": "Frame al secondo supportati per il dispositivo attivo",
"edt_conf_v4l2_framerate_title": "Frame al secondo",
"edt_conf_v4l2_greenSignalThreshold_expl": "Scurisce valori bassi di verde (riconosciuti come nero)",
"edt_conf_v4l2_greenSignalThreshold_title": "Soglia segnale verde",
"edt_conf_v4l2_hardware_brightness_expl": "Imposta la luminosità dell'hardware",
"edt_conf_v4l2_hardware_brightness_title": "Controllo hardware della luminosità",
"edt_conf_v4l2_hardware_contrast_expl": "Imposta il contrasto hardware",
"edt_conf_v4l2_hardware_contrast_title": "Controllo hardware del contrasto",
"edt_conf_v4l2_hardware_hue_expl": "Imposta la tonalità dell'hardware",
"edt_conf_v4l2_hardware_hue_title": "Controllo della tonalità hardware",
"edt_conf_v4l2_hardware_saturation_expl": "Imposta la saturazione hardware",
"edt_conf_v4l2_hardware_saturation_title": "Controllo della saturazione hardware",
"edt_conf_v4l2_hardware_set_defaults": "Controlli hardware predefiniti",
"edt_conf_v4l2_hardware_set_defaults_tip": "Imposta i valori predefiniti del dispositivo per luminosità, contrasto, tonalità e saturazione",
"edt_conf_v4l2_heading_title": "Cattura USB",
"edt_conf_v4l2_input_expl": "Seleziona l'input video per il tuo dispositivo. 'Automatico' mantiene il Valero scelto dall'interfaccia v4l2.",
"edt_conf_v4l2_input_title": "Input",
"edt_conf_v4l2_noSignalCounterThreshold_expl": "Conteggio dei fotogrammi (controllalo con l'attuale modalità FPS del grabber) dopo il quale viene attivato il segnale di assenza",
"edt_conf_v4l2_noSignalCounterThreshold_title": "Soglia del contatore di segnale",
"edt_conf_v4l2_redSignalThreshold_expl": "Scurisce valori bassi di rosso (riconosciuti come nero)",
"edt_conf_v4l2_redSignalThreshold_title": "Soglia segnale rosso",
"edt_conf_v4l2_resolution_expl": "Lista Risoluzioni supportate per il dispositivo attivo",
@ -435,12 +518,21 @@
"edt_conf_webc_sslport_expl": "Porta del webserver HTTPS",
"edt_conf_webc_sslport_title": "Porta HTTPS",
"edt_dev_auth_key_title": "Token di autenticazione",
"edt_dev_auth_key_title_info": "Token di autenticazione necessario per accedere al dispositivo",
"edt_dev_enum_sub_min_cool_adjust": "Regolazione freddo min",
"edt_dev_enum_sub_min_warm_adjust": "Regolazione calore min",
"edt_dev_enum_subtract_minimum": "Sottrai minimo",
"edt_dev_enum_white_off": "Bianco off",
"edt_dev_general_autostart_title": "avvio automatico",
"edt_dev_general_autostart_title_info": "Il dispositivo LED è acceso durante l'avvio oppure no",
"edt_dev_general_colorOrder_title": "Ordine byte RGB",
"edt_dev_general_colorOrder_title_info": "L'ordine dei colori del dispositivo",
"edt_dev_general_enableAttemptsInterval_title": "Intervallo tra tentativi",
"edt_dev_general_enableAttemptsInterval_title_info": "Intervallo tra due tentativi di connessione.",
"edt_dev_general_enableAttempts_title": "Tentativi di connessione",
"edt_dev_general_enableAttempts_title_info": "Numero di tentativi di connessione di un dispositivo prima che entri in uno stato di errore.",
"edt_dev_general_hardwareLedCount_title": "Numero di LED Hardware",
"edt_dev_general_hardwareLedCount_title_info": "Il numero di LED fisici disponibili per il dispositivo specificato",
"edt_dev_general_heading_title": "Impostazioni Generali",
"edt_dev_general_name_title": "Nome configurazione",
"edt_dev_general_rewriteTime_title": "Tempo di ricarica",
@ -449,21 +541,28 @@
"edt_dev_spec_FCsetConfig_title": "Imposta configurazione Fadecandy",
"edt_dev_spec_LBap102Mode_title": "Modalità LightBerry APA102",
"edt_dev_spec_PBFiFo_title": "Pi-Blaster FiFo",
"edt_dev_spec_ada_mode_title": "Adalight - Standard",
"edt_dev_spec_awa_mode_title": "HyperSerial - Alta velocità",
"edt_dev_spec_baudrate_title": "Baudrate",
"edt_dev_spec_blackLightsTimeout_title": "Timeout rilevamento segnale su nero",
"edt_dev_spec_brightnessFactor_title": "Fattore luminosità",
"edt_dev_spec_brightnessMax_title": "Luminosità massima",
"edt_dev_spec_brightnessMin_title": "Luminosità minima",
"edt_dev_spec_brightnessMin_title": "Luminosità minima",
"edt_dev_spec_brightnessOverwrite_title": "Sovrascrivi luminosità",
"edt_dev_spec_brightnessThreshold_title": "Luminosità minima per rilevamento segnale",
"edt_dev_spec_brightness_title": "Luminosità",
"edt_dev_spec_candyGamma_title": "Modalità \"Candy\" (doppia correzione gamma)",
"edt_dev_spec_chanperfixture_title": "Canali per dispositivo",
"edt_dev_spec_cid_title": "CID",
"edt_dev_spec_clientKey_title": "Clientkey",
"edt_dev_spec_colorComponent_title": "Componente colore",
"edt_dev_spec_debugLevel_title": "Livello Debug",
"edt_dev_spec_debugStreamer_title": "Debug Streamer",
"edt_dev_spec_delayAfterConnect_title": "Ritardo dopo la connessione",
"edt_dev_spec_devices_discovered_none": "Nessun dispositivo rilevato",
"edt_dev_spec_devices_discovered_title": "Dispositivi trovato",
"edt_dev_spec_devices_discovered_title_info": "Seleziona il tuo dispositivo LED trovato",
"edt_dev_spec_devices_discovered_title_info_custom": "Seleziona il tuo dispositivo LED trovato o configurane uno personalizzato",
"edt_dev_spec_devices_discovery_inprogress": "Ricerca in corso",
"edt_dev_spec_dithering_title": "Dithering",
"edt_dev_spec_dmaNumber_title": "Canale DMA",
"edt_dev_spec_gamma_title": "Gamma",
@ -478,6 +577,7 @@
"edt_dev_spec_intervall_title": "Intervallo",
"edt_dev_spec_invert_title": "Inverti segnale",
"edt_dev_spec_latchtime_title": "Tempo di latch",
"edt_dev_spec_latchtime_title_info": "Il tempo di latch è l'intervallo di tempo richiesto da un dispositivo fino all'elaborazione del successivo aggiornamento. Durante tale periodo di tempo, tutti gli aggiornamenti effettuati vengono ignorati.",
"edt_dev_spec_ledIndex_title": "Indice LED",
"edt_dev_spec_ledType_title": "Tipo LED",
"edt_dev_spec_lightid_itemtitle": "ID",
@ -491,6 +591,8 @@
"edt_dev_spec_networkDeviceName_title": "Nome dispositivo di rete",
"edt_dev_spec_networkDevicePort_title": "Porta",
"edt_dev_spec_numberOfLeds_title": "Numero di LEDs",
"edt_dev_spec_onBlackTimeToPowerOff": "È ora di spegnere la lampada se viene attivato il livello di nero",
"edt_dev_spec_onBlackTimeToPowerOn": "È ora di accendere la lampada se il segnale viene ripristinato",
"edt_dev_spec_orbIds_title": "Orb ID",
"edt_dev_spec_order_left_right_title": "2.",
"edt_dev_spec_order_top_down_title": "1.",
@ -498,18 +600,29 @@
"edt_dev_spec_panel_start_position": "Pannello d'inizio [0-max panels]",
"edt_dev_spec_panelorganisation_title": "Sequenza numerazione pannelli",
"edt_dev_spec_pid_title": "PID",
"edt_dev_spec_port_expl": "Porta di servizio [1-65535]",
"edt_dev_spec_port_title": "Porta",
"edt_dev_spec_printTimeStamp_title": "Aggiungi timestamp",
"edt_dev_spec_pwmChannel_title": "Canale PWM",
"edt_dev_spec_razer_device_title": "Dispositivo Razer Chroma",
"edt_dev_spec_restoreOriginalState_title": "Ripristina lo stato delle luci",
"edt_dev_spec_restoreOriginalState_title_info": "Ripristina lo stato originale del dispositivo quando il dispositivo è disabilitato",
"edt_dev_spec_rgbw_calibration_blue": "Aspetto del canale blu/bianco",
"edt_dev_spec_rgbw_calibration_enable": "Calibrazione del canale del bianco (solo RGBW)",
"edt_dev_spec_rgbw_calibration_green": "Aspetto canale verde/bianco",
"edt_dev_spec_rgbw_calibration_limit": "Limite canale bianco",
"edt_dev_spec_rgbw_calibration_red": "Aspetto del canale rosso/bianco",
"edt_dev_spec_serial_title": "Numero seriale",
"edt_dev_spec_spipath_title": "Percorso SPI",
"edt_dev_spec_sslHSTimeoutMax_title": "Timeout massimo handkshake streamer",
"edt_dev_spec_sslHSTimeoutMin_title": "Timeout minimo handkshake streamer",
"edt_dev_spec_sslReadTimeout_title": "Timeout lettura streamer",
"edt_dev_spec_stream_protocol_title": "Protocollo di streaming",
"edt_dev_spec_switchOffOnBlack_title": "Spegni o accendi il nero",
"edt_dev_spec_switchOffOnbelowMinBrightness_title": "Spegni, sotto il minimo",
"edt_dev_spec_syncOverwrite_title": "Disabilita la sincronizzazione",
"edt_dev_spec_targetIpHost_expl": "Nome host (DNS/mDNS) o indirizzo IP (IPv4 o IPv6)",
"edt_dev_spec_targetIpHost_title": "IP di destinazione/nome host",
"edt_dev_spec_targetIpHost_title_info": "Il nome host o l'indirizzo IP del dispositivo",
"edt_dev_spec_targetIp_title": "IP di destinazione",
"edt_dev_spec_transeffect_title": "Effetto Transizione",
"edt_dev_spec_transistionTimeExtra_title": "Tempo extra di buio",
@ -573,9 +686,14 @@
"edt_eff_frequency": "Frequenza",
"edt_eff_gif_header": "GIF",
"edt_eff_gif_header_desc": "Questo effetto riproduce file .gif. Fornisci un semplice loop video come effetto.",
"edt_eff_grayscale": "Scala di grigi",
"edt_eff_height": "Altezza",
"edt_eff_huechange": "Cambiamento colore",
"edt_eff_image": "file immagine",
"edt_eff_image_source": "Fonte immagine",
"edt_eff_image_source_file": "File locale",
"edt_eff_image_source_url": "URL",
"edt_eff_initial_blink": "Flash per attirare l'attenzione",
"edt_eff_interval": "Intervallo",
"edt_eff_knightrider_header": "Supercar",
"edt_eff_knightrider_header_desc": "K.I.T.T. è tornato! Lo scanner frontale della nota automobile, questa volta non solo in rosso.",
@ -613,6 +731,7 @@
"edt_eff_reversedirection": "Inverti direzione",
"edt_eff_rotationtime": "Tempo di rotazione",
"edt_eff_saturation": "Saturazione",
"edt_eff_set_post_color": "Imposta il colore del post dopo l'allarme",
"edt_eff_showseconds": "Mostra secondi",
"edt_eff_sleeptime": "Tempo di riposo",
"edt_eff_smooth_custom": "Abilita sfumatura",
@ -631,6 +750,7 @@
"edt_eff_traces_header_desc": "Necessita redesign",
"edt_eff_trails_header": "Scie",
"edt_eff_trails_header_desc": "Stelle colorate che cadono dall'alto verso il basso",
"edt_eff_url": "Indirizzo dell'immagine",
"edt_eff_waves_header": "Onde",
"edt_eff_waves_header_desc": "Onde di colore! Scegli i colori, tempo di rotazione, direzione e altro.",
"edt_eff_whichleds": "Quali Leds",
@ -655,6 +775,10 @@
"edt_msg_error_disallow": "Il valore non deve essere di tipo $1",
"edt_msg_error_disallow_union": "Il valore non deve essere di uno dei tipi forniti non ammessi",
"edt_msg_error_enum": "Il valore deve essere uno tra quelli enumerati",
"edt_msg_error_hostname": "Il nome host ha il formato errato",
"edt_msg_error_invalid_epoch": "La data deve essere successiva al 1° gennaio 1970",
"edt_msg_error_ipv4": "Il valore deve essere un indirizzo IPv4 valido sotto forma di 4 numeri compresi tra 0 e 255, separati da punti",
"edt_msg_error_ipv6": "Il valore deve essere un indirizzo IPv6 valido",
"edt_msg_error_maxItems": "Il valore deve contenere al massimo $1 elementi",
"edt_msg_error_maxLength": "Il valore deve essere al massimo lungo $1 caratteri",
"edt_msg_error_maxProperties": "L'oggetto deve avere al massimo $1 proprietà",
@ -675,6 +799,8 @@
"edt_msg_error_type": "Il valore deve essere di tipo $1",
"edt_msg_error_type_union": "Il valore deve essere di uno dei tipi forniti",
"edt_msg_error_uniqueItems": "Il vettore deve contenere elementi diversi",
"edt_msgcust_error_hostname_ip": "Non è un nome host valido né IPv4 né IPv6",
"edt_msgcust_error_hostname_ip4": "Non è un nome host valido né IPv4",
"effectsconfigurator_button_conttest": "Test continuo",
"effectsconfigurator_button_deleffect": "Cancella Effetto",
"effectsconfigurator_button_editeffect": "Carica Effetto",
@ -686,7 +812,7 @@
"effectsconfigurator_label_effectname": "Nome Effetto",
"effectsconfigurator_label_intro": "Crea nuovi effetti calibrati a tuo piacimento a partire dagli effetti base. A seconda dell'effetto sono disponibili opzioni come colore, velocità, direzione e altri.",
"general_access_advanced": "Avanzate",
"general_access_default": "Default",
"general_access_default": "Predefinito",
"general_access_expert": "Esperto",
"general_btn_back": "Indietro",
"general_btn_cancel": "Annulla",
@ -699,6 +825,7 @@
"general_btn_off": "Off",
"general_btn_ok": "OK",
"general_btn_on": "On",
"general_btn_overwrite": "Sovrascrivi",
"general_btn_rename": "Rinomina",
"general_btn_restarthyperion": "Riavvia Hyperion",
"general_btn_save": "Salva",
@ -718,7 +845,7 @@
"general_comp_FORWARDER": "Forwarder",
"general_comp_GRABBER": "Cattura di Sistema",
"general_comp_LEDDEVICE": "Dispositivo LED",
"general_comp_PROTOSERVER": "Server Protocol Buffers",
"general_comp_PROTOSERVER": "Buffer del protocollo del server",
"general_comp_SMOOTHING": "Sfumatura",
"general_comp_V4L": "Cattura USB",
"general_country_cn": "Cina",
@ -730,14 +857,23 @@
"general_country_ru": "Russia",
"general_country_uk": "Regno Unito",
"general_country_us": "Stati Uniti",
"general_disabled": "disabilitato",
"general_enabled": "abilitato",
"general_speech_ca": "Catalano",
"general_speech_cs": "Czech",
"general_speech_da": "Danimarca",
"general_speech_de": "Tedesco",
"general_speech_el": "Greco",
"general_speech_en": "Inglese",
"general_speech_es": "Spagnolo",
"general_speech_fr": "Francese",
"general_speech_hu": "Ungheria",
"general_speech_it": "Italiano",
"general_speech_ja": "Giapponese",
"general_speech_nb": "Norvegese (Bokmål)",
"general_speech_nl": "Olandese",
"general_speech_pl": "Polacco",
"general_speech_pt": "Portoghese",
"general_speech_ro": "Rumeno",
"general_speech_ru": "Russo",
"general_speech_sv": "Svedese",
@ -757,6 +893,10 @@
"infoDialog_import_confirm_title": "Conferma import",
"infoDialog_import_hyperror_text": "Il file di configurazione selezionato \"$1\" non può essere importato. Non è compatibile con Hyperion 2.0 e superiori!",
"infoDialog_import_jsonerror_text": "Il file di configurazione selezionato \"$1\" non è un file .json o è corrotto. Messaggio di errore: ($2)",
"infoDialog_password_current_text": "Password attuale",
"infoDialog_password_minimum_length": "Le password devono contenere almeno 8 caratteri.",
"infoDialog_password_new_text": "Nuova Password",
"infoDialog_username_text": "Nome utente",
"infoDialog_wizrgb_text": "L'ordine dei Byte RGB è già impostato correttamente.",
"infoDialog_writeconf_error_text": "Salvataggio della configurazione fallito.",
"infoDialog_writeimage_error_text": "Il file selezionato \"$1\" non è un immagine o è corrotto! Seleziona un altro file.",
@ -776,6 +916,7 @@
"main_ledsim_btn_togglelednumber": "Numeri LED",
"main_ledsim_btn_toggleleds": "Mostra LEDs",
"main_ledsim_btn_togglelivevideo": "Video live",
"main_ledsim_btn_togglesigdetect": "Area di rilevamento del segnale",
"main_ledsim_text": "Visualizzazione live dei colori dei led e, opzionalmente, lo stream video dal dispositivo di cattura.",
"main_ledsim_title": "Visualizzazione LED",
"main_menu_about_token": "Info su Hyperion",
@ -787,6 +928,7 @@
"main_menu_general_conf_token": "Generale",
"main_menu_grabber_conf_token": "Hardware di cattura",
"main_menu_input_selection_token": "Selezione Input",
"main_menu_instcapture_conf_token": "Fonti",
"main_menu_leds_conf_token": "Hardware LED",
"main_menu_logging_token": "Log",
"main_menu_network_conf_token": "Servizi di Rete",
@ -886,6 +1028,7 @@
"wiz_cc_testintrok": "Premi il bottone qui sotto per iniziare un test video.",
"wiz_cc_testintrowok": "Guarda il link di seguito per il download dei video di test",
"wiz_cc_title": "Assistente calibrazione colore",
"wiz_cc_try_connect": "Connessione...",
"wiz_cololight_desc2": "Ora scegli quali Cololights dovrebbero essere aggiunti. Per identificare le singole luci, premere il pulsante a destra.",
"wiz_cololight_intro1": "Questa procedura guidata configura Hyperion per il sistema Cololight. Le caratteristiche sono il rilevamento automatico di Cololight e la regolazione automatica delle impostazioni di Hyperion! In breve: bastano pochi clic e il gioco è fatto!<br />Nota: in caso di una Strip Cololight, potrebbe essere necessario correggere manualmente il numero e il layout dei LED",
"wiz_cololight_noprops": "Impossibile ottenere le proprietà del dispositivo: definire manualmente il numero dei LED",
@ -921,6 +1064,7 @@
"wiz_hue_username": "ID Utente",
"wiz_identify": "Identifica",
"wiz_identify_light": "Identifica $1",
"wiz_identify_tip": "Identifica il dispositivo configurato accendendolo",
"wiz_ids_disabled": "Disattivato",
"wiz_ids_entire": "Immagine intera",
"wiz_noLights": "Nessun $1 trovato! Per favore connetti le luci alla rete o configurale manualmente",

View File

@ -10,6 +10,9 @@
"InfoDialog_nowrite_foottext": "Interfejs WebUI zostanie odblokowany automatycznie po rozwiązaniu problemu!",
"InfoDialog_nowrite_text": "Hyperion nie może zapisać do aktualnie załadowanego pliku konfiguracyjnego. zmień uprawnienia zapisu plików, aby kontynuować.",
"InfoDialog_nowrite_title": "Nie masz uprawnień do zapisu!",
"InfoDialog_systemRestart_title": "Restart",
"InfoDialog_systemResume_title": "Wznów",
"InfoDialog_systemSuspend_title": "Zawieś",
"about_3rd_party_licenses": "Licencje stron trzecich",
"about_3rd_party_licenses_error": "Mieliśmy problem z gromadzeniem informacji o licencjach stron trzecich z sieci. <br /> Kliknij ten link do zasobu GitHub.",
"about_build": "Build:",
@ -254,6 +257,8 @@
"edt_conf_color_blue_title": "Niebieski",
"edt_conf_color_brightnessComp_expl": "Kompensuje różnice jasności między czerwonym, zielonym, niebieskim, cyjanowym, purpurowym, żółtym i białym. 100 oznacza pełną kompensację, 0 oznacza brak kompensacji",
"edt_conf_color_brightnessComp_title": "Kompensacja jasności",
"edt_conf_color_brightnessGain_expl": "Reguluje jasność kolorów. 1.0 oznacza brak zmian, powyżej 1.0 zwiększa jasność, poniżej 1.0 zmniejsza jasność.",
"edt_conf_color_brightnessGain_title": "Wzmocnienie jasności",
"edt_conf_color_brightness_expl": "Ustaw jasność LEDów",
"edt_conf_color_brightness_title": "Jasność",
"edt_conf_color_channelAdjustment_header_expl": "Utwórz profile kolorów, które można przypisać do określonego profilu. Dostosuj kolor, gamma, jasność, kompensację i więcej",
@ -280,6 +285,8 @@
"edt_conf_color_magenta_title": "Magenta",
"edt_conf_color_red_expl": "Skalibrowana wartość koloru czerwonego",
"edt_conf_color_red_title": "Czerwony",
"edt_conf_color_saturationGain_expl": "Reguluje nasycenie kolorów. 1.0 oznacza brak zmian, powyżej 1.0 zwiększa nasycenie, poniżej 1.0 zmniejsza nasycenie.",
"edt_conf_color_saturationGain_title": "Wzmocnienie nasycenia",
"edt_conf_color_white_expl": "Skalibrowana wartość koloru białego.",
"edt_conf_color_white_title": "Biały",
"edt_conf_color_yellow_expl": "Skalibrowana wartość koloru żółtego",
@ -393,7 +400,7 @@
"edt_conf_general_priority_title": "Kanał priorytetowy",
"edt_conf_grabber_discovered_expl": "Wybierz wykryte urządzenie do przechwytywania",
"edt_conf_grabber_discovered_none": "Nie wykryto urządzenia do przechwytywania",
"edt_conf_grabber_discovered_title": "Wykryto urządzenie",
"edt_conf_grabber_discovered_title": "Wykryte urządzenia",
"edt_conf_grabber_discovered_title_info": "Wybierz wykryte urządzenie do przechwytywania",
"edt_conf_grabber_discovery_inprogress": "Wykrywanie w toku",
"edt_conf_instC_screen_grabber_device_expl": "Używane urządzenie do przechwytywania ekranu",
@ -435,8 +442,6 @@
"edt_conf_smooth_heading_title": "Wygładzanie",
"edt_conf_smooth_interpolationRate_expl": "Szybkość obliczania wygładzanych ramek pośrednich.",
"edt_conf_smooth_interpolationRate_title": "Współczynnik interpolacji",
"edt_conf_smooth_outputRate_expl": "Prędkość wyjściowa do twojego kontrolera led.",
"edt_conf_smooth_outputRate_title": "Szybkość wyjściowa",
"edt_conf_smooth_time_ms_expl": "Jak długo wygładzanie powinno zbierać obrazy?",
"edt_conf_smooth_time_ms_title": "Czas",
"edt_conf_smooth_type_expl": "Rodzaj wygładzania.",
@ -539,9 +544,13 @@
"edt_dev_spec_FCsetConfig_title": "Ustaw konfigurację zanikania",
"edt_dev_spec_LBap102Mode_title": "Tryb \"LightBerry APA102\"",
"edt_dev_spec_PBFiFo_title": "Pi-Blaster FiFo",
"edt_dev_spec_ada_mode_title": "Adalight - Standard",
"edt_dev_spec_awa_mode_title": "HyperSerial - High speed",
"edt_dev_spec_baudrate_title": "Prędkość (Baudrate)",
"edt_dev_spec_blackLightsTimeout_title": "Limit czasu wykrywania sygnału na czarno",
"edt_dev_spec_brightnessFactor_title": "Współczynnik jasności",
"edt_dev_spec_brightnessMax_title": "Maksymalna jasność",
"edt_dev_spec_brightnessMin_title": "Minimalna jasność",
"edt_dev_spec_brightnessOverwrite_title": "Nadpisz jasność",
"edt_dev_spec_brightnessThreshold_title": "Minimalna jasność wykrywania sygnału",
"edt_dev_spec_brightness_title": "Jasność",
@ -601,6 +610,11 @@
"edt_dev_spec_razer_device_title": "Urządzenie Razer Chroma",
"edt_dev_spec_restoreOriginalState_title": "Przywróć oryginalny stan świateł, gdy są wyłączone",
"edt_dev_spec_restoreOriginalState_title_info": "Przywróć pierwotny stan urządzenia, gdy jest ono wyłączone",
"edt_dev_spec_rgbw_calibration_blue": "Wygląd kanału niebieskiego/białego",
"edt_dev_spec_rgbw_calibration_enable": "Kalibracja kanału bieli (tylko RGBW)",
"edt_dev_spec_rgbw_calibration_green": "Wygląd kanału zielonego/białego",
"edt_dev_spec_rgbw_calibration_limit": "Limit kanału białego",
"edt_dev_spec_rgbw_calibration_red": "Wygląd kanału czerwonego/białego",
"edt_dev_spec_serial_title": "Numer seryjny",
"edt_dev_spec_spipath_title": "SPI path",
"edt_dev_spec_sslHSTimeoutMax_title": "Maksymalny limit czasu uzgadniania streamera",
@ -848,9 +862,11 @@
"general_country_us": "Stany Zjednoczone (United States)",
"general_disabled": "wyłączony",
"general_enabled": "włączony",
"general_speech_ca": "Kataloński",
"general_speech_cs": "Czeski (Czech)",
"general_speech_da": "Duński",
"general_speech_de": "Niemiecki (German)",
"general_speech_el": "Grecki",
"general_speech_en": "Angielski (English)",
"general_speech_es": "Hiszpański (Spanish)",
"general_speech_fr": "Francuski (French)",

View File

@ -10,6 +10,9 @@
"InfoDialog_nowrite_foottext": "Веб-интерфейс будет разблокирован автоматически после того, как вы решите проблему!",
"InfoDialog_nowrite_text": "Hyperion не может выполнять запись в ваш текущий загруженный файл конфигурации. Чтобы продолжить, восстановите права доступа к файлу.",
"InfoDialog_nowrite_title": "Ошибка разрешения записи!",
"InfoDialog_systemRestart_title": "Перезапустить",
"InfoDialog_systemResume_title": "Продолжить",
"InfoDialog_systemSuspend_title": "Отключить",
"about_3rd_party_licenses": "Сторонние лицензии",
"about_3rd_party_licenses_error": "У нас возникли проблемы со сбором информации о сторонних лицензиях из Интернета. <br /> Перейдите по этой ссылке на GitHub.",
"about_build": "Сборка",
@ -51,6 +54,8 @@
"conf_leds_contr_label_contrtype": "Тип контроллера:",
"conf_leds_device_info_log": "Если ваши светодиоды не работают, проверьте здесь наличие ошибок:",
"conf_leds_device_intro": "Hyperion поддерживает множество контроллеров для передачи данных на целевое устройство. Выберите светодиодный контроллер из списка и настройте его. Мы выбрали лучшие настройки по умолчанию для каждого устройства.",
"conf_leds_error_get_properties_text": "Ошибка при работе с устройством. Проверьте настройки.",
"conf_leds_error_get_properties_title": "Настройки устройства",
"conf_leds_error_hwled_gt_layout": "Количество светодиодов оборудования ($1) больше, чем количество светодиодов, настроенных с помощью макета ($2), <br> $3 {{plural:$3|Светодиод|Светодиоды}} останутся черными, если вы продолжите.",
"conf_leds_error_hwled_gt_maxled": "Количество светодиодов оборудования ($1) превышает максимальное количество светодиодов, поддерживаемое устройством ($2). <br> Счетчик аппаратных светодиодов установлен на ($3).",
"conf_leds_error_hwled_lt_layout": "Количество светодиодных индикаторов оборудования ($1) меньше, чем количество светодиодов, настроенных с помощью макета ($2). <br> Количество светодиодов, настроенных в макете, не должно превышать количество доступных светодиодов",
@ -62,6 +67,7 @@
"conf_leds_layout_blacklist_start_title": "Начальный светодиод",
"conf_leds_layout_blacklistleds_title": "Светодиоды из черного списка",
"conf_leds_layout_btn_checklist": "Показать сверку",
"conf_leds_layout_btn_keystone": "Коррекция трапеции",
"conf_leds_layout_button_savelay": "Сохранить раскладку",
"conf_leds_layout_button_updsim": "Просмотр обновления",
"conf_leds_layout_checkp1": "Черный светодиод — это ваш первый светодиод, первый светодиод — это точка, в которую вы вводите сигнал данных.",
@ -81,6 +87,16 @@
"conf_leds_layout_cl_leftbottom": "Левый 50% - 100% снизу",
"conf_leds_layout_cl_leftmiddle": "Левый 25% - 75% посередине",
"conf_leds_layout_cl_lefttop": "Слева 0% - 50% сверху",
"conf_leds_layout_cl_lightPosBottomLeft11": "Низ: 75 - 100% слева",
"conf_leds_layout_cl_lightPosBottomLeft112": "Низ: 0 - 50% слева",
"conf_leds_layout_cl_lightPosBottomLeft12": "Низ: 25 - 50% слева",
"conf_leds_layout_cl_lightPosBottomLeft121": "Низ: 50 - 100% слева",
"conf_leds_layout_cl_lightPosBottomLeft14": "Низ: 0 - 25% слева",
"conf_leds_layout_cl_lightPosBottomLeft34": "Низ: 50 - 75% слева",
"conf_leds_layout_cl_lightPosBottomLeftNewMid": "Низ: 25 - 75% слева",
"conf_leds_layout_cl_lightPosTopLeft112": "Верх: 0 - 50% слева",
"conf_leds_layout_cl_lightPosTopLeft121": "Верх: 50 - 100% слева",
"conf_leds_layout_cl_lightPosTopLeftNewMid": "Верх: 25 - 75% слева",
"conf_leds_layout_cl_overlap": "Нахлёст",
"conf_leds_layout_cl_reversdir": "Обратное направление",
"conf_leds_layout_cl_right": "Справа",
@ -95,6 +111,7 @@
"conf_leds_layout_generatedconf": "Сгенерированная/Текущая Конфигурация LED",
"conf_leds_layout_intro": "Вам также нужна LED-раскладка, которая отражает положение ваших светодиодов. Классическая раскладка обычно представляет ТВ-рамку, но поддерживается и LED-матрица (LED-стена). Вид на этой раскладке ВСЕГДА СПЕРЕДИ вашего ТВ.",
"conf_leds_layout_ma_cabling": "Подключение",
"conf_leds_layout_ma_direction": "Направление",
"conf_leds_layout_ma_horiz": "Горизонтально",
"conf_leds_layout_ma_optbottomleft": "Низ слева",
"conf_leds_layout_ma_optbottomright": "Низ справа",
@ -181,6 +198,7 @@
"dashboard_infobox_label_instance": "Пример:",
"dashboard_infobox_label_latesthyp": "Последняя версия Hyperion:",
"dashboard_infobox_label_platform": "Платформа:",
"dashboard_infobox_label_port_boblight": "Boblight сервер:",
"dashboard_infobox_label_port_flat": "Плоский буфер:",
"dashboard_infobox_label_port_json": "JSON-сервер",
"dashboard_infobox_label_port_proto": "Протобуфер:",
@ -213,6 +231,7 @@
"edt_append_percent_v": "% верт.",
"edt_append_pixel": "Пиксель",
"edt_append_s": "сек",
"edt_append_sdegree": "с/градус",
"edt_conf_bb_blurRemoveCnt_expl": "Количество пикселей, которые удаляются с обнаруженной границы, чтобы убрать размытие.",
"edt_conf_bb_blurRemoveCnt_title": "Размытие пикселя",
"edt_conf_bb_borderFrameCnt_expl": "Количество кадров до установки согласованной обнаруженной границы.",
@ -238,6 +257,8 @@
"edt_conf_color_blue_title": "Синий",
"edt_conf_color_brightnessComp_expl": "Компенсирует разницу в яркости между красным, зеленым, синим, голубым, пурпурным, жёлтым и белым. 100 означает полную компенсацию, 0 без компенсации",
"edt_conf_color_brightnessComp_title": "Компенсация яркости",
"edt_conf_color_brightnessGain_expl": "Настройка яркости. 1.0 - без коррекции, больше 1.0 - повышает, а меньше 1.0 уменьшает яркость.",
"edt_conf_color_brightnessGain_title": "Яркость",
"edt_conf_color_brightness_expl": "установить общую яркость светодиодов",
"edt_conf_color_brightness_title": "Яркость",
"edt_conf_color_channelAdjustment_header_expl": "Создавайте цветовые профили, которые можно назначить конкретному компоненту. Отрегулируйте цвет, гамму, яркость, компенсацию и многое другое.",
@ -264,6 +285,8 @@
"edt_conf_color_magenta_title": "Пурпурный",
"edt_conf_color_red_expl": "Откалиброванное значение красного.",
"edt_conf_color_red_title": "Красный",
"edt_conf_color_saturationGain_expl": "Настройка насыщенности цветов. 1.0 - без коррекции, больше 1.0 - повышает, а меньше 1.0 уменьшает насыщенность.",
"edt_conf_color_saturationGain_title": "Насыщенность",
"edt_conf_color_white_expl": "Калиброванное значение белого.",
"edt_conf_color_white_title": "Белый",
"edt_conf_color_yellow_expl": "Откалиброванное значение жёлтого цвета.",
@ -319,6 +342,8 @@
"edt_conf_enum_top_down": "Сверху вниз",
"edt_conf_enum_transeffect_smooth": "Сглаживание",
"edt_conf_enum_transeffect_sudden": "Внезапный",
"edt_conf_enum_udp_ddp": "DDP",
"edt_conf_enum_udp_raw": "RAW",
"edt_conf_enum_unicolor_mean": "Одноцветный",
"edt_conf_fbs_heading_title": "Сервер Flatbuffers",
"edt_conf_fbs_timeout_expl": "Если данные за указанный период не поступают, компонент будет (мягко) отключён.",
@ -347,11 +372,18 @@
"edt_conf_fge_type_title": "Тип",
"edt_conf_fw_flat_expl": "Одна цель плоского буфера на строку. Содержит IP: ПОРТ (Пример: 127.0.0.1:19401)",
"edt_conf_fw_flat_itemtitle": "цель плоского буфера",
"edt_conf_fw_flat_services_discovered_expl": "Обнаруженные Hyperion сервера с flatbuffer сервисами",
"edt_conf_fw_flat_services_discovered_title": "Найденные Flatbuffer цели",
"edt_conf_fw_flat_title": "Список целей плоского буфера",
"edt_conf_fw_heading_title": "Экспедитор",
"edt_conf_fw_json_expl": "Одна json цель на строку. Содержит IP:PORT (Пример: 127.0.0.1:19446)",
"edt_conf_fw_json_itemtitle": "Цель Json",
"edt_conf_fw_json_itemtitle": "Цель JSON",
"edt_conf_fw_json_services_discovered_expl": "Обнаруженные Hyperion сервера с JSON-API сервисами",
"edt_conf_fw_json_services_discovered_title": "Найденные JSON цели",
"edt_conf_fw_json_title": "Список целей json",
"edt_conf_fw_remote_service_discovered_none": "Не найдено никаких сервисов",
"edt_conf_fw_service_name_expl": "Название провайдера",
"edt_conf_fw_service_name_title": "Название сервиса",
"edt_conf_gen_configVersion_title": "Версия конфигурации",
"edt_conf_gen_heading_title": "Общие настройки",
"edt_conf_gen_name_expl": "Пользовательское имя, которое используется для обнаружения Hyperion. (Полезно с более чем одним экземпляром Hyperion)",
@ -410,8 +442,6 @@
"edt_conf_smooth_heading_title": "Сглаживание",
"edt_conf_smooth_interpolationRate_expl": "Скорость расчета плавных промежуточных кадров.",
"edt_conf_smooth_interpolationRate_title": "Скорость интерполяции",
"edt_conf_smooth_outputRate_expl": "Скорость вывода на ваш светодиодный контроллер.",
"edt_conf_smooth_outputRate_title": "Выходная скорость",
"edt_conf_smooth_time_ms_expl": "Как долго сглаживание должно собирать картинки?",
"edt_conf_smooth_time_ms_title": "Время",
"edt_conf_smooth_type_expl": "Тип сглаживания.",
@ -497,8 +527,13 @@
"edt_dev_enum_subtract_minimum": "Уменьшить минимум",
"edt_dev_enum_white_off": "Выключить белый ",
"edt_dev_general_autostart_title": "Автозапуск",
"edt_dev_general_autostart_title_info": "Включать LED устройство при загрузке или нет",
"edt_dev_general_colorOrder_title": "Порядок байтов RGB",
"edt_dev_general_colorOrder_title_info": "Порядок цвета устройства",
"edt_dev_general_enableAttemptsInterval_title": "Задержка",
"edt_dev_general_enableAttemptsInterval_title_info": "Задержка между попытками подключения",
"edt_dev_general_enableAttempts_title": "Количество попыток",
"edt_dev_general_enableAttempts_title_info": "Количество попыток подключения к устройству до аварийного состояния.",
"edt_dev_general_hardwareLedCount_title": "Количество светодиодных индикаторов оборудования",
"edt_dev_general_hardwareLedCount_title_info": "Количество физических светодиодов, доступных для данного устройства",
"edt_dev_general_heading_title": "Общие настройки",
@ -509,12 +544,17 @@
"edt_dev_spec_FCsetConfig_title": "Установить конфигурацию fadecandy",
"edt_dev_spec_LBap102Mode_title": "Режим LightBerry APA102",
"edt_dev_spec_PBFiFo_title": "Pi-Blaster FiFo",
"edt_dev_spec_ada_mode_title": "Adalight - Стандартно",
"edt_dev_spec_awa_mode_title": "HyperSerial - Высокая скорость",
"edt_dev_spec_baudrate_title": "Скорость",
"edt_dev_spec_blackLightsTimeout_title": "Тайм-аут обнаружения сигнала на черном",
"edt_dev_spec_brightnessFactor_title": "Фактор яркости",
"edt_dev_spec_brightnessMax_title": "Максимальная яркость",
"edt_dev_spec_brightnessMin_title": "Минимальная яркость",
"edt_dev_spec_brightnessOverwrite_title": "Перезаписать яркость",
"edt_dev_spec_brightnessThreshold_title": "Минимальная яркость обнаружения сигнала",
"edt_dev_spec_brightness_title": "Яркость",
"edt_dev_spec_candyGamma_title": "'Candy' режим (двойная гамма коррекция)",
"edt_dev_spec_chanperfixture_title": "Каналов на прибор",
"edt_dev_spec_cid_title": "CID",
"edt_dev_spec_clientKey_title": "Клиентский ключ",
@ -530,6 +570,7 @@
"edt_dev_spec_dmaNumber_title": "Канал DMA",
"edt_dev_spec_gamma_title": "Гамма",
"edt_dev_spec_globalBrightnessControlMaxLevel_title": "Максимальный текущий уровень",
"edt_dev_spec_globalBrightnessControlThreshold_title": "Адаптивный контроль тока",
"edt_dev_spec_gpioBcm_title": "Вывод GPIO",
"edt_dev_spec_gpioMap_title": "Отображение GPIO",
"edt_dev_spec_gpioNumber_title": "Номер GPIO",
@ -553,6 +594,8 @@
"edt_dev_spec_networkDeviceName_title": "Сетевое имя устройства",
"edt_dev_spec_networkDevicePort_title": "Порт",
"edt_dev_spec_numberOfLeds_title": "Количество светодиодов",
"edt_dev_spec_onBlackTimeToPowerOff": "Время до отключения подсветки если сработала проверка уровня черного",
"edt_dev_spec_onBlackTimeToPowerOn": "Время до включения подсветки после восстановления сигнала",
"edt_dev_spec_orbIds_title": "ID сфер",
"edt_dev_spec_order_left_right_title": "2.",
"edt_dev_spec_order_top_down_title": "1.",
@ -560,19 +603,27 @@
"edt_dev_spec_panel_start_position": "Стартовая панель [0-макс панели]",
"edt_dev_spec_panelorganisation_title": "Последовательность нумерации панелей",
"edt_dev_spec_pid_title": "PID",
"edt_dev_spec_port_expl": "Сервисный порт [1-65535]",
"edt_dev_spec_port_title": "Порт",
"edt_dev_spec_printTimeStamp_title": "Добавить отметку времени",
"edt_dev_spec_pwmChannel_title": "Канал ШИМ (PWM)",
"edt_dev_spec_razer_device_title": "Устройство Razer Chroma",
"edt_dev_spec_restoreOriginalState_title": "Восстановить состояние огней",
"edt_dev_spec_restoreOriginalState_title_info": "Восстановить исходное состояние устройства, когда устройство отключено",
"edt_dev_spec_rgbw_calibration_blue": "Соотношение Синего/Белого каналов",
"edt_dev_spec_rgbw_calibration_enable": "Калибровка белого (только для RGBW)",
"edt_dev_spec_rgbw_calibration_green": "Соотношение Зеленого/Белого каналов",
"edt_dev_spec_rgbw_calibration_limit": "Ограничение белого",
"edt_dev_spec_rgbw_calibration_red": "Соотношение Красного/Белого каналов",
"edt_dev_spec_serial_title": "Серийный номер",
"edt_dev_spec_spipath_title": "Устройство SPI",
"edt_dev_spec_sslHSTimeoutMax_title": "Максимальное время ожидания подтверждения стримером",
"edt_dev_spec_sslHSTimeoutMin_title": "Минимальное время ожидания подтверждения стримером",
"edt_dev_spec_stream_protocol_title": "Протокол",
"edt_dev_spec_switchOffOnBlack_title": "Выключить черный",
"edt_dev_spec_switchOffOnbelowMinBrightness_title": "Отключение, ниже минимального",
"edt_dev_spec_syncOverwrite_title": "Выключить синхронизацию",
"edt_dev_spec_targetIpHost_expl": "Имя хоста (DNS/mDNS) или IP адрес (IPv4 or IPv6)",
"edt_dev_spec_targetIpHost_title": "Целевое имя хоста/IP-адрес",
"edt_dev_spec_targetIpHost_title_info": "Имя хоста или IP-адрес устройства",
"edt_dev_spec_targetIp_title": "Целевой IP-адрес",
@ -811,14 +862,17 @@
"general_country_us": "Соединённые Штаты Америки",
"general_disabled": "отключено",
"general_enabled": "включено",
"general_speech_ca": "Каталонский",
"general_speech_cs": "Чешский",
"general_speech_da": "Danish",
"general_speech_da": "Датский",
"general_speech_de": "Немецкий",
"general_speech_el": "Греческий",
"general_speech_en": "Английский",
"general_speech_es": "Испанский",
"general_speech_fr": "французский",
"general_speech_hu": "Hungarian",
"general_speech_hu": "Венгерский",
"general_speech_it": "Итальянский",
"general_speech_ja": "Японский",
"general_speech_nb": "норвежский",
"general_speech_nl": "Dutch",
"general_speech_pl": "Polish",

View File

@ -10,6 +10,9 @@
"InfoDialog_nowrite_foottext": "Webbkonfigurationen kommer att släppas igen automatiskt så snart problemet har åtgärdats!",
"InfoDialog_nowrite_text": "Hyperion har inte skrivbehörighet till den för närvarande inlästa konfigurationen. Korrigera filbehörigheterna för att fortsätta.",
"InfoDialog_nowrite_title": "Skrivåtkomstfel!",
"InfoDialog_systemRestart_title": "Starta om",
"InfoDialog_systemResume_title": "Återuppta",
"InfoDialog_systemSuspend_title": "Stäng av",
"about_3rd_party_licenses": "Tredjepartslicenser",
"about_3rd_party_licenses_error": "Vi hade problem med att ladda tredjepartslicenserna från internet. <br />Klicka här för att komma åt filen på GitHub.",
"about_build": "Bygge",
@ -55,7 +58,9 @@
"conf_leds_error_get_properties_title": "Enhetsegenskaper",
"conf_leds_error_hwled_gt_layout": "Antalet givna hårdvarulysdioder ($1) är större än antalet definierade i LED-layouten ($2), $3 {{plural:$3|LEDs kommer|LEDs kommer att vara}} förblir svarta.",
"conf_leds_error_hwled_gt_maxled": "Antalet LED-lampor för hårdvara ($1) är större än det maximala antalet lysdioder som stöds av enheten ($2). <br> Antalet LED-lampor för hårdvara är inställt på ($3).",
"conf_leds_error_hwled_gt_maxled_protocol": "Antalet LED-lampor för hårdvara ($1) är större än det maximala antalet lysdioder som stöds av streamingprotokollet ($2). <br> Strömningsprotokollet kommer att ändras till ($3).",
"conf_leds_error_hwled_lt_layout": "Antalet givna hårdvarulysdioder ($1) är mindre än antalet definierade i LED-layouten ($2). <br> I LED-layouten får inte fler lysdioder konfigureras än vad som är tillgängligt.",
"conf_leds_error_wled_segment_missing": "Det för närvarande konfigurerade segmentet ($1) är inte konfigurerat på din WLED-enhet.<br>Du kan behöva kontrollera WLED-konfigurationen!<br>Konfigurationssidan representerar den aktuella WLED-inställningen.",
"conf_leds_info_ws281x": "Hyperion måste köras med 'root'-privilegier för denna styrenhetstyp!",
"conf_leds_layout_advanced": "Utökade alternativ",
"conf_leds_layout_blacklist_num_title": "Antal lysdioder",
@ -439,8 +444,6 @@
"edt_conf_smooth_heading_title": "Utjämning",
"edt_conf_smooth_interpolationRate_expl": "Frekvens i vilken mellanliggande utjämningssteg beräknas.",
"edt_conf_smooth_interpolationRate_title": "Interpolationsfrekvens",
"edt_conf_smooth_outputRate_expl": "Utgångsfrekvensen till LED-enheten",
"edt_conf_smooth_outputRate_title": "Utfrekvens",
"edt_conf_smooth_time_ms_expl": "Hur länge ska utjämningen samla bilder?",
"edt_conf_smooth_time_ms_title": "Tid",
"edt_conf_smooth_type_expl": "Utjämningsalgoritm.",
@ -614,10 +617,17 @@
"edt_dev_spec_rgbw_calibration_green": "Grön/Vit kanalförhållande",
"edt_dev_spec_rgbw_calibration_limit": "Vit kanalgräns",
"edt_dev_spec_rgbw_calibration_red": "Röd/Vit kanalförhållande",
"edt_dev_spec_segmentId_title": "Segment-ID",
"edt_dev_spec_segmentsOverlapValidation_error": "Korrigera WLED-inställningen! Segmentet får inte överlappa med {{plural:$1| segment|segments}}: \"$2\".",
"edt_dev_spec_segmentsSwitchOffOthers_title": "Stäng av övriga segment",
"edt_dev_spec_segments_disabled_title": "Segmentströmning inaktiverad vid WLED.",
"edt_dev_spec_segments_title": "Streama till segment",
"edt_dev_spec_serial_title": "Serienummer",
"edt_dev_spec_spipath_title": "SPI Pfad",
"edt_dev_spec_sslHSTimeoutMax_title": "Streamer handskakning maximal timeout",
"edt_dev_spec_sslHSTimeoutMin_title": "Minsta timeout för Streamerhandslag",
"edt_dev_spec_stayOnAfterStreaming_title": "Förbli på efter streaming",
"edt_dev_spec_stayOnAfterStreaming_title_info": "Enheten förblir på efter streaming eller återställning.",
"edt_dev_spec_stream_protocol_title": "Strömningsprotokoll",
"edt_dev_spec_switchOffOnBlack_title": "Av på svart",
"edt_dev_spec_switchOffOnbelowMinBrightness_title": "Av vid lägsta",
@ -861,9 +871,11 @@
"general_country_us": "USA",
"general_disabled": "Inaktiverad",
"general_enabled": "Aktiverad",
"general_speech_ca": "Katalanska",
"general_speech_cs": "Tjeckiska",
"general_speech_da": "Danska",
"general_speech_de": "Tyska",
"general_speech_el": "Grekiska",
"general_speech_en": "Engelska",
"general_speech_es": "Spanska",
"general_speech_fr": "Franska",

View File

@ -24,8 +24,10 @@
<script src="js/lib/jquery/jquery-migrate-3.3.2.min.js"></script>
<!-- jQuery - Dev -->
<!script src="js/lib/jquery/dev/jquery-3.6.0.js"></script>
<!script src="js/lib/jquery/dev/jquery-migrate-3.3.2.js"></script>
<!--
<script src="js/lib/jquery/dev/jquery-3.6.0.js"></script>
<script src="js/lib/jquery/dev/jquery-migrate-3.3.2.js"></script>
-->
<!-- SemVer -->
<script src='js/lib/semver.js'></script>
@ -213,6 +215,39 @@
</li>
</ul>
</li>
<!-- /.dropdown -->
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-power-off fa-fw"></i> <i class="fa fa-caret-down"></i>
</a>
<ul class="dropdown-menu dropdown-alerts">
<li id="btn_systemSuspend">
<a>
<div>
<i class="fa fa-stop fa-fw"></i>
<span data-i18n="InfoDialog_systemSuspend_title"></span>
</div>
</a>
</li>
<li id="btn_systemResume">
<a>
<div>
<i class="fa fa-play fa-fw"></i>
<span data-i18n="InfoDialog_systemResume_title"></span>
</div>
</a>
</li>
<li class="divider"></li>
<li id="btn_systemRestart">
<a>
<div>
<i class="fa fa-refresh fa-fw"></i>
<span data-i18n="InfoDialog_systemRestart_title"></span>
</div>
</a>
</li>
</ul>
</li>
<!-- /.lock-ui -->
<li class="dropdown" id="btn_lock_ui" style="display:none">

View File

@ -58,7 +58,8 @@ $(document).ready(function () {
if (components[idx].name != "ALL") {
if ((components[idx].name === "FORWARDER" && window.currentHyperionInstance != 0) ||
(components[idx].name === "GRABBER" && !window.serverConfig.framegrabber.enable) ||
(components[idx].name === "V4L" && !window.serverConfig.grabberV4L2.enable))
(components[idx].name === "V4L" && !window.serverConfig.grabberV4L2.enable) ||
(components[idx].name === "AUDIO" && !window.serverConfig.grabberAudio.enable))
continue;
var comp_enabled = components[idx].enabled ? "checked" : "";
@ -104,8 +105,9 @@ $(document).ready(function () {
var screenGrabberAvailable = (window.serverInfo.grabbers.screen.available.length !== 0);
var videoGrabberAvailable = (window.serverInfo.grabbers.video.available.length !== 0);
const audioGrabberAvailable = (window.serverInfo.grabbers.audio.available.length !== 0);
if (screenGrabberAvailable || videoGrabberAvailable) {
if (screenGrabberAvailable || videoGrabberAvailable || audioGrabberAvailable) {
if (screenGrabberAvailable) {
var screenGrabber = window.serverConfig.framegrabber.enable ? $.i18n('general_enabled') : $.i18n('general_disabled');
@ -120,6 +122,13 @@ $(document).ready(function () {
} else {
$("#dash_video_grabber_row").hide();
}
if (audioGrabberAvailable) {
const audioGrabber = window.serverConfig.grabberAudio.enable ? $.i18n('general_enabled') : $.i18n('general_disabled');
$('#dash_audio_grabber').html(audioGrabber);
} else {
$("#dash_audio_grabber_row").hide();
}
} else {
$("#dash_capture_hw").hide();
}

View File

@ -4,9 +4,11 @@ $(document).ready(function () {
var screenGrabberAvailable = (window.serverInfo.grabbers.screen.available.length !== 0);
var videoGrabberAvailable = (window.serverInfo.grabbers.video.available.length !== 0);
const audioGrabberAvailable = (window.serverInfo.grabbers.audio.available.length !== 0);
var CEC_ENABLED = (jQuery.inArray("cec", window.serverInfo.services) !== -1);
var conf_editor_video = null;
var conf_editor_audio = null;
var conf_editor_screen = null;
var configuredDevice = "";
@ -38,6 +40,22 @@ $(document).ready(function () {
}
}
// Audio-Grabber
if (audioGrabberAvailable) {
$('#conf_cont').append(createRow('conf_cont_audio'));
$('#conf_cont_audio').append(createOptPanel('fa-volume', $.i18n("edt_conf_audio_heading_title"), 'editor_container_audiograbber', 'btn_submit_audiograbber', 'panel-system', 'audiograbberPanelId'));
if (storedAccess === 'expert') {
const conf_cont_audio_footer = document.getElementById("editor_container_audiograbber").nextElementSibling;
$(conf_cont_audio_footer).prepend('<button class="btn btn-primary mdi-24px" id="btn_audiograbber_set_effect_defaults" disabled data-toggle="tooltip" data-placement="top" title="' + $.i18n("edt_conf_audio_hardware_set_defaults_tip") + '">'
+ '<i class= "fa fa-fw fa-undo" ></i >' + $.i18n("edt_conf_audio_effect_set_defaults") + '</button > ');
}
if (window.showOptHelp) {
$('#conf_cont_audio').append(createHelpTable(window.schema.grabberAudio.properties, $.i18n("edt_conf_audio_heading_title"), "audiograbberHelpPanelId"));
}
}
JSONEditor.defaults.custom_validators.push(function (schema, value, path) {
var errors = [];
@ -309,7 +327,7 @@ $(document).ready(function () {
var saveOptions = conf_editor_screen.getValue();
var instCaptOptions = window.serverConfig.instCapture;
instCaptOptions.systemEnable = true;
instCaptOptions.systemEnable = saveOptions.framegrabber.enable;
saveOptions.instCapture = instCaptOptions;
requestWriteConfig(saveOptions);
@ -661,7 +679,7 @@ $(document).ready(function () {
var saveOptions = conf_editor_video.getValue();
var instCaptOptions = window.serverConfig.instCapture;
instCaptOptions.v4lEnable = true;
instCaptOptions.v4lEnable = saveOptions.grabberV4L2.enable;
saveOptions.instCapture = instCaptOptions;
requestWriteConfig(saveOptions);
@ -694,6 +712,121 @@ $(document).ready(function () {
});
}
// External Input Sources (Audio-Grabbers)
if (audioGrabberAvailable) {
conf_editor_audio = createJsonEditor('editor_container_audiograbber', {
grabberAudio: window.schema.grabberAudio
}, true, true);
conf_editor_audio.on('ready', () => {
// Trigger conf_editor_audio.watch - 'root.grabberAudio.enable'
const audioEnable = window.serverConfig.grabberAudio.enable;
conf_editor_audio.getEditor("root.grabberAudio.enable").setValue(audioEnable);
});
conf_editor_audio.on('change', () => {
// Validate the current editor's content
if (!conf_editor_audio.validate().length) {
const deviceSelected = conf_editor_audio.getEditor("root.grabberAudio.available_devices").getValue();
switch (deviceSelected) {
case "SELECT":
showInputOptionsForKey(conf_editor_audio, "grabberAudio", ["enable", "available_devices"], false);
break;
case "NONE":
showInputOptionsForKey(conf_editor_audio, "grabberAudio", ["enable", "available_devices"], false);
break;
default:
window.readOnlyMode ? $('#btn_submit_audiograbber').prop('disabled', true) : $('#btn_submit_audiograbber').prop('disabled', false);
break;
}
}
else {
$('#btn_submit_audiograbber').prop('disabled', true);
}
});
// Enable
conf_editor_audio.watch('root.grabberAudio.enable', () => {
const audioEnable = conf_editor_audio.getEditor("root.grabberAudio.enable").getValue();
if (audioEnable)
{
showInputOptionsForKey(conf_editor_audio, "grabberAudio", "enable", true);
$('#btn_audiograbber_set_effect_defaults').show();
if (window.showOptHelp) {
$('#audiograbberHelpPanelId').show();
}
discoverInputSources("audio");
}
else
{
$('#btn_submit_audiograbber').prop('disabled', false);
$('#btn_audiograbber_set_effect_defaults').hide();
showInputOptionsForKey(conf_editor_audio, "grabberAudio", "enable", false);
$('#audiograbberHelpPanelId').hide();
}
});
// Available Devices
conf_editor_audio.watch('root.grabberAudio.available_devices', () => {
const deviceSelected = conf_editor_audio.getEditor("root.grabberAudio.available_devices").getValue();
if (deviceSelected === "SELECT" || deviceSelected === "NONE" || deviceSelected === "") {
$('#btn_submit_audiograbber').prop('disabled', true);
showInputOptionsForKey(conf_editor_audio, "grabberAudio", ["enable", "available_devices"], false);
}
else
{
showInputOptionsForKey(conf_editor_audio, "grabberAudio", ["enable", "available_devices"], true);
const deviceProperties = getPropertiesOfDevice("audio", deviceSelected);
//Update hidden input element
conf_editor_audio.getEditor("root.grabberAudio.device").setValue(deviceProperties.device);
//Enfore configured JSON-editor dependencies
conf_editor_audio.notifyWatchers("root.grabberAudio.audioEffect");
//Enable set defaults button
$('#btn_audiograbber_set_effect_defaults').prop('disabled', false);
if (conf_editor_audio.validate().length && !window.readOnlyMode) {
$('#btn_submit_audiograbber').prop('disabled', false);
}
}
});
$('#btn_submit_audiograbber').off().on('click', function () {
const saveOptions = conf_editor_audio.getValue();
const instCaptOptions = window.serverConfig.instCapture;
instCaptOptions.audioEnable = saveOptions.grabberAudio.enable;
saveOptions.instCapture = instCaptOptions;
requestWriteConfig(saveOptions);
});
// ------------------------------------------------------------------
$('#btn_audiograbber_set_effect_defaults').off().on('click', function () {
const currentEffect = conf_editor_audio.getEditor("root.grabberAudio.audioEffect").getValue();
var effectEditor = conf_editor_audio.getEditor("root.grabberAudio." + currentEffect);
var defaultProperties = effectEditor.schema.defaultProperties;
var default_values = {};
for (const item of defaultProperties) {
default_values[item] = effectEditor.schema.properties[item].default;
}
effectEditor.setValue(default_values);
});
}
// ------------------------------------------------------------------
//////////////////////////////////////////////////
@ -706,6 +839,9 @@ $(document).ready(function () {
if (videoGrabberAvailable) {
createHint("intro", $.i18n('conf_grabber_v4l_intro'), "editor_container_videograbber");
}
if (audioGrabberAvailable) {
createHint("intro", $.i18n('conf_grabber_audio_intro'), "editor_container_audiograbber");
}
}
removeOverlay();
@ -773,6 +909,38 @@ $(document).ready(function () {
}
};
// build dynamic audio input enum
const updateAudioSourcesList = function (type, discoveryInfo) {
const enumVals = [];
const enumTitelVals = [];
let enumDefaultVal = "";
let addSelect = false;
if (jQuery.isEmptyObject(discoveryInfo)) {
enumVals.push("NONE");
enumTitelVals.push($.i18n('edt_conf_grabber_discovered_none'));
}
else {
for (const device of discoveryInfo) {
enumVals.push(device.device_name);
}
conf_editor_audio.getEditor('root.grabberAudio').enable();
configuredDevice = window.serverConfig.grabberAudio.available_devices;
if ($.inArray(configuredDevice, enumVals) != -1) {
enumDefaultVal = configuredDevice;
}
else {
addSelect = true;
}
}
if (enumVals.length > 0) {
updateJsonEditorSelection(conf_editor_audio, 'root.grabberAudio',
'available_devices', {}, enumVals, enumTitelVals, enumDefaultVal, addSelect, false);
}
};
async function discoverInputSources(type, params) {
const result = await requestInputSourcesDiscovery(type, params);
@ -782,7 +950,8 @@ $(document).ready(function () {
}
else {
discoveryResult = {
"video_sources": []
"video_sources": [],
"audio_soruces": []
};
}
@ -799,6 +968,12 @@ $(document).ready(function () {
updateVideoSourcesList(type, discoveredInputSources.video);
}
break;
case "audio":
discoveredInputSources.audio = discoveryResult.audio_sources;
if (audioGrabberAvailable) {
updateAudioSourcesList(type, discoveredInputSources.audio);
}
break;
}
}

View File

@ -218,7 +218,9 @@ $(document).ready(function () {
loadContent(undefined,true);
//Hide capture menu entries, if no grabbers are available
if ((window.serverInfo.grabbers.screen.available.length === 0) && (window.serverInfo.grabbers.video.available.length === 0)) {
if ((window.serverInfo.grabbers.screen.available.length === 0) &&
(window.serverInfo.grabbers.video.available.length === 0) &&
(window.serverInfo.grabbers.audio.available.length === 0)) {
$("#MenuItemGrabber").attr('style', 'display:none')
if ((jQuery.inArray("boblight", window.serverInfo.services) === -1)) {
$("#MenuItemInstCapture").attr('style', 'display:none')
@ -278,8 +280,9 @@ $(document).ready(function () {
if (getStorage('lastSelectedInstance'))
removeStorage('lastSelectedInstance')
currentHyperionInstance = 0;
currentHyperionInstanceName = getInstanceNameByIndex(0);
window.currentHyperionInstance = 0;
window.currentHyperionInstanceName = getInstanceNameByIndex(0);
requestServerConfig();
setTimeout(requestServerInfo, 100)
setTimeout(requestTokenInfo, 200)
@ -293,7 +296,7 @@ $(document).ready(function () {
$('#btn_hypinstanceswitch').toggle(false)
// update listing for button
updateUiOnInstance(currentHyperionInstance);
updateUiOnInstance(window.currentHyperionInstance);
updateHyperionInstanceListing();
});

View File

@ -3,6 +3,7 @@ $(document).ready(function () {
var screenGrabberAvailable = (window.serverInfo.grabbers.screen.available.length !== 0);
var videoGrabberAvailable = (window.serverInfo.grabbers.video.available.length !== 0);
const audioGrabberAvailable = (window.serverInfo.grabbers.audio.available.length !== 0);
var BOBLIGHT_ENABLED = (jQuery.inArray("boblight", window.serverInfo.services) !== -1);
@ -15,7 +16,7 @@ $(document).ready(function () {
// Instance Capture
if (window.showOptHelp) {
if (screenGrabberAvailable || videoGrabberAvailable) {
if (screenGrabberAvailable || videoGrabberAvailable || audioGrabberAvailable) {
$('#conf_cont').append(createRow('conf_cont_instCapt'));
$('#conf_cont_instCapt').append(createOptPanel('fa-camera', $.i18n("edt_conf_instCapture_heading_title"), 'editor_container_instCapt', 'btn_submit_instCapt', ''));
$('#conf_cont_instCapt').append(createHelpTable(window.schema.instCapture.properties, $.i18n("edt_conf_instCapture_heading_title")));
@ -29,7 +30,7 @@ $(document).ready(function () {
}
else {
$('#conf_cont').addClass('row');
if (screenGrabberAvailable || videoGrabberAvailable) {
if (screenGrabberAvailable || videoGrabberAvailable || audioGrabberAvailable) {
$('#conf_cont').append(createOptPanel('fa-camera', $.i18n("edt_conf_instCapture_heading_title"), 'editor_container_instCapt', 'btn_submit_instCapt', ''));
}
if (BOBLIGHT_ENABLED) {
@ -37,7 +38,7 @@ $(document).ready(function () {
}
}
if (screenGrabberAvailable || videoGrabberAvailable) {
if (screenGrabberAvailable || videoGrabberAvailable || audioGrabberAvailable) {
// Instance Capture
conf_editor_instCapt = createJsonEditor('editor_container_instCapt', {
@ -81,12 +82,29 @@ $(document).ready(function () {
showInputOptionForItem(conf_editor_instCapt, "instCapture", "v4lPriority", false);
}
if (audioGrabberAvailable) {
if (!window.serverConfig.grabberAudio.enable) {
conf_editor_instCapt.getEditor("root.instCapture.audioEnable").setValue(false);
conf_editor_instCapt.getEditor("root.instCapture.audioEnable").disable();
}
else {
conf_editor_instCapt.getEditor("root.instCapture.audioEnable").setValue(window.serverConfig.instCapture.audioEnable);
}
} else {
showInputOptionForItem(conf_editor_instCapt, "instCapture", "audioGrabberDevice", false);
showInputOptionForItem(conf_editor_instCapt, "instCapture", "audioEnable", false);
showInputOptionForItem(conf_editor_instCapt, "instCapture", "audioPriority", false);
}
});
conf_editor_instCapt.on('change', function () {
if (!conf_editor_instCapt.validate().length) {
if (!window.serverConfig.framegrabber.enable && !window.serverConfig.grabberV4L2.enable) {
if (!window.serverConfig.framegrabber.enable &&
!window.serverConfig.grabberV4L2.enable &&
!window.serverConfig.grabberAudio.enable) {
$('#btn_submit_instCapt').prop('disabled', true);
} else {
window.readOnlyMode ? $('#btn_submit_instCapt').prop('disabled', true) : $('#btn_submit_instCapt').prop('disabled', false);
@ -130,6 +148,23 @@ $(document).ready(function () {
}
});
conf_editor_instCapt.watch('root.instCapture.audioEnable', () => {
const audioEnable = conf_editor_instCapt.getEditor("root.instCapture.audioEnable").getValue();
if (audioEnable) {
conf_editor_instCapt.getEditor("root.instCapture.audioGrabberDevice").setValue(window.serverConfig.grabberAudio.available_devices);
conf_editor_instCapt.getEditor("root.instCapture.audioGrabberDevice").disable();
showInputOptions("instCapture", ["audioGrabberDevice"], true);
showInputOptions("instCapture", ["audioPriority"], true);
}
else {
if (!window.serverConfig.grabberAudio.enable) {
conf_editor_instCapt.getEditor("root.instCapture.audioEnable").disable();
}
showInputOptions("instCapture", ["audioGrabberDevice"], false);
showInputOptions("instCapture", ["audioPriority"], false);
}
});
$('#btn_submit_instCapt').off().on('click', function () {
requestWriteConfig(conf_editor_instCapt.getValue());
});

View File

@ -1002,15 +1002,25 @@ $(document).ready(function () {
addJsonEditorHostValidation();
JSONEditor.defaults.custom_validators.push(function (schema, value, path) {
var errors = [];
if (path === "root.specificOptions.segments.segmentList") {
var overlapSegNames = validateWledSegmentConfig(value);
if (overlapSegNames.length > 0) {
errors.push({
path: "root.specificOptions.segments",
message: $.i18n('edt_dev_spec_segmentsOverlapValidation_error', overlapSegNames.length, overlapSegNames.join(', '))
});
}
}
return errors;
});
$("#leddevices").off().on("change", function () {
var generalOptions = window.serverSchema.properties.device;
var ledType = $(this).val();
// philipshueentertainment backward fix
if (ledType == "philipshueentertainment")
ledType = "philipshue";
var specificOptions = window.serverSchema.properties.alldevices[ledType];
conf_editor = createJsonEditor('editor_container_leddevice', {
@ -1045,13 +1055,10 @@ $(document).ready(function () {
$('#btn_led_device_wiz').off();
if (ledType == "philipshue") {
$('#root_specificOptions_useEntertainmentAPI').on("change", function () {
var ledWizardType = (this.checked) ? "philipshueentertainment" : ledType;
var data = { type: ledWizardType };
var hue_title = (this.checked) ? 'wiz_hue_e_title' : 'wiz_hue_title';
changeWizard(data, hue_title, startWizardPhilipsHue);
});
$("#root_specificOptions_useEntertainmentAPI").trigger("change");
var ledWizardType = ledType;
var data = { type: ledWizardType };
var hue_title = 'wiz_hue_title';
changeWizard(data, hue_title, startWizardPhilipsHue);
}
else if (ledType == "atmoorb") {
var ledWizardType = (this.checked) ? "atmoorb" : ledType;
@ -1080,8 +1087,8 @@ $(document).ready(function () {
$('#btn_test_controller').hide();
switch (ledType) {
case "cololight":
case "wled":
case "cololight":
case "nanoleaf":
showAllDeviceInputOptions("hostList", false);
case "apa102":
@ -1107,7 +1114,22 @@ $(document).ready(function () {
if (storedAccess === 'expert') {
filter.discoverAll = true;
}
discover_device(ledType, filter);
$('#btn_submit_controller').prop('disabled', true);
discover_device(ledType, filter)
.then(discoveryResult => {
updateOutputSelectList(ledType, discoveryResult);
})
.then(discoveryResult => {
if (ledType === "wled") {
updateElementsWled(ledType);
}
})
.catch(error => {
showNotification('danger', "Device discovery for " + ledType + " failed with error:" + error);
});
hwLedCountDefault = 1;
colorOrderDefault = "rgb";
break;
@ -1211,8 +1233,8 @@ $(document).ready(function () {
}
break;
case "cololight":
case "wled":
case "cololight":
var hostList = conf_editor.getEditor("root.specificOptions.hostList").getValue();
if (hostList !== "SELECT") {
var host = conf_editor.getEditor("root.specificOptions.host").getValue();
@ -1339,7 +1361,9 @@ $(document).ready(function () {
break;
case "wled":
params = { host: host, filter: "info" };
//Ensure that elements are defaulted for new host
updateElementsWled(ledType, host);
params = { host: host };
getProperties_device(ledType, host, params);
break;
@ -1452,6 +1476,10 @@ $(document).ready(function () {
}
conf_editor.getEditor("root.specificOptions.rateList").setValue(rate);
break;
case "wled":
var hardwareLedCount = conf_editor.getEditor("root.generalOptions.hardwareLedCount").getValue();
validateWledLedCount(hardwareLedCount);
break;
default:
}
});
@ -1547,12 +1575,54 @@ $(document).ready(function () {
}
});
//WLED
conf_editor.watch('root.specificOptions.segments.segmentList', () => {
//Update hidden streamSegmentId element
var selectedSegment = conf_editor.getEditor("root.specificOptions.segments.segmentList").getValue();
var streamSegmentId = parseInt(selectedSegment);
conf_editor.getEditor("root.specificOptions.segments.streamSegmentId").setValue(streamSegmentId);
if (devicesProperties[ledType]) {
var host = conf_editor.getEditor("root.specificOptions.host").getValue();
var ledDeviceProperties = devicesProperties[ledType][host];
if (ledDeviceProperties) {
var hardwareLedCount = 1;
if (streamSegmentId > -1) {
// Set hardware LED count to segment length
if (ledDeviceProperties.state) {
var segments = ledDeviceProperties.state.seg;
var segmentConfig = segments.filter(seg => seg.id == streamSegmentId)[0];
hardwareLedCount = segmentConfig.len;
}
} else {
//"Use main segment only" is disabled, i.e. stream to all LEDs
if (ledDeviceProperties.info) {
hardwareLedCount = ledDeviceProperties.info.leds.count;
}
}
conf_editor.getEditor("root.generalOptions.hardwareLedCount").setValue(hardwareLedCount);
}
}
});
//Handle Hardware Led Count constraint list
conf_editor.watch('root.generalOptions.hardwareLedCountList', () => {
var hwLedCountSelected = conf_editor.getEditor("root.generalOptions.hardwareLedCountList").getValue();
conf_editor.getEditor("root.generalOptions.hardwareLedCount").setValue(Number(hwLedCountSelected));
});
//Handle Hardware Led update and constraints
conf_editor.watch('root.generalOptions.hardwareLedCount', () => {
var hardwareLedCount = conf_editor.getEditor("root.generalOptions.hardwareLedCount").getValue();
switch (ledType) {
case "wled":
validateWledLedCount(hardwareLedCount);
break;
default:
}
});
});
//philipshueentertainment backward fix
@ -1798,8 +1868,8 @@ function saveLedConfig(genDefLayout = false) {
location.reload();
}
// build dynamic enum
var updateSelectList = function (ledType, discoveryInfo) {
// build dynamic enum for hosts or output paths
var updateOutputSelectList = function (ledType, discoveryInfo) {
// Only update, if ledType is equal of selected controller type and discovery info exists
if (ledType !== $("#leddevices").val() || !discoveryInfo.devices) {
return;
@ -1810,7 +1880,7 @@ var updateSelectList = function (ledType, discoveryInfo) {
var key;
var enumVals = [];
var enumTitelVals = [];
var enumTitleVals = [];
var enumDefaultVal = "";
var addSelect = false;
var addCustom = false;
@ -1835,7 +1905,7 @@ var updateSelectList = function (ledType, discoveryInfo) {
if (discoveryInfo.devices.length === 0) {
enumVals.push("NONE");
enumTitelVals.push($.i18n('edt_dev_spec_devices_discovered_none'));
enumTitleVals.push($.i18n('edt_dev_spec_devices_discovered_none'));
}
else {
var name;
@ -1876,7 +1946,7 @@ var updateSelectList = function (ledType, discoveryInfo) {
}
enumVals.push(host);
enumTitelVals.push(name);
enumTitleVals.push(name);
}
//Always allow to add custom configuration
@ -1904,7 +1974,7 @@ var updateSelectList = function (ledType, discoveryInfo) {
if (discoveryInfo.devices.length == 0) {
enumVals.push("NONE");
enumTitelVals.push($.i18n('edt_dev_spec_devices_discovered_none'));
enumTitleVals.push($.i18n('edt_dev_spec_devices_discovered_none'));
$('#btn_submit_controller').prop('disabled', true);
showAllDeviceInputOptions(key, false);
}
@ -1922,7 +1992,7 @@ var updateSelectList = function (ledType, discoveryInfo) {
} else {
enumVals.push(device.portName);
}
enumTitelVals.push(device.portName + " (" + device.vendorIdentifier + "|" + device.productIdentifier + ") - " + device.manufacturer);
enumTitleVals.push(device.portName + " (" + device.vendorIdentifier + "|" + device.productIdentifier + ") - " + device.manufacturer);
}
// Select configured device
@ -1951,7 +2021,7 @@ var updateSelectList = function (ledType, discoveryInfo) {
if (discoveryInfo.devices.length == 0) {
enumVals.push("NONE");
enumTitelVals.push($.i18n('edt_dev_spec_devices_discovered_none'));
enumTitleVals.push($.i18n('edt_dev_spec_devices_discovered_none'));
$('#btn_submit_controller').prop('disabled', true);
showAllDeviceInputOptions(key, false);
}
@ -1970,7 +2040,7 @@ var updateSelectList = function (ledType, discoveryInfo) {
case "piblaster":
for (const device of discoveryInfo.devices) {
enumVals.push(device.systemLocation);
enumTitelVals.push(device.deviceName + " (" + device.systemLocation + ")");
enumTitleVals.push(device.deviceName + " (" + device.systemLocation + ")");
}
// Select configured device
@ -1991,9 +2061,9 @@ var updateSelectList = function (ledType, discoveryInfo) {
case "devRPiPWM":
key = ledType;
if (discoveryInfo.devices.length == 0) {
if (!discoveryInfo.isUserAdmin) {
enumVals.push("NONE");
enumTitelVals.push($.i18n('edt_dev_spec_devices_discovered_none'));
enumTitleVals.push($.i18n('edt_dev_spec_devices_discovered_none'));
$('#btn_submit_controller').prop('disabled', true);
showAllDeviceInputOptions(key, false);
@ -2004,18 +2074,19 @@ var updateSelectList = function (ledType, discoveryInfo) {
}
if (enumVals.length > 0) {
updateJsonEditorSelection(conf_editor, 'root.specificOptions', key, addSchemaElements, enumVals, enumTitelVals, enumDefaultVal, addSelect, addCustom);
updateJsonEditorSelection(conf_editor, 'root.specificOptions', key, addSchemaElements, enumVals, enumTitleVals, enumDefaultVal, addSelect, addCustom);
}
};
async function discover_device(ledType, params) {
$('#btn_submit_controller').prop('disabled', true);
const result = await requestLedDeviceDiscovery(ledType, params);
var discoveryResult;
if (result && !result.error) {
var discoveryResult = {};
if (result) {
if (result.error) {
throw (result.error);
}
discoveryResult = result.info;
}
else {
@ -2024,8 +2095,7 @@ async function discover_device(ledType, params) {
ledDevicetype: ledType
}
}
updateSelectList(ledType, discoveryResult);
return discoveryResult;
}
async function getProperties_device(ledType, key, params) {
@ -2089,23 +2159,7 @@ function updateElements(ledType, key) {
conf_editor.getEditor("root.generalOptions.hardwareLedCount").setValue(hardwareLedCount);
break;
case "wled":
var ledProperties = devicesProperties[ledType][key];
if (ledProperties && ledProperties.leds) {
hardwareLedCount = ledProperties.leds.count;
if (ledProperties.maxLedCount) {
var maxLedCount = ledProperties.maxLedCount;
if (hardwareLedCount > maxLedCount) {
showInfoDialog('warning', $.i18n("conf_leds_config_warning"), $.i18n('conf_leds_error_hwled_gt_maxled', hardwareLedCount, maxLedCount, maxLedCount));
hardwareLedCount = maxLedCount;
conf_editor.getEditor("root.specificOptions.streamProtocol").setValue("RAW");
//Workaround, as value seems to getting updated property when a 'getEditor("root.specificOptions").getValue()' is done during save
var editor = conf_editor.getEditor("root.specificOptions");
editor.value["streamProtocol"] = "RAW";
}
}
}
conf_editor.getEditor("root.generalOptions.hardwareLedCount").setValue(hardwareLedCount);
updateElementsWled(ledType, key);
break;
case "nanoleaf":
@ -2190,3 +2244,167 @@ function disableAutoResolvedGeneralOptions() {
conf_editor.getEditor("root.generalOptions.colorOrder").disable();
}
function validateWledSegmentConfig(streamSegmentId) {
var overlapSegNames = [];
if (streamSegmentId > -1) {
if (!jQuery.isEmptyObject(devicesProperties)) {
var host = conf_editor.getEditor("root.specificOptions.host").getValue();
var ledProperties = devicesProperties['wled'][host];
if (ledProperties && ledProperties.state) {
var segments = ledProperties.state.seg;
var segmentConfig = segments.filter(seg => seg.id == streamSegmentId)[0];
var overlappingSegments = segments.filter((seg) => {
if (seg.id != streamSegmentId) {
if ((segmentConfig.start >= seg.stop) || (segmentConfig.start < seg.start && segmentConfig.stop <= seg.start)) {
return false;
}
return true;
}
});
if (overlappingSegments.length > 0) {
var overlapSegNames = [];
for (const segment of overlappingSegments) {
if (segment.n) {
overlapSegNames.push(segment.n);
} else {
overlapSegNames.push("Segment " + segment.id);
}
}
}
}
}
}
return overlapSegNames;
}
function validateWledLedCount(hardwareLedCount) {
if (!jQuery.isEmptyObject(devicesProperties)) {
var host = conf_editor.getEditor("root.specificOptions.host").getValue();
var ledDeviceProperties = devicesProperties["wled"][host];
if (ledDeviceProperties) {
var streamProtocol = conf_editor.getEditor("root.specificOptions.streamProtocol").getValue();
if (streamProtocol === "RAW") {
var maxLedCount = 490;
if (ledDeviceProperties.maxLedCount) {
//WLED not DDP ready
maxLedCount = ledDeviceProperties.maxLedCount;
if (hardwareLedCount > maxLedCount) {
showInfoDialog('warning', $.i18n("conf_leds_config_warning"), $.i18n('conf_leds_error_hwled_gt_maxled', hardwareLedCount, maxLedCount, maxLedCount));
hardwareLedCount = maxLedCount;
conf_editor.getEditor("root.generalOptions.hardwareLedCount").setValue(hardwareLedCount);
conf_editor.getEditor("root.specificOptions.streamProtocol").setValue("RAW");
}
} else {
//WLED is DDP ready
if (hardwareLedCount > maxLedCount) {
var newStreamingProtocol = "DDP";
showInfoDialog('warning', $.i18n("conf_leds_config_warning"), $.i18n('conf_leds_error_hwled_gt_maxled_protocol', hardwareLedCount, maxLedCount, newStreamingProtocol));
conf_editor.getEditor("root.specificOptions.streamProtocol").setValue(newStreamingProtocol);
}
}
}
}
}
}
function updateElementsWled(ledType, key) {
// Get configured device's details
var configuredDeviceType = window.serverConfig.device.type;
var configuredHost = window.serverConfig.device.host;
var host = conf_editor.getEditor("root.specificOptions.host").getValue();
//New segment selection list values
var enumSegSelectVals = [];
var enumSegSelectTitleVals = [];
var enumSegSelectDefaultVal = "";
var defaultSegmentId = "-1";
if (devicesProperties[ledType] && devicesProperties[ledType][key]) {
var ledDeviceProperties = devicesProperties[ledType][key];
if (!jQuery.isEmptyObject(ledDeviceProperties)) {
if (ledDeviceProperties.info) {
if (!ledDeviceProperties.info.hasOwnProperty("liveseg") || ledDeviceProperties.info.liveseg < 0) {
// "Use main segment only" is disabled
enumSegSelectVals.push(defaultSegmentId);
enumSegSelectTitleVals.push($.i18n('edt_dev_spec_segments_disabled_title'));
enumSegSelectDefaultVal = defaultSegmentId;
} else {
if (ledDeviceProperties.state) {
//Prepare new segment selection list
var segments = ledDeviceProperties.state.seg;
for (const segment of segments) {
enumSegSelectVals.push(segment.id.toString());
if (segment.n) {
enumSegSelectTitleVals.push(segment.n);
} else {
enumSegSelectTitleVals.push("Segment " + segment.id);
}
}
var currentSegmentId = conf_editor.getEditor("root.specificOptions.segments.streamSegmentId").getValue().toString();
enumSegSelectDefaultVal = currentSegmentId;
}
}
// Check if currently configured segment is available at WLED
var configuredDeviceType = window.serverConfig.device.type;
var configuredHost = window.serverConfig.device.host;
var host = conf_editor.getEditor("root.specificOptions.host").getValue();
if (configuredDeviceType == ledType && configuredHost == host) {
var configuredStreamSegmentId = window.serverConfig.device.segments.streamSegmentId.toString();
var segmentIdFound = enumSegSelectVals.filter(segId => segId == configuredStreamSegmentId).length;
if (!segmentIdFound) {
showInfoDialog('warning', $.i18n("conf_leds_config_warning"), $.i18n('conf_leds_error_wled_segment_missing', configuredStreamSegmentId));
}
}
}
}
} else {
//If failed to get properties
var hardwareLedCount;
var segmentConfig = false;
if (configuredDeviceType == ledType && configuredHost == host) {
// Populate elements from existing configuration
if (window.serverConfig.device.segments) {
segmentConfig = true;
}
hardwareLedCount = window.serverConfig.device.hardwareLedCount;
} else {
// Populate elements with default values
hardwareLedCount = 1;
}
if (segmentConfig && segmentConfig.streamSegmentId > defaultSegmentId) {
var configuredstreamSegmentId = window.serverConfig.device.segments.streamSegmentId.toString();
enumSegSelectVals = [configuredstreamSegmentId];
enumSegSelectTitleVals = ["Segment " + configuredstreamSegmentId];
enumSegSelectDefaultVal = configuredstreamSegmentId;
} else {
enumSegSelectVals.push(defaultSegmentId);
enumSegSelectTitleVals.push($.i18n('edt_dev_spec_segments_disabled_title'));
enumSegSelectDefaultVal = defaultSegmentId;
}
conf_editor.getEditor("root.generalOptions.hardwareLedCount").setValue(hardwareLedCount);
}
updateJsonEditorSelection(conf_editor, 'root.specificOptions.segments',
'segmentList', {}, enumSegSelectVals, enumSegSelectTitleVals, enumSegSelectDefaultVal, false, false);
//Show additional configuration options, if more than one segment is available
var showAdditionalOptions = false;
if (enumSegSelectVals.length > 1) {
showAdditionalOptions = true;
}
showInputOptionForItem(conf_editor, "root.specificOptions.segments", "switchOffOtherSegments", showAdditionalOptions);
}

View File

@ -35,7 +35,8 @@ $(document).ready(function () {
function infoSummary() {
var info = "";
info += 'Hyperion System Summary Report (' + window.serverConfig.general.name + '), Reported instance: ' + window.currentHyperionInstanceName + '\n';
info += 'Hyperion System Summary Report (' + window.serverConfig.general.name + ')\n';
info += 'Reported instance: [' + window.currentHyperionInstance + '] - ' + window.currentHyperionInstanceName + '\n';
info += "\n< ----- System information -------------------- >\n";
info += getSystemInfo() + '\n';
@ -43,22 +44,36 @@ $(document).ready(function () {
info += "\n< ----- Configured Instances ------------------ >\n";
var instances = window.serverInfo.instance;
for (var i = 0; i < instances.length; i++) {
info += instances[i].instance + ': ' + instances[i].friendly_name + ' Running: ' + instances[i].running + '\n';
info += instances[i].instance + ': ' + instances[i].friendly_name + ', Running: ' + instances[i].running + '\n';
}
info += "\n< ----- This instance's priorities ------------ >\n";
var prios = window.serverInfo.priorities;
for (var i = 0; i < prios.length; i++) {
info += prios[i].priority + ': ';
if (prios[i].visible) {
info += ' VISIBLE!';
if (prios.length > 0) {
for (var i = 0; i < prios.length; i++) {
var prio = prios[i].priority.toString().padStart(3, '0');
info += prio + ': ';
if (prios[i].visible) {
info += ' VISIBLE -';
}
else {
info += ' INVISIBLE -';
}
info += ' (' + prios[i].componentId + ')';
if (prios[i].owner) {
info += ' (Owner: ' + prios[i].owner + ')';
}
info += '\n';
}
else {
info += ' ';
}
info += ' (' + prios[i].componentId + ') Owner: ' + prios[i].owner + '\n';
} else {
info += 'The current priority list is empty!\n';
}
info += 'priorities_autoselect: ' + window.serverInfo.priorities_autoselect + '\n';
info += 'Autoselect: ' + window.serverInfo.priorities_autoselect + '\n';
info += "\n< ----- This instance components' status ------->\n";
var comps = window.serverInfo.components;
@ -67,7 +82,7 @@ $(document).ready(function () {
}
info += "\n< ----- This instance's configuration --------- >\n";
info += JSON.stringify(window.serverConfig) + '\n';
info += JSON.stringify(window.serverConfig, null, 2) + '\n';
info += "\n< ----- Current Log --------------------------- >\n";
var logMsgs = document.getElementById("logmessages").textContent;
@ -193,18 +208,19 @@ $(document).ready(function () {
});
// toggle fullscreen button in log output
$(".fullscreen-btn").mousedown(function(e) {
$(".fullscreen-btn").mousedown(function (e) {
e.preventDefault();
});
$(".fullscreen-btn").click(function(e) {
$(".fullscreen-btn").click(function (e) {
e.preventDefault();
$(this).children('i')
.toggleClass('fa-expand')
.toggleClass('fa-compress');
$('#conf_cont').toggle();
$('#logmessages').css('max-height', $('#logmessages').css('max-height') !== 'none' ? 'none' : '400px' );
$('#logmessages').css('max-height', $('#logmessages').css('max-height') !== 'none' ? 'none' : '400px');
});
removeOverlay();
});

View File

@ -97,7 +97,7 @@ $(document).ready(function () {
}
function updateInputSelect() {
$('.sstbody').html("");
$('.sstbody').empty();
var prios = window.serverInfo.priorities;
var clearAll = false;
@ -154,6 +154,9 @@ $(document).ready(function () {
case "V4L":
owner = $.i18n('general_comp_V4L') + ': (' + owner + ')';
break;
case "AUDIO":
owner = $.i18n('general_comp_AUDIO') + ': (' + owner + ')';
break;
case "BOBLIGHTSERVER":
owner = $.i18n('general_comp_BOBLIGHTSERVER');
break;
@ -219,7 +222,8 @@ $(document).ready(function () {
for (const comp of components) {
if (comp.name === "ALL" || (comp.name === "FORWARDER" && window.currentHyperionInstance != 0) ||
(comp.name === "GRABBER" && !window.serverConfig.framegrabber.enable) ||
(comp.name === "V4L" && !window.serverConfig.grabberV4L2.enable))
(comp.name === "V4L" && !window.serverConfig.grabberV4L2.enable) ||
(comp.name === "AUDIO" && !window.serverConfig.grabberAudio.enable))
continue;
const enable_style = (comp.enabled ? "checked" : "");

View File

@ -318,6 +318,21 @@ function requestSysInfo()
sendToHyperion("sysinfo");
}
function requestSystemSuspend()
{
sendToHyperion("system","suspend");
}
function requestSystemResume()
{
sendToHyperion("system","resume");
}
function requestSystemRestart()
{
sendToHyperion("system","restart");
}
function requestServerConfigSchema()
{
sendToHyperion("config","getschema");

View File

@ -75,6 +75,21 @@ $(document).ready(function () {
changePassword();
});
//Suspend Hyperion
$('#btn_systemSuspend').off().on('click', function () {
requestSystemSuspend();
});
//Resume Hyperion
$('#btn_systemResume').off().on('click', function () {
requestSystemResume();
});
//Restart Hyperion
$('#btn_systemRestart').off().on('click', function () {
requestSystemRestart();
});
//Lock Ui
$('#btn_lock_ui').off().on('click', function () {
removeStorage('loginToken');

View File

@ -171,6 +171,10 @@ function initLanguageSelection() {
}
function updateUiOnInstance(inst) {
window.currentHyperionInstance = inst;
window.currentHyperionInstanceName = getInstanceNameByIndex(inst);
$("#active_instance_friendly_name").text(getInstanceNameByIndex(inst));
if (window.serverInfo.instance.filter(entry => entry.running).length > 1) {
$('#btn_hypinstanceswitch').toggle(true);
@ -316,7 +320,7 @@ function showInfoDialog(type, header, message) {
$(document).on('click', '[data-dismiss-modal]', function () {
var target = $(this).attr('data-dismiss-modal');
$(target).modal('hide'); // lgtm [js/xss-through-dom]
$.find(target).modal('hide');
});
}
@ -407,6 +411,32 @@ function isJsonString(str) {
return "";
}
const getObjectProperty = (obj, path) => path.split(".").reduce((o, key) => o && typeof o[key] !== 'undefined' ? o[key] : undefined, obj);
const setObjectProperty = (object, path, value) => {
const parts = path.split('.');
const limit = parts.length - 1;
for (let i = 0; i < limit; ++i) {
const key = parts[i];
if (key === "__proto__" || key === "constructor") continue;
object = object[key] ?? (object[key] = {});
}
const key = parts[limit];
object[key] = value;
};
function getLongPropertiesPath(path) {
if (path) {
var path = path.replace('root.', '');
const parts = path.split('.');
parts.forEach(function (part, index) {
this[index] += ".properties";
}, parts);
path = parts.join('.') + '.';
}
return path;
}
function createJsonEditor(container, schema, setconfig, usePanel, arrayre) {
$('#' + container).off();
$('#' + container).html("");
@ -527,7 +557,8 @@ function updateJsonEditorSelection(rootEditor, path, key, addElements, newEnumVa
editor.original_schema.properties[key] = orginalProperties;
editor.schema.properties[key] = newSchema[key];
rootEditor.validator.schema.properties[editor.key].properties[key] = newSchema[key];
//Update schema properties for validator
setObjectProperty(rootEditor.validator.schema.properties, getLongPropertiesPath(path) + key, newSchema[key]);
editor.removeObjectProperty(key);
delete editor.cached_editors[key];
@ -596,7 +627,8 @@ function updateJsonEditorMultiSelection(rootEditor, path, key, addElements, newE
editor.original_schema.properties[key] = orginalProperties;
editor.schema.properties[key] = newSchema[key];
rootEditor.validator.schema.properties[editor.key].properties[key] = newSchema[key];
//Update schema properties for validator
setObjectProperty(rootEditor.validator.schema.properties, getLongPropertiesPath(path) + key, newSchema[key]);
editor.removeObjectProperty(key);
delete editor.cached_editors[key];
@ -644,7 +676,8 @@ function updateJsonEditorRange(rootEditor, path, key, minimum, maximum, defaultV
editor.original_schema.properties[key] = orginalProperties;
editor.schema.properties[key] = newSchema[key];
rootEditor.validator.schema.properties[editor.key].properties[key] = newSchema[key];
//Update schema properties for validator
setObjectProperty(rootEditor.validator.schema.properties, getLongPropertiesPath(path) + key, newSchema[key]);
editor.removeObjectProperty(key);
delete editor.cached_editors[key];
@ -1187,6 +1220,7 @@ function getSystemInfo() {
//info += '- Log lvl: ' + window.serverConfig.logger.level + '\n';
info += '- Avail Screen Cap.: ' + window.serverInfo.grabbers.screen.available + '\n';
info += '- Avail Video Cap.: ' + window.serverInfo.grabbers.video.available + '\n';
info += '- Avail Audio Cap.: ' + window.serverInfo.grabbers.audio.available + '\n';
info += '- Avail Services: ' + window.serverInfo.services + '\n';
info += '- Config path: ' + shy.rootPath + '\n';
info += '- Database: ' + (shy.readOnlyMode ? "ready-only" : "read/write") + '\n';
@ -1246,15 +1280,26 @@ function isAccessLevelCompliant(accessLevel) {
}
function showInputOptions(path, elements, state) {
if (!path.startsWith("root.")) {
path = ["root", path].join('.');
}
for (var i = 0; i < elements.length; i++) {
$('[data-schemapath="root.' + path + '.' + elements[i] + '"]').toggle(state);
$('[data-schemapath="' + path + '.' + elements[i] + '"]').toggle(state);
}
}
function showInputOptionForItem(editor, path, item, state) {
var accessLevel = editor.schema.properties[path].properties[item].access;
//Get access level for full path and item
var accessLevel = getObjectProperty(editor.schema.properties, getLongPropertiesPath(path) + item + ".access");
// Enable element only, if access level compliant
if (!state || isAccessLevelCompliant(accessLevel)) {
if (!path) {
debugger;
path = editor.path;
}
showInputOptions(path, [item], state);
}
}
@ -1269,17 +1314,26 @@ function showInputOptionsForKey(editor, item, showForKeys, state) {
if (typeof showForKeys === 'string') {
keysToshow.push(showForKeys);
} else {
return
return;
}
}
for (var key in editor.schema.properties[item].properties) {
for (let key in editor.schema.properties[item].properties) {
if ($.inArray(key, keysToshow) === -1) {
var accessLevel = editor.schema.properties[item].properties[key].access;
const accessLevel = editor.schema.properties[item].properties[key].access;
var hidden = false;
if (editor.schema.properties[item].properties[key].options) {
hidden = editor.schema.properties[item].properties[key].options.hidden;
if (typeof hidden === 'undefined') {
hidden = false;
}
}
//Always disable all elements, but only enable elements, if access level compliant
if (!state || isAccessLevelCompliant(accessLevel)) {
elements.push(key);
if (!hidden) {
elements.push(key);
}
}
}
}
@ -1314,7 +1368,7 @@ function isValidIPv6(value) {
function isValidHostname(value) {
if (value.match(
'^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])(.([a-zA-Z0-9]|[_a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]))*$' //lgtm [js/redos]
'^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])(.([a-zA-Z0-9]|[_a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]))*$'
))
return true;
else
@ -1323,7 +1377,7 @@ function isValidHostname(value) {
function isValidServicename(value) {
if (value.match(
'^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9 -]{0,61}[a-zA-Z0-9])(.([a-zA-Z0-9]|[_a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]))*$' //lgtm [js/redos]
'^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9 -]{0,61}[a-zA-Z0-9])(.([a-zA-Z0-9]|[_a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]))*$'
))
return true;
else

View File

@ -604,7 +604,7 @@ var lightPosTopLeft112 = { hmin: 0, hmax: 0.5, vmin: 0, vmax: 0.15 };
var lightPosTopLeft121 = { hmin: 0.5, hmax: 1, vmin: 0, vmax: 0.15 };
var lightPosTopLeftNewMid = { hmin: 0.25, hmax: 0.75, vmin: 0, vmax: 0.15 };
function assignLightPos(id, pos, name) {
function assignLightPos(pos, name) {
var i = null;
if (pos === "top")
@ -695,52 +695,50 @@ devicesProperties = {};
var hueIPs = [];
var hueIPsinc = 0;
var hueLights = null;
var hueGroups = null;
var hueLights = [];
var hueEntertainmentConfigs = [];
var hueEntertainmentServices = [];
var lightLocation = [];
var groupLights = [];
var groupChannels = [];
var groupLightsLocations = [];
var hueType = "philipshue";
var isAPIv2Ready = true;
var isEntertainmentReady = true;
function startWizardPhilipsHue(e) {
if (typeof e.data.type != "undefined") hueType = e.data.type;
//create html
var hue_title = 'wiz_hue_title';
var hue_intro1 = 'wiz_hue_intro1';
var hue_intro1 = 'wiz_hue_e_intro1';
var hue_desc1 = 'wiz_hue_desc1';
var hue_create_user = 'wiz_hue_create_user';
if (hueType == 'philipshueentertainment') {
hue_title = 'wiz_hue_e_title';
hue_intro1 = 'wiz_hue_e_intro1';
hue_desc1 = 'wiz_hue_e_desc1';
hue_create_user = 'wiz_hue_e_create_user';
}
$('#wiz_header').html('<i class="fa fa-magic fa-fw"></i>' + $.i18n(hue_title));
$('#wizp1_body').html('<h4 style="font-weight:bold;text-transform:uppercase;">' + $.i18n(hue_title) + '</h4><p>' + $.i18n(hue_intro1) + '</p>');
$('#wizp1_footer').html('<button type="button" class="btn btn-primary" id="btn_wiz_cont"><i class="fa fa-fw fa-check"></i>' + $.i18n('general_btn_continue') + '</button><button type="button" class="btn btn-danger" data-dismiss="modal"><i class="fa fa-fw fa-close"></i>' + $.i18n('general_btn_cancel') + '</button>');
$('#wizp2_body').html('<div id="wh_topcontainer"></div>');
var hidePort = "hidden-lg";
if (storedAccess === 'expert') {
hidePort = "";
}
$('#wh_topcontainer').append('<p class="text-left" style="font-weight:bold">' + $.i18n(hue_desc1) + '</p>' +
var topContainer_html = '<p class="text-left" style="font-weight:bold">' + $.i18n(hue_desc1) + '</p>' +
'<div class="row">' +
'<div class="col-md-2">' +
' <p class="text-left">' + $.i18n('wiz_hue_ip') + '</p></div>' +
' <div class="col-md-7"><div class="input-group">' +
' <span class="input-group-addon" id="retry_bridge" style="cursor:pointer"><i class="fa fa-refresh"></i></span>' +
' <input type="text" class="input-group form-control" id="host" placeholder="' + $.i18n('wiz_hue_ip') + '"></div></div>' +
' <div class="col-md-3 ' + hidePort + '"><div class="input-group">' +
' <span class="input-group-addon">:</span>' +
' <input type="text" class="input-group form-control" id="port" placeholder="' + $.i18n('edt_conf_general_port_title') + '"></div></div>' +
'</div><p><span style="font-weight:bold;color:red" id="wiz_hue_ipstate"></span><span style="font-weight:bold;" id="wiz_hue_discovered"></span></p>'
);
$('#wh_topcontainer').append();
$('#wh_topcontainer').append('<div class="form-group" id="usrcont" style="display:none"></div>');
' <select id="hue_bridge_select" class="hue_bridge_sel_watch form-control">' + '</select>' + '</div></div>' +
' <div class="col-md-7"><div class="input-group">' +
' <span class="input-group-addon"><i class="fa fa-arrow-right"></i></span>' +
' <input type="text" class="input-group form-control" id="host" placeholder="' + $.i18n('wiz_hue_ip') + '"></div></div>';
if (storedAccess === 'expert') {
topContainer_html += '<div class="col-md-3"><div class="input-group">' +
'<span class="input-group-addon">:</span>' +
'<input type="text" class="input-group form-control" id="port" placeholder="' + $.i18n('edt_conf_general_port_title') + '"></div></div>';
}
topContainer_html += '</div><p><span style="font-weight:bold;color:red" id="wiz_hue_ipstate"></span><span style="font-weight:bold;" id="wiz_hue_discovered"></span></p>';
topContainer_html += '<div class="form-group" id="usrcont" style="display:none"></div>';
$('#wh_topcontainer').append(topContainer_html);
$('#usrcont').append('<div class="row"><div class="col-md-2"><p class="text-left">' + $.i18n('wiz_hue_username') + '</p ></div>' +
'<div class="col-md-7">' +
@ -751,23 +749,18 @@ function startWizardPhilipsHue(e) {
'</div><input type="hidden" id="groupId">'
);
if (hueType == 'philipshueentertainment') {
$('#usrcont').append('<div class="row"><div class="col-md-2"><p class="text-left">' + $.i18n('wiz_hue_clientkey') +
'</p></div><div class="col-md-7"><input class="form-control" id="clientkey" type="text"></div></div><br>');
}
$('#usrcont').append('<div id="hue_client_key_r" class="row"><div class="col-md-2"><p class="text-left">' + $.i18n('wiz_hue_clientkey') +
'</p></div><div class="col-md-7"><input class="form-control" id="clientkey" type="text"></div></div><br>');
$('#usrcont').append('<p><span style="font-weight:bold;color:red" id="wiz_hue_usrstate"></span><\p>' +
'<button type="button" class="btn btn-primary" style="display:none" id="wiz_hue_create_user"> <i class="fa fa-fw fa-plus"></i>' + $.i18n(hue_create_user) + '</button>');
if (hueType == 'philipshueentertainment') {
$('#wizp2_body').append('<div id="hue_grp_ids_t" style="display:none"><p class="text-left" style="font-weight:bold">' + $.i18n('wiz_hue_e_desc2') + '</p></div>');
createTable("gidsh", "gidsb", "hue_grp_ids_t");
$('.gidsh').append(createTableRow([$.i18n('edt_dev_spec_groupId_title'), $.i18n('wiz_hue_e_use_group')], true));
$('#wizp2_body').append('<div id="hue_ids_t" style="display:none"><p class="text-left" style="font-weight:bold" id="hue_id_headline">' + $.i18n('wiz_hue_e_desc3') + '</p></div>');
}
else {
$('#wizp2_body').append('<div id="hue_ids_t" style="display:none"><p class="text-left" style="font-weight:bold" id="hue_id_headline">' + $.i18n('wiz_hue_desc2') + '</p></div>');
}
$('#wizp2_body').append('<div id="hue_grp_ids_t" style="display:none"><p class="text-left" style="font-weight:bold">' + $.i18n('wiz_hue_e_desc2') + '</p></div>');
createTable("gidsh", "gidsb", "hue_grp_ids_t");
$('.gidsh').append(createTableRow([$.i18n('edt_dev_spec_groupId_title'), ""], true));
$('#wizp2_body').append('<div id="hue_ids_t" style="display:none"><p class="text-left" style="font-weight:bold" id="hue_id_headline">' + $.i18n('wiz_hue_e_desc3') + '</p></div>');
createTable("lidsh", "lidsb", "hue_ids_t");
$('.lidsh').append(createTableRow([$.i18n('edt_dev_spec_lightid_title'), $.i18n('wiz_pos'), $.i18n('wiz_identify')], true));
$('#wizp2_footer').html('<button type="button" class="btn btn-primary" id="btn_wiz_save" style="display:none"><i class="fa fa-fw fa-save"></i>' + $.i18n('general_btn_save') + '</button><button type="button" class="btn btn-danger" id="btn_wiz_abort"><i class="fa fa-fw fa-close"></i>' + $.i18n('general_btn_cancel') + '</button>');
@ -793,13 +786,26 @@ function startWizardPhilipsHue(e) {
function checkHueBridge(cb, hueUser) {
var usr = (typeof hueUser != "undefined") ? hueUser : 'config';
if (usr == 'config') $('#wiz_hue_discovered').html("");
if (usr === 'config') {
$('#wiz_hue_discovered').html("");
}
if (hueIPs[hueIPsinc]) {
var host = hueIPs[hueIPsinc].host;
var port = hueIPs[hueIPsinc].port;
getProperties_hue_bridge(cb, decodeURIComponent(host), port, usr);
if (usr != '')
{
getProperties_hue_bridge(cb, decodeURIComponent(host), port, usr);
}
else
{
cb(false, usr);
}
if (isAPIv2Ready) {
$('#port').val(443);
}
}
}
@ -811,37 +817,51 @@ function checkBridgeResult(reply, usr) {
$('#port').val(hueIPs[hueIPsinc].port)
$('#usrcont').toggle(true);
checkHueBridge(checkUserResult, $('#user').val() ? $('#user').val() : "newdeveloper");
checkHueBridge(checkUserResult, $('#user').val());
}
else {
//increment and check again
if (hueIPs.length - 1 > hueIPsinc) {
hueIPsinc++;
checkHueBridge(checkBridgeResult);
}
else {
$('#usrcont').toggle(false);
$('#wiz_hue_ipstate').html($.i18n('wiz_hue_failure_ip'));
}
$('#usrcont').toggle(false);
$('#wiz_hue_ipstate').html($.i18n('wiz_hue_failure_ip'));
}
};
function checkUserResult(reply, usr) {
function checkUserResult(reply, username) {
$('#usrcont').toggle(true);
if (reply) {
$('#user').val(usr);
if (hueType == 'philipshueentertainment' && $('#clientkey').val() == "") {
var hue_create_user = 'wiz_hue_e_create_user';
if (!isEntertainmentReady) {
hue_create_user = 'wiz_hue_create_user';
$('#hue_client_key_r').toggle(false);
} else {
$('#hue_client_key_r').toggle(true);
}
$('#wiz_hue_create_user').text($.i18n(hue_create_user));
$('#wiz_hue_create_user').toggle(true);
if (reply) {
$('#user').val(username);
if (isEntertainmentReady && $('#clientkey').val() == "") {
$('#wiz_hue_usrstate').html($.i18n('wiz_hue_e_clientkey_needed'));
$('#wiz_hue_create_user').toggle(true);
} else {
$('#wiz_hue_usrstate').html("");
$('#wiz_hue_create_user').toggle(false);
if (hueType == 'philipshue') {
get_hue_lights();
}
if (hueType == 'philipshueentertainment') {
get_hue_groups();
if (isEntertainmentReady) {
$('#hue_id_headline').text($.i18n('wiz_hue_e_desc3'));
$('#hue_grp_ids_t').toggle(true);
get_hue_groups(username);
} else {
$('#hue_id_headline').text($.i18n('wiz_hue_desc2'));
$('#hue_grp_ids_t').toggle(false);
get_hue_lights(username);
}
}
}
@ -852,16 +872,73 @@ function checkUserResult(reply, usr) {
}
};
function useGroupId(id) {
$('#groupId').val(id);
groupLights = hueGroups[id].lights;
groupLightsLocations = hueGroups[id].locations;
get_hue_lights();
function useGroupId(id, username) {
$('#groupId').val(hueEntertainmentConfigs[id].id);
if (isAPIv2Ready) {
var group = hueEntertainmentConfigs[id];
groupLights = [];
for (const light of group.light_services) {
groupLights.push(light.rid);
}
groupChannels = [];
for (const channel of group.channels) {
groupChannels.push(channel);
}
groupLightsLocations = [];
for (const location of group.locations.service_locations) {
groupLightsLocations.push(location);
}
} else {
//Ensure ligthIDs are strings
groupLights = hueEntertainmentConfigs[id].lights.map(num => {
return String(num);
});
var lightLocations = hueEntertainmentConfigs[id].locations;
for (var locationID in lightLocations) {
var lightLocation = {};
let position = {
x: lightLocations[locationID][0],
y: lightLocations[locationID][1],
z: lightLocations[locationID][2]
};
lightLocation.position = position;
groupLightsLocations.push(lightLocation);
}
}
get_hue_lights(username);
}
function updateBridgeDetails(properties) {
var ledDeviceProperties = properties.config;
if (!jQuery.isEmptyObject(ledDeviceProperties)) {
isEntertainmentReady = properties.isEntertainmentReady;
isAPIv2Ready = properties.isAPIv2Ready;
if (ledDeviceProperties.name && ledDeviceProperties.bridgeid && ledDeviceProperties.modelid) {
$('#wiz_hue_discovered').html(
"Bridge: " + ledDeviceProperties.name +
", Modelid: " + ledDeviceProperties.modelid +
", Firmware: " + ledDeviceProperties.swversion + "<br/>" +
"API-Version: " + ledDeviceProperties.apiversion +
", Entertainment: " + (isEntertainmentReady ? "&#10003;" : "-") +
", APIv2: " + (isAPIv2Ready ? "&#10003;" : "-")
);
}
}
}
async function discover_hue_bridges() {
$('#wiz_hue_ipstate').html($.i18n('edt_dev_spec_devices_discovery_inprogress'));
$('#wiz_hue_discovered').html("")
// $('#wiz_hue_discovered').html("")
const res = await requestLedDeviceDiscovery('philipshue');
if (res && !res.error) {
const r = res.info;
@ -897,11 +974,6 @@ async function discover_hue_bridges() {
port = device.port;
}
//Remap https port to http port until Hue-API v2 is supported
if (port == 443) {
port = 80;
}
if (host) {
if (!hueIPs.some(item => item.host === host)) {
@ -910,22 +982,39 @@ async function discover_hue_bridges() {
}
}
}
$('#wiz_hue_ipstate').html("");
$('#host').val(hueIPs[hueIPsinc].host)
$('#port').val(hueIPs[hueIPsinc].port)
var usr = $('#user').val();
if (usr != "") {
checkHueBridge(checkUserResult, usr);
} else {
checkHueBridge(checkBridgeResult);
$('#hue_bridge_select').html("");
for (var key in hueIPs) {
$('#hue_bridge_select').append(createSelOpt(key, hueIPs[key].host));
}
$('.hue_bridge_sel_watch').on("click", function () {
hueIPsinc = $(this).val();
var name = $("#hue_bridge_select option:selected").text();
$('#host').val(name);
$('#port').val(hueIPs[hueIPsinc].port)
var usr = $('#user').val();
if (usr != "") {
checkHueBridge(checkUserResult, usr);
} else {
checkHueBridge(checkBridgeResult);
}
});
$('.hue_bridge_sel_watch').click();
}
}
}
async function getProperties_hue_bridge(cb, hostAddress, port, username, resourceFilter) {
let params = { host: hostAddress, user: username, filter: resourceFilter };
let params = { host: hostAddress, username: username, filter: resourceFilter };
if (port !== 'undefined') {
params.port = parseInt(port);
}
@ -939,23 +1028,27 @@ async function getProperties_hue_bridge(cb, hostAddress, port, username, resourc
}
// Use device's properties, if properties in chache
if (devicesProperties[ledType][key]) {
if (devicesProperties[ledType][key] && devicesProperties[ledType][key][username]) {
updateBridgeDetails(devicesProperties[ledType][key]);
cb(true, username);
} else {
const res = await requestLedDeviceProperties(ledType, params);
if (res && !res.error) {
var ledDeviceProperties = res.info.properties;
if (!jQuery.isEmptyObject(ledDeviceProperties)) {
devicesProperties[ledType][key] = {};
devicesProperties[ledType][key][username] = ledDeviceProperties;
isAPIv2Ready = res.info.isAPIv2Ready;
devicesProperties[ledType][key].isAPIv2Ready = isAPIv2Ready;
isEntertainmentReady = res.info.isEntertainmentReady;
devicesProperties[ledType][key].isEntertainmentReady = isEntertainmentReady;
updateBridgeDetails(devicesProperties[ledType][key]);
if (username === "config") {
if (ledDeviceProperties.name && ledDeviceProperties.bridgeid && ledDeviceProperties.modelid) {
$('#wiz_hue_discovered').html("Bridge: " + ledDeviceProperties.name + ", Modelid: " + ledDeviceProperties.modelid + ", API-Version: " + ledDeviceProperties.apiversion);
cb(true);
}
cb(true);
} else {
devicesProperties[ledType][key] = ledDeviceProperties;
cb(true, username);
}
} else {
@ -967,12 +1060,12 @@ async function getProperties_hue_bridge(cb, hostAddress, port, username, resourc
}
}
async function identify_hue_device(hostAddress, port, username, id) {
async function identify_hue_device(hostAddress, port, username, name, id, id_v1) {
var disabled = $('#btn_wiz_save').is(':disabled');
// Take care that new record cannot be save during background process
$('#btn_wiz_save').prop('disabled', true);
let params = { host: decodeURIComponent(hostAddress), user: username, lightId: id };
let params = { host: decodeURIComponent(hostAddress), username: username, lightName: decodeURIComponent(name), lightId: id, lightId_v1: id_v1 };
if (port !== 'undefined') {
params.port = parseInt(port);
@ -997,11 +1090,9 @@ function beginWizardHue() {
$('#user').val(usr);
}
if (hueType == 'philipshueentertainment') {
var clkey = eV("clientkey");
if (clkey != "") {
$('#clientkey').val(clkey);
}
var clkey = eV("clientkey");
if (clkey != "") {
$('#clientkey').val(clkey);
}
//check if host is empty/reachable/search for bridge
@ -1022,7 +1113,7 @@ function beginWizardHue() {
else {
$('#port').val('');
}
hueIPs.unshift({ host: host, port: port });
hueIPs.push({ host: host, port: port });
if (usr != "") {
checkHueBridge(checkUserResult, usr);
@ -1032,12 +1123,18 @@ function beginWizardHue() {
}
$('#retry_bridge').off().on('click', function () {
var host = $('#host').val();
var port = parseInt($('#port').val());
if ($('#host').val() != "") {
if (host != "") {
hueIPs = [];
hueIPsinc = 0;
hueIPs.push({ host: $('#host').val(), port: $('#port').val() });
var idx = hueIPs.findIndex(item => item.host === host && item.port === port);
if (idx === -1) {
hueIPs.push({ host: host, port: port });
hueIPsinc = hueIPs.length - 1;
} else {
hueIPsinc = idx;
}
}
else {
discover_hue_bridges();
@ -1052,29 +1149,177 @@ function beginWizardHue() {
});
$('#retry_usr').off().on('click', function () {
checkHueBridge(checkUserResult, $('#user').val() ? $('#user').val() : "newdeveloper");
checkHueBridge(checkUserResult, $('#user').val());
});
$('#wiz_hue_create_user').off().on('click', function () {
if ($('#host').val() != "") {
hueIPs.unshift({ host: $('#host').val(), port: $('#port').val() });
}
createHueUser();
});
function assignLightEntertainmentPos(isFocusCenter, position, name, id) {
var x = position.x;
var z = position.z;
if (isFocusCenter) {
// Map lights as in centered range -0.5 to 0.5
if (x < -0.5) {
x = -0.5;
} else if (x > 0.5) {
x = 0.5;
}
if (z < -0.5) {
z = -0.5;
} else if (z > 0.5) {
z = 0.5;
}
} else {
// Map lights as in full range -1 to 1
x /= 2;
z /= 2;
}
var h = x + 0.5;
var v = -z + 0.5;
var hmin = h - 0.05;
var hmax = h + 0.05;
var vmin = v - 0.05;
var vmax = v + 0.05;
let layoutObject = {
hmin: hmin < 0 ? 0 : hmin,
hmax: hmax > 1 ? 1 : hmax,
vmin: vmin < 0 ? 0 : vmin,
vmax: vmax > 1 ? 1 : vmax,
name: name
};
if (id) {
layoutObject.name += "_" + id;
}
return layoutObject;
}
function assignSegmentedLightPos(segment, position, name) {
var layoutObjects = [];
var segTotalLength = 0;
for (var key in segment) {
segTotalLength += segment[key].length;
}
var min;
var max;
var horizontal = true;
var layoutObject = assignLightPos(position, name);
if (position === "left" || position === "right") {
// vertical distribution
min = layoutObject.vmin;
max = layoutObject.vmax;
horizontal = false;
} else {
// horizontal distribution
min = layoutObject.hmin;
max = layoutObject.hmax;
}
var step = (max - min) / segTotalLength;
var start = min;
for (var key in segment) {
min = start;
max = round(start + segment[key].length * step);
if (horizontal) {
layoutObject.hmin = min;
layoutObject.hmax = max;
} else {
layoutObject.vmin = min;
layoutObject.vmax = max;
}
layoutObject.name = name + "_" + key;
layoutObjects.push(JSON.parse(JSON.stringify(layoutObject)));
start = max;
}
return layoutObjects;
}
$('#btn_wiz_save').off().on("click", function () {
var hueLedConfig = [];
var finalLightIds = [];
var channelNumber = 0;
//create hue led config
for (var key in hueLights) {
if (hueType == 'philipshueentertainment') {
if (groupLights.indexOf(key) == -1) continue;
}
if ($('#hue_' + key).val() != "disabled") {
finalLightIds.push(key);
var idx_content = assignLightPos(key, $('#hue_' + key).val(), hueLights[key].name);
hueLedConfig.push(JSON.parse(JSON.stringify(idx_content)));
for (var key in groupLights) {
var lightId = groupLights[key];
if ($('#hue_' + lightId).val() != "disabled") {
finalLightIds.push(lightId);
var lightName;
if (isAPIv2Ready) {
var light = hueLights.find(light => light.id === lightId);
lightName = light.metadata.name;
} else {
lightName = hueLights[lightId].name;
}
var position = $('#hue_' + lightId).val();
var lightIdx = groupLights.indexOf(lightId);
var lightLocation = groupLightsLocations[lightIdx];
var serviceID;
if (isAPIv2Ready) {
serviceID = lightLocation.service.rid;
}
if (position.startsWith("entertainment")) {
// Layout per entertainment area definition at bridge
var isFocusCenter = false;
if (position === "entertainment_center") {
isFocusCenter = true;
}
if (isAPIv2Ready) {
groupChannels.forEach((channel) => {
if (channel.members[0].service.rid === serviceID) {
var layoutObject = assignLightEntertainmentPos(isFocusCenter, channel.position, lightName, channel.channel_id);
hueLedConfig.push(JSON.parse(JSON.stringify(layoutObject)));
++channelNumber;
}
});
} else {
var layoutObject = assignLightEntertainmentPos(isFocusCenter, lightLocation.position, lightName);
hueLedConfig.push(JSON.parse(JSON.stringify(layoutObject)));
}
}
else {
// Layout per manual settings
var maxSegments = 1;
if (isAPIv2Ready) {
var service = hueEntertainmentServices.find(service => service.id === serviceID);
maxSegments = service.segments.max_segments;
}
if (maxSegments > 1) {
var segment = service.segments.segments;
var layoutObjects = assignSegmentedLightPos(segment, position, lightName);
hueLedConfig.push(...layoutObjects);
} else {
var layoutObject = assignLightPos(position, lightName);
hueLedConfig.push(JSON.parse(JSON.stringify(layoutObject)));
}
channelNumber += maxSegments;
}
}
}
@ -1109,7 +1354,7 @@ function beginWizardHue() {
d.brightnessFactor = parseFloat(eV("brightnessFactor", 1));
d.clientkey = $('#clientkey').val();
d.groupId = parseInt($('#groupId').val());
d.groupId = $('#groupId').val();
d.blackLightsTimeout = parseInt(eV("blackLightsTimeout", 5000));
d.brightnessMin = parseFloat(eV("brightnessMin", 0));
d.brightnessMax = parseFloat(eV("brightnessMax", 1));
@ -1122,8 +1367,16 @@ function beginWizardHue() {
d.enableAttempts = parseInt(conf_editor.getEditor("root.generalOptions.enableAttempts").getValue());
d.enableAttemptsInterval = parseInt(conf_editor.getEditor("root.generalOptions.enableAttemptsInterval").getValue());
if (hueType == 'philipshue') {
d.useEntertainmentAPI = false;
d.useEntertainmentAPI = isEntertainmentReady;
d.useAPIv2 = isAPIv2Ready;
if (isEntertainmentReady) {
d.hardwareLedCount = channelNumber;
if (window.serverConfig.device.type !== d.type) {
//smoothing on, if new device
sc.smoothing = { enable: true };
}
} else {
d.hardwareLedCount = finalLightIds.length;
d.verbose = false;
if (window.serverConfig.device.type !== d.type) {
@ -1132,15 +1385,6 @@ function beginWizardHue() {
}
}
if (hueType == 'philipshueentertainment') {
d.useEntertainmentAPI = true;
d.hardwareLedCount = groupLights.length;
if (window.serverConfig.device.type !== d.type) {
//smoothing on, if new device
sc.smoothing = { enable: true };
}
}
window.serverConfig.device = d;
requestWriteConfig(sc, true);
@ -1151,7 +1395,6 @@ function beginWizardHue() {
}
function createHueUser() {
var host = hueIPs[hueIPsinc].host;
var port = hueIPs[hueIPsinc].port;
@ -1196,7 +1439,8 @@ function createHueUser() {
conf_editor.getEditor("root.specificOptions.host").setValue(host);
conf_editor.getEditor("root.specificOptions.port").setValue(port);
}
if (hueType == 'philipshueentertainment') {
if (isEntertainmentReady) {
var clientkey = response.clientkey;
if (clientkey != 'undefined') {
$('#clientkey').val(clientkey);
@ -1218,37 +1462,52 @@ function createHueUser() {
}, retryInterval * 1000);
}
function get_hue_groups() {
function get_hue_groups(username) {
var host = hueIPs[hueIPsinc].host;
if (devicesProperties['philipshue'][host]) {
var ledProperties = devicesProperties['philipshue'][host];
if (devicesProperties['philipshue'][host] && devicesProperties['philipshue'][host][username]) {
var ledProperties = devicesProperties['philipshue'][host][username];
if (!jQuery.isEmptyObject(ledProperties)) {
hueGroups = ledProperties.groups;
if (Object.keys(hueGroups).length > 0) {
$('.lidsb').html("");
$('#wh_topcontainer').toggle(false);
$('#hue_grp_ids_t').toggle(true);
var gC = 0;
for (var groupid in hueGroups) {
if (hueGroups[groupid].type == 'Entertainment') {
$('.gidsb').append(createTableRow([groupid + ' (' + hueGroups[groupid].name + ')', '<button class="btn btn-sm btn-primary" onClick=useGroupId(' + groupid + ')>' + $.i18n('wiz_hue_e_use_groupid', groupid) + '</button>']));
gC++;
}
}
if (gC == 0) {
noAPISupport('wiz_hue_e_noegrpids');
if (isAPIv2Ready) {
if (!jQuery.isEmptyObject(ledProperties.data)) {
if (Object.keys(ledProperties.data).length > 0) {
hueEntertainmentConfigs = ledProperties.data.filter(config => {
return config.type === "entertainment_configuration";
});
hueEntertainmentServices = ledProperties.data.filter(config => {
return (config.type === "entertainment" && config.renderer === true);
});
}
}
} else {
if (!jQuery.isEmptyObject(ledProperties.groups)) {
hueEntertainmentConfigs = [];
var hueGroups = ledProperties.groups;
for (var groupid in hueGroups) {
if (hueGroups[groupid].type == 'Entertainment') {
hueGroups[groupid].id = groupid;
hueEntertainmentConfigs.push(hueGroups[groupid]);
}
}
}
}
if (Object.keys(hueEntertainmentConfigs).length > 0) {
$('.lidsb').html("");
$('#wh_topcontainer').toggle(false);
$('#hue_grp_ids_t').toggle(true);
for (var groupid in hueEntertainmentConfigs) {
$('.gidsb').append(createTableRow([groupid + ' (' + hueEntertainmentConfigs[groupid].name + ')', '<button class="btn btn-sm btn-primary" onClick=useGroupId("' + groupid + '","' + username + '")>' + $.i18n('wiz_hue_e_use_group') + '</button>']));
}
} else {
noAPISupport('wiz_hue_e_noegrpids', username);
}
}
}
function noAPISupport(txt) {
function noAPISupport(txt, username) {
showNotification('danger', $.i18n('wiz_hue_e_title'), $.i18n('wiz_hue_e_noapisupport_hint'));
conf_editor.getEditor("root.specificOptions.useEntertainmentAPI").setValue(false);
$("#root_specificOptions_useEntertainmentAPI").trigger("change");
@ -1257,51 +1516,82 @@ function noAPISupport(txt) {
var txt = (txt) ? $.i18n(txt) : $.i18n('wiz_hue_e_nogrpids');
$('<p style="font-weight:bold;color:red;">' + txt + '<br />' + $.i18n('wiz_hue_e_noapisupport') + '</p>').insertBefore('#wizp2_body #hue_ids_t');
$('#hue_id_headline').html($.i18n('wiz_hue_desc2'));
hueType = 'philipshue';
get_hue_lights();
get_hue_lights(username);
}
function get_hue_lights() {
function get_hue_lights(username) {
var host = hueIPs[hueIPsinc].host;
if (devicesProperties['philipshue'][host]) {
var ledProperties = devicesProperties['philipshue'][host];
if (devicesProperties['philipshue'][host] && devicesProperties['philipshue'][host][username]) {
var ledProperties = devicesProperties['philipshue'][host][username];
if (!jQuery.isEmptyObject(ledProperties.lights)) {
hueLights = ledProperties.lights;
if (Object.keys(hueLights).length > 0) {
if (hueType == 'philipshue') {
$('#wh_topcontainer').toggle(false);
if (isAPIv2Ready) {
if (!jQuery.isEmptyObject(ledProperties.data)) {
if (Object.keys(ledProperties.data).length > 0) {
hueLights = ledProperties.data.filter(config => {
return config.type === "light";
});
}
$('#hue_ids_t, #btn_wiz_save').toggle(true);
}
} else {
if (!jQuery.isEmptyObject(ledProperties.lights)) {
hueLights = ledProperties.lights;
}
}
var lightOptions = [
"top", "topleft", "topright",
"bottom", "bottomleft", "bottomright",
"left", "lefttop", "leftmiddle", "leftbottom",
"right", "righttop", "rightmiddle", "rightbottom",
"entire",
"lightPosTopLeft112", "lightPosTopLeftNewMid", "lightPosTopLeft121",
"lightPosBottomLeft14", "lightPosBottomLeft12", "lightPosBottomLeft34", "lightPosBottomLeft11",
"lightPosBottomLeft112", "lightPosBottomLeftNewMid", "lightPosBottomLeft121"
];
if (Object.keys(hueLights).length > 0) {
if (!isEntertainmentReady) {
$('#wh_topcontainer').toggle(false);
}
$('#hue_ids_t, #btn_wiz_save').toggle(true);
if (hueType == 'philipshue') {
lightOptions.unshift("disabled");
var lightOptions = [
"top", "topleft", "topright",
"bottom", "bottomleft", "bottomright",
"left", "lefttop", "leftmiddle", "leftbottom",
"right", "righttop", "rightmiddle", "rightbottom",
"entire",
"lightPosTopLeft112", "lightPosTopLeftNewMid", "lightPosTopLeft121",
"lightPosBottomLeft14", "lightPosBottomLeft12", "lightPosBottomLeft34", "lightPosBottomLeft11",
"lightPosBottomLeft112", "lightPosBottomLeftNewMid", "lightPosBottomLeft121"
];
if (isEntertainmentReady) {
lightOptions.unshift("entertainment_center");
lightOptions.unshift("entertainment");
} else {
lightOptions.unshift("disabled");
groupLights = Object.keys(hueLights);
}
$('.lidsb').html("");
var pos = "";
for (var id in groupLights) {
var lightId = groupLights[id];
var lightId_v1 = "/lights/" + lightId;
var lightName;
if (isAPIv2Ready) {
var light = hueLights.find(light => light.id === lightId);
lightName = light.metadata.name;
lightId_v1 = light.id_v1;
} else {
lightName = hueLights[lightId].name;
}
$('.lidsb').html("");
var pos = "";
for (var lightid in hueLights) {
if (hueType == 'philipshueentertainment') {
if (groupLights.indexOf(lightid) == -1) continue;
if (isEntertainmentReady) {
var lightLocation = {};
lightLocation = groupLightsLocations[id];
if (lightLocation) {
if (isAPIv2Ready) {
pos = 0;
} else {
var x = lightLocation.position.x;
var y = lightLocation.position.y;
var z = lightLocation.position.z;
if (groupLightsLocations.hasOwnProperty(lightid)) {
lightLocation = groupLightsLocations[lightid];
var x = lightLocation[0];
var y = lightLocation[1];
var z = lightLocation[2];
var xval = (x < 0) ? "left" : "right";
if (z != 1 && x >= -0.25 && x <= 0.25) xval = "";
switch (z) {
@ -1317,37 +1607,39 @@ function get_hue_lights() {
}
}
}
var options = "";
for (var opt in lightOptions) {
var val = lightOptions[opt];
var txt = (val != 'entire' && val != 'disabled') ? 'conf_leds_layout_cl_' : 'wiz_ids_';
options += '<option value="' + val + '"';
if (pos == val) options += ' selected="selected"';
options += '>' + $.i18n(txt + val) + '</option>';
}
$('.lidsb').append(createTableRow([lightid + ' (' + hueLights[lightid].name + ')', '<select id="hue_' + lightid + '" class="hue_sel_watch form-control">'
+ options
+ '</select>', '<button class="btn btn-sm btn-primary" onClick=identify_hue_device("' + encodeURIComponent($("#host").val()) + '","' + $('#port').val() + '","' + $("#user").val() + '",' + lightid + ')>' + $.i18n('wiz_hue_blinkblue', lightid) + '</button>']));
}
if (hueType != 'philipshueentertainment') {
$('.hue_sel_watch').on("change", function () {
var cC = 0;
for (var key in hueLights) {
if ($('#hue_' + key).val() != "disabled") {
cC++;
}
var options = "";
for (var opt in lightOptions) {
var val = lightOptions[opt];
var txt = (val != 'entire' && val != 'disabled') ? 'conf_leds_layout_cl_' : 'wiz_ids_';
options += '<option value="' + val + '"';
if (pos == val) options += ' selected="selected"';
options += '>' + $.i18n(txt + val) + '</option>';
}
$('.lidsb').append(createTableRow([id + ' (' + lightName + ')', '<select id="hue_' + lightId + '" class="hue_sel_watch form-control">'
+ options
+ '</select>', '<button class="btn btn-sm btn-primary" onClick=identify_hue_device("' + encodeURIComponent($("#host").val()) + '","' + $('#port').val() + '","' + $("#user").val() + '","' + encodeURIComponent(lightName) + '","' + lightId + '","' + lightId_v1 + '")>' + $.i18n('wiz_hue_blinkblue', id) + '</button>']));
}
if (!isEntertainmentReady) {
$('.hue_sel_watch').on("change", function () {
var cC = 0;
for (var key in hueLights) {
if ($('#hue_' + key).val() != "disabled") {
cC++;
}
}
(cC == 0 || window.readOnlyMode) ? $('#btn_wiz_save').prop("disabled", true) : $('#btn_wiz_save').prop("disabled", false);
});
}
$('.hue_sel_watch').trigger('change');
}
else {
var txt = '<p style="font-weight:bold;color:red;">' + $.i18n('wiz_hue_noids') + '</p>';
$('#wizp2_body').append(txt);
(cC == 0 || window.readOnlyMode) ? $('#btn_wiz_save').prop("disabled", true) : $('#btn_wiz_save').prop("disabled", false);
});
}
$('.hue_sel_watch').trigger('change');
}
else {
var txt = '<p style="font-weight:bold;color:red;">' + $.i18n('wiz_hue_noids') + '</p>';
$('#wizp2_body').append(txt);
}
}
}
@ -1425,7 +1717,7 @@ function beginWizardYeelight() {
finalLights.push(lights[key]);
var idx_content = assignLightPos(key, $('#yee_' + key).val(), name);
var idx_content = assignLightPos($('#yee_' + key).val(), name);
yeelightLedConfig.push(JSON.parse(JSON.stringify(idx_content)));
}
}
@ -1721,7 +2013,7 @@ function beginWizardAtmoOrb() {
if (lights[key].host !== "")
name += ':' + lights[key].host;
var idx_content = assignLightPos(key, $('#orb_' + key).val(), name);
var idx_content = assignLightPos($('#orb_' + key).val(), name);
atmoorbLedConfig.push(JSON.parse(JSON.stringify(idx_content)));
}
}

View File

@ -62,8 +62,7 @@ function printHelp {
echo "########################################################
## A script to compile Hyperion inside a docker container
## Requires installed Docker: https://www.docker.com/
## Without arguments it will compile Hyperion for Debian Buster (x86_64) and uses Hyperion code from GitHub repository.
## Supports Raspberry Pi (armv6l, armv7l) cross compilation (Debian Stretch/Buster) and native compilation (Raspbian Stretch/Buster)
## Without arguments it will compile Hyperion for Debian Bullseye (x86_64) and uses Hyperion code from GitHub repository.
## For all images and tags currently available, see https://github.com/orgs/hyperion-project/packages
##
## Homepage: https://www.hyperion-project.org
@ -72,8 +71,8 @@ echo "########################################################
# These are possible arguments to modify the script behaviour with their default values
#
# docker-compile.sh -h, --help # Show this help message
# docker-compile.sh -i, --image # The docker image, e.g., x86_64, armv6l, armv7l, aarch64, rpi-raspbian
# docker-compile.sh -t, --tag # The docker tag, e.g., stretch, buster, bullseye, bookworm
# docker-compile.sh -i, --image # The docker image, e.g., x86_64, armv6l, armv7l, aarch64
# docker-compile.sh -t, --tag # The docker tag, e.g., buster, bullseye, bookworm
# docker-compile.sh -b, --type # Release or Debug build
# docker-compile.sh -p, --packages # If true, build packages with CPack
# docker-compile.sh -l, --local # Run build using local code files

239
bin/scripts/install_pr.sh Executable file
View File

@ -0,0 +1,239 @@
#!/bin/bash
# Script for downloading a specific open Pull Request Artifact from Hyperion.NG
# Fixed variables
api_url="https://api.github.com/repos/hyperion-project/hyperion.ng"
type wget > /dev/null 2> /dev/null
hasWget=$?
type curl > /dev/null 2> /dev/null
hasCurl=$?
type python3 > /dev/null 2> /dev/null
hasPython3=$?
type python > /dev/null 2> /dev/null
hasPython2=$?
if [[ "${hasWget}" -ne 0 ]] && [[ "${hasCurl}" -ne 0 ]]; then
echo '---> Critical Error: wget or curl required to download pull request artifacts'
exit 1
fi
if [[ "${hasPython3}" -eq 0 ]]; then
pythonCmd="python3"
else
if [[ "${hasPython2}" -eq 0 ]]; then
pythonCmd="python"
else
echo '---> Critical Error: python3 or python2 required to download pull request artifacts'
fi
exit 1
fi
function request_call() {
if [ $hasWget -eq 0 ]; then
echo $(wget --quiet --header="Authorization: token ${PR_TOKEN}" -O - $1)
elif [ $hasCurl -eq 0 ]; then
echo $(curl -skH "Authorization: token ${PR_TOKEN}" $1)
fi
}
while getopts ":c:t:m:r:" opt; do
case "$opt" in
t) PR_TOKEN=$OPTARG ;;
r) run_id=$OPTARG ;;
m) ARCHITECTURE=$OPTARG ;;
c) CONFIGDIR=$OPTARG ;;
esac
done
shift $(( OPTIND - 1 ))
# Check for a command line argument (PR number)
if [ "$1" == "" ] || [ $# -gt 1 ] || [ -z ${PR_TOKEN} ]; then
echo "Usage: $0 -t <git_token> -m <architecture> -r <run_id> -c <hyperion config directory> <PR_NUMBER>" >&2
exit 1
else
pr_number="$1"
fi
# Set welcome message
echo '*******************************************************************************'
echo 'This script will download a specific open Pull Request Artifact from Hyperion.NG'
echo 'Created by hyperion-project.org - the official Hyperion source.'
echo '*******************************************************************************'
# Determine the architecture, if not given
if [[ -z ${ARCHITECTURE} ]]; then
ARCHITECTURE=`uname -m`
fi
#Test if multiarchitecture setup, i.e. user-space is 32bit
if [ ${ARCHITECTURE} == "aarch64" ]; then
USER_ARCHITECTURE=$ARCHITECTURE
IS_V7L=`cat /proc/$$/maps |grep -m1 -c v7l`
if [ $IS_V7L -ne 0 ]; then
USER_ARCHITECTURE="armv7l"
else
IS_V6L=`cat /proc/$$/maps |grep -m1 -c v6l`
if [ $IS_V6L -ne 0 ]; then
USER_ARCHITECTURE="armv6l"
fi
fi
if [ $ARCHITECTURE != $USER_ARCHITECTURE ]; then
echo "---> Identified kernel target architecture: $ARCHITECTURE"
echo "---> Identified user space target architecture: $USER_ARCHITECTURE"
ARCHITECTURE=$USER_ARCHITECTURE
fi
fi
echo 'armv6l armv7l aarch64 x86_64' | grep -qw ${ARCHITECTURE}
if [ $? -ne 0 ]; then
echo "---> Critical Error: Target architecture $ARCHITECTURE is unknown -> abort"
exit 1
else
echo "---> Download Pull Request for identified runtime architecture: $ARCHITECTURE"
fi
# Determine if PR number exists
pulls=$(request_call "$api_url/pulls?state=open")
pr_exists=$(echo "$pulls" | tr '\r\n' ' ' | ${pythonCmd} -c """
import json,sys
data = json.load(sys.stdin)
for i in data:
if i['number'] == "$pr_number":
print('exists')
break
""" 2>/dev/null)
if [ "$pr_exists" != "exists" ]; then
echo "---> Pull Request $pr_number not found as open PR -> abort"
exit 1
fi
# Get head_sha value from 'pr_number'
head_sha=$(echo "$pulls" | tr '\r\n' ' ' | ${pythonCmd} -c """
import json,sys
data = json.load(sys.stdin)
for i in data:
if i['number'] == "$pr_number":
print(i['head']['sha'])
break
""" 2>/dev/null)
if [ -z "$head_sha" ]; then
echo "---> The specified PR #$pr_number has no longer any artifacts or has been closed."
echo "---> It may be older than 14 days. Ask the PR creator to recreate the artifacts at the following URL:"
echo "---> https://github.com/hyperion-project/hyperion.ng/pull/$pr_number"
exit 1
fi
if [ -z "$run_id" ]; then
# Determine run_id from head_sha
runs=$(request_call "$api_url/actions/runs?head_sha=$head_sha")
run_id=$(echo "$runs" | tr '\r\n' ' ' | ${pythonCmd} -c """
import json,sys
data = json.load(sys.stdin)
for i in data['workflow_runs']:
if i['name'] == 'Hyperion PR Build':
print(i['id'])
break
""" 2>/dev/null)
fi
if [ -z "$run_id" ]; then
echo "---> The specified PR #$pr_number has no longer any artifacts."
echo "---> It may be older than 14 days. Ask the PR creator to recreate the artifacts at the following URL:"
echo "---> https://github.com/hyperion-project/hyperion.ng/pull/$pr_number"
exit 1
fi
# Get archive_download_url from workflow
artifacts=$(request_call "$api_url/actions/runs/$run_id/artifacts")
archive_download_url=$(echo "$artifacts" | tr '\r\n' ' ' | ${pythonCmd} -c """
import json,sys
data = json.load(sys.stdin)
for i in data['artifacts']:
if i['name'] == '"$ARCHITECTURE"':
print(i['archive_download_url'])
break
""" 2>/dev/null)
if [ -z "$archive_download_url" ]; then
echo "---> The specified PR #$pr_number has no longer any artifacts."
echo "---> It may be older than 14 days. Ask the PR creator to recreate the artifacts at the following URL:"
echo "---> https://github.com/hyperion-project/hyperion.ng/pull/$pr_number"
exit 1
fi
# Download packed PR artifact
echo "---> Downloading the Pull Request #$pr_number"
if [ $hasCurl -eq 0 ]; then
curl -skH "Authorization: token ${PR_TOKEN}" -o $HOME/temp.zip -L --get $archive_download_url
elif [ $hasWget -eq 0 ]; then
echo "wget"
wget --quiet --header="Authorization: token ${PR_TOKEN}" -O $HOME/temp.zip $archive_download_url
fi
# Create new folder & extract PR artifact
echo "---> Extracting packed Artifact"
mkdir -p $HOME/hyperion_pr$pr_number
unzip -p $HOME/temp.zip | tar --strip-components=2 -C $HOME/hyperion_pr$pr_number share/hyperion/ -xz
# Delete PR artifact
echo '---> Remove temporary files'
rm $HOME/temp.zip 2>/dev/null
# Create the startup script
echo '---> Create startup script'
STARTUP_SCRIPT="#!/bin/bash -e
# Stop hyperion service, if it is running
"'CURRENT_SERVICE=$(systemctl --type service | { grep -o "hyperion.*\.service" || true; })
if [[ ! -z ${CURRENT_SERVICE} ]]; then
echo "---> Stop current service: ${CURRENT_SERVICE}"
STOPCMD="systemctl stop --quiet ${CURRENT_SERVICE} --now"
USERNAME=${SUDO_USER:-$(whoami)}
if [ ${USERNAME} != "root" ]; then
STOPCMD="sudo ${STOPCMD}"
fi
${STOPCMD} >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "---> Critical Error: Failed to stop service: ${CURRENT_SERVICE}, Hyperion may not be started. Stop Hyperion manually."
else
echo "---> Service ${CURRENT_SERVICE} successfully stopped, Hyperion will be started"
fi
fi'""
TARGET_CONFIGDIR="$HOME/hyperion_pr$pr_number/config"
if [[ ! -z ${CONFIGDIR} ]]; then
STARTUP_SCRIPT+="
# Copy existing configuration file
"'echo "Copy existing configuration from "'${CONFIGDIR}"
mkdir -p "$TARGET_CONFIGDIR"
cp -ri "${CONFIGDIR}/*" "$TARGET_CONFIGDIR""
fi
STARTUP_SCRIPT+="
# Start PR artifact
cd $HOME/hyperion_pr$pr_number
./bin/hyperiond -d -u $TARGET_CONFIGDIR"
# Place startup script
echo "$STARTUP_SCRIPT" > $HOME/hyperion_pr$pr_number/$pr_number.sh
# Set the executen bit
chmod +x -R $HOME/hyperion_pr$pr_number/$pr_number.sh
echo "*******************************************************************************"
echo "Download finished!"
$REBOOTMESSAGE
echo "You can test the pull request with this command: ~/hyperion_pr$pr_number/$pr_number.sh"
echo "Remove the test installation with: rm -R ~/hyperion_pr$pr_number"
echo "Feedback is welcome at https://github.com/hyperion-project/hyperion.ng/pull/$pr_number"
echo "*******************************************************************************"

View File

@ -48,6 +48,7 @@ macro(DeployMacOS TARGET)
foreach(PLUGIN "platforms" "sqldrivers" "imageformats")
if(EXISTS ${PLUGIN_DIR}/${PLUGIN})
file(GLOB files "${PLUGIN_DIR}/${PLUGIN}/*")
list(FILTER files EXCLUDE REGEX ".*libqwebp\\.dylib$")
foreach(file ${files})
file(GET_RUNTIME_DEPENDENCIES
EXECUTABLES ${file}
@ -132,28 +133,33 @@ macro(DeployLinux TARGET)
include(GetPrerequisites)
set(SYSTEM_LIBS_SKIP
"libatomic"
"libc"
"libdbus"
"libdl"
"libexpat"
"libfontconfig"
"libfreetype"
"libgcc_s"
"libgcrypt"
"libGL"
"libGLdispatch"
"libglib"
"libglib-2"
"libGLX"
"libgpg-error"
"liblz4"
"liblzma"
"libm"
"libpcre"
"libpcre2"
"libpthread"
"librt"
"libstdc++"
"libsystemd"
"libudev"
"libusb"
"libusb-1"
"libutil"
"libX11"
"libuuid"
"libz"
)
)
if (ENABLE_DISPMANX)
list(APPEND SYSTEM_LIBS_SKIP "libcec")
@ -161,7 +167,9 @@ macro(DeployLinux TARGET)
# Extract dependencies ignoring the system ones
get_prerequisites(${TARGET_FILE} DEPENDENCIES 0 1 "" "")
message(STATUS "Dependencies for target file: ${DEPENDENCIES}")
# Append symlink and non-symlink dependencies to the list
set(PREREQUISITE_LIBS "")
foreach(DEPENDENCY ${DEPENDENCIES})
@ -203,6 +211,8 @@ macro(DeployLinux TARGET)
get_filename_component(file_canonical ${openssl_lib} REALPATH)
gp_append_unique(PREREQUISITE_LIBS ${file_canonical})
endforeach()
else()
message( WARNING "OpenSSL NOT found (https webserver will not work)")
endif(OPENSSL_FOUND)
# Detect the Qt plugin directory, source: https://github.com/lxde/lxqt-qtplugin/blob/master/src/CMakeLists.txt

View File

@ -1,4 +1,4 @@
execute_process( COMMAND git config --global --add safe.directory ${CMAKE_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} ERROR_QUIET )
execute_process( COMMAND git log -1 --format=%cn-%t/%h-%ct WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE BUILD_ID ERROR_QUIET )
execute_process( COMMAND sh -c "git branch | grep '^*' | sed 's;^*;;g' " WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE VERSION_ID ERROR_QUIET )
execute_process( COMMAND sh -c "git remote --verbose | grep origin | grep fetch | cut -f2 | cut -d' ' -f1" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE GIT_REMOTE_PATH ERROR_QUIET )

View File

@ -1,4 +1,4 @@
# - Find the Windows SDK aka Platform SDK
# - Find the Windows SDK aka Platform SDK (from https://github.com/rpavlik/cmake-modules)
#
# Relevant Wikipedia article: http://en.wikipedia.org/wiki/Microsoft_Windows_SDK
#
@ -49,10 +49,11 @@
# http://academic.cleardefinition.com
# Iowa State University HCI Graduate Program/VRAC
#
# Copyright Iowa State University 2012.
# Copyright 2012, Iowa State University
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
# SPDX-License-Identifier: BSL-1.0
set(_preferred_sdk_dirs) # pre-output
set(_win_sdk_dirs) # pre-output
@ -76,6 +77,9 @@ endmacro()
# although version numbers listed on that page don't necessarily match the directory
# used by the installer.
set(_winsdk_win10vers
10.0.22000.0
10.0.20348.0
10.0.19041.0
10.0.18362.0 # Win10 1903 "19H1"
10.0.17763.0 # Win10 1809 "October 2018 Update"
10.0.17134.0 # Redstone 4 aka Win10 1803 "April 2018 Update"

View File

@ -24,6 +24,8 @@
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>LSUIElement</key>
<string>1</string>
<key>NSHumanReadableCopyright</key>
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
<key>Source Code</key>

View File

@ -72,7 +72,7 @@ endif()
# .deb files for apt
# https://cmake.org/cmake/help/latest/cpack_gen/deb.html
SET ( CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_SOURCE_DIR}/cmake/package-scripts/preinst;${CMAKE_SOURCE_DIR}/cmake/package-scripts/postinst;${CMAKE_SOURCE_DIR}/cmake/package-scripts/prerm" )
SET ( CPACK_DEBIAN_PACKAGE_DEPENDS "libcec6 | libcec4" )
SET ( CPACK_DEBIAN_PACKAGE_DEPENDS "libcec6 | libcec4 | libcec (>= 4.0)" )
SET ( CPACK_DEBIAN_PACKAGE_SECTION "Miscellaneous" )
# .rpm for rpm
@ -155,6 +155,9 @@ if(ENABLE_FLATBUF_CONNECT)
if(ENABLE_V4L2)
SET ( CPACK_COMPONENTS_ALL ${CPACK_COMPONENTS_ALL} "hyperion_v4l2" )
endif()
if(ENABLE_AUDIO)
SET ( CPACK_COMPONENTS_ALL ${CPACK_COMPONENTS_ALL} "hyperion_audio" )
endif()
if(ENABLE_X11)
SET ( CPACK_COMPONENTS_ALL ${CPACK_COMPONENTS_ALL} "hyperion_x11" )
endif()

View File

@ -1,239 +1,236 @@
{
"general" :
{
"name" : "My Hyperion Config",
"configVersion": "configVersionValue",
"previousVersion": "previousVersionValue",
"watchedVersionBranch" : "Stable",
"showOptHelp" : true
"general": {
"name": "My Hyperion Config",
"configVersion": "configVersionValue",
"previousVersion": "previousVersionValue",
"watchedVersionBranch": "Stable",
"showOptHelp": true
},
"logger" :
{
"level" : "warn"
"logger": {
"level": "warn"
},
"device" :
{
"type" : "file",
"hardwareLedCount" : 1,
"autoStart" : true,
"output" : "/dev/null",
"colorOrder" : "rgb",
"latchTime" : 0,
"device": {
"type": "file",
"hardwareLedCount": 1,
"autoStart": true,
"output": "/dev/null",
"colorOrder": "rgb",
"latchTime": 0,
"rewriteTime": 0,
"enableAttempts": 6,
"enableAttemptsInterval": 15
},
"color" :
{
"imageToLedMappingType" : "multicolor_mean",
"channelAdjustment" :
[
"color": {
"imageToLedMappingType": "multicolor_mean",
"channelAdjustment": [
{
"id" : "default",
"leds" : "*",
"white" : [255,255,255],
"red" : [255,0,0],
"green" : [0,255,0],
"blue" : [0,0,255],
"cyan" : [0,255,255],
"magenta" : [255,0,255],
"yellow" : [255,255,0],
"gammaRed" : 2.2,
"gammaGreen" : 2.2,
"gammaBlue" : 2.2,
"backlightThreshold" : 0,
"backlightColored" : false,
"brightness" : 100,
"brightnessCompensation" : 100,
"saturationGain" : 1.0,
"brightnessGain" : 1.0
"id": "default",
"leds": "*",
"white": [ 255, 255, 255 ],
"red": [ 255, 0, 0 ],
"green": [ 0, 255, 0 ],
"blue": [ 0, 0, 255 ],
"cyan": [ 0, 255, 255 ],
"magenta": [ 255, 0, 255 ],
"yellow": [ 255, 255, 0 ],
"gammaRed": 2.2,
"gammaGreen": 2.2,
"gammaBlue": 2.2,
"backlightThreshold": 0,
"backlightColored": false,
"brightness": 100,
"brightnessCompensation": 100,
"saturationGain": 1.0,
"brightnessGain": 1.0
}
]
},
"smoothing" :
{
"enable" : true,
"type" : "linear",
"time_ms" : 200,
"updateFrequency" : 25.0000,
"interpolationRate" : 25.0000,
"decay" : 1,
"dithering" : false,
"updateDelay" : 0
"smoothing": {
"enable": true,
"type": "linear",
"time_ms": 150,
"updateFrequency": 25.0000,
"interpolationRate": 25.0000,
"decay": 1,
"dithering": false,
"updateDelay": 0
},
"grabberV4L2" :
{
"enable" : false,
"device" : "none",
"input" : 0,
"encoding" : "NO_CHANGE",
"width" : 0,
"height" : 0,
"fps" : 15,
"flip" : "NO_CHANGE",
"fpsSoftwareDecimation" : 0,
"sizeDecimation" : 8,
"cropLeft" : 0,
"cropRight" : 0,
"cropTop" : 0,
"cropBottom" : 0,
"redSignalThreshold" : 0,
"greenSignalThreshold" : 100,
"blueSignalThreshold" : 0,
"signalDetection" : false,
"noSignalCounterThreshold" : 200,
"cecDetection" : false,
"sDVOffsetMin" : 0.1,
"sDVOffsetMax" : 0.9,
"sDHOffsetMin" : 0.4,
"sDHOffsetMax" : 0.46,
"hardware_brightness" : 0,
"hardware_contrast" : 0,
"hardware_saturation" : 0,
"hardware_hue" : 0
"grabberV4L2": {
"enable": false,
"device": "none",
"input": 0,
"encoding": "NO_CHANGE",
"width": 0,
"height": 0,
"fps": 15,
"flip": "NO_CHANGE",
"fpsSoftwareDecimation": 0,
"sizeDecimation": 8,
"cropLeft": 0,
"cropRight": 0,
"cropTop": 0,
"cropBottom": 0,
"redSignalThreshold": 0,
"greenSignalThreshold": 100,
"blueSignalThreshold": 0,
"signalDetection": false,
"noSignalCounterThreshold": 200,
"cecDetection": false,
"sDVOffsetMin": 0.1,
"sDVOffsetMax": 0.9,
"sDHOffsetMin": 0.4,
"sDHOffsetMax": 0.46,
"hardware_brightness": 0,
"hardware_contrast": 0,
"hardware_saturation": 0,
"hardware_hue": 0
},
"framegrabber" :
{
"enable" : false,
"device" : "auto",
"input" : 0,
"width" : 80,
"height" : 45,
"fps" : 10,
"pixelDecimation" : 8,
"cropLeft" : 0,
"cropRight" : 0,
"cropTop" : 0,
"cropBottom" : 0
"grabberAudio": {
"enable": false,
"device": "auto",
"audioEffect": "vuMeter",
"vuMeter": {
"flip": "NO_CHANGE",
"hotColor": [ 255, 0, 0 ],
"multiplier": 1,
"safeColor": [ 0, 255, 0 ],
"safeValue": 45,
"tolerance": 5,
"warnColor": [ 255, 255, 0 ],
"warnValue": 80
}
},
"blackborderdetector" :
{
"enable" : true,
"threshold" : 5,
"unknownFrameCnt" : 600,
"borderFrameCnt" : 50,
"maxInconsistentCnt" : 10,
"blurRemoveCnt" : 1,
"mode" : "default"
"framegrabber": {
"enable": false,
"device": "auto",
"input": 0,
"width": 80,
"height": 45,
"fps": 10,
"pixelDecimation": 8,
"cropLeft": 0,
"cropRight": 0,
"cropTop": 0,
"cropBottom": 0
},
"foregroundEffect" :
{
"enable" : true,
"type" : "effect",
"color" : [0,0,255],
"effect" : "Rainbow swirl fast",
"duration_ms" : 3000
"blackborderdetector": {
"enable": true,
"threshold": 5,
"unknownFrameCnt": 600,
"borderFrameCnt": 50,
"maxInconsistentCnt": 10,
"blurRemoveCnt": 1,
"mode": "default"
},
"backgroundEffect" :
{
"enable" : false,
"type" : "effect",
"color" : [255,138,0],
"effect" : "Warm mood blobs"
"foregroundEffect": {
"enable": true,
"type": "effect",
"color": [ 0, 0, 255 ],
"effect": "Rainbow swirl fast",
"duration_ms": 3000
},
"forwarder" :
{
"enable" : false,
"jsonapi" : [],
"flatbuffer" : []
"backgroundEffect": {
"enable": false,
"type": "effect",
"color": [ 255, 138, 0 ],
"effect": "Warm mood blobs"
},
"jsonServer" :
{
"port" : 19444
"forwarder": {
"enable": false,
"jsonapi": [],
"flatbuffer": []
},
"flatbufServer" :
{
"enable" : true,
"port" : 19400,
"timeout" : 5
"jsonServer": {
"port": 19444
},
"protoServer" :
{
"enable" : true,
"port" : 19445,
"timeout" : 5
"flatbufServer": {
"enable": true,
"port": 19400,
"timeout": 5
},
"boblightServer" :
{
"enable" : false,
"port" : 19333,
"priority" : 128
"protoServer": {
"enable": true,
"port": 19445,
"timeout": 5
},
"webConfig" :
{
"document_root" : "",
"port" : 8090,
"sslPort" : 8092,
"crtPath" : "",
"keyPath" : "",
"keyPassPhrase" : ""
"boblightServer": {
"enable": false,
"port": 19333,
"priority": 128
},
"effects" :
{
"paths" : ["$ROOT/custom-effects"],
"disable": [""]
"webConfig": {
"document_root": "",
"port": 8090,
"sslPort": 8092,
"crtPath": "",
"keyPath": "",
"keyPassPhrase": ""
},
"instCapture" :
{
"systemEnable" : false,
"systemGrabberDevice" : "NONE",
"systemPriority" : 250,
"v4lEnable" : false,
"v4lGrabberDevice" : "NONE",
"v4lPriority" : 240
"effects": {
"paths": [ "$ROOT/custom-effects" ],
"disable": [ "" ]
},
"network" :
{
"internetAccessAPI" : false,
"restirctedInternetAccessAPI" : false,
"ipWhitelist" : [],
"apiAuth" : true,
"localApiAuth" : false,
"instCapture": {
"systemEnable": false,
"systemGrabberDevice": "NONE",
"systemPriority": 250,
"v4lEnable": false,
"v4lGrabberDevice": "NONE",
"v4lPriority": 240,
"audioEnable": false,
"audioGrabberDevice": "NONE",
"audioPriority": 230
},
"network": {
"internetAccessAPI": false,
"restirctedInternetAccessAPI": false,
"ipWhitelist": [],
"apiAuth": true,
"localApiAuth": false,
"localAdminAuth": true
},
"ledConfig" :
{
"classic":
{
"top" : 1,
"bottom" : 0,
"left" : 0,
"right" : 0,
"glength" : 0,
"gpos" : 0,
"position" : 0,
"reverse" : false,
"hdepth" : 8,
"vdepth" : 5,
"overlap" : 0,
"edgegap" : 0,
"ptlh" : 0,
"ptlv" : 0,
"ptrh" : 100,
"ptrv" : 0,
"pblh" : 0,
"pblv" : 100,
"pbrh" : 100,
"pbrv" : 100
},
"ledConfig": {
"classic": {
"top": 1,
"bottom": 0,
"left": 0,
"right": 0,
"glength": 0,
"gpos": 0,
"position": 0,
"reverse": false,
"hdepth": 8,
"vdepth": 5,
"overlap": 0,
"edgegap": 0,
"ptlh": 0,
"ptlv": 0,
"ptrh": 100,
"ptrv": 0,
"pblh": 0,
"pblv": 100,
"pbrh": 100,
"pbrv": 100
},
"matrix": {
"ledshoriz": 1,
@ -244,8 +241,7 @@
}
},
"leds":
[
"leds": [
{
"hmax": 1,
"hmin": 0,

13
debian/distributions vendored
View File

@ -1,11 +1,3 @@
Origin: Hyperion-Project
Label: apt.hyperion-project.org
Codename: bionic
Architectures: amd64 armhf arm64
Components: main
Description: Official APT Repository by Hyperion Project
SignWith: yes
Origin: Hyperion-Project
Label: apt.hyperion-project.org
Codename: focal
@ -32,9 +24,8 @@ SignWith: yes
Origin: Hyperion-Project
Label: apt.hyperion-project.org
Suite: oldoldstable
Codename: stretch
Architectures: armhf amd64
Codename: lunar
Architectures: amd64
Components: main
Description: Official APT Repository by Hyperion Project
SignWith: yes

View File

@ -1,37 +0,0 @@
cmake_minimum_required(VERSION 3.2)
project(mbedtls)
set(DOWNLOAD_DIR "@MBEDTLS_DOWNLOAD_DIR@")
set(SOURCE_DIR "@MBEDTLS_SOURCE_DIR@")
set(BINARY_DIR "@MBEDTLS_BINARY_DIR@")
set(INSTALL_DIR "@MBEDTLS_INSTALL_DIR@")
set(CMAKE_ARGS "@MBEDTLS_CMAKE_ARGS@")
set(LOGGING "@MBEDTLS_LOGGING@")
include(ExternalProject)
ExternalProject_Add(
mbedtls
GIT_REPOSITORY "https://github.com/ARMmbed/mbedtls.git"
GIT_TAG "v3.1.0" # Bump versions manually if necessary, do not rely on origin/master to be stable
BUILD_ALWAYS OFF
DOWNLOAD_DIR "${DOWNLOAD_DIR}"
SOURCE_DIR "${SOURCE_DIR}"
BINARY_DIR "${BINARY_DIR}"
INSTALL_DIR "${INSTALL_DIR}"
CMAKE_ARGS ${CMAKE_ARGS}
CONFIGURE_COMMAND ""
UPDATE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
LOG_DOWNLOAD ${LOGGING}
LOG_UPDATE ${LOGGING}
LOG_PATCH ${LOGGING}
LOG_CONFIGURE ${LOGGING}
LOG_BUILD ${LOGGING}
LOG_INSTALL ${LOGGING}
LOG_TEST ${LOGGING}
LOG_MERGED_STDOUTERR ${LOGGING}
LOG_OUTPUT_ON_FAILURE ${LOGGING}
)

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.2)
cmake_minimum_required(VERSION 3.5)
project(qmdnsengine)

View File

@ -133,6 +133,9 @@ endif()
if(ENABLE_PROTOBUF_SERVER)
set(USE_SYSTEM_PROTO_LIBS ${DEFAULT_USE_SYSTEM_PROTO_LIBS} CACHE BOOL "use protobuf library from system")
# defines for 3rd party sub-modules
set(ABSL_PROPAGATE_CXX_STD ON CACHE BOOL "Build abseil-cpp with C++ version requirements propagated")
if (USE_SYSTEM_PROTO_LIBS)
find_package(Protobuf REQUIRED)
@ -150,7 +153,7 @@ if(ENABLE_PROTOBUF_SERVER)
set(protobuf_MSVC_STATIC_RUNTIME OFF CACHE BOOL "Build protobuf static")
endif()
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/external/protobuf/cmake")
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/external/protobuf")
# define the include for the protobuf library
set(PROTOBUF_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/external/protobuf/src")
@ -160,6 +163,7 @@ if(ENABLE_PROTOBUF_SERVER)
# define the protobuf library
set(PROTOBUF_LIBRARIES protobuf::libprotobuf)
endif()
# redefine at parent scope
@ -265,15 +269,19 @@ if(ENABLE_DEV_NETWORK)
set(DEFAULT_USE_SYSTEM_MBEDTLS_LIBS OFF PARENT_SCOPE)
set(USE_SYSTEM_MBEDTLS_LIBS OFF)
endif (NOT MBEDTLS_FOUND)
endif (USE_SYSTEM_MBEDTLS_LIBS)
else()
cmake_minimum_required(VERSION 3.5.1)
set(CMAKE_POLICY_DEFAULT_CMP0071 NEW)
if (NOT USE_SYSTEM_MBEDTLS_LIBS)
cmake_minimum_required(VERSION 3.2)
set(DEFAULT_USE_SYSTEM_MBEDTLS_LIBS OFF CACHE BOOL "system mbedtls libraries not found, disable use system mbedtls libraries")
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared mbedtls libraries")
set(ENABLE_TESTING OFF CACHE BOOL "Disable mbedTLS tests")
set(GEN_FILES OFF CACHE BOOL "Disable mbedTLS auto-generated files")
set(ENABLE_PROGRAMS OFF CACHE BOOL "Disable mbedTLS programs")
#set(LINK_WITH_PTHREAD ON CACHE BOOL "Enable mbedTLS library linked to pthread.")
set(USE_SHARED_MBEDTLS_LIBRARY OFF CACHE BOOL "Disable mbedTLS shared libraries")
set(USE_STATIC_MBEDTLS_LIBRARY ON CACHE BOOL "Enable mbedTLS static libraries")
@ -287,69 +295,7 @@ if(ENABLE_DEV_NETWORK)
set(MBEDTLS_LOGGING 0)
endif ()
set(MBEDTLS_CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX:PATH=${MBEDTLS_INSTALL_DIR}
-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
-DUSE_SHARED_MBEDTLS_LIBRARY:BOOL=OFF
-DUSE_STATIC_MBEDTLS_LIBRARY:BOOL=ON
-DENABLE_TESTING:BOOL=OFF
-DENABLE_PROGRAMS:BOOL=OFF
-DLINK_WITH_PTHREAD:BOOL=ON
-Wno-dev
#-DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=TRUE
)
set(ENABLE_MBEDTLS_FETCH_CONTENT ON)
if (ENABLE_MBEDTLS_FETCH_CONTENT AND CMAKE_VERSION VERSION_GREATER_EQUAL 3.11)
include(FetchContent)
FetchContent_Declare(
mbedtls
GIT_REPOSITORY https://github.com/ARMmbed/mbedtls.git
GIT_TAG "v3.1.0" # Bump versions manually if necessary, do not rely on origin/master to be stable
BUILD_ALWAYS OFF
GIT_PROGRESS 1
DOWNLOAD_DIR "${MBEDTLS_DOWNLOAD_DIR}"
SOURCE_DIR "${MBEDTLS_SOURCE_DIR}"
BINARY_DIR "${MBEDTLS_BINARY_DIR}"
INSTALL_DIR "${MBEDTLS_INSTALL_DIR}"
CMAKE_ARGS ${MBEDTLS_CMAKE_ARGS}
BUILD_COMMAND ""
INSTALL_COMMAND ""
LOG_DOWNLOAD ${MBEDTLS_LOGGING}
LOG_UPDATE ${MBEDTLS_LOGGING}
LOG_PATCH ${MBEDTLS_LOGGING}
LOG_CONFIGURE ${MBEDTLS_LOGGING}
LOG_BUILD ${MBEDTLS_LOGGING}
LOG_INSTALL ${MBEDTLS_LOGGING}
LOG_TEST ${MBEDTLS_LOGGING}
LOG_MERGED_STDOUTERR ${MBEDTLS_LOGGING}
LOG_OUTPUT_ON_FAILURE ${MBEDTLS_LOGGING}
)
if (CMAKE_VERSION VERSION_LESS 3.14)
macro (FetchContent_MakeAvailable NAME)
FetchContent_GetProperties(${NAME})
if (NOT ${NAME}_POPULATED)
FetchContent_Populate(${NAME})
add_subdirectory(${${NAME}_SOURCE_DIR} ${${NAME}_BINARY_DIR})
endif ()
endmacro ()
endif ()
FetchContent_MakeAvailable(mbedtls)
else ()
set(ENABLE_MBEDTLS_FETCH_CONTENT OFF PARENT_SCOPE)
if(NOT DEFINED BUILD_MBEDTLS_ONCE)
set(BUILD_MBEDTLS_ONCE CACHE INTERNAL "Done")
configure_file(${CMAKE_SOURCE_DIR}/dependencies/CMakeLists-mbedtls.txt.in ${MBEDTLS_DOWNLOAD_DIR}/CMakeLists.txt @ONLY)
execute_process(COMMAND ${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX:PATH=${MBEDTLS_INSTALL_DIR} -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} -G "${CMAKE_GENERATOR}" . WORKING_DIRECTORY ${MBEDTLS_DOWNLOAD_DIR})
execute_process(COMMAND ${CMAKE_COMMAND} --build . WORKING_DIRECTORY ${MBEDTLS_DOWNLOAD_DIR})
add_subdirectory(${MBEDTLS_SOURCE_DIR} ${MBEDTLS_BINARY_DIR})
endif()
endif ()
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/external/mbedtls)
set (MBEDTLS_INCLUDE_DIR "${MBEDTLS_SOURCE_DIR}/include")
set (MBEDTLS_INCLUDE_DIR ${MBEDTLS_INCLUDE_DIR} PARENT_SCOPE)
@ -387,5 +333,5 @@ if(ENABLE_DEV_NETWORK)
mark_as_advanced (MBEDTLS_INCLUDE_DIR MBEDTLS_LIBRARIES MBEDTLS_SSL_LIBRARY MBEDTLS_X509_LIBRARY MBEDTLS_CRYPTO_LIBRARY)
endif (NOT USE_SYSTEM_MBEDTLS_LIBS)
endif (USE_SYSTEM_MBEDTLS_LIBS)
endif(ENABLE_DEV_NETWORK)

@ -1 +1 @@
Subproject commit 8468eab83bacc8bbd6cb5ae22197af06a9437b2d
Subproject commit 0100f6a5779831fa7a651e4b67ef389a8752bd9b

1
dependencies/external/mbedtls vendored Submodule

@ -0,0 +1 @@
Subproject commit 1873d3bfc2da771672bd8e7e8f41f57e0af77f33

@ -1 +1 @@
Subproject commit 5ad0697c868235f24559dc07f8a42870d160af76
Subproject commit 2c5fa078d8e86e5f4bd34e6f4c9ea9e8d7d4d44a

@ -1 +1 @@
Subproject commit 1ba8e385708fb7802b09c0177a7ea4293948e25c
Subproject commit 1f47b59ed603223d1376d36c788c89af67ae2fdc

View File

@ -1,34 +1,12 @@
# With Docker
If you are using [Docker](https://www.docker.com/), you can compile Hyperion inside a docker container. This keeps your system clean and with a simple script it's easy to use. Supported is also cross compiling for Raspberry Pi (Debian Stretch or higher). To compile Hyperion just execute one of the following commands.
If you are using [Docker](https://www.docker.com/), you can compile Hyperion inside a docker container. This keeps your system clean and with a simple script it's easy to use. Supported is also cross compiling for Raspberry Pi (Debian Buster or higher). To compile Hyperion just execute one of the following commands.
The compiled binaries and packages will be available at the deploy folder next to the script.<br/>
Note: call the script with `./docker-compile.sh -h` for more options.
## Native compilation on Raspberry Pi for:
**Raspbian Stretch**
```console
wget -qN https://raw.github.com/hyperion-project/hyperion.ng/master/bin/scripts/docker-compile.sh && chmod +x *.sh && ./docker-compile.sh -i rpi-raspbian -t stretch
```
**Raspbian Buster/Raspberry Pi OS**
```console
wget -qN https://raw.github.com/hyperion-project/hyperion.ng/master/bin/scripts/docker-compile.sh && chmod +x *.sh && ./docker-compile.sh -i rpi-raspbian -t buster
```
**Raspberry Pi OS Bullseye**
```console
wget -qN https://raw.github.com/hyperion-project/hyperion.ng/master/bin/scripts/docker-compile.sh && chmod +x *.sh && ./docker-compile.sh -i rpi-raspbian -t bullseye
```
**Raspberry Pi OS Bookworm**
```console
wget -qN https://raw.github.com/hyperion-project/hyperion.ng/master/bin/scripts/docker-compile.sh && chmod +x *.sh && ./docker-compile.sh -i rpi-raspbian -t bookworm
```
## Cross compilation on x86_64 for:
**x86_64 (Debian Stretch):**
```console
wget -qN https://raw.github.com/hyperion-project/hyperion.ng/master/bin/scripts/docker-compile.sh && chmod +x *.sh && ./docker-compile.sh -i x86_64 -t stretch
```
**x86_64 (Debian Buster):**
```console
wget -qN https://raw.github.com/hyperion-project/hyperion.ng/master/bin/scripts/docker-compile.sh && chmod +x *.sh && ./docker-compile.sh -i x86_64 -t buster
@ -41,10 +19,6 @@ wget -qN https://raw.github.com/hyperion-project/hyperion.ng/master/bin/scripts/
```console
wget -qN https://raw.github.com/hyperion-project/hyperion.ng/master/bin/scripts/docker-compile.sh && chmod +x *.sh && ./docker-compile.sh -i x86_64 -t bookworm
```
**Raspberry Pi v1 & ZERO (Debian Stretch)**
```console
wget -qN https://raw.github.com/hyperion-project/hyperion.ng/master/bin/scripts/docker-compile.sh && chmod +x *.sh && ./docker-compile.sh -i armv6l -t stretch
```
**Raspberry Pi v1 & ZERO (Debian Buster)**
```console
wget -qN https://raw.github.com/hyperion-project/hyperion.ng/master/bin/scripts/docker-compile.sh && chmod +x *.sh && ./docker-compile.sh -i armv6l -t buster
@ -57,10 +31,6 @@ wget -qN https://raw.github.com/hyperion-project/hyperion.ng/master/bin/scripts/
```console
wget -qN https://raw.github.com/hyperion-project/hyperion.ng/master/bin/scripts/docker-compile.sh && chmod +x *.sh && ./docker-compile.sh -i armv6l -t bookworm
```
**Raspberry Pi 2/3/4 (Debian Stretch)**
```console
wget -qN https://raw.github.com/hyperion-project/hyperion.ng/master/bin/scripts/docker-compile.sh && chmod +x *.sh && ./docker-compile.sh -i armv7l -t stretch
```
**Raspberry Pi 2/3/4 (Debian Buster)**
```console
wget -qN https://raw.github.com/hyperion-project/hyperion.ng/master/bin/scripts/docker-compile.sh && chmod +x *.sh && ./docker-compile.sh -i armv7l -t buster
@ -69,6 +39,7 @@ wget -qN https://raw.github.com/hyperion-project/hyperion.ng/master/bin/scripts/
```console
wget -qN https://raw.github.com/hyperion-project/hyperion.ng/master/bin/scripts/docker-compile.sh && chmod +x *.sh && ./docker-compile.sh -i armv7l -t bullseye
```
## Cross compilation on x86_64 for developers
Using additional options you can cross compile locally
-l: use a local hyperion source code directory rather than cloning from GitHub
@ -79,6 +50,7 @@ Using additional options you can cross compile locally
cd $HYPERION_HOME
./bin/scripts/docker-compile.sh -l -c -i armv7l -t bullseye
```
# The usual way
## Debian/Ubuntu/Win10LinuxSubsystem
@ -87,14 +59,14 @@ cd $HYPERION_HOME
```console
sudo apt-get update
sudo apt-get install git cmake build-essential qtbase5-dev libqt5serialport5-dev libqt5sql5-sqlite libqt5svg5-dev libqt5x11extras5-dev libusb-1.0-0-dev python3-dev libturbojpeg0-dev libjpeg-dev libssl-dev
sudo apt-get install git cmake build-essential qtbase5-dev libqt5serialport5-dev libqt5sql5-sqlite libqt5svg5-dev libqt5x11extras5-dev libusb-1.0-0-dev python3-dev libasound2-dev libturbojpeg0-dev libjpeg-dev libssl-dev
```
**Ubuntu (22.04+) - Qt6 based**
```console
sudo apt-get update
sudo apt-get install git cmake build-essential qt6-base-dev libqt6serialport6-dev libvulkan-dev libgl1-mesa-dev libusb-1.0-0-dev python3-dev libturbojpeg0-dev libjpeg-dev libssl-dev pkg-config
sudo apt-get install git cmake build-essential qt6-base-dev libqt6serialport6-dev libxkbcommon-dev libvulkan-dev libgl1-mesa-dev libusb-1.0-0-dev python3-dev libasound2-dev libturbojpeg0-dev libjpeg-dev libssl-dev pkg-config
```
**For Linux X11/XCB grabber support**
@ -136,7 +108,7 @@ See [AUR](https://aur.archlinux.org/packages/?O=0&SeB=nd&K=hyperion&outdated=&SB
The following dependencies are needed to build hyperion.ng on fedora.
```console
sudo dnf -y groupinstall "Development Tools"
sudo dnf install python3-devel qt-devel qt5-qtbase-devel qt5-qtserialport-devel xrandr xcb-util-image-devel qt5-qtx11extras-devel turbojpeg-devel libusb-devel xcb-util-devel dbus-devel openssl-devel fedora-packager rpmdevtools gcc libcec-devel
sudo dnf install python3-devel qt-devel qt5-qtbase-devel qt5-qtserialport-devel xrandr xcb-util-image-devel qt5-qtx11extras-devel alsa-lib-devel turbojpeg-devel libusb-devel xcb-util-devel dbus-devel openssl-devel fedora-packager rpmdevtools gcc libcec-devel
```
After installing the dependencies, you can continue with the compile instructions later on this page (the more detailed way..).

View File

@ -0,0 +1,42 @@
# Build a new Release
## Preparation
- Check, if new Ubuntu or Debian versions need to be added as build environment or remove unsupported (optional)
- Merge all outstading PRs or changes valid to be included in the release. Address any github-code-scanning findings before.
- Update missing non-English translations in Poeditor (optional)
- Export translations provided since last release from Poeditor into Hyperion-Git
- Update the `.version` file with the new release version
- Update the `CHANGELOG.md` with missing documentation and change from "Unreleased" to new release version.
- Push updated `.version` & `CHANGELOG.md` to master or create an PR (in case you might want to add some minor, late fixes)
## Execution
- Push a new tag to the master branch of hyperion-project/hyperion.ng repository, e.g. `git push origin 2.0.15`
The push will create a draft release including an update to Hyperion's apt repository
- On Hyperion's apt repository,
- Backup the main directory, in case a fall back is requried (optional)
- Move the content of the `draft-release` directory into the main diectory
- On GitHub, edit the draft release's description and publish the release
(this triggers the HyperBian build on top of the release)
- Check the HyperBian is build sucessfully with the correct release
## Rollover
Prepare next beta release and nighly builds
- Update the `.version` file with the next release version incl. beta.1, e.g. `2.0.16-beta.1`
- Add an "Unreleased" selection to `CHANGELOG.md`, plus empty sections to allow capturing changes.
- Push updated `.version` & `CHANGELOG.md` to master

View File

@ -7,12 +7,12 @@ In case of problems, it is recommended checking with the wider Hyperion communit
| Hardware | OS | Version | Screen-Grabber | Package | Comments |
|-----------|-----------------|--------------------|-----------------------------------------|-------------------------------------------------------------------------------|------------------------------------|
| X64 | Windows | 10 | QT&#xB9; | [Windows-AMD64.exe](https://github.com/hyperion-project/hyperion.ng/releases) | Direct X9 Grabber via self-compile |
| X64 | Ubuntu | 18.04, 20.04, 22.04&#xB2; | QT&#xB9;<br/>XCB/X11&#xB9; | [Linux-x86_64.deb](https://github.com/hyperion-project/hyperion.ng/releases) | |
| X64 | Debian | 9, 10, 11, 12&#xB3;| QT&#xB9;<br/>XCB/X11&#xB9; | [Linux-x86_64.deb](https://github.com/hyperion-project/hyperion.ng/releases) | |
| RPi 4 | HyperBian | 9, 10, 11, 12&#xB3;| QT&#xB9;<br/>XCB/X11&#xB9;<br/>DispmanX | [HyperBian.zip](https://github.com/Hyperion-Project/HyperBian/releases) | |
| RPi 4 | Raspberry Pi OS | 9, 10, 11, 12&#xB3;| QT&#xB9;<br/>XCB/X11&#xB9;<br/>DispmanX | [Linux-armv7l.deb](https://github.com/hyperion-project/hyperion.ng/releases) | |
| RPi 3 /3+ | HyperBian | 9, 10, 11, 12&#xB3;| QT&#xB9;<br/>XCB/X11&#xB9;<br/>DispmanX | [HyperBian.zip](https://github.com/hyperion-project/hyperion.ng/releases) | |
| RPi 3 /3+ | Raspberry Pi OS | 9, 10, 11, 12&#xB3;| QT&#xB9;<br/>XCB/X11&#xB9;<br/>DispmanX | [Linux-armv7l.deb](https://github.com/hyperion-project/hyperion.ng/releases) | |
| X64 | Ubuntu | 20.04, 22.04, 23.04&#xB2; | QT&#xB9;<br/>XCB/X11&#xB9; | [Linux-x86_64.deb](https://github.com/hyperion-project/hyperion.ng/releases) | |
| X64 | Debian | 10, 11, 12&#xB3; | QT&#xB9;<br/>XCB/X11&#xB9; | [Linux-x86_64.deb](https://github.com/hyperion-project/hyperion.ng/releases) | |
| RPi 4 | HyperBian | 10, 11, 12&#xB3; | QT&#xB9;<br/>XCB/X11&#xB9;<br/>DispmanX | [HyperBian.zip](https://github.com/Hyperion-Project/HyperBian/releases) | |
| RPi 4 | Raspberry Pi OS | 10, 11, 12&#xB3; | QT&#xB9;<br/>XCB/X11&#xB9;<br/>DispmanX | [Linux-armv7l.deb](https://github.com/hyperion-project/hyperion.ng/releases) | |
| RPi 3 /3+ | HyperBian | 10, 11, 12&#xB3; | QT&#xB9;<br/>XCB/X11&#xB9;<br/>DispmanX | [HyperBian.zip](https://github.com/hyperion-project/hyperion.ng/releases) | |
| RPi 3 /3+ | Raspberry Pi OS | 10, 11, 12&#xB3; | QT&#xB9;<br/>XCB/X11&#xB9;<br/>DispmanX | [Linux-armv7l.deb](https://github.com/hyperion-project/hyperion.ng/releases) | |
## Unofficial
In case you have an additional working setups you would like to share with the community, please get in touch or issue a PR to have the table updated.
@ -20,13 +20,18 @@ In case you have an additional working setups you would like to share with the c
| Hardware | OS | Version | Screen-Grabber | Package | Comments |
|---------------|-----------------|----------------|-----------------------------------------|---------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------|
| X64 | macOS | 11, 12 | QT<br>OSX | [macOS-x86_64.tar.gz](https://github.com/hyperion-project/hyperion.ng/releases) | M1 not tested |
| X64 | Fedora | 35 | QT&#xB9;<br/>XCB/X11&#xB9; | [Linux-x86_64.rpm](https://github.com/hyperion-project/hyperion.ng/releases) | |
| X64 | Fedora | 38 | QT&#xB9;<br/>XCB/X11&#xB9; | [Linux-x86_64.rpm](https://github.com/hyperion-project/hyperion.ng/releases) | |
| X64 | Arch | | QT&#xB9;<br/>XCB/X11&#xB9; | [Linux-x86_64.rpm](https://github.com/hyperion-project/hyperion.ng/releases) | |
| RPi 0/ 1 / 2 | Raspberry Pi OS | 9, 10, 11, 12&#xB3;| QT&#xB9;<br/>XCB/X11&#xB9;<br/>DispmanX | [Linux-armv6l.tar.gz](https://github.com/hyperion-project/hyperion.ng/releases) | No recommended |
| RPi 0/ 1 / 2 | Raspberry Pi OS | 10, 11, 12&#xB3;| QT&#xB9;<br/>XCB/X11&#xB9;<br/>DispmanX | [Linux-armv6l.tar.gz](https://github.com/hyperion-project/hyperion.ng/releases) | No recommended |
| X64 | LibreElec | 11.x (Nexus) | [Kodi add-on](https://github.com/hyperion-project/hyperion.kodi/releases) | [Linux-x86_64.tar.gz](https://github.com/hyperion-project/hyperion.ng/releases) | [Install on LibreELEC](https://hyperion-project.org/forum/index.php?thread/10463-install-hyperion-ng-on-libreelec-x86-64-rpi-inoffiziell-unofficially/) |
| RPi 4 | LibreElec | 11.x (Nexus) | - | [Linux-armv7l.tar.gz](https://github.com/hyperion-project/hyperion.ng/releases) | [Install on LibreELEC](https://hyperion-project.org/forum/index.php?thread/10463-install-hyperion-ng-on-libreelec-x86-64-rpi-inoffiziell-unofficially/) |
| RPi 4 | LibreElec | 10.x (Matrix) | - | [Linux-armv7l.tar.gz](https://github.com/hyperion-project/hyperion.ng/releases) | [Install on LibreELEC](https://hyperion-project.org/forum/index.php?thread/10463-install-hyperion-ng-on-libreelec-x86-64-rpi-inoffiziell-unofficially/) |
| RPi 4 | LibreElec | 9.2.x (Leia) | QT&#xB9;<br/>DispmanX | [Linux-armv7l.tar.gz](https://github.com/hyperion-project/hyperion.ng/releases) | [Install on LibreELEC](https://hyperion-project.org/forum/index.php?thread/10463-install-hyperion-ng-on-libreelec-x86-64-rpi-inoffiziell-unofficially/) |
| RPi 3 /3+ | LibreElec | 11.x (Nexus) | - | [Linux-armv7l.tar.gz](https://github.com/hyperion-project/hyperion.ng/releases) | [Install on LibreELEC](https://hyperion-project.org/forum/index.php?thread/10463-install-hyperion-ng-on-libreelec-x86-64-rpi-inoffiziell-unofficially/) |
| RPi 3 /3+ | LibreElec | 10.x (Matrix) | - | [Linux-armv7l.tar.gz](https://github.com/hyperion-project/hyperion.ng/releases) | [Install on LibreELEC](https://hyperion-project.org/forum/index.php?thread/10463-install-hyperion-ng-on-libreelec-x86-64-rpi-inoffiziell-unofficially/) |
| RPi 3 /3+ | LibreElec | 9.2.x (Leia) | QT&#xB9;<br/>DispmanX | [Linux-armv7l.tar.gz](https://github.com/hyperion-project/hyperion.ng/releases) | [Install on LibreELEC](https://hyperion-project.org/forum/index.php?thread/10463-install-hyperion-ng-on-libreelec-x86-64-rpi-inoffiziell-unofficially/) |
| Amlogic | CoreElec | 21.x (Omega) | Amlogic | CoreElec Plugin | Supported via CoreElec project |
| Amlogic | CoreElec | 20.x (Nexus) | Amlogic | CoreElec Plugin | Supported via CoreElec project |
| Amlogic | CoreElec | 19.x (Matrix) | Amlogic | CoreElec Plugin | Supported via CoreElec project |
| Amlogic | CoreElec | 9.2.x (Leia) | Amlogic | CoreElec Plugin | Supported via CoreElec project |
| Vero4K | OSMC | | | | [hyperion-vero4k](https://github.com/hissingshark/hyperion-vero4k) |
@ -35,5 +40,5 @@ In case you have an additional working setups you would like to share with the c
Legend
---
&#xB9; Requires an environment with `DISPLAY` defined\
&#xB2; 18=Bionic Beaver, 20=Focal Fossa, 22=Jammy Jellyfish\
&#xB3; 9=Stretch, 10=Buster, 11=Bullseye, 12=Bookworm
&#xB2; 20=Focal Fossa, 22=Jammy Jellyfish, 23=Lunar Lobster\
&#xB3; 10=Buster, 11=Bullseye, 12=Bookworm

View File

@ -1,54 +1,54 @@
import hyperion, time
# Get the parameters
speed = float(hyperion.args.get('speed', 1.0))
fadeFactor = float(hyperion.args.get('fadeFactor', 0.7))
color = hyperion.args.get('color', (255,0,0))
# Check parameters
speed = max(0.0001, speed)
fadeFactor = max(0.0, min(fadeFactor, 1.0))
# Initialize the led data
width = 25
imageData = bytearray(width * (0,0,0))
imageData[0] = color[0]
imageData[1] = color[1]
imageData[2] = color[2]
# Calculate the sleep time and rotation increment
increment = 1
sleepTime = 1.0 / (speed * width)
while sleepTime < 0.05:
increment *= 2
sleepTime *= 2
# Start the write data loop
position = 0
direction = 1
while not hyperion.abort():
hyperion.setImage(width, 1, imageData)
# Move data into next state
for i in range(increment):
position += direction
if position == -1:
position = 1
direction = 1
elif position == width:
position = width-2
direction = -1
# Fade the old data
for j in range(width):
imageData[3*j] = int(fadeFactor * imageData[3*j])
imageData[3*j+1] = int(fadeFactor * imageData[3*j+1])
imageData[3*j+2] = int(fadeFactor * imageData[3*j+2])
# Insert new data
imageData[3*position] = color[0]
imageData[3*position+1] = color[1]
imageData[3*position+2] = color[2]
# Sleep for a while
time.sleep(sleepTime)
import hyperion, time
# Get the parameters
speed = float(hyperion.args.get('speed', 1.0))
fadeFactor = float(hyperion.args.get('fadeFactor', 0.7))
color = hyperion.args.get('color', (255,0,0))
# Check parameters
speed = max(0.0001, speed)
fadeFactor = max(0.0, min(fadeFactor, 1.0))
# Initialize the led data
width = 25
imageData = bytearray(width * (0,0,0))
imageData[0] = color[0]
imageData[1] = color[1]
imageData[2] = color[2]
# Calculate the sleep time and rotation increment
increment = 1
sleepTime = 1.0 / (speed * width)
while sleepTime < 0.05:
increment *= 2
sleepTime *= 2
# Start the write data loop
position = 0
direction = 1
while not hyperion.abort():
hyperion.setImage(width, 1, imageData)
# Move data into next state
for unused in range(increment):
position += direction
if position == -1:
position = 1
direction = 1
elif position == width:
position = width-2
direction = -1
# Fade the old data
for j in range(width):
imageData[3*j] = int(fadeFactor * imageData[3*j])
imageData[3*j+1] = int(fadeFactor * imageData[3*j+1])
imageData[3*j+2] = int(fadeFactor * imageData[3*j+2])
# Insert new data
imageData[3*position] = color[0]
imageData[3*position+1] = color[1]
imageData[3*position+2] = color[2]
# Sleep for a while
time.sleep(sleepTime)

BIN
effects/matrix.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 KiB

View File

@ -9,8 +9,8 @@
"cropTop": 0,
"fps": 30,
"grayscale": false,
"imageSource": "url",
"imageSource": "file",
"reverse": false,
"url": "https://i.gifer.com/embedded/download/1j6F.gif"
"file": "matrix.gif"
}
}

View File

@ -1,23 +1,23 @@
import hyperion, time, colorsys
# Get the parameters
rotationTime = float(hyperion.args.get('rotation-time', 30.0))
brightness = float(hyperion.args.get('brightness', 100))/100.0
saturation = float(hyperion.args.get('saturation', 100))/100.0
reverse = bool(hyperion.args.get('reverse', False))
# Calculate the sleep time and hue increment
sleepTime = 0.1
hueIncrement = sleepTime / rotationTime
# Switch direction if needed
if reverse:
increment = -increment
# Start the write data loop
hue = 0.0
while not hyperion.abort():
rgb = colorsys.hsv_to_rgb(hue, saturation, brightness)
hyperion.setColor(int(255*rgb[0]), int(255*rgb[1]), int(255*rgb[2]))
hue = (hue + hueIncrement) % 1.0
time.sleep(sleepTime)
import hyperion, time, colorsys
# Get the parameters
rotationTime = float(hyperion.args.get('rotation-time', 30.0))
brightness = float(hyperion.args.get('brightness', 100))/100.0
saturation = float(hyperion.args.get('saturation', 100))/100.0
reverse = bool(hyperion.args.get('reverse', False))
# Calculate the sleep time and hue increment
sleepTime = 0.1
hueIncrement = sleepTime / rotationTime
# Switch direction if needed
if reverse:
hueIncrement = -hueIncrement
# Start the write data loop
hue = 0.0
while not hyperion.abort():
rgb = colorsys.hsv_to_rgb(hue, saturation, brightness)
hyperion.setColor(int(255*rgb[0]), int(255*rgb[1]), int(255*rgb[2]))
hue = (hue + hueIncrement) % 1.0
time.sleep(sleepTime)

View File

@ -1,43 +1,43 @@
import hyperion, time
# get options from args
sleepTime = float(hyperion.args.get('speed', 1.5)) * 0.005
whiteLevel = int(hyperion.args.get('whiteLevel', 0))
lvl = int(hyperion.args.get('colorLevel', 220))
# check value
whiteLevel = min( whiteLevel, 254 )
lvl = min( lvl, 255 )
if whiteLevel >= lvl:
lvl = 255
# Initialize the led data
ledData = bytearray()
for i in range(hyperion.ledCount):
ledData += bytearray((0,0,0))
runners = [
{ "pos":0, "step": 4, "lvl":lvl},
{ "pos":1, "step": 5, "lvl":lvl},
{ "pos":2, "step": 6, "lvl":lvl},
{ "pos":0, "step": 7, "lvl":lvl},
{ "pos":1, "step": 8, "lvl":lvl},
{ "pos":2, "step": 9, "lvl":lvl},
#{ "pos":0, "step":10, "lvl":lvl},
#{ "pos":1, "step":11, "lvl":lvl},
#{ "pos":2, "step":12, "lvl":lvl},
]
# Start the write data loop
counter = 0
while not hyperion.abort():
counter += 1
for r in runners:
if counter % r["step"] == 0:
ledData[r["pos"]] = whiteLevel
r["pos"] = (r["pos"]+3) % (hyperion.ledCount*3)
ledData[r["pos"]] = r["lvl"]
hyperion.setColor(ledData)
time.sleep(sleepTime)
import hyperion, time
# get options from args
sleepTime = float(hyperion.args.get('speed', 1.5)) * 0.005
whiteLevel = int(hyperion.args.get('whiteLevel', 0))
lvl = int(hyperion.args.get('colorLevel', 220))
# check value
whiteLevel = min( whiteLevel, 254 )
lvl = min( lvl, 255 )
if whiteLevel >= lvl:
lvl = 255
# Initialize the led data
ledData = bytearray()
for unused in range(hyperion.ledCount):
ledData += bytearray((0,0,0))
runners = [
{ "pos":0, "step": 4, "lvl":lvl},
{ "pos":1, "step": 5, "lvl":lvl},
{ "pos":2, "step": 6, "lvl":lvl},
{ "pos":0, "step": 7, "lvl":lvl},
{ "pos":1, "step": 8, "lvl":lvl},
{ "pos":2, "step": 9, "lvl":lvl},
#{ "pos":0, "step":10, "lvl":lvl},
#{ "pos":1, "step":11, "lvl":lvl},
#{ "pos":2, "step":12, "lvl":lvl},
]
# Start the write data loop
counter = 0
while not hyperion.abort():
counter += 1
for r in runners:
if counter % r["step"] == 0:
ledData[r["pos"]] = whiteLevel
r["pos"] = (r["pos"]+3) % (hyperion.ledCount*3)
ledData[r["pos"]] = r["lvl"]
hyperion.setColor(ledData)
time.sleep(sleepTime)

View File

@ -42,7 +42,7 @@ def buildGradient(cc, closeCircle = True):
pos = 0
if len(cc[0]) == 4:
withAlpha = True
for c in cc:
if withAlpha:
alpha = int(c[3]*255)
@ -50,7 +50,7 @@ def buildGradient(cc, closeCircle = True):
alpha = 255
pos += posfac
ba += bytearray([pos,c[0],c[1],c[2],alpha])
if closeCircle:
# last color as first color
lC = cc[-1]
@ -61,6 +61,7 @@ def buildGradient(cc, closeCircle = True):
ba += bytearray([0,lC[0],lC[1],lC[2],alpha])
return ba
return bytearray()
def rotateAngle( increment = 1):
global angle

View File

@ -1,98 +1,98 @@
import hyperion
import time
import colorsys
import random
min_len = int(hyperion.args.get('min_len', 3))
max_len = int(hyperion.args.get('max_len', 3))
#iHeight = int(hyperion.args.get('iHeight', 8))
trails = int(hyperion.args.get('int', 8))
sleepTime = float(hyperion.args.get('speed', 1)) / 1000.0
color = list(hyperion.args.get('color', (255,255,255)))
randomise = bool(hyperion.args.get('random', False))
iWidth = hyperion.imageWidth()
iHeight = hyperion.imageHeight()
class trail:
def __init__(self):
return
def start(self, x, y, step, color, _len, _h):
self.pos = 0.0
self.step = step
self.h = _h
self.x = x
self.data = []
brigtness = color[2]
step_brigtness = color[2] / _len
for i in range(0, _len):
rgb = colorsys.hsv_to_rgb(color[0], color[1], brigtness)
self.data.insert(0, (int(255*rgb[0]), int(255*rgb[1]), int(255*rgb[2])))
brigtness -= step_brigtness
self.data.extend([(0,0,0)]*(_h-y))
if len(self.data) < _h:
for i in range (_h-len(self.data)):
self.data.insert(0, (0,0,0))
def getdata(self):
self.pos += self.step
if self.pos > 1.0:
self.pos = 0.0
self.data.pop()
self.data.insert(0, (0,0,0))
return self.x, self.data[-self.h:], all(x == self.data[0] for x in self.data)
tr = []
for i in range(trails):
r = {'exec': trail()}
if randomise:
col = (random.uniform(0.0, 1.0),1,1)
else:
col = colorsys.rgb_to_hsv(color[0]/255.0, color[1]/255.0, color[2]/255.0)
r['exec'].start(
random.randint(0, iWidth),
random.randint(0, iHeight),
random.uniform(0.2, 0.8),
col,
random.randint(min_len, max_len),
iHeight
)
tr.append(r)
# Start the write data loop
while not hyperion.abort():
ledData = bytearray()
for r in tr:
r['x'], r['data'], c = r['exec'].getdata()
if c:
if randomise:
col = (random.uniform(0.0, 1.0),1,1)
else:
col = colorsys.rgb_to_hsv(color[0]/255.0, color[1]/255.0, color[2]/255.0)
r['exec'].start(
random.randint(0, iWidth),
random.randint(0, iHeight),
random.uniform(0.2, 0.8),
col,
random.randint(min_len, max_len),
iHeight
)
for y in range(0, iHeight):
for x in range(0, iWidth):
for r in tr:
if x == r['x']:
led = bytearray(r['data'][y])
break
led = bytearray((0,0,0))
ledData += led
hyperion.setImage(iWidth,iHeight,ledData)
time.sleep(sleepTime)
import hyperion
import time
import colorsys
import random
min_len = int(hyperion.args.get('min_len', 3))
max_len = int(hyperion.args.get('max_len', 3))
#iHeight = int(hyperion.args.get('iHeight', 8))
trails = int(hyperion.args.get('int', 8))
sleepTime = float(hyperion.args.get('speed', 1)) / 1000.0
color = list(hyperion.args.get('color', (255,255,255)))
randomise = bool(hyperion.args.get('random', False))
iWidth = hyperion.imageWidth()
iHeight = hyperion.imageHeight()
class trail:
def __init__(self):
return
def start(self, x, y, step, color, _len, _h):
self.pos = 0.0
self.step = step
self.h = _h
self.x = x
self.data = []
brigtness = color[2]
step_brigtness = color[2] / _len
for i in range(0, _len):
rgb = colorsys.hsv_to_rgb(color[0], color[1], brigtness)
self.data.insert(0, (int(255*rgb[0]), int(255*rgb[1]), int(255*rgb[2])))
brigtness -= step_brigtness
self.data.extend([(0,0,0)]*(_h-y))
if len(self.data) < _h:
for i in range (_h-len(self.data)):
self.data.insert(0, (0,0,0))
def getdata(self):
self.pos += self.step
if self.pos > 1.0:
self.pos = 0.0
self.data.pop()
self.data.insert(0, (0,0,0))
return self.x, self.data[-self.h:], all(x == self.data[0] for x in self.data)
tr = []
for unused in range(trails):
r = {'exec': trail()}
if randomise:
col = (random.uniform(0.0, 1.0),1,1)
else:
col = colorsys.rgb_to_hsv(color[0]/255.0, color[1]/255.0, color[2]/255.0)
r['exec'].start(
random.randint(0, iWidth),
random.randint(0, iHeight),
random.uniform(0.2, 0.8),
col,
random.randint(min_len, max_len),
iHeight
)
tr.append(r)
# Start the write data loop
while not hyperion.abort():
ledData = bytearray()
for r in tr:
r['x'], r['data'], c = r['exec'].getdata()
if c:
if randomise:
col = (random.uniform(0.0, 1.0),1,1)
else:
col = colorsys.rgb_to_hsv(color[0]/255.0, color[1]/255.0, color[2]/255.0)
r['exec'].start(
random.randint(0, iWidth),
random.randint(0, iHeight),
random.uniform(0.2, 0.8),
col,
random.randint(min_len, max_len),
iHeight
)
for y in range(0, iHeight):
for x in range(0, iWidth):
for r in tr:
if x == r['x']:
led = bytearray(r['data'][y])
break
led = bytearray((0,0,0))
ledData += led
hyperion.setImage(iWidth,iHeight,ledData)
time.sleep(sleepTime)

View File

@ -1,77 +1,71 @@
import hyperion, time, math, random
randomCenter = bool(hyperion.args.get('random-center', False))
centerX = float(hyperion.args.get('center_x', -0.15))
centerY = float(hyperion.args.get('center_y', -0.25))
rotationTime = float(hyperion.args.get('rotation_time', 90))
colors = hyperion.args.get('colors', ((255,0,0),(255,255,0),(0,255,0),(0,255,255),(0,0,255),(255,0,255)))
reverse = bool(hyperion.args.get('reverse', False))
reverseTime = int(hyperion.args.get('reverse_time', 0))
#rotate = bool(hyperion.args.get('rotate', True))
positions = []
# calc center if random
if randomCenter:
centerX = random.uniform(0.0, 1.0)
centerY = random.uniform(0.0, 1.0)
rCenterX = int(round(float(hyperion.imageWidth())*centerX))
rCenterY = int(round(float(hyperion.imageHeight())*centerY))
#calc interval
sleepTime = max(1/(255/rotationTime), 0.016)
#calc diagonal
if centerX < 0.5:
cX = 1.0-centerX
else:
cX = 0.0+centerX
if centerY < 0.5:
cY = 1.0-centerY
else:
cY = 0.0+centerY
diag = int(round(math.sqrt(((cX*hyperion.imageWidth())**2)+((cY*hyperion.imageHeight())**2))))
# some diagonal overhead
diag = int(diag*1.3)
# calc positions
pos = 0
step = int(255/len(colors))
for _ in colors:
positions.append(pos)
pos += step
# target time
targetTime = time.time()+float(reverseTime)
#hyperion.imageCOffset(int(hyperion.imageWidth()/2), int(hyperion.imageHeight()/2))
while not hyperion.abort():
# verify reverseTime, randomize reverseTime based on reverseTime up to reversedTime*2
if reverseTime >= 1:
now = time.time()
if now > targetTime:
reverse = not reverse
targetTime = time.time()+random.uniform(float(reverseTime), float(reverseTime*2.0))
# apply rotate
#if rotate:
# hyperion.imageCRotate(1)
# prepare bytearray with colors and positions
gradientBa = bytearray()
it = 0
for color in colors:
gradientBa += bytearray((positions[it],color[0],color[1],color[2]))
it += 1
hyperion.imageRadialGradient(rCenterX,rCenterY, diag, gradientBa,0)
# increment positions
for i, pos in enumerate(positions):
if reverse:
positions[i] = pos - 1 if pos >= 1 else 255
else:
positions[i] = pos + 1 if pos <= 254 else 0
hyperion.imageShow()
time.sleep(sleepTime)
import hyperion, time, math, random
randomCenter = bool(hyperion.args.get('random-center', False))
centerX = float(hyperion.args.get('center_x', -0.15))
centerY = float(hyperion.args.get('center_y', -0.25))
rotationTime = float(hyperion.args.get('rotation_time', 90))
colors = hyperion.args.get('colors', ((255,0,0),(255,255,0),(0,255,0),(0,255,255),(0,0,255),(255,0,255)))
reverse = bool(hyperion.args.get('reverse', False))
reverseTime = int(hyperion.args.get('reverse_time', 0))
positions = []
# calc center if random
if randomCenter:
centerX = random.uniform(0.0, 1.0)
centerY = random.uniform(0.0, 1.0)
rCenterX = int(round(float(hyperion.imageWidth())*centerX))
rCenterY = int(round(float(hyperion.imageHeight())*centerY))
#calc interval
sleepTime = max(1/(255/rotationTime), 0.016)
#calc diagonal
if centerX < 0.5:
cX = 1.0-centerX
else:
cX = 0.0+centerX
if centerY < 0.5:
cY = 1.0-centerY
else:
cY = 0.0+centerY
diag = int(round(math.hypot(cX*hyperion.imageWidth(),cY*hyperion.imageHeight())))
# some diagonal overhead
diag = int(diag*1.3)
# calc positions
pos = 0
step = int(255/len(colors))
for _ in colors:
positions.append(pos)
pos += step
# target time
targetTime = time.time()+float(reverseTime)
while not hyperion.abort():
# verify reverseTime, randomize reverseTime based on reverseTime up to reversedTime*2
if reverseTime >= 1:
now = time.time()
if now > targetTime:
reverse = not reverse
targetTime = time.time()+random.uniform(float(reverseTime), float(reverseTime*2.0))
# prepare bytearray with colors and positions
gradientBa = bytearray()
it = 0
for color in colors:
gradientBa += bytearray((positions[it],color[0],color[1],color[2]))
it += 1
hyperion.imageRadialGradient(rCenterX,rCenterY, diag, gradientBa,0)
# increment positions
for i, pos in enumerate(positions):
if reverse:
positions[i] = pos - 1 if pos >= 1 else 255
else:
positions[i] = pos + 1 if pos <= 254 else 0
hyperion.imageShow()
time.sleep(sleepTime)

View File

@ -1,30 +1,30 @@
import hyperion, time
# Get the parameters
sleepTime = float(hyperion.args.get('sleepTime', 1000))/1000.0
length = hyperion.args.get('length', 1)
color1 = hyperion.args.get('color1', (255,255,255))
color2 = hyperion.args.get('color2', (255,0,0))
# Initialize the led data
i = 0
ledDataOdd = bytearray()
while i < hyperion.ledCount:
for l in range(length):
if i<hyperion.ledCount:
ledDataOdd += bytearray((int(color1[0]), int(color1[1]), int(color1[2])))
i += 1
for l in range(length):
if i<hyperion.ledCount:
ledDataOdd += bytearray((int(color2[0]), int(color2[1]), int(color2[2])))
i += 1
ledDataEven = ledDataOdd[3*length:] + ledDataOdd[0:3*length]
# Start the write data loop
while not hyperion.abort():
hyperion.setColor(ledDataOdd)
time.sleep(sleepTime)
hyperion.setColor(ledDataEven)
time.sleep(sleepTime)
import hyperion, time
# Get the parameters
sleepTime = float(hyperion.args.get('sleepTime', 1000))/1000.0
length = hyperion.args.get('length', 1)
color1 = hyperion.args.get('color1', (255,255,255))
color2 = hyperion.args.get('color2', (255,0,0))
# Initialize the led data
i = 0
ledDataOdd = bytearray()
while i < hyperion.ledCount:
for unused in range(length):
if i<hyperion.ledCount:
ledDataOdd += bytearray((int(color1[0]), int(color1[1]), int(color1[2])))
i += 1
for unused in range(length):
if i<hyperion.ledCount:
ledDataOdd += bytearray((int(color2[0]), int(color2[1]), int(color2[2])))
i += 1
ledDataEven = ledDataOdd[3*length:] + ledDataOdd[0:3*length]
# Start the write data loop
while not hyperion.abort():
hyperion.setColor(ledDataOdd)
time.sleep(sleepTime)
hyperion.setColor(ledDataEven)
time.sleep(sleepTime)

View File

@ -157,12 +157,7 @@ protected:
///
bool setHyperionInstance(quint8 inst);
///
/// @brief Get all contrable components and their state
///
std::map<hyperion::Components, bool> getAllComponents();
///
///
/// @brief Check if Hyperion ist enabled
/// @return True when enabled else false
///

View File

@ -88,6 +88,11 @@ private slots:
///
void handleInstanceStateChange(InstanceState state, quint8 instance, const QString &name = QString());
///
/// @brief Stream a new LED Colors update
///
void streamLedColorsUpdate();
signals:
///
/// Signal emits with the reply message provided with handleMessage()
@ -99,6 +104,26 @@ signals:
///
void forwardJsonMessage(QJsonObject);
///
/// Signal emits whenever a suspend/resume request for all instances should be forwarded
///
void suspendAll(bool isSuspend);
///
/// Signal emits whenever a toggle suspend/resume request for all instances should be forwarded
///
void toggleSuspendAll();
///
/// Signal emits whenever a idle mode request for all instances should be forwarded
///
void idleAll(bool isIdle);
///
/// Signal emits whenever a toggle idle/working mode request for all instances should be forwarded
///
void toggleIdleAll();
private:
// true if further callbacks are forbidden (http)
bool _noListener;
@ -298,6 +323,12 @@ private:
///
void handleServiceCommand(const QJsonObject &message, const QString &command, int tan);
/// Handle an incoming JSON message for actions related to the overall Hyperion system
///
/// @param message the incoming message
///
void handleSystemCommand(const QJsonObject &message, const QString &command, int tan);
///
/// Handle an incoming JSON message of unknown type
///

View File

@ -1,4 +1,3 @@
//#include <iostream>
#pragma once
// Utils includes
@ -219,7 +218,6 @@ namespace hyperion
|| !isBlack(image((width - x), y))
|| !isBlack(image((width - x), (height - y))))
{
// std::cout << "y " << y << " lt " << int(isBlack(color1)) << " lb " << int(isBlack(color2)) << " rt " << int(isBlack(color3)) << " rb " << int(isBlack(color4)) << std::endl;
firstNonBlackYPixelIndex = y;
break;
}

View File

@ -111,7 +111,7 @@ public:
// server port services
list << "jsonServer" << "protoServer" << "flatbufServer" << "forwarder" << "webConfig" << "network"
// capture
<< "framegrabber" << "grabberV4L2"
<< "framegrabber" << "grabberV4L2" << "grabberAudio"
// other
<< "logger" << "general";

View File

@ -0,0 +1,196 @@
#ifndef AUDIOGRABBER_H
#define AUDIOGRABBER_H
#include <QObject>
#include <QColor>
#include <cmath>
// Hyperion-utils includes
#include <utils/ColorRgb.h>
#include <hyperion/Grabber.h>
#include <utils/Logger.h>
///
/// Base Audio Grabber Class
///
/// This class is extended by the windows audio grabber to provied DirectX9 access to the audio devices
/// This class is extended by the linux audio grabber to provide ALSA access to the audio devices
///
/// @brief The DirectX9 capture implementation
///
class AudioGrabber : public Grabber
{
Q_OBJECT
public:
///
/// Device properties
///
/// this structure holds the name, id, and inputs of the enumerated audio devices.
///
struct DeviceProperties
{
QString name = QString();
QString id = QString();
QMultiMap<QString, int> inputs = QMultiMap<QString, int>();
};
AudioGrabber();
~AudioGrabber() override;
///
/// Start audio capturing session
///
/// @returns true if successful
virtual bool start();
///
/// Stop audio capturing session
///
virtual void stop();
///
/// Restart the audio capturing session
///
void restart();
Logger* getLog();
///
/// Set Device
///
/// configures the audio device used by the grabber
///
/// @param[in] device identifier of audio device
void setDevice(const QString& device);
///
/// Set Configuration
///
/// sets the audio grabber's configuration parameters
///
/// @param[in] config object of configuration parameters
void setConfiguration(const QJsonObject& config);
///
/// Reset Multiplier
///
/// resets the calcualted audio multiplier so that it is recalculated
/// currently the multiplier is only reduced based on loudness.
///
/// TODO: also calculate a low signal and reset the multiplier
///
void resetMultiplier();
///
/// Discover
///
/// discovers audio devices in the system
///
/// @param[in] params discover parameters
/// @return array of audio devices
virtual QJsonArray discover(const QJsonObject& params);
signals:
void newFrame(const Image<ColorRgb>& image);
protected:
///
/// Process Audio Frame
///
/// this functions takes in an audio buffer and emits a visual representation of the audio data
///
/// @param[in] buffer The audio buffer to process
/// @param[in] length The length of audio data in the buffer
void processAudioFrame(int16_t* buffer, int length);
///
/// Audio device id / properties map
///
/// properties include information such as name, inputs, and etc...
///
QMap<QString, AudioGrabber::DeviceProperties> _deviceProperties;
///
/// Current device
///
QString _device;
///
/// Hot Color
///
/// the color of the leds when the signal is high or hot
///
QColor _hotColor;
///
/// Warn value
///
/// The maximum value of the warning color. above this threshold the signal is considered hot
///
int _warnValue;
///
/// Warn color
///
/// the color of the leds when the signal is in between the safe and warn value threshold
///
QColor _warnColor;
///
/// Save value
///
/// The maximum value of the safe color. above this threshold the signal enteres the warn zone.
/// below the signal is in the safe zone.
///
int _safeValue;
///
/// Safe color
///
/// the color of the leds when the signal is below the safe threshold
///
QColor _safeColor;
///
/// Multiplier
///
/// this value is used to multiply the input signal value. Some inputs may have a very low signal
/// and the multiplier is used to get the desired visualization.
///
/// When the multiplier is configured to 0, the multiplier is automatically configured based off of the average
/// signal amplitude and tolernace.
///
double _multiplier;
///
/// Tolerance
///
/// The tolerance is used to calculate what percentage of the top end part of the signal to ignore when
/// calculating the multiplier. This enables the effect to reach the hot zone with an auto configured multiplier
///
int _tolerance;
///
/// Dynamic Multiplier
///
/// This is the current value of the automatically configured multiplier.
///
double _dynamicMultiplier;
///
/// Started
///
/// true if the capturing session has started.
///
bool _started;
private:
///
/// @brief free the _screen pointer
///
void freeResources();
};
#endif // AUDIOGRABBER_H

View File

@ -0,0 +1,91 @@
#ifndef AUDIOGRABBERLINUX_H
#define AUDIOGRABBERLINUX_H
#include <pthread.h>
#include <sched.h>
#include <alsa/asoundlib.h>
// Hyperion-utils includes
#include <grabber/AudioGrabber.h>
///
/// @brief The Linux Audio capture implementation
///
class AudioGrabberLinux : public AudioGrabber
{
public:
AudioGrabberLinux();
~AudioGrabberLinux() override;
///
/// Process audio buffer
///
void processAudioBuffer(snd_pcm_sframes_t frames);
///
/// Is Running Flag
///
std::atomic<bool> _isRunning;
///
/// Current capture device
///
snd_pcm_t * _captureDevice;
public slots:
///
/// Start audio capturing session
///
/// @returns true if successful
bool start() override;
///
/// Stop audio capturing session
///
void stop() override;
///
/// Discovery audio devices
///
QJsonArray discover(const QJsonObject& params) override;
private:
///
/// Refresh audio devices
///
void refreshDevices();
///
/// Configure current audio capture interface
///
bool configureCaptureInterface();
///
/// Get device name from path
///
QString getDeviceName(const QString& devicePath) const;
///
/// Current sample rate
///
unsigned int _sampleRate;
///
/// Audio capture thread
///
pthread_t _audioThread;
///
/// ALSA device configuration parameters
///
snd_pcm_hw_params_t * _captureDeviceConfig;
};
///
/// Audio processing thread function
///
static void* AudioThreadRunner(void* params);
#endif // AUDIOGRABBERLINUX_H

View File

@ -0,0 +1,81 @@
#ifndef AUDIOGRABBERWINDOWS_H
#define AUDIOGRABBERWINDOWS_H
// Hyperion-utils includes
#include <grabber/AudioGrabber.h>
#include <DSound.h>
///
/// @brief The Windows Audio capture implementation
///
class AudioGrabberWindows : public AudioGrabber
{
public:
AudioGrabberWindows();
~AudioGrabberWindows() override;
public slots:
bool start() override;
void stop() override;
QJsonArray discover(const QJsonObject& params) override;
private:
void refreshDevices();
bool configureCaptureInterface();
QString getDeviceName(const QString& devicePath) const;
void processAudioBuffer();
LPDIRECTSOUNDCAPTURE8 recordingDevice;
LPDIRECTSOUNDCAPTUREBUFFER8 recordingBuffer;
HANDLE audioThread;
DWORD bufferCapturePosition;
DWORD bufferCaptureSize;
DWORD notificationSize;
static DWORD WINAPI AudioThreadRunner(LPVOID param);
HANDLE notificationEvent;
std::atomic<bool> isRunning{ false };
static BOOL CALLBACK DirectSoundEnumProcessor(LPGUID deviceIdGuid, LPCWSTR deviceDescStr,
LPCWSTR deviceModelStr, LPVOID context)
{
// Skip undefined audio devices
if (deviceIdGuid == NULL)
return TRUE;
QMap<QString, AudioGrabber::DeviceProperties>* devices = (QMap<QString, AudioGrabber::DeviceProperties>*)context;
AudioGrabber::DeviceProperties device;
// Process Device Information
QString deviceName = QString::fromWCharArray(deviceDescStr);
// Process Device ID
LPOLESTR deviceIdStr;
HRESULT res = StringFromCLSID(*deviceIdGuid, &deviceIdStr);
if (FAILED(res))
{
Error(Logger::getInstance("AUDIOGRABBER"), "Failed to get CLSID-string for %s with error: 0x%08x: %s", QSTRING_CSTR(deviceName), res, std::system_category().message(res).c_str());
return FALSE;
}
QString deviceId = QString::fromWCharArray(deviceIdStr);
CoTaskMemFree(deviceIdStr);
Debug(Logger::getInstance("AUDIOGRABBER"), "Found Audio Device: %s", QSTRING_CSTR(deviceName));
device.id = deviceId;
device.name = deviceName;
devices->insert(deviceId, device);
return TRUE;
}
};
#endif // AUDIOGRABBERWINDOWS_H

View File

@ -0,0 +1,69 @@
#pragma once
#include <hyperion/GrabberWrapper.h>
#ifdef WIN32
#include <grabber/AudioGrabberWindows.h>
#endif
#ifdef __linux__
#include <grabber/AudioGrabberLinux.h>
#endif
///
/// Audio Grabber wrapper
///
class AudioWrapper : public GrabberWrapper
{
public:
// The AudioWrapper has no params...
///
/// Constructs the Audio grabber with a specified grab size and update rate.
///
/// @param[in] device Audio Device Identifier
/// @param[in] updateRate_Hz The audio grab rate [Hz]
///
AudioWrapper();
///
/// Destructor of this Audio grabber. Releases any claimed resources.
///
~AudioWrapper() override;
///
/// Settings update handler
///
void handleSettingsUpdate(settings::type type, const QJsonDocument& config) override;
public slots:
///
/// Performs a single frame grab and computes the led-colors
///
void action() override;
///
/// Start audio capturing session
///
/// @returns true if successful
bool start() override;
///
/// Stop audio capturing session
///
void stop() override;
private:
void newFrame(const Image<ColorRgb>& image);
/// The actual grabber
#ifdef WIN32
AudioGrabberWindows _grabber;
#endif
#ifdef __linux__
AudioGrabberLinux _grabber;
#endif
};

View File

@ -4,12 +4,14 @@
enum class GrabberType {
SCREEN,
VIDEO,
AUDIO,
};
enum class GrabberTypeFilter {
ALL,
SCREEN,
VIDEO,
AUDIO,
};
#endif // GRABBERTYPE_H

View File

@ -20,6 +20,7 @@ public:
, _hyperion(hyperion)
, _prioMuxer(_hyperion->getMuxerInstance())
, _isBgEffectEnabled(false)
, _isSuspended(false)
{
QString subComponent = parent()->property("instance").toString();
_log = Logger::getInstance("HYPERION", subComponent);
@ -33,6 +34,11 @@ public:
this->handlePriorityUpdate();
});
// listen for suspend/resume requests, to not start a background effect when system goes into suspend mode
connect(_hyperion, &Hyperion::suspendRequest, this, [=] (bool isSuspended) {
_isSuspended = isSuspended;
});
// initialization
handleSettingsUpdate(settings::BGEFFECT, _hyperion->getSetting(settings::BGEFFECT));
}
@ -109,7 +115,7 @@ private slots:
Debug(_log,"Stop background (color-) effect as it moved out of scope");
_hyperion->clear(PriorityMuxer::BG_PRIORITY);
}
else if (_prioMuxer->getCurrentPriority() == PriorityMuxer::LOWEST_PRIORITY && _isBgEffectEnabled)
else if (!_isSuspended && _prioMuxer->getCurrentPriority() == PriorityMuxer::LOWEST_PRIORITY && _isBgEffectEnabled)
{
Debug(_log,"Start background (color-) effect as it moved in scope");
emit handleSettingsUpdate (settings::BGEFFECT, _bgEffectConfig);
@ -126,6 +132,8 @@ private:
QJsonDocument _bgEffectConfig;
bool _isBgEffectEnabled;
bool _isSuspended;
};
#endif // BGEFFECTHANDLER_H

View File

@ -20,6 +20,7 @@ public:
void setSystemCaptureEnable(bool enable);
void setV4LCaptureEnable(bool enable);
void setAudioCaptureEnable(bool enable);
private slots:
///
@ -48,11 +49,22 @@ private slots:
///
void handleV4lImage(const QString& name, const Image<ColorRgb> & image);
///
/// @brief forward audio image
/// @param image The image
///
void handleAudioImage(const QString& name, const Image<ColorRgb>& image);
///
/// @brief Is called from _v4lInactiveTimer to set source after specific time to inactive
///
void setV4lInactive();
///
/// @brief Is called from _audioInactiveTimer to set source after specific time to inactive
///
void setAudioInactive();
///
/// @brief Is called from _systemInactiveTimer to set source after specific time to inactive
///
@ -73,4 +85,10 @@ private:
quint8 _v4lCaptPrio;
QString _v4lCaptName;
QTimer* _v4lInactiveTimer;
/// Reflect state of audio capture and prio
bool _audioCaptEnabled;
quint8 _audioCaptPrio;
QString _audioCaptName;
QTimer* _audioInactiveTimer;
};

View File

@ -7,12 +7,15 @@
#include <map>
#include <QObject>
#include <QVector>
class Hyperion;
typedef QVector<hyperion::Components> ComponentList;
///
/// @brief The component register reflects and manages the current state of all components and Hyperion as a whole
/// It emits also real component state changes (triggert from the specific component), which can be used for listening APIs (Network Clients/Plugins)
/// It emits also real component state changes (triggered from the specific component), which can be used for listening APIs (Network Clients/Plugins)
///
class ComponentRegister : public QObject
{
@ -36,23 +39,32 @@ signals:
///
/// @brief Emits whenever a component changed (really) the state
/// @param comp The component
/// @param state The new state of the component
/// @param isActive The new state of the component
///
void updatedComponentState(hyperion::Components comp, bool state);
void updatedComponentState(hyperion::Components comp, bool isActive);
public slots:
///
/// @brief is called whenever a component change a state, DO NOT CALL FROM API, use signal hyperion->compStateChangeRequest
/// @param comp The component
/// @param state The new state of the component
/// @param isActive The new state of the component
///
void setNewComponentState(hyperion::Components comp, bool activated);
void setNewComponentState(hyperion::Components comp, bool isActive);
private slots:
///
/// @brief Handle COMP_ALL changes from Hyperion->compStateChangeRequest
/// @param comp COMP_ALL
/// @param isActive The new state for all components
///
void handleCompStateChangeRequest(hyperion::Components comps, bool activated);
void handleCompStateChangeRequest(hyperion::Components comps, bool isActive);
///
/// @brief Activate/Deactivate all components, except those provided by the list of excluded components
/// @param isActive The new state for all components
/// @param execludeList of excluded components
///
void handleCompStateChangeRequestAll(bool isActive, const ComponentList& excludeList = ComponentList{});
private:
/// Hyperion instance

View File

@ -43,8 +43,10 @@ public:
static QMap<int, QString> GRABBER_SYS_CLIENTS;
static QMap<int, QString> GRABBER_V4L_CLIENTS;
static QMap<int, QString> GRABBER_AUDIO_CLIENTS;
static bool GLOBAL_GRABBER_SYS_ENABLE;
static bool GLOBAL_GRABBER_V4L_ENABLE;
static bool GLOBAL_GRABBER_AUDIO_ENABLE;
///
/// Starts the grabber which produces led values with the specified update rate
@ -78,6 +80,8 @@ public:
void setSysGrabberState(bool sysGrabberState){ GLOBAL_GRABBER_SYS_ENABLE = sysGrabberState; }
bool getV4lGrabberState() const { return GLOBAL_GRABBER_V4L_ENABLE; }
void setV4lGrabberState(bool v4lGrabberState){ GLOBAL_GRABBER_V4L_ENABLE = v4lGrabberState; }
bool getAudioGrabberState() const { return GLOBAL_GRABBER_AUDIO_ENABLE; }
void setAudioGrabberState(bool audioGrabberState) { GLOBAL_GRABBER_AUDIO_ENABLE = audioGrabberState; }
static QStringList availableGrabbers(GrabberTypeFilter type = GrabberTypeFilter::ALL);
@ -147,10 +151,7 @@ private slots:
void handleSourceRequest(hyperion::Components component, int hyperionInd, bool listen);
///
/// @brief Update Update capture rate
/// @param type interval between frames in milliseconds
///
void updateTimer(int interval);
protected:
@ -168,6 +169,11 @@ protected:
///
virtual bool close() { return true; }
/// @brief Update Update capture rate
/// @param type interval between frames in milliseconds
///
void updateTimer(int interval);
QString _grabberName;

View File

@ -389,6 +389,20 @@ public slots:
int getLatchTime() const;
///
/// @brief Set hyperion in suspend mode or resume from suspend/idle.
/// All instances and components will be disabled/enabled.
/// @param isSupend True, components will be deactivated, else put into their previous state before suspend
///
void setSuspend(bool isSupend);
///
/// @brief Set hyperion in idle /working mode.
/// In idle, all instances and components will be disabled besides the output processing (LED-Devices, smoothing).
/// @param isIdle True, selected components will be deactivated, else put into their previous state before idle
///
void setIdle(bool isIdle);
signals:
/// Signal which is emitted when a priority channel is actively cleared
/// This signal will not be emitted when a priority channel time out
@ -406,6 +420,18 @@ signals:
///
void compStateChangeRequest(hyperion::Components component, bool enabled);
///
/// @brief Emits when all (besides excluded) components are subject to state changes
/// @param isActive The new state for all components
/// @param execlude List of excluded components
void compStateChangeRequestAll(bool isActive, const ComponentList& excludeList = {});
/// Signal which is emitted, when system is to be suspended/resumed
void suspendRequest(bool isSuspend);
/// Signal which is emitted, when system should go into idle/working mode
void idleRequest(bool isIdle);
///
/// @brief Emits whenever the imageToLedsMapping has changed
/// @param mappingType The new mapping type
@ -428,6 +454,9 @@ signals:
/// Signal which is emitted, when a new V4l proto image should be forwarded
void forwardV4lProtoMessage(const QString&, const Image<ColorRgb>&);
/// Signal which is emitted, when a new Audio proto image should be forwarded
void forwardAudioProtoMessage(const QString&, const Image<ColorRgb>&);
#if defined(ENABLE_FLATBUF_SERVER) || defined(ENABLE_PROTOBUF_SERVER)
/// Signal which is emitted, when a new Flat-/Proto- Buffer image should be forwarded
void forwardBufferMessage(const QString&, const Image<ColorRgb>&);

View File

@ -74,10 +74,26 @@ public slots:
bool stopInstance(quint8 inst);
///
/// @brief Toggle the state of all Hyperion instances
/// @param pause If true all instances toggle to pause, else to resume
/// @brief Suspend (disable) all Hyperion instances
///
void toggleStateAllInstances(bool pause = false);
void suspend();
///
/// @brief Resume (resume) all Hyperion instances
///
void resume();
///
/// @brief Toggle the state of all Hyperion instances for an idle sceanrio (user is not interacting with the system
/// @param isIdle, If true all instances toggle to idle, else to resume
///
void toggleIdle(bool isIdle);
///
/// @brief Toggle the state of all Hyperion instances
/// @param enable, If false all instances toggle to pause, else to resume
///
void toggleStateAllInstances(bool enable = false);
///
/// @brief Create a new Hyperion instance entry in db
@ -125,6 +141,11 @@ signals:
///
void startInstanceResponse(QObject *caller, const int &tan);
void triggerSuspend(bool isSuspend);
void triggerToggleSuspend();
void triggerIdle(bool isIdle);
void triggerToggleIdle();
signals:
///////////////////////////////////////
/// FROM HYPERIONDAEMON TO HYPERION ///

View File

@ -1,6 +1,7 @@
#pragma once
#include <QString>
#include <QSharedPointer>
// Utils includes
#include <utils/Image.h>
@ -46,7 +47,7 @@ public:
/// @param[in] width The new width of the buffer-image
/// @param[in] height The new height of the buffer-image
///
void setSize(unsigned width, unsigned height);
void setSize(int width, int height);
///
/// @brief Update the led string (eg on settings change)
@ -56,6 +57,19 @@ public:
/// Returns state of black border detector
bool blackBorderDetectorEnabled() const;
///
/// Factor to reduce the number of pixels evaluated during processing
///
/// @param[in] count Use every "count" pixel
void setReducedPixelSetFactorFactor(int count);
///
/// Set the accuracy used during processing
/// (only for selected types)
///
/// @param[in] level The accuracy level (0-4)
void setAccuracyLevel(int level);
/// Returns the current _userMappingType, this may not be the current applied type!
int getUserLedMappingType() const { return _userMappingType; }
@ -98,30 +112,45 @@ public:
}
///
/// Processes the image to a list of led colors. This will update the size of the buffer-image
/// if required and call the image-to-leds mapping to determine the mean color per led.
/// Processes the image to a list of LED colors. This will update the size of the buffer-image
/// if required and call the image-to-LEDs mapping to determine the color per LED.
///
/// @param[in] image The image to translate to led values
/// @param[in] image The image to translate to LED values
///
/// @return The color value per led
/// @return The color value per LED
///
template <typename Pixel_T>
std::vector<ColorRgb> process(const Image<Pixel_T>& image)
{
std::vector<ColorRgb> colors;
if (image.width()>0 && image.height()>0)
{
// Ensure that the buffer-image is the proper size
setSize(image);
assert(!_imageToLedColors.isNull());
// Check black border detection
verifyBorder(image);
// Create a result vector and call the 'in place' function
switch (_mappingType)
{
case 1: colors = _imageToLeds->getUniLedColor(image); break;
default: colors = _imageToLeds->getMeanLedColor(image);
case 1:
colors = _imageToLedColors->getUniLedColor(image);
break;
case 2:
colors = _imageToLedColors->getMeanLedColorSqrt(image);
break;
case 3:
colors = _imageToLedColors->getDominantLedColor(image);
break;
case 4:
colors = _imageToLedColors->getDominantLedColorAdv(image);
break;
default:
colors = _imageToLedColors->getMeanLedColor(image);
}
}
else
@ -136,8 +165,8 @@ public:
///
/// Determines the led colors of the image in the buffer.
///
/// @param[in] image The image to translate to led values
/// @param[out] ledColors The color value per led
/// @param[in] image The image to translate to LED values
/// @param[out] ledColors The color value per LED
///
template <typename Pixel_T>
void process(const Image<Pixel_T>& image, std::vector<ColorRgb>& ledColors)
@ -153,8 +182,20 @@ public:
// Determine the mean or uni colors of each led (using the existing mapping)
switch (_mappingType)
{
case 1: _imageToLeds->getUniLedColor(image, ledColors); break;
default: _imageToLeds->getMeanLedColor(image, ledColors);
case 1:
_imageToLedColors->getUniLedColor(image, ledColors);
break;
case 2:
_imageToLedColors->getMeanLedColorSqrt(image, ledColors);
break;
case 3:
_imageToLedColors->getDominantLedColor(image, ledColors);
break;
case 4:
_imageToLedColors->getDominantLedColorAdv(image, ledColors);
break;
default:
_imageToLedColors->getMeanLedColor(image, ledColors);
}
}
else
@ -164,9 +205,9 @@ public:
}
///
/// Get the hscan and vscan parameters for a single led
/// Get the hscan and vscan parameters for a single LED
///
/// @param[in] led Index of the led
/// @param[in] led Index of the LED
/// @param[out] hscanBegin begin of the hscan
/// @param[out] hscanEnd end of the hscan
/// @param[out] vscanBegin begin of the hscan
@ -175,6 +216,13 @@ public:
bool getScanParameters(size_t led, double & hscanBegin, double & hscanEnd, double & vscanBegin, double & vscanEnd) const;
private:
void registerProcessingUnit(
int width,
int height,
int horizontalBorder,
int verticalBorder);
///
/// Performs black-border detection (if enabled) on the given image
///
@ -183,34 +231,25 @@ private:
template <typename Pixel_T>
void verifyBorder(const Image<Pixel_T> & image)
{
if (!_borderProcessor->enabled() && ( _imageToLeds->horizontalBorder()!=0 || _imageToLeds->verticalBorder()!=0 ))
if (!_borderProcessor->enabled() && ( _imageToLedColors->horizontalBorder()!=0 || _imageToLedColors->verticalBorder()!=0 ))
{
Debug(_log, "Reset border");
_borderProcessor->process(image);
delete _imageToLeds;
_imageToLeds = new hyperion::ImageToLedsMap(image.width(), image.height(), 0, 0, _ledString.leds());
registerProcessingUnit(image.width(), image.height(), 0, 0);
}
if(_borderProcessor->enabled() && _borderProcessor->process(image))
{
const hyperion::BlackBorder border = _borderProcessor->getCurrentBorder();
// Clean up the old mapping
delete _imageToLeds;
if (border.unknown)
{
// Construct a new buffer and mapping
_imageToLeds = new hyperion::ImageToLedsMap(image.width(), image.height(), 0, 0, _ledString.leds());
registerProcessingUnit(image.width(), image.height(), 0, 0);
}
else
{
// Construct a new buffer and mapping
_imageToLeds = new hyperion::ImageToLedsMap(image.width(), image.height(), border.horizontalSize, border.verticalSize, _ledString.leds());
registerProcessingUnit(image.width(), image.height(), border.horizontalSize, border.verticalSize);
}
//Debug(Logger::getInstance("BLACKBORDER"), "CURRENT BORDER TYPE: unknown=%d hor.size=%d vert.size=%d",
// border.unknown, border.horizontalSize, border.verticalSize );
}
}
@ -218,6 +257,7 @@ private slots:
void handleSettingsUpdate(settings::type type, const QJsonDocument& config);
private:
Logger * _log;
/// The Led-string specification
LedString _ledString;
@ -226,15 +266,18 @@ private:
hyperion::BlackBorderProcessor * _borderProcessor;
/// The mapping of image-pixels to LEDs
hyperion::ImageToLedsMap* _imageToLeds;
QSharedPointer<hyperion::ImageToLedsMap> _imageToLedColors;
/// Type of image 2 led mapping
/// Type of image to LED mapping
int _mappingType;
/// Type of last requested user type
int _userMappingType;
/// Type of last requested hard type
int _hardMappingType;
int _accuraryLevel;
int _reducedPixelSetFactorFactor;
/// Hyperion instance pointer
Hyperion* _hyperion;
};

View File

@ -1,72 +1,90 @@
#pragma once
#ifndef IMAGETOLEDSMAP_H
#define IMAGETOLEDSMAP_H
// STL includes
#include <cassert>
#include <memory>
#include <sstream>
#include <cmath>
// hyperion-utils includes
#include <utils/Image.h>
#include <utils/Logger.h>
#include <utils/ColorRgbScalar.h>
#include <utils/ColorSys.h>
// hyperion includes
#include <hyperion/LedString.h>
namespace hyperion
{
///
/// The ImageToLedsMap holds a mapping of indices into an image to leds. It can be used to
/// calculate the average (or mean) color per led for a specific region.
/// The ImageToLedsMap holds a mapping of indices into an image to LEDs. It can be used to
/// calculate the average (aka mean) or dominant color per LED for a given region.
///
class ImageToLedsMap
class ImageToLedsMap : public QObject
{
Q_OBJECT
public:
///
/// Constructs an mapping from the absolute indices in an image to each led based on the border
/// definition given in the list of leds. The map holds absolute indices to any given image,
/// Constructs an mapping from the absolute indices in an image to each LED based on the border
/// definition given in the list of LEDs. The map holds absolute indices to any given image,
/// provided that it is row-oriented.
/// The mapping is created purely on size (width and height). The given borders are excluded
/// from indexing.
///
/// @param[in] log Logger
/// @param[in] width The width of the indexed image
/// @param[in] height The width of the indexed image
/// @param[in] horizontalBorder The size of the horizontal border (0=no border)
/// @param[in] verticalBorder The size of the vertical border (0=no border)
/// @param[in] leds The list with led specifications
/// @param[in] reducedProcessingFactor Factor to reduce the number of pixels evaluated during processing
/// @param[in] accuraryLevel The accuracy used during processing (only for selected types)
///
ImageToLedsMap(
const unsigned width,
const unsigned height,
const unsigned horizontalBorder,
const unsigned verticalBorder,
const std::vector<Led> & leds);
Logger* log,
int width,
int height,
int horizontalBorder,
int verticalBorder,
const std::vector<Led> & leds,
int reducedProcessingFactor = 0,
int accuraryLevel = 0);
///
/// Returns the width of the indexed image
///
/// @return The width of the indexed image [pixels]
///
unsigned width() const;
int width() const;
///
/// Returns the height of the indexed image
///
/// @return The height of the indexed image [pixels]
///
unsigned height() const;
int height() const;
unsigned horizontalBorder() const { return _horizontalBorder; }
unsigned verticalBorder() const { return _verticalBorder; }
int horizontalBorder() const { return _horizontalBorder; }
int verticalBorder() const { return _verticalBorder; }
///
/// Determines the mean color for each led using the mapping the image given
/// Set the accuracy used during processing
/// (only for selected types)
///
/// @param[in] level The accuracy level (0-4)
void setAccuracyLevel (int level);
///
/// Determines the mean color for each LED using the LED area mapping given
/// at construction.
///
/// @param[in] image The image from which to extract the led colors
///
/// @return ledColors The vector containing the output
/// @return The vector containing the output
///
template <typename Pixel_T>
std::vector<ColorRgb> getMeanLedColor(const Image<Pixel_T> & image) const
@ -77,20 +95,18 @@ namespace hyperion
}
///
/// Determines the mean color for each led using the mapping the image given
/// Determines the mean color for each LED using the LED area mapping given
/// at construction.
///
/// @param[in] image The image from which to extract the led colors
/// @param[in] image The image from which to extract the LED colors
/// @param[out] ledColors The vector containing the output
///
template <typename Pixel_T>
void getMeanLedColor(const Image<Pixel_T> & image, std::vector<ColorRgb> & ledColors) const
{
// Sanity check for the number of leds
//assert(_colorsMap.size() == ledColors.size());
if(_colorsMap.size() != ledColors.size())
{
Debug(Logger::getInstance("HYPERION"), "ImageToLedsMap: colorsMap.size != ledColors.size -> %d != %d", _colorsMap.size(), ledColors.size());
Debug(_log, "ImageToLedsMap: colorsMap.size != ledColors.size -> %d != %d", _colorsMap.size(), ledColors.size());
return;
}
@ -104,12 +120,52 @@ namespace hyperion
}
///
/// Determines the uni color for each led using the mapping the image given
/// Determines the mean color squared for each LED using the LED area mapping given
/// at construction.
///
/// @param[in] image The image from which to extract the led colors
///
/// @return ledColors The vector containing the output
/// @return The vector containing the output
///
template <typename Pixel_T>
std::vector<ColorRgb> getMeanLedColorSqrt(const Image<Pixel_T> & image) const
{
std::vector<ColorRgb> colors(_colorsMap.size(), ColorRgb{0,0,0});
getMeanLedColorSqrt(image, colors);
return colors;
}
///
/// Determines the mean color squared for each LED using the LED area mapping given
/// at construction.
///
/// @param[in] image The image from which to extract the LED colors
/// @param[out] ledColors The vector containing the output
///
template <typename Pixel_T>
void getMeanLedColorSqrt(const Image<Pixel_T> & image, std::vector<ColorRgb> & ledColors) const
{
if(_colorsMap.size() != ledColors.size())
{
Debug(_log, "ImageToLedsMap: colorsMap.size != ledColors.size -> %d != %d", _colorsMap.size(), ledColors.size());
return;
}
// Iterate each led and compute the mean
auto led = ledColors.begin();
for (auto colors = _colorsMap.begin(); colors != _colorsMap.end(); ++colors, ++led)
{
const ColorRgb color = calcMeanColorSqrt(image, *colors);
*led = color;
}
}
///
/// Determines the mean color of the image and assigns it to all LEDs
///
/// @param[in] image The image from which to extract the led color
///
/// @return The vector containing the output
///
template <typename Pixel_T>
std::vector<ColorRgb> getUniLedColor(const Image<Pixel_T> & image) const
@ -120,57 +176,145 @@ namespace hyperion
}
///
/// Determines the uni color for each led using the mapping the image given
/// at construction.
/// Determines the mean color of the image and assigns it to all LEDs
///
/// @param[in] image The image from which to extract the led colors
/// @param[in] image The image from which to extract the LED colors
/// @param[out] ledColors The vector containing the output
///
template <typename Pixel_T>
void getUniLedColor(const Image<Pixel_T> & image, std::vector<ColorRgb> & ledColors) const
{
// Sanity check for the number of leds
// assert(_colorsMap.size() == ledColors.size());
if(_colorsMap.size() != ledColors.size())
{
Debug(Logger::getInstance("HYPERION"), "ImageToLedsMap: colorsMap.size != ledColors.size -> %d != %d", _colorsMap.size(), ledColors.size());
Debug(_log, "ImageToLedsMap: colorsMap.size != ledColors.size -> %d != %d", _colorsMap.size(), ledColors.size());
return;
}
// calculate uni color
const ColorRgb color = calcMeanColor(image);
//Update all LEDs with same color
std::fill(ledColors.begin(),ledColors.end(), color);
}
private:
/// The width of the indexed image
const unsigned _width;
/// The height of the indexed image
const unsigned _height;
const unsigned _horizontalBorder;
const unsigned _verticalBorder;
/// The absolute indices into the image for each led
std::vector<std::vector<int32_t>> _colorsMap;
///
/// Determines the dominant color for each LED using the LED area mapping given
/// at construction.
///
/// @param[in] image The image from which to extract the LED color
///
/// @return The vector containing the output
///
template <typename Pixel_T>
std::vector<ColorRgb> getDominantLedColor(const Image<Pixel_T> & image) const
{
std::vector<ColorRgb> colors(_colorsMap.size(), ColorRgb{0,0,0});
getDominantLedColor(image, colors);
return colors;
}
///
/// Calculates the 'mean color' of the given list. This is the mean over each color-channel
/// Determines the dominant color for each LED using the LED area mapping given
/// at construction.
///
/// @param[in] image The image from which to extract the LED colors
/// @param[out] ledColors The vector containing the output
///
template <typename Pixel_T>
void getDominantLedColor(const Image<Pixel_T> & image, std::vector<ColorRgb> & ledColors) const
{
// Sanity check for the number of LEDs
if(_colorsMap.size() != ledColors.size())
{
Debug(_log, "ImageToLedsMap: colorsMap.size != ledColors.size -> %d != %d", _colorsMap.size(), ledColors.size());
return;
}
// Iterate each led and compute the dominant color
auto led = ledColors.begin();
for (auto colors = _colorsMap.begin(); colors != _colorsMap.end(); ++colors, ++led)
{
const ColorRgb color = calculateDominantColor(image, *colors);
*led = color;
}
}
///
/// Determines the dominant color using a k-means algorithm for each LED using the LED area mapping given
/// at construction.
///
/// @param[in] image The image from which to extract the LED color
///
/// @return The vector containing the output
///
template <typename Pixel_T>
std::vector<ColorRgb> getDominantLedColorAdv(const Image<Pixel_T> & image) const
{
std::vector<ColorRgb> colors(_colorsMap.size(), ColorRgb{0,0,0});
getDominantLedColorAdv(image, colors);
return colors;
}
///
/// Determines the dominant color using a k-means algorithm for each LED using the LED area mapping given
/// at construction.
///
/// @param[in] image The image from which to extract the LED colors
/// @param[out] ledColors The vector containing the output
///
template <typename Pixel_T>
void getDominantLedColorAdv(const Image<Pixel_T> & image, std::vector<ColorRgb> & ledColors) const
{
// Sanity check for the number of LEDs
if(_colorsMap.size() != ledColors.size())
{
Debug(_log, "ImageToLedsMap: colorsMap.size != ledColors.size -> %d != %d", _colorsMap.size(), ledColors.size());
return;
}
// Iterate each led and compute the dominant color
auto led = ledColors.begin();
for (auto colors = _colorsMap.begin(); colors != _colorsMap.end(); ++colors, ++led)
{
const ColorRgb color = calculateDominantColorAdv(image, *colors);
*led = color;
}
}
private:
Logger* _log;
/// The width of the indexed image
const int _width;
/// The height of the indexed image
const int _height;
const int _horizontalBorder;
const int _verticalBorder;
/// Evaluate every "count" pixel
int _nextPixelCount;
/// Number of clusters used during dominant color advanced processing (k-means)
int _clusterCount;
/// The absolute indices into the image for each led
std::vector<std::vector<int>> _colorsMap;
///
/// Calculates the 'mean color' over the given image. This is the mean over each color-channel
/// (red, green, blue)
///
/// @param[in] image The image a section from which an average color must be computed
/// @param[in] colors The list with colors
/// @param[in] pixels The list of pixel indices for the given image to be evaluated///
///
/// @return The mean of the given list of colors (or black when empty)
///
template <typename Pixel_T>
ColorRgb calcMeanColor(const Image<Pixel_T> & image, const std::vector<int32_t> & colors) const
ColorRgb calcMeanColor(const Image<Pixel_T> & image, const std::vector<int32_t> & pixels) const
{
const auto colorVecSize = colors.size();
if (colorVecSize == 0)
const auto pixelNum = pixels.size();
if (pixelNum == 0)
{
return ColorRgb::BLACK;
}
@ -179,20 +323,20 @@ namespace hyperion
uint_fast32_t cummRed = 0;
uint_fast32_t cummGreen = 0;
uint_fast32_t cummBlue = 0;
const auto& imgData = image.memptr();
for (const unsigned colorOffset : colors)
const auto& imgData = image.memptr();
for (const int pixelOffset : pixels)
{
const auto& pixel = imgData[colorOffset];
const auto& pixel = imgData[pixelOffset];
cummRed += pixel.red;
cummGreen += pixel.green;
cummBlue += pixel.blue;
}
// Compute the average of each color channel
const uint8_t avgRed = uint8_t(cummRed/colorVecSize);
const uint8_t avgGreen = uint8_t(cummGreen/colorVecSize);
const uint8_t avgBlue = uint8_t(cummBlue/colorVecSize);
const uint8_t avgRed = uint8_t(cummRed/pixelNum);
const uint8_t avgGreen = uint8_t(cummGreen/pixelNum);
const uint8_t avgBlue = uint8_t(cummBlue/pixelNum);
// Return the computed color
return {avgRed, avgGreen, avgBlue};
@ -213,11 +357,11 @@ namespace hyperion
uint_fast32_t cummRed = 0;
uint_fast32_t cummGreen = 0;
uint_fast32_t cummBlue = 0;
const unsigned imageSize = image.width() * image.height();
const unsigned pixelNum = image.width() * image.height();
const auto& imgData = image.memptr();
for (unsigned idx=0; idx<imageSize; idx++)
for (unsigned idx=0; idx<pixelNum; idx++)
{
const auto& pixel = imgData[idx];
cummRed += pixel.red;
@ -226,13 +370,293 @@ namespace hyperion
}
// Compute the average of each color channel
const uint8_t avgRed = uint8_t(cummRed/imageSize);
const uint8_t avgGreen = uint8_t(cummGreen/imageSize);
const uint8_t avgBlue = uint8_t(cummBlue/imageSize);
const uint8_t avgRed = uint8_t(cummRed/pixelNum);
const uint8_t avgGreen = uint8_t(cummGreen/pixelNum);
const uint8_t avgBlue = uint8_t(cummBlue/pixelNum);
// Return the computed color
return {avgRed, avgGreen, avgBlue};
}
///
/// Calculates the 'mean color' squared over the given image. This is the mean over each color-channel
/// (red, green, blue)
///
/// @param[in] image The image a section from which an average color must be computed
/// @param[in] pixels The list of pixel indices for the given image to be evaluated
///
/// @return The mean of the given list of colors (or black when empty)
///
template <typename Pixel_T>
ColorRgb calcMeanColorSqrt(const Image<Pixel_T> & image, const std::vector<int32_t> & pixels) const
{
const auto pixelNum = pixels.size();
if (pixelNum == 0)
{
return ColorRgb::BLACK;
}
// Accumulate the squared sum of each separate color channel
uint_fast32_t cummRed = 0;
uint_fast32_t cummGreen = 0;
uint_fast32_t cummBlue = 0;
const auto& imgData = image.memptr();
for (const int colorOffset : pixels)
{
const auto& pixel = imgData[colorOffset];
cummRed += pixel.red * pixel.red;
cummGreen += pixel.green * pixel.green;
cummBlue += pixel.blue * pixel.blue;
}
// Compute the average of each color channel
#ifdef WIN32
#undef min
#endif
const uint8_t avgRed = static_cast<uint8_t>(std::min(std::lround(std::sqrt(static_cast<double>(cummRed / pixelNum))), 255L));
const uint8_t avgGreen = static_cast<uint8_t>(std::min(std::lround(sqrt(static_cast<double>(cummGreen / pixelNum))), 255L));
const uint8_t avgBlue = static_cast<uint8_t>(std::min(std::lround(sqrt(static_cast<double>(cummBlue / pixelNum))), 255L));
// Return the computed color
return {avgRed, avgGreen, avgBlue};
}
///
/// Calculates the 'mean color' squared over the given image. This is the mean over each color-channel
/// (red, green, blue)
///
/// @param[in] image The image a section from which an average color must be computed
///
/// @return The mean of the given list of colors (or black when empty)
///
template <typename Pixel_T>
ColorRgb calcMeanColorSqrt(const Image<Pixel_T> & image) const
{
// Accumulate the squared sum of each separate color channel
uint_fast32_t cummRed = 0;
uint_fast32_t cummGreen = 0;
uint_fast32_t cummBlue = 0;
const unsigned pixelNum = image.width() * image.height();
const auto& imgData = image.memptr();
for (int idx=0; idx<pixelNum; ++idx)
{
const auto& pixel = imgData[idx];
cummRed += pixel.red * pixel.red;
cummGreen += pixel.green * pixel.green;
cummBlue += pixel.blue * pixel.blue;
}
// Compute the average of each color channel
const uint8_t avgRed = uint8_t(std::lround(sqrt(static_cast<double>(cummRed/pixelNum))));
const uint8_t avgGreen = uint8_t(std::lround(sqrt(static_cast<double>(cummGreen/pixelNum))));
const uint8_t avgBlue = uint8_t(std::lround(sqrt(static_cast<double>(cummBlue/pixelNum))));
// Return the computed color
return {avgRed, avgGreen, avgBlue};
}
///
/// Calculates the 'dominant color' of an image area defined by a list of pixel indices
///
/// @param[in] image The image for which a dominant color is to be computed
/// @param[in] pixels The list of pixel indices for the given image to be evaluated
///
/// @return The image area's dominant color or black, if no pixel indices provided
///
template <typename Pixel_T>
ColorRgb calculateDominantColor(const Image<Pixel_T> & image, const std::vector<int> & pixels) const
{
ColorRgb dominantColor {ColorRgb::BLACK};
const auto pixelNum = pixels.size();
if (pixelNum > 0)
{
const auto& imgData = image.memptr();
QMap<QRgb,int> colorDistributionMap;
int count = 0;
for (const int pixelOffset : pixels)
{
QRgb color = imgData[pixelOffset].rgb();
if (colorDistributionMap.contains(color)) {
colorDistributionMap[color] = colorDistributionMap[color] + 1;
}
else {
colorDistributionMap[color] = 1;
}
int colorsFound = colorDistributionMap[color];
if (colorsFound > count) {
dominantColor.setRgb(color);
count = colorsFound;
}
}
}
return dominantColor;
}
///
/// Calculates the 'dominant color' of an image
///
/// @param[in] image The image for which a dominant color is to be computed
///
/// @return The image's dominant color
///
template <typename Pixel_T>
ColorRgb calculateDominantColor(const Image<Pixel_T> & image) const
{
const unsigned pixelNum = image.width() * image.height();
std::vector<int> pixels(pixelNum);
std::iota(pixels.begin(), pixels.end(), 0);
return calculateDominantColor(image, pixels);
}
template <typename Pixel_T>
struct ColorCluster {
ColorCluster():count(0) {}
ColorCluster(Pixel_T color):count(0),color(color) {}
Pixel_T color;
Pixel_T newColor;
int count;
};
const ColorRgb DEFAULT_CLUSTER_COLORS[5] {
{ColorRgb::BLACK},
{ColorRgb::GREEN},
{ColorRgb::WHITE},
{ColorRgb::RED},
{ColorRgb::YELLOW}
};
///
/// Calculates the 'dominant color' of an image area defined by a list of pixel indices
/// using a k-means algorithm (https://robocraft.ru/computervision/1063)
///
/// @param[in] image The image for which a dominant color is to be computed
/// @param[in] pixels The list of pixel indices for the given image to be evaluated
///
/// @return The image area's dominant color or black, if no pixel indices provided
///
template <typename Pixel_T>
ColorRgb calculateDominantColorAdv(const Image<Pixel_T> & image, const std::vector<int> & pixels) const
{
ColorRgb dominantColor {ColorRgb::BLACK};
const auto pixelNum = pixels.size();
if (pixelNum > 0)
{
// initial cluster with different colors
auto clusters = std::unique_ptr< ColorCluster<ColorRgbScalar> >(new ColorCluster<ColorRgbScalar>[_clusterCount]);
for(int k = 0; k < _clusterCount; ++k)
{
clusters.get()[k].newColor = DEFAULT_CLUSTER_COLORS[k];
}
// k-means
double min_rgb_euclidean {0};
double old_rgb_euclidean {0};
while(1)
{
for(int k = 0; k < _clusterCount; ++k)
{
clusters.get()[k].count = 0;
clusters.get()[k].color = clusters.get()[k].newColor;
clusters.get()[k].newColor.setRgb(ColorRgb::BLACK);
}
const auto& imgData = image.memptr();
for (const int pixelOffset : pixels)
{
const auto& pixel = imgData[pixelOffset];
min_rgb_euclidean = 255 * 255 * 255;
int clusterIndex = -1;
for(int k = 0; k < _clusterCount; ++k)
{
double euclid = ColorSys::rgb_euclidean(ColorRgbScalar(pixel), clusters.get()[k].color);
if( euclid < min_rgb_euclidean ) {
min_rgb_euclidean = euclid;
clusterIndex = k;
}
}
clusters.get()[clusterIndex].count++;
clusters.get()[clusterIndex].newColor += ColorRgbScalar(pixel);
}
min_rgb_euclidean = 0;
for(int k = 0; k < _clusterCount; ++k)
{
if (clusters.get()[k].count > 0)
{
// new color
clusters.get()[k].newColor /= clusters.get()[k].count;
double ecli = ColorSys::rgb_euclidean(clusters.get()[k].newColor, clusters.get()[k].color);
if(ecli > min_rgb_euclidean)
{
min_rgb_euclidean = ecli;
}
}
}
if( fabs(min_rgb_euclidean - old_rgb_euclidean) < 1)
{
break;
}
old_rgb_euclidean = min_rgb_euclidean;
}
int colorsFoundMax = 0;
int dominantClusterIdx {0};
for(int clusterIdx=0; clusterIdx < _clusterCount; ++clusterIdx){
int colorsFoundinCluster = clusters.get()[clusterIdx].count;
if (colorsFoundinCluster > colorsFoundMax) {
colorsFoundMax = colorsFoundinCluster;
dominantClusterIdx = clusterIdx;
}
}
dominantColor.red = static_cast<uint8_t>(clusters.get()[dominantClusterIdx].newColor.red);
dominantColor.green = static_cast<uint8_t>(clusters.get()[dominantClusterIdx].newColor.green);
dominantColor.blue = static_cast<uint8_t>(clusters.get()[dominantClusterIdx].newColor.blue);
}
return dominantColor;
}
///
/// Calculates the 'dominant color' of an image area defined by a list of pixel indices
/// using a k-means algorithm (https://robocraft.ru/computervision/1063)
///
/// @param[in] image The image for which a dominant color is to be computed
///
/// @return The image's dominant color
///
template <typename Pixel_T>
ColorRgb calculateDominantColorAdv(const Image<Pixel_T> & image) const
{
const unsigned pixelNum = image.width() * image.height();
std::vector<int> pixels(pixelNum);
std::iota(pixels.begin(), pixels.end(), 0);
return calculateDominantColorAdv(image, pixels);
}
};
} // end namespace hyperion
#endif // IMAGETOLEDSMAP_H

View File

@ -10,6 +10,7 @@
// QT includes
#include <QString>
#include <QJsonArray>
// Forward class declarations
namespace Json { class Value; }
@ -73,7 +74,7 @@ inline ColorOrder stringToColorOrder(const QString & order)
}
///
/// The Led structure contains the definition of the image portion used to determine a single led's
/// The Led structure contains the definition of the image portion used to determine a single LED's
/// color.
/// @verbatim
/// |--------------------image--|
@ -89,39 +90,66 @@ inline ColorOrder stringToColorOrder(const QString & order)
///
struct Led
{
/// The minimum vertical scan line included for this leds color
/// The minimum vertical scan line included for this LEDs color
double minX_frac;
/// The maximum vertical scan line included for this leds color
/// The maximum vertical scan line included for this LEDs color
double maxX_frac;
/// The minimum horizontal scan line included for this leds color
/// The minimum horizontal scan line included for this LEDs color
double minY_frac;
/// The maximum horizontal scan line included for this leds color
/// The maximum horizontal scan line included for this LEDs color
double maxY_frac;
/// A LEDs at {0,0,0,0} is not visible and therefore treated as blacklisted
bool isBlacklisted {false};
/// the color order
ColorOrder colorOrder;
};
///
/// The LedString contains the image integration information of the leds
/// The LedString contains the image integration information of the LEDs
///
class LedString
{
public:
///
/// Returns the led specifications
/// Returns the LED specifications
///
/// @return The list with led specifications
///
std::vector<Led>& leds();
///
/// Returns the led specifications
/// Returns the LED specifications
///
/// @return The list with led specifications
///
const std::vector<Led>& leds() const;
///
/// Returns the IDs of blacklisted LEDs
///
/// @return ID List of blacklisted LEDs
///
std::vector<int>& blacklistedLedIds();
///
/// Returns the IDs of blacklisted LEDs
///
/// @return ID List of blacklisted LEDs
///
const std::vector<int>& blacklistedLedIds() const;
///
/// Check, if teh layout has blacklisted LEDs configured
///
/// @return True, if blacklisted LEDs are configured
///
bool hasBlackListedLeds ();
static LedString createLedString(const QJsonArray& ledConfigArray, const ColorOrder deviceOrder);
private:
/// The list with led specifications
std::vector<Led> mLeds;
/// The list with LED specifications
std::vector<Led> _leds;
/// The list containing IDs of blacklisted LED
std::vector<int> _blacklistedLedIds;
};

View File

@ -289,6 +289,9 @@ private:
int _currentConfigId;
bool _enabled;
//The system enable state, to restore smoothing state after effect with smoothing ran
bool _enabledSystemCfg;
/// The type of smoothing to perform
SmoothingType _smoothingType;

View File

@ -438,7 +438,10 @@ protected:
uint _ledRGBWCount;
/// Does the device allow restoring the original state?
bool _isRestoreOrigState;
bool _isRestoreOrigState;
/// Does the device should be kept on after streaming
bool _isStayOnAfterStreaming;
/// Device, lights state before streaming via hyperion
QJsonObject _orignalStateValues;
@ -460,6 +463,9 @@ protected:
/// Is the device in error state and stopped?
bool _isDeviceInError;
/// Is the device in error state, but is retries might resolve the situation?
bool _isDeviceRecoverable;
/// Timestamp of last write
QDateTime _lastWriteTime;
@ -476,8 +482,9 @@ protected slots:
/// @brief Set device in error state
///
/// @param[in] errorMsg The error message to be logged
/// @param[in] isRecoverable If False, no further retries will be done
///
virtual void setInError( const QString& errorMsg);
virtual void setInError( const QString& errorMsg, bool isRecoverable=true);
private:

View File

@ -19,6 +19,7 @@
// Utility includes
#include <utils/Logger.h>
#include <utils/WeakConnect.h>
namespace {
constexpr std::chrono::milliseconds DEFAULT_DISCOVER_TIMEOUT{ 500 };
@ -103,61 +104,6 @@ private slots:
void onServiceRemoved(const QMdnsEngine::Service& service);
private:
// template <typename Func1, typename Func2, typename std::enable_if_t<std::is_member_pointer<Func2>::value, int> = 0>
// static inline QMetaObject::Connection weakConnect(typename QtPrivate::FunctionPointer<Func1>::Object* sender,
// Func1 signal,
// typename QtPrivate::FunctionPointer<Func2>::Object* receiver,
// Func2 slot)
// {
// QMetaObject::Connection conn_normal = QObject::connect(sender, signal, receiver, slot);
// QMetaObject::Connection* conn_delete = new QMetaObject::Connection();
// *conn_delete = QObject::connect(sender, signal, [conn_normal, conn_delete]() {
// QObject::disconnect(conn_normal);
// QObject::disconnect(*conn_delete);
// delete conn_delete;
// });
// return conn_normal;
// }
template <typename Func1, typename Func2, typename std::enable_if_t<!std::is_member_pointer<Func2>::value, int> = 0>
static inline QMetaObject::Connection weakConnect(typename QtPrivate::FunctionPointer<Func1>::Object* sender,
Func1 signal,
Func2 slot)
{
QMetaObject::Connection conn_normal = QObject::connect(sender, signal, slot);
QMetaObject::Connection* conn_delete = new QMetaObject::Connection();
*conn_delete = QObject::connect(sender, signal, [conn_normal, conn_delete]() {
QObject::disconnect(conn_normal);
QObject::disconnect(*conn_delete);
delete conn_delete;
});
return conn_normal;
}
// template <typename Func1, typename Func2, typename std::enable_if_t<!std::is_member_pointer<Func2>::value, int> = 0>
// static inline QMetaObject::Connection weakConnect(typename QtPrivate::FunctionPointer<Func1>::Object* sender,
// Func1 signal,
// typename QtPrivate::FunctionPointer<Func2>::Object* receiver,
// Func2 slot)
// {
// Q_UNUSED(receiver);
// QMetaObject::Connection conn_normal = QObject::connect(sender, signal, slot);
// QMetaObject::Connection* conn_delete = new QMetaObject::Connection();
// *conn_delete = QObject::connect(sender, signal, [conn_normal, conn_delete]() {
// QObject::disconnect(conn_normal);
// QObject::disconnect(*conn_delete);
// delete conn_delete;
// });
// return conn_normal;
// }
/// The logger instance for mDNS-Service
Logger* _log;

View File

@ -4,7 +4,9 @@
#include <cstdint>
#include <iostream>
#include <QString>
#include <QTextStream>
#include <QRgb>
///
/// Plain-Old-Data structure containing the red-green-blue color specification. Size of the
@ -51,6 +53,18 @@ struct ColorRgb
return a;
}
QRgb rgb() const
{
return qRgb(red,green,blue);
}
void setRgb(QRgb rgb)
{
red = static_cast<uint8_t>(qRed(rgb));
green = static_cast<uint8_t>(qGreen(rgb));
blue = static_cast<uint8_t>(qBlue(rgb));
}
QString toQString() const
{
return QString("(%1,%2,%3)").arg(red).arg(green).arg(blue);

View File

@ -0,0 +1,203 @@
#ifndef COLORRGBSCALAR_H
#define COLORRGBSCALAR_H
// STL includes
#include <cstdint>
#include <iostream>
#include <QString>
#include <QTextStream>
#include <QRgb>
#include <utils/ColorRgb.h>
///
/// Plain-Old-Data structure containing the red-green-blue color specification. Size of the
/// structure is exactly 3 times int for easy writing to led-device
///
struct ColorRgbScalar
{
/// The red color channel
int red;
/// The green color channel
int green;
/// The blue color channel
int blue;
/// 'Black' RgbColor (0, 0, 0)
static const ColorRgbScalar BLACK;
/// 'Red' RgbColor (255, 0, 0)
static const ColorRgbScalar RED;
/// 'Green' RgbColor (0, 255, 0)
static const ColorRgbScalar GREEN;
/// 'Blue' RgbColor (0, 0, 255)
static const ColorRgbScalar BLUE;
/// 'Yellow' RgbColor (255, 255, 0)
static const ColorRgbScalar YELLOW;
/// 'White' RgbColor (255, 255, 255)
static const ColorRgbScalar WHITE;
ColorRgbScalar() = default;
ColorRgbScalar(int _red, int _green,int _blue):
red(_red),
green(_green),
blue(_blue)
{
}
ColorRgbScalar(ColorRgb rgb):
red(rgb.red),
green(rgb.green),
blue(rgb.blue)
{
}
ColorRgbScalar operator-(const ColorRgbScalar& b) const
{
ColorRgbScalar a(*this);
a.red -= b.red;
a.green -= b.green;
a.blue -= b.blue;
return a;
}
void setRgb(QRgb rgb)
{
red = qRed(rgb);
green = qGreen(rgb);
blue = qBlue(rgb);
}
void setRgb(ColorRgb rgb)
{
red = rgb.red;
green = rgb.green;
blue = rgb.blue;
}
QString toQString() const
{
return QString("(%1,%2,%3)").arg(red).arg(green).arg(blue);
}
};
/// Assert to ensure that the size of the structure is 'only' 3 times int
static_assert(sizeof(ColorRgbScalar) == 3 * sizeof(int), "Incorrect size of ColorRgbInt");
///
/// Stream operator to write ColorRgbInt to an outputstream (format "'{'[red]','[green]','[blue]'}'")
///
/// @param os The output stream
/// @param color The color to write
/// @return The output stream (with the color written to it)
///
inline std::ostream& operator<<(std::ostream& os, const ColorRgbScalar& color)
{
os << "{"
<< static_cast<unsigned>(color.red) << ","
<< static_cast<unsigned>(color.green) << ","
<< static_cast<unsigned>(color.blue)
<< "}";
return os;
}
///
/// Stream operator to write ColorRgbInt to a QTextStream (format "'{'[red]','[green]','[blue]'}'")
///
/// @param os The output stream
/// @param color The color to write
/// @return The output stream (with the color written to it)
///
inline QTextStream& operator<<(QTextStream &os, const ColorRgbScalar& color)
{
os << "{"
<< static_cast<unsigned>(color.red) << ","
<< static_cast<unsigned>(color.green) << ","
<< static_cast<unsigned>(color.blue)
<< "}";
return os;
}
/// Compare operator to check if a color is 'equal' to another color
inline bool operator==(const ColorRgbScalar & lhs, const ColorRgbScalar & rhs)
{
return lhs.red == rhs.red &&
lhs.green == rhs.green &&
lhs.blue == rhs.blue;
}
/// Compare operator to check if a color is 'smaller' than another color
inline bool operator<(const ColorRgbScalar & lhs, const ColorRgbScalar & rhs)
{
return lhs.red < rhs.red &&
lhs.green < rhs.green &&
lhs.blue < rhs.blue;
}
/// Compare operator to check if a color is 'not equal' to another color
inline bool operator!=(const ColorRgbScalar & lhs, const ColorRgbScalar & rhs)
{
return !(lhs == rhs);
}
/// Compare operator to check if a color is 'smaller' than or 'equal' to another color
inline bool operator<=(const ColorRgbScalar & lhs, const ColorRgbScalar & rhs)
{
return lhs.red <= rhs.red &&
lhs.green <= rhs.green &&
lhs.blue <= rhs.blue;
}
/// Compare operator to check if a color is 'greater' to another color
inline bool operator>(const ColorRgbScalar & lhs, const ColorRgbScalar & rhs)
{
return lhs.red > rhs.red &&
lhs.green > rhs.green &&
lhs.blue > rhs.blue;
}
/// Compare operator to check if a color is 'greater' than or 'equal' to another color
inline bool operator>=(const ColorRgbScalar & lhs, const ColorRgbScalar & rhs)
{
return lhs.red >= rhs.red &&
lhs.green >= rhs.green &&
lhs.blue >= rhs.blue;
}
inline ColorRgbScalar& operator+=(ColorRgbScalar& lhs, const ColorRgbScalar& rhs)
{
lhs.red += rhs.red;
lhs.green += rhs.green;
lhs.blue += rhs.blue;
return lhs;
}
inline ColorRgbScalar operator+(ColorRgbScalar lhs, const ColorRgbScalar rhs)
{
lhs += rhs;
return lhs;
}
inline ColorRgbScalar& operator/=(ColorRgbScalar& lhs, int count)
{
if (count > 0)
{
lhs.red /= count;
lhs.green /= count;
lhs.blue /= count;
}
return lhs;
}
inline ColorRgbScalar operator/(ColorRgbScalar lhs, int count)
{
lhs /= count;
return lhs;
}
#endif // COLORRGBSCALAR_H

View File

@ -30,11 +30,11 @@ struct ColorRgba
static const ColorRgba WHITE;
};
/// Assert to ensure that the size of the structure is 'only' 3 bytes
/// Assert to ensure that the size of the structure is 'only' 4 bytes
static_assert(sizeof(ColorRgba) == 4, "Incorrect size of ColorARGB");
///
/// Stream operator to write ColorRgb to an outputstream (format "'{'[alpha]', '[red]','[green]','[blue]'}'")
/// Stream operator to write ColorRgba to an outputstream (format "'{'[alpha]', '[red]','[green]','[blue]'}'")
///
/// @param os The output stream
/// @param color The color to write

View File

@ -105,6 +105,19 @@ public:
/// @note See https://bottosson.github.io/posts/colorpicker/#okhsv
///
static void okhsv2rgb(double hue, double saturation, double value, uint8_t & red, uint8_t & green, uint8_t & blue);
template <typename Pixel_T>
static double rgb_euclidean(Pixel_T p1, Pixel_T p2)
{
double val = sqrt(
(p1.red - p2.red) * (p1.red - p2.red) +
(p1.green - p2.green) * (p1.green - p2.green) +
(p1.blue - p2.blue) * (p1.blue - p2.blue)
);
return val;
}
};
#endif // COLORSYS_H

View File

@ -23,6 +23,7 @@ enum Components
#endif
COMP_GRABBER,
COMP_V4L,
COMP_AUDIO,
COMP_COLOR,
COMP_IMAGE,
COMP_EFFECT,
@ -50,6 +51,7 @@ inline const char* componentToString(Components c)
#endif
case COMP_GRABBER: return "Framegrabber";
case COMP_V4L: return "V4L capture device";
case COMP_AUDIO: return "Audio capture device";
case COMP_COLOR: return "Solid color";
case COMP_EFFECT: return "Effect";
case COMP_IMAGE: return "Image";
@ -79,6 +81,7 @@ inline const char* componentToIdString(Components c)
#endif
case COMP_GRABBER: return "GRABBER";
case COMP_V4L: return "V4L";
case COMP_AUDIO: return "AUDIO";
case COMP_COLOR: return "COLOR";
case COMP_EFFECT: return "EFFECT";
case COMP_IMAGE: return "IMAGE";
@ -107,6 +110,7 @@ inline Components stringToComponent(const QString& component)
#endif
if (cmp == "GRABBER") return COMP_GRABBER;
if (cmp == "V4L") return COMP_V4L;
if (cmp == "AUDIO") return COMP_AUDIO;
if (cmp == "COLOR") return COMP_COLOR;
if (cmp == "EFFECT") return COMP_EFFECT;
if (cmp == "IMAGE") return COMP_IMAGE;

Some files were not shown because too many files have changed in this diff Show More