Compare commits

...

31 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
89 changed files with 3328 additions and 1391 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 =
#

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 }}
@ -121,7 +144,7 @@ jobs:
done
- name: Upload packages to APT server (DRAFT)
uses: SamKirkland/FTP-Deploy-Action@4.3.3
uses: SamKirkland/FTP-Deploy-Action@v4.3.4
with:
server: apt.hyperion-project.org
username: ${{ secrets.APT_USER }}

View File

@ -1,12 +1,4 @@
[
{
"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, libasound2-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, libasound2, 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",
@ -32,12 +24,12 @@
"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, libasound2-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, libasound2, 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",
@ -59,7 +51,7 @@
"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, 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",
"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

View File

@ -24,7 +24,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: recursive
@ -68,7 +68,7 @@ jobs:
with:
sarif_file: sarif-results/${{ matrix.language }}.sarif
- name: Upload loc as a Build Artifact
uses: actions/upload-artifact@v2.2.0
uses: actions/upload-artifact@v3
with:
name: sarif-results
path: sarif-results

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 }}
@ -171,7 +171,7 @@ jobs:
done
- name: Upload packages to nightly server
uses: SamKirkland/FTP-Deploy-Action@4.3.3
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
@ -150,7 +150,7 @@ jobs:
with:
path: C:\Users\runneradmin\AppData\Local\Temp\chocolatey
key: ${{ runner.os }}-chocolatey
# - name: Install Python
# shell: powershell
# run: |
@ -159,7 +159,8 @@ jobs:
- name: Install OpenSSL, DirectX SDK
shell: powershell
run: |
choco install --no-progress 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
@ -124,7 +124,8 @@ jobs:
- name: Install OpenSSL, DirectX SDK
shell: powershell
run: |
choco install --no-progress 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: |
@ -161,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
@ -195,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.1
uses: peter-evans/repository-dispatch@v2.1.2
if: ${{ github.repository_owner == 'hyperion-project'}}
with:
repository: hyperion-project/HyperBian

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.15
2.0.16-beta.1

View File

@ -4,6 +4,20 @@ 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.15...HEAD)
### Breaking
### Added
### 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

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 )
@ -180,19 +178,18 @@ if ( "${PLATFORM}" MATCHES "osx" )
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()
@ -201,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()

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

@ -9,7 +9,7 @@
[![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

@ -86,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",
@ -560,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",
@ -616,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",
@ -681,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",
@ -1085,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

@ -327,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);
@ -679,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);
@ -805,7 +805,7 @@ $(document).ready(function () {
const saveOptions = conf_editor_audio.getValue();
const instCaptOptions = window.serverConfig.instCapture;
instCaptOptions.audioEnable = true;
instCaptOptions.audioEnable = saveOptions.grabberAudio.enable;
saveOptions.instCapture = instCaptOptions;
requestWriteConfig(saveOptions);

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')

View File

@ -1021,11 +1021,6 @@ $(document).ready(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', {
@ -1060,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;
@ -2069,7 +2061,7 @@ var updateOutputSelectList = function (ledType, discoveryInfo) {
case "devRPiPWM":
key = ledType;
if (discoveryInfo.devices.length == 0) {
if (!discoveryInfo.isUserAdmin) {
enumVals.push("NONE");
enumTitleVals.push($.i18n('edt_dev_spec_devices_discovered_none'));
$('#btn_submit_controller').prop('disabled', true);
@ -2331,6 +2323,7 @@ function updateElementsWled(ledType, key) {
var enumSegSelectVals = [];
var enumSegSelectTitleVals = [];
var enumSegSelectDefaultVal = "";
var defaultSegmentId = "-1";
if (devicesProperties[ledType] && devicesProperties[ledType][key]) {
var ledDeviceProperties = devicesProperties[ledType][key];
@ -2338,9 +2331,8 @@ function updateElementsWled(ledType, key) {
if (!jQuery.isEmptyObject(ledDeviceProperties)) {
if (ledDeviceProperties.info) {
if (ledDeviceProperties.info.liveseg && ledDeviceProperties.info.liveseg < 0) {
if (!ledDeviceProperties.info.hasOwnProperty("liveseg") || ledDeviceProperties.info.liveseg < 0) {
// "Use main segment only" is disabled
var defaultSegmentId = "-1";
enumSegSelectVals.push(defaultSegmentId);
enumSegSelectTitleVals.push($.i18n('edt_dev_spec_segments_disabled_title'));
enumSegSelectDefaultVal = defaultSegmentId;
@ -2392,13 +2384,12 @@ function updateElementsWled(ledType, key) {
hardwareLedCount = 1;
}
if (segmentConfig) {
if (segmentConfig && segmentConfig.streamSegmentId > defaultSegmentId) {
var configuredstreamSegmentId = window.serverConfig.device.segments.streamSegmentId.toString();
enumSegSelectVals = [configuredstreamSegmentId];
enumSegSelectTitleVals = ["Segment " + configuredstreamSegmentId];
enumSegSelectDefaultVal = configuredstreamSegmentId;
} else {
defaultSegmentId = "-1";
enumSegSelectVals.push(defaultSegmentId);
enumSegSelectTitleVals.push($.i18n('edt_dev_spec_segments_disabled_title'));
enumSegSelectDefaultVal = defaultSegmentId;

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,22 +872,73 @@ function checkUserResult(reply, usr) {
}
};
function useGroupId(id) {
$('#groupId').val(id);
function useGroupId(id, username) {
$('#groupId').val(hueEntertainmentConfigs[id].id);
if (isAPIv2Ready) {
var group = hueEntertainmentConfigs[id];
//Ensure ligthIDs are strings
groupLights = hueGroups[id].lights.map(num => {
return String(num);
});
groupLights = [];
for (const light of group.light_services) {
groupLights.push(light.rid);
}
groupLightsLocations = hueGroups[id].locations;
get_hue_lights();
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;
@ -903,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)) {
@ -916,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);
}
@ -945,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 {
@ -973,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);
@ -1003,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,13 +1107,13 @@ function beginWizardHue() {
$('#host').val(host);
var port = eV("port");
if (port == 0) {
$('#port').val(80);
}
else {
if (port > 0) {
$('#port').val(port);
}
hueIPs.unshift({ host: host, port: port });
else {
$('#port').val('');
}
hueIPs.push({ host: host, port: port });
if (usr != "") {
checkHueBridge(checkUserResult, usr);
@ -1038,18 +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;
var port = $('#port').val();
if (isNaN(port) || port < 1 || port > 65535) {
port = 80;
$('#port').val(80);
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;
}
hueIPs.push({ host: $('#host').val(), port: port });
}
else {
discover_hue_bridges();
@ -1064,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;
}
}
}
@ -1121,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));
@ -1134,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) {
@ -1144,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);
@ -1163,7 +1395,6 @@ function beginWizardHue() {
}
function createHueUser() {
var host = hueIPs[hueIPsinc].host;
var port = hueIPs[hueIPsinc].port;
@ -1208,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);
@ -1230,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");
@ -1269,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) {
@ -1329,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);
}
}
}
@ -1437,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)));
}
}
@ -1733,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

@ -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>

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,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)
@ -160,6 +163,7 @@ if(ENABLE_PROTOBUF_SERVER)
# define the protobuf library
set(PROTOBUF_LIBRARIES protobuf::libprotobuf)
endif()
# redefine at parent scope
@ -266,7 +270,7 @@ if(ENABLE_DEV_NETWORK)
set(USE_SYSTEM_MBEDTLS_LIBS OFF)
endif (NOT MBEDTLS_FOUND)
else()
cmake_minimum_required(VERSION 3.2)
cmake_minimum_required(VERSION 3.5.1)
set(CMAKE_POLICY_DEFAULT_CMP0071 NEW)

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

@ -1 +1 @@
Subproject commit 8c89224991adff88d53cd380f42a2baa36f91454
Subproject commit 1873d3bfc2da771672bd8e7e8f41f57e0af77f33

@ -1 +1 @@
Subproject commit f0dc78d7e6e331b8c6bb2d5283e06aa26883ca7c
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
@ -94,7 +66,7 @@ sudo apt-get install git cmake build-essential qtbase5-dev libqt5serialport5-dev
```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 libasound2-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**

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

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

@ -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()

View File

@ -39,8 +39,8 @@ class AudioGrabberWindows : public AudioGrabber
HANDLE notificationEvent;
std::atomic<bool> isRunning{ false };
static BOOL CALLBACK DirectSoundEnumProcessor(LPGUID deviceIdGuid, LPCTSTR deviceDescStr,
LPCTSTR deviceModelStr, LPVOID context)
static BOOL CALLBACK DirectSoundEnumProcessor(LPGUID deviceIdGuid, LPCWSTR deviceDescStr,
LPCWSTR deviceModelStr, LPVOID context)
{
// Skip undefined audio devices
if (deviceIdGuid == NULL)
@ -50,12 +50,15 @@ static BOOL CALLBACK DirectSoundEnumProcessor(LPGUID deviceIdGuid, LPCTSTR devic
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", deviceDescStr, res, std::system_category().message(res).c_str());
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;
}
@ -63,10 +66,7 @@ static BOOL CALLBACK DirectSoundEnumProcessor(LPGUID deviceIdGuid, LPCTSTR devic
CoTaskMemFree(deviceIdStr);
// Process Device Information
QString deviceName = QString::fromLocal8Bit(deviceDescStr);
Debug(Logger::getInstance("AUDIOGRABBER"), "Found Audio Device: %s", deviceDescStr);
Debug(Logger::getInstance("AUDIOGRABBER"), "Found Audio Device: %s", QSTRING_CSTR(deviceName));
device.id = deviceId;
device.name = deviceName;

View File

@ -413,9 +413,13 @@ namespace hyperion
}
// Compute the average of each color channel
const uint8_t avgRed = uint8_t(std::min(std::lround(sqrt(static_cast<double>(cummRed/pixelNum))), 255L));
const uint8_t avgGreen = uint8_t(std::min(std::lround(sqrt(static_cast<double>(cummGreen/pixelNum))), 255L));
const uint8_t avgBlue = uint8_t(std::min(std::lround(sqrt(static_cast<double>(cummBlue/pixelNum))), 255L));
#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};

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

@ -1,6 +1,6 @@
#pragma once
#define QSTRING_CSTR(str) str.toLocal8Bit().constData()
#define QSTRING_CSTR(str) str.toUtf8().constData()
typedef QList< int > QIntList;

View File

@ -177,44 +177,6 @@ namespace hyperion {
return adjustment;
}
/**
* Construct the 'led-string' with the integration area definition per led and the color
* ordering of the RGB channels
* @param ledsConfig The configuration of the led areas
* @param deviceOrder The default RGB channel ordering
* @return The constructed ledstring
*/
static LedString createLedString(const QJsonArray& ledConfigArray, const ColorOrder deviceOrder)
{
LedString ledString;
const QString deviceOrderStr = colorOrderToString(deviceOrder);
for (signed i = 0; i < ledConfigArray.size(); ++i)
{
const QJsonObject& ledConfig = ledConfigArray[i].toObject();
Led led;
led.minX_frac = qMax(0.0, qMin(1.0, ledConfig["hmin"].toDouble()));
led.maxX_frac = qMax(0.0, qMin(1.0, ledConfig["hmax"].toDouble()));
led.minY_frac = qMax(0.0, qMin(1.0, ledConfig["vmin"].toDouble()));
led.maxY_frac = qMax(0.0, qMin(1.0, ledConfig["vmax"].toDouble()));
// Fix if the user swapped min and max
if (led.minX_frac > led.maxX_frac)
{
std::swap(led.minX_frac, led.maxX_frac);
}
if (led.minY_frac > led.maxY_frac)
{
std::swap(led.minY_frac, led.maxY_frac);
}
// Get the order of the rgb channels for this led (default is device order)
led.colorOrder = stringToColorOrder(ledConfig["colorOrder"].toString(deviceOrderStr));
ledString.leds().push_back(led);
}
return ledString;
}
static QSize getLedLayoutGridSize(const QJsonArray& ledConfigArray)
{
std::vector<int> midPointsX;

View File

@ -140,6 +140,8 @@ void JsonAPI::initialize()
connect(this, &JsonAPI::toggleSuspendAll, _instanceManager, &HyperionIManager::triggerToggleSuspend);
connect(this, &JsonAPI::idleAll, _instanceManager, &HyperionIManager::triggerIdle);
connect(this, &JsonAPI::toggleIdleAll, _instanceManager, &HyperionIManager::triggerToggleIdle);
connect(_ledStreamTimer, &QTimer::timeout, this, &JsonAPI::streamLedColorsUpdate, Qt::UniqueConnection);
}
bool JsonAPI::handleInstanceSwitch(quint8 inst, bool forced)
@ -404,7 +406,7 @@ void JsonAPI::handleServerInfoCommand(const QJsonObject &message, const QString
activePriorities.removeAll(PriorityMuxer::LOWEST_PRIORITY);
int currentPriority = _hyperion->getCurrentPriority();
for(int priority : qAsConst(activePriorities))
for(int priority : std::as_const(activePriorities))
{
const Hyperion::InputInfo &priorityInfo = _hyperion->getPriorityInfo(priority);
@ -1139,6 +1141,11 @@ void JsonAPI::handleComponentStateCommand(const QJsonObject &message, const QStr
sendSuccessReply(command, tan);
}
void JsonAPI::streamLedColorsUpdate()
{
emit streamLedcolorsUpdate(_currentLedValues);
}
void JsonAPI::handleLedColorsCommand(const QJsonObject &message, const QString &command, int tan)
{
// create result
@ -1154,21 +1161,21 @@ void JsonAPI::handleLedColorsCommand(const QJsonObject &message, const QString &
_streaming_leds_reply["tan"] = tan;
connect(_hyperion, &Hyperion::rawLedColors, this, [=](const std::vector<ColorRgb> &ledValues) {
_currentLedValues = ledValues;
// necessary because Qt::UniqueConnection for lambdas does not work until 5.9
// see: https://bugreports.qt.io/browse/QTBUG-52438
if (!_ledStreamConnection)
_ledStreamConnection = connect(_ledStreamTimer, &QTimer::timeout, this, [=]() {
emit streamLedcolorsUpdate(_currentLedValues);
},
Qt::UniqueConnection);
if (ledValues != _currentLedValues)
{
_currentLedValues = ledValues;
if (!_ledStreamTimer->isActive() || _ledStreamTimer->interval() != streaming_interval)
{
_ledStreamTimer->start(streaming_interval);
}
}
else
{
_ledStreamTimer->stop();
}
});
// start the timer
if (!_ledStreamTimer->isActive() || _ledStreamTimer->interval() != streaming_interval)
_ledStreamTimer->start(streaming_interval);
},
Qt::UniqueConnection);
// push once
_hyperion->update();
}
@ -1387,7 +1394,7 @@ void JsonAPI::handleAuthorizeCommand(const QJsonObject &message, const QString &
if (API::getPendingTokenRequests(vec))
{
QJsonArray arr;
for (const auto &entry : qAsConst(vec))
for (const auto &entry : std::as_const(vec))
{
QJsonObject obj;
obj["comment"] = entry.comment;

View File

@ -199,7 +199,7 @@ void JsonCB::handlePriorityUpdate(int currentPriority, const PriorityMuxer::Inpu
activePriorities.removeAll(PriorityMuxer::LOWEST_PRIORITY);
for (int priority : qAsConst(activePriorities)) {
for (int priority : std::as_const(activePriorities)) {
const Hyperion::InputInfo& priorityInfo = activeInputs[priority];

View File

@ -7,6 +7,7 @@ SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/cec)
FILE (GLOB CEC_SOURCES "${CURRENT_HEADER_DIR}/*.h" "${CURRENT_SOURCE_DIR}/*.h" "${CURRENT_SOURCE_DIR}/*.cpp")
add_library(cechandler ${CEC_SOURCES})
list(GET CEC_LIBRARIES 0 CEC_LIBRARIES)
add_definitions(-DCEC_LIBRARY="${CEC_LIBRARIES}")
include_directories(${CEC_INCLUDE_DIRS})

View File

@ -7,6 +7,7 @@
#include <QThreadStorage>
#include <QUuid>
#include <QDir>
#include <QMetaType>
#ifdef _WIN32
#include <stdexcept>
@ -425,15 +426,15 @@ void DBManager::doAddBindValue(QSqlQuery& query, const QVariantList& variants) c
auto t = variant.userType();
switch(t)
{
case QVariant::UInt:
case QVariant::Int:
case QVariant::Bool:
case QMetaType::UInt:
case QMetaType::Int:
case QMetaType::Bool:
query.addBindValue(variant.toInt());
break;
case QVariant::Double:
case QMetaType::Double:
query.addBindValue(variant.toFloat());
break;
case QVariant::ByteArray:
case QMetaType::QByteArray:
query.addBindValue(variant.toByteArray());
break;
default:

View File

@ -224,7 +224,7 @@ void EffectFileHandler::updateEffects()
}
QMap<QString, EffectDefinition> availableEffects;
for (const QString& path : qAsConst(efxPathList))
for (const QString& path : std::as_const(efxPathList))
{
QDir directory(path);
if (!directory.exists())
@ -241,8 +241,8 @@ void EffectFileHandler::updateEffects()
else
{
int efxCount = 0;
QStringList filenames = directory.entryList(QStringList() << "*.json", QDir::Files, QDir::Name | QDir::IgnoreCase);
for (const QString& filename : qAsConst(filenames))
const QStringList filenames = directory.entryList(QStringList() << "*.json", QDir::Files, QDir::Name | QDir::IgnoreCase);
for (const QString& filename : filenames)
{
EffectDefinition def;
if (loadEffectDefinition(path, filename, def))
@ -268,8 +268,8 @@ void EffectFileHandler::updateEffects()
QString schemaPath = path + "schema" + '/';
directory.setPath(schemaPath);
QStringList schemaFileNames = directory.entryList(QStringList() << "*.json", QDir::Files, QDir::Name | QDir::IgnoreCase);
for (const QString& schemaFileName : qAsConst(schemaFileNames))
const QStringList schemaFileNames = directory.entryList(QStringList() << "*.json", QDir::Files, QDir::Name | QDir::IgnoreCase);
for (const QString& schemaFileName : schemaFileNames)
{
EffectSchema pyEffect;
if (loadEffectSchema(path, directory.filePath(schemaFileName), pyEffect))
@ -282,7 +282,7 @@ void EffectFileHandler::updateEffects()
}
}
for (const auto& item : qAsConst(availableEffects))
for (const auto& item : std::as_const(availableEffects))
{
_availableEffects.push_back(item);
}

View File

@ -269,7 +269,7 @@ int MessageForwarder::startJsonTargets(const QJsonObject& config)
if (!_jsonTargets.isEmpty())
{
for (const auto& targetHost : qAsConst(_jsonTargets))
for (const auto& targetHost : std::as_const(_jsonTargets))
{
Info(_log, "Forwarding now to JSON-target host: %s port: %u", QSTRING_CSTR(targetHost.host.toString()), targetHost.port);
}
@ -286,7 +286,7 @@ void MessageForwarder::stopJsonTargets()
if (!_jsonTargets.isEmpty())
{
disconnect(_hyperion, &Hyperion::forwardJsonMessage, nullptr, nullptr);
for (const auto& targetHost : qAsConst(_jsonTargets))
for (const auto& targetHost : std::as_const(_jsonTargets))
{
Info(_log, "Stopped forwarding to JSON-target host: %s port: %u", QSTRING_CSTR(targetHost.host.toString()), targetHost.port);
}
@ -373,7 +373,7 @@ int MessageForwarder::startFlatbufferTargets(const QJsonObject& config)
if (!_flatbufferTargets.isEmpty())
{
for (const auto& targetHost : qAsConst(_flatbufferTargets))
for (const auto& targetHost : std::as_const(_flatbufferTargets))
{
Info(_log, "Forwarding now to Flatbuffer-target host: %s port: %u", QSTRING_CSTR(targetHost.host.toString()), targetHost.port);
}
@ -399,7 +399,7 @@ void MessageForwarder::stopFlatbufferTargets()
_messageForwarderFlatBufHelper = nullptr;
}
for (const auto& targetHost : qAsConst(_flatbufferTargets))
for (const auto& targetHost : std::as_const(_flatbufferTargets))
{
Info(_log, "Stopped forwarding to Flatbuffer-target host: %s port: %u", QSTRING_CSTR(targetHost.host.toString()), targetHost.port);
}
@ -412,7 +412,7 @@ void MessageForwarder::forwardJsonMessage(const QJsonObject& message)
if (_forwarder_enabled)
{
QTcpSocket client;
for (const auto& targetHost : qAsConst(_jsonTargets))
for (const auto& targetHost : std::as_const(_jsonTargets))
{
client.connectToHost(targetHost.host, targetHost.port);
if (client.waitForConnected(CONNECT_TIMEOUT.count()))

View File

@ -9,6 +9,15 @@
// Constants
namespace {
const uint16_t RESOLUTION = 255;
//Constants vuMeter
const QJsonArray DEFAULT_HOTCOLOR { 255,0,0 };
const QJsonArray DEFAULT_WARNCOLOR { 255,255,0 };
const QJsonArray DEFAULT_SAFECOLOR { 0,255,0 };
const int DEFAULT_WARNVALUE { 80 };
const int DEFAULT_SAFEVALUE { 45 };
const int DEFAULT_MULTIPLIER { 0 };
const int DEFAULT_TOLERANCE { 20 };
}
#if (QT_VERSION < QT_VERSION_CHECK(5, 14, 0))
@ -28,12 +37,12 @@ AudioGrabber::AudioGrabber()
, _deviceProperties()
, _device("none")
, _hotColor(QColorConstants::Red)
, _warnValue(80)
, _warnValue(DEFAULT_WARNVALUE)
, _warnColor(QColorConstants::Yellow)
, _safeValue(45)
, _safeValue(DEFAULT_SAFEVALUE)
, _safeColor(QColorConstants::Green)
, _multiplier(0)
, _tolerance(20)
, _multiplier(DEFAULT_MULTIPLIER)
, _tolerance(DEFAULT_TOLERANCE)
, _dynamicMultiplier(INT16_MAX)
, _started(false)
{
@ -61,18 +70,27 @@ void AudioGrabber::setDevice(const QString& device)
void AudioGrabber::setConfiguration(const QJsonObject& config)
{
QJsonArray hotColorArray = config["hotColor"].toArray(QJsonArray::fromVariantList(QList<QVariant>({ QVariant(255), QVariant(0), QVariant(0) })));
QJsonArray warnColorArray = config["warnColor"].toArray(QJsonArray::fromVariantList(QList<QVariant>({ QVariant(255), QVariant(255), QVariant(0) })));
QJsonArray safeColorArray = config["safeColor"].toArray(QJsonArray::fromVariantList(QList<QVariant>({ QVariant(0), QVariant(255), QVariant(0) })));
QString audioEffect = config["audioEffect"].toString();
QJsonObject audioEffectConfig = config[audioEffect].toObject();
_hotColor = QColor(hotColorArray.at(0).toInt(), hotColorArray.at(1).toInt(), hotColorArray.at(2).toInt());
_warnColor = QColor(warnColorArray.at(0).toInt(), warnColorArray.at(1).toInt(), warnColorArray.at(2).toInt());
_safeColor = QColor(safeColorArray.at(0).toInt(), safeColorArray.at(1).toInt(), safeColorArray.at(2).toInt());
if (audioEffect == "vuMeter")
{
QJsonArray hotColorArray = audioEffectConfig.value("hotColor").toArray(DEFAULT_HOTCOLOR);
QJsonArray warnColorArray = audioEffectConfig.value("warnColor").toArray(DEFAULT_WARNCOLOR);
QJsonArray safeColorArray = audioEffectConfig.value("safeColor").toArray(DEFAULT_SAFECOLOR);
_warnValue = config["warnValue"].toInt(80);
_safeValue = config["safeValue"].toInt(45);
_multiplier = config["multiplier"].toDouble(0);
_tolerance = config["tolerance"].toInt(20);
_hotColor = QColor(hotColorArray.at(0).toInt(), hotColorArray.at(1).toInt(), hotColorArray.at(2).toInt());
_warnColor = QColor(warnColorArray.at(0).toInt(), warnColorArray.at(1).toInt(), warnColorArray.at(2).toInt());
_safeColor = QColor(safeColorArray.at(0).toInt(), safeColorArray.at(1).toInt(), safeColorArray.at(2).toInt());
_warnValue = audioEffectConfig["warnValue"].toInt(DEFAULT_WARNVALUE);
_safeValue = audioEffectConfig["safeValue"].toInt(DEFAULT_SAFEVALUE);
_multiplier = audioEffectConfig["multiplier"].toDouble(DEFAULT_MULTIPLIER);
_tolerance = audioEffectConfig["tolerance"].toInt(DEFAULT_MULTIPLIER);
}
else
{
Error(_log, "Unknow Audio-Effect: \"%s\" configured", QSTRING_CSTR(audioEffect));
}
}
void AudioGrabber::resetMultiplier()

View File

@ -1,4 +1,7 @@
#include <grabber/AudioGrabberWindows.h>
#include <climits>
#include <QImage>
#include <QJsonObject>
#include <QJsonArray>
@ -61,7 +64,10 @@ bool AudioGrabberWindows::configureCaptureInterface()
// wFormatTag, nChannels, nSamplesPerSec, mAvgBytesPerSec,
// nBlockAlign, wBitsPerSample, cbSize
notificationSize = max(1024, audioFormat.nAvgBytesPerSec / 8);
#ifdef WIN32
#undef max
#endif
notificationSize = std::max(static_cast<DWORD>(1024), static_cast<DWORD>(audioFormat.nAvgBytesPerSec / 8));
notificationSize -= notificationSize % audioFormat.nBlockAlign;
bufferCaptureSize = notificationSize * AUDIO_NOTIFICATION_COUNT;

View File

@ -2,8 +2,8 @@
SET( CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber )
SET( CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/audio )
if (WIN32)
add_definitions(-DUNICODE -D_UNICODE)
FILE ( GLOB AUDIO_GRABBER_SOURCES "${CURRENT_HEADER_DIR}/Audio*Windows.h" "${CURRENT_HEADER_DIR}/AudioGrabber.h" "${CURRENT_HEADER_DIR}/AudioWrapper.h" "${CURRENT_SOURCE_DIR}/*.h" "${CURRENT_SOURCE_DIR}/*Windows.cpp" "${CURRENT_SOURCE_DIR}/AudioGrabber.cpp" "${CURRENT_SOURCE_DIR}/AudioWrapper.cpp")
elseif(${CMAKE_SYSTEM} MATCHES "Linux")
FILE ( GLOB AUDIO_GRABBER_SOURCES "${CURRENT_HEADER_DIR}/Audio*Linux.h" "${CURRENT_HEADER_DIR}/AudioGrabber.h" "${CURRENT_HEADER_DIR}/AudioWrapper.h" "${CURRENT_SOURCE_DIR}/*.h" "${CURRENT_SOURCE_DIR}/*Linux.cpp" "${CURRENT_SOURCE_DIR}/AudioGrabber.cpp" "${CURRENT_SOURCE_DIR}/AudioWrapper.cpp")

View File

@ -103,7 +103,7 @@ bool QtGrabber::setupDisplay()
Info(_log, "Available Displays:");
int index = 0;
for (auto* screen : qAsConst(screens))
for (auto* screen : std::as_const(screens))
{
const QRect geo = screen->geometry();
Info(_log, "Display %d: Name: %s Resolution: [%dx%d], Geometry: (L,T,R,B) %d,%d,%d,%d Depth:%dbit", index, QSTRING_CSTR(screen->name()), geo.width(), geo.height(), geo.x(), geo.y(), geo.x() + geo.width(), geo.y() + geo.height(), screen->depth());

View File

@ -97,7 +97,7 @@ void CaptureCont::setSystemCaptureEnable(bool enable)
}
else
{
disconnect(GlobalSignals::getInstance(), &GlobalSignals::setSystemImage, this, 0);
disconnect(GlobalSignals::getInstance(), &GlobalSignals::setSystemImage, this, nullptr);
_hyperion->clear(_systemCaptPrio);
_systemInactiveTimer->stop();
_systemCaptName = "";
@ -120,7 +120,7 @@ void CaptureCont::setV4LCaptureEnable(bool enable)
}
else
{
disconnect(GlobalSignals::getInstance(), &GlobalSignals::setV4lImage, this, 0);
disconnect(GlobalSignals::getInstance(), &GlobalSignals::setV4lImage, this, nullptr);
_hyperion->clear(_v4lCaptPrio);
_v4lInactiveTimer->stop();
_v4lCaptName = "";
@ -143,7 +143,7 @@ void CaptureCont::setAudioCaptureEnable(bool enable)
}
else
{
disconnect(GlobalSignals::getInstance(), &GlobalSignals::setAudioImage, this, 0);
disconnect(GlobalSignals::getInstance(), &GlobalSignals::setAudioImage, this, nullptr);
_hyperion->clear(_audioCaptPrio);
_audioInactiveTimer->stop();
_audioCaptName = "";

View File

@ -61,7 +61,7 @@ ComponentRegister::ComponentRegister(Hyperion* hyperion)
vect << COMP_FORWARDER;
#endif
for(auto e : qAsConst(vect))
for(auto e : std::as_const(vect))
{
_componentStates.emplace(e, (e == COMP_ALL));
}

View File

@ -290,7 +290,7 @@ void GrabberWrapper::handleSourceRequest(hyperion::Components component, int hyp
else
GRABBER_AUDIO_CLIENTS.remove(hyperionInd);
if (GRABBER_AUDIO_CLIENTS.empty())
if (GRABBER_AUDIO_CLIENTS.empty() || !getAudioGrabberState())
stop();
else
start();

View File

@ -52,7 +52,7 @@ Hyperion::Hyperion(quint8 instance, bool readonlyMode)
, _instIndex(instance)
, _settingsManager(new SettingsManager(instance, this, readonlyMode))
, _componentRegister(nullptr)
, _ledString(hyperion::createLedString(getSetting(settings::LEDS).array(), hyperion::createColorOrder(getSetting(settings::DEVICE).object())))
, _ledString(LedString::createLedString(getSetting(settings::LEDS).array(), hyperion::createColorOrder(getSetting(settings::DEVICE).object())))
, _imageProcessor(nullptr)
, _muxer(nullptr)
, _raw2ledAdjustment(hyperion::createLedColorsAdjustment(static_cast<int>(_ledString.leds().size()), getSetting(settings::COLOR).object()))
@ -255,7 +255,7 @@ void Hyperion::handleSettingsUpdate(settings::type type, const QJsonDocument& co
#endif
// ledstring, img processor, muxer, ledGridSize (effect-engine image based effects), _ledBuffer and ByteOrder of ledstring
_ledString = hyperion::createLedString(leds, hyperion::createColorOrder(getSetting(settings::DEVICE).object()));
_ledString = LedString::createLedString(leds, hyperion::createColorOrder(getSetting(settings::DEVICE).object()));
_imageProcessor->setLedString(_ledString);
_muxer->updateLedColorsLength(static_cast<int>(_ledString.leds().size()));
_ledGridSize = hyperion::getLedLayoutGridSize(leds);
@ -291,7 +291,7 @@ void Hyperion::handleSettingsUpdate(settings::type type, const QJsonDocument& co
// force ledString update, if device ByteOrder changed
if(_ledDeviceWrapper->getColorOrder() != dev["colorOrder"].toString("rgb"))
{
_ledString = hyperion::createLedString(getSetting(settings::LEDS).array(), hyperion::createColorOrder(dev));
_ledString = LedString::createLedString(getSetting(settings::LEDS).array(), hyperion::createColorOrder(dev));
_imageProcessor->setLedString(_ledString);
_ledStringColorOrder.clear();
@ -671,6 +671,18 @@ void Hyperion::update()
else
{
_ledBuffer = priorityInfo.ledColors;
if (_ledString.hasBlackListedLeds())
{
for (int id : _ledString.blacklistedLedIds())
{
if (id > _ledBuffer.size()-1)
{
break;
}
_ledBuffer.at(id) = ColorRgb::BLACK;
}
}
}
// emit rawLedColors before transform

View File

@ -1,16 +1,92 @@
// STL includes
#include <cstring>
#include <iostream>
// hyperion includes
#include <hyperion/LedString.h>
// QT includes
#include <QJsonObject>
std::vector<Led>& LedString::leds()
{
return mLeds;
return _leds;
}
const std::vector<Led>& LedString::leds() const
{
return mLeds;
return _leds;
}
std::vector<int>& LedString::blacklistedLedIds()
{
return _blacklistedLedIds;
}
const std::vector<int>& LedString::blacklistedLedIds() const
{
return _blacklistedLedIds;
}
bool LedString::hasBlackListedLeds()
{
if (_blacklistedLedIds.size() > 0)
{
return true;
}
else
{
return false;
}
}
/**
* Construct the 'led-string' with the integration area definition per led and the color
* ordering of the RGB channels
* @param ledsConfig The configuration of the led areas
* @param deviceOrder The default RGB channel ordering
* @return The constructed ledstring
*/
LedString LedString::createLedString(const QJsonArray& ledConfigArray, const ColorOrder deviceOrder)
{
LedString ledString;
const QString deviceOrderStr = colorOrderToString(deviceOrder);
for (signed i = 0; i < ledConfigArray.size(); ++i)
{
const QJsonObject& ledConfig = ledConfigArray[i].toObject();
Led led;
led.minX_frac = qMax(0.0, qMin(1.0, ledConfig["hmin"].toDouble()));
led.maxX_frac = qMax(0.0, qMin(1.0, ledConfig["hmax"].toDouble()));
led.minY_frac = qMax(0.0, qMin(1.0, ledConfig["vmin"].toDouble()));
led.maxY_frac = qMax(0.0, qMin(1.0, ledConfig["vmax"].toDouble()));
// Fix if the user swapped min and max
if (led.minX_frac > led.maxX_frac)
{
std::swap(led.minX_frac, led.maxX_frac);
}
if (led.minY_frac > led.maxY_frac)
{
std::swap(led.minY_frac, led.maxY_frac);
}
// Get the order of the rgb channels for this led (default is device order)
led.colorOrder = stringToColorOrder(ledConfig["colorOrder"].toString(deviceOrderStr));
led.isBlacklisted = false;
if (led.minX_frac < std::numeric_limits<double>::epsilon() &&
led.maxX_frac < std::numeric_limits<double>::epsilon() &&
led.minY_frac < std::numeric_limits<double>::epsilon() &&
led.maxY_frac < std::numeric_limits<double>::epsilon()
)
{
led.isBlacklisted = true;
ledString.blacklistedLedIds().push_back(i);
}
ledString.leds().push_back(led);
}
return ledString;
}

View File

@ -58,9 +58,9 @@ SettingsManager::SettingsManager(quint8 instance, QObject* parent, bool readonly
}
// transform json to string lists
QStringList keyList = defaultConfig.keys();
const QStringList keyList = defaultConfig.keys();
QStringList defValueList;
for (const auto& key : qAsConst(keyList))
for (const auto& key : keyList)
{
if (defaultConfig[key].isObject())
{
@ -73,7 +73,7 @@ SettingsManager::SettingsManager(quint8 instance, QObject* parent, bool readonly
}
// fill database with default data if required
for (const auto& key : qAsConst(keyList))
for (const auto& key : keyList)
{
QString val = defValueList.takeFirst();
// prevent overwrite
@ -86,7 +86,7 @@ SettingsManager::SettingsManager(quint8 instance, QObject* parent, bool readonly
// need to validate all data in database construct the entire data object
// TODO refactor schemaChecker to accept QJsonArray in validate(); QJsonDocument container? To validate them per entry...
QJsonObject dbConfig;
for (const auto& key : qAsConst(keyList))
for (const auto& key : keyList)
{
QJsonDocument doc = _sTable->getSettingsRecord(key);
if (doc.isArray())
@ -242,9 +242,9 @@ bool SettingsManager::saveSettings(QJsonObject config, bool correct)
_qconfig = config;
// extract keys and data
QStringList keyList = config.keys();
const QStringList keyList = config.keys();
QStringList newValueList;
for (const auto& key : qAsConst(keyList))
for (const auto& key : keyList)
{
if (config[key].isObject())
{
@ -258,7 +258,7 @@ bool SettingsManager::saveSettings(QJsonObject config, bool correct)
bool rc = true;
// compare database data with new data to emit/save changes accordingly
for (const auto& key : qAsConst(keyList))
for (const auto& key : keyList)
{
QString data = newValueList.takeFirst();
if (_sTable->getSettingsRecordString(key) != data)
@ -269,7 +269,15 @@ bool SettingsManager::saveSettings(QJsonObject config, bool correct)
}
else
{
emit settingsChanged(settings::stringToType(key), QJsonDocument::fromJson(data.toLocal8Bit()));
QJsonParseError error;
QJsonDocument jsonDocument = QJsonDocument::fromJson(data.toUtf8(), &error);
if (error.error != QJsonParseError::NoError) {
Error(_log, "Error parsing JSON: %s", QSTRING_CSTR(error.errorString()));
rc = false;
}
else {
emit settingsChanged(settings::stringToType(key), jsonDocument);
}
}
}
}
@ -618,10 +626,10 @@ bool SettingsManager::handleConfigUpgrade(QJsonObject& config)
QJsonArray json;
if (newForwarderConfig.contains("json"))
{
QJsonArray oldJson = newForwarderConfig["json"].toArray();
const QJsonArray oldJson = newForwarderConfig["json"].toArray();
QJsonObject newJsonConfig;
for (const QJsonValue& value : qAsConst(oldJson))
for (const QJsonValue& value : oldJson)
{
if (value.isString())
{
@ -661,10 +669,10 @@ bool SettingsManager::handleConfigUpgrade(QJsonObject& config)
QJsonArray flatbuffer;
if (newForwarderConfig.contains("flat"))
{
QJsonArray oldFlatbuffer = newForwarderConfig["flat"].toArray();
const QJsonArray oldFlatbuffer = newForwarderConfig["flat"].toArray();
QJsonObject newFlattbufferConfig;
for (const QJsonValue& value : qAsConst(oldFlatbuffer))
for (const QJsonValue& value : oldFlatbuffer)
{
if (value.isString())
{
@ -715,6 +723,7 @@ bool SettingsManager::handleConfigUpgrade(QJsonObject& config)
}
//Migration steps for versions <= 2.0.13
_previousVersion = targetVersion;
targetVersion.setVersion("2.0.13");
if (_previousVersion <= targetVersion)
{
@ -766,6 +775,60 @@ bool SettingsManager::handleConfigUpgrade(QJsonObject& config)
}
}
}
//Migration steps for versions <= 2.0.16
_previousVersion = targetVersion;
targetVersion.setVersion("2.0.16");
if (_previousVersion <= targetVersion)
{
Info(_log, "Instance [%u]: Migrate from version [%s] to version [%s] or later", _instance, _previousVersion.getVersion().c_str(), targetVersion.getVersion().c_str());
// Have Hostname/IP-address separate from port for LED-Devices
if (config.contains("device"))
{
QJsonObject newDeviceConfig = config["device"].toObject();
if (newDeviceConfig.contains("type"))
{
QString type = newDeviceConfig["type"].toString();
if ( type == "philipshue")
{
if (newDeviceConfig.contains("groupId"))
{
if (newDeviceConfig["groupId"].isDouble())
{
int groupID = newDeviceConfig["groupId"].toInt();
newDeviceConfig["groupId"] = QString::number(groupID);
migrated = true;
}
}
if (newDeviceConfig.contains("lightIds"))
{
QJsonArray lightIds = newDeviceConfig.value( "lightIds").toArray();
// Iterate through the JSON array and update integer values to strings
for (int i = 0; i < lightIds.size(); ++i) {
QJsonValue value = lightIds.at(i);
if (value.isDouble())
{
int lightId = value.toInt();
lightIds.replace(i, QString::number(lightId));
migrated = true;
}
}
newDeviceConfig["lightIds"] = lightIds;
}
}
}
if (migrated)
{
config["device"] = newDeviceConfig;
Debug(_log, "LED-Device records migrated");
}
}
}
}
}
return migrated;

View File

@ -13,7 +13,7 @@
"port" :
{
"type" : "integer",
"title" : "edt_conf_general_port_title",
"title" : "edt_conf_webc_port_title",
"minimum" : 80,
"maximum" : 65535,
"default" : 8090,

File diff suppressed because it is too large Load Diff

View File

@ -16,31 +16,6 @@
#include "ProviderRestApi.h"
#include "ProviderUdpSSL.h"
//Streaming message header and payload definition
const uint8_t HEADER[] =
{
'H', 'u', 'e', 'S', 't', 'r', 'e', 'a', 'm', //protocol
0x01, 0x00, //version 1.0
0x01, //sequence number 1
0x00, 0x00, //Reserved write 0s
0x01, //xy Brightness
0x00, // Reserved, write 0s
};
const uint8_t PAYLOAD_PER_LIGHT[] =
{
0x01, 0x00, 0x06, //light ID
//color: 16 bpc
0xff, 0xff,
0xff, 0xff,
0xff, 0xff,
/*
(message.R >> 8) & 0xff, message.R & 0xff,
(message.G >> 8) & 0xff, message.G & 0xff,
(message.B >> 8) & 0xff, message.B & 0xff
*/
};
/**
* A XY color point in the color space of the hue system without brightness.
*/
@ -145,12 +120,18 @@ public:
/// Constructs the light.
///
/// @param log the logger
/// @param bridge the bridge
/// @param useApiV2 make use of Hue API version 2
/// @param id the light id
/// @param lightAttributes the light's attributes as provied by the Hue Bridge
/// @param onBlackTimeToPowerOff Timeframe of Black output that triggers powering off the light
/// @param onBlackTimeToPowerOn Timeframe of non Black output that triggers powering on the light
///
PhilipsHueLight(Logger* log, int id, QJsonObject values, int ledidx,
int onBlackTimeToPowerOff,
int onBlackTimeToPowerOn);
PhilipsHueLight(Logger* log, bool useApiV2, const QString& id, const QJsonObject& lightAttributes,
int onBlackTimeToPowerOff,
int onBlackTimeToPowerOn);
void setDeviceDetails(const QJsonObject& details);
void setEntertainmentSrvDetails(const QJsonObject& details);
///
/// @param on
@ -167,7 +148,14 @@ public:
///
void setColor(const CiColor& color);
int getId() const;
QString getId() const;
QString getdeviceId() const;
QString getProduct() const;
QString getModel() const;
QString getName() const;
QString getArcheType() const;
int getMaxSegments() const;
bool getOnOffState() const;
int getTransitionTime() const;
@ -179,7 +167,7 @@ public:
CiColorTriangle getColorSpace() const;
void saveOriginalState(const QJsonObject& values);
QString getOriginalState() const;
QJsonObject getOriginalState() const;
bool isBusy();
bool isBlack(bool isBlack);
@ -189,24 +177,30 @@ public:
private:
Logger* _log;
/// light id
int _id;
int _ledidx;
bool _useApiV2;
QString _id;
QString _deviceId;
QString _product;
QString _model;
QString _name;
QString _archeType;
QString _gamutType;
int _maxSegments;
bool _on;
int _transitionTime;
CiColor _color;
bool _hasColor;
/// darkes blue color in hue lamp GAMUT = black
CiColor _colorBlack;
/// The model id of the hue lamp which is used to determine the color space.
QString _modelId;
QString _lightname;
CiColorTriangle _colorSpace;
/// The json string of the original state.
QJsonObject _originalStateJSON;
QString _originalState;
QJsonObject _originalState;
CiColor _originalColor;
qint64 _lastSendColorTime;
qint64 _lastBlackTime;
@ -242,23 +236,40 @@ public:
QJsonDocument get(const QString& route);
///
/// @brief Perform a REST-API POST
/// @brief Perform a REST-API GET
///
/// @param route the route of the POST request.
/// @param content the content of the POST request.
/// @param routeElements the route's elements of the GET request.
///
QJsonDocument put(const QString& route, const QString& content, bool supressError = false);
/// @return the content of the GET request.
///
QJsonDocument get(const QStringList& routeElements);
QJsonDocument getLightState( int lightId);
void setLightState( int lightId = 0, const QString &state = "");
///
/// @brief Perform a REST-API PUT
///
/// @param routeElements the route's elements of the PUT request.
/// @param content the content of the PUT request.
/// @param supressError Treat an error as a warning
///
/// @return the content of the PUT request.
///
QJsonDocument put(const QStringList& routeElements, const QJsonObject& content, bool supressError = false);
QMap<int,QJsonObject> getLightMap() const;
QJsonDocument retrieveBridgeDetails();
QJsonObject getDeviceDetails(const QString& deviceId);
QJsonObject getEntertainmentSrvDetails(const QString& deviceId);
QMap<int,QJsonObject> getGroupMap() const;
QJsonObject getLightDetails(const QString& lightId);
QJsonDocument setLightState(const QString& lightId, const QJsonObject& state);
QString getGroupName(int groupId = 0) const;
QMap<QString,QJsonObject> getDevicesMap() const;
QMap<QString,QJsonObject> getLightMap() const;
QMap<QString,QJsonObject> getGroupMap() const;
QMap<QString,QJsonObject> getEntertainmentMap() const;
QJsonArray getGroupLights(int groupId = 0) const;
QString getGroupName(const QString& groupId) const;
QStringList getGroupLights(const QString& groupId) const;
int getGroupChannelsCount(const QString& groupId) const;
protected:
@ -289,7 +300,7 @@ protected:
///
/// @param[in] response from Hue-Bridge in JSON-format
/// @param[in] suppressError Treat an error as a warning
///
///
/// return True, Hue Bridge reports error
///
bool checkApiError(const QJsonDocument& response, bool supressError = false);
@ -338,23 +349,41 @@ protected:
///
QJsonObject addAuthorization(const QJsonObject& params) override;
bool isApiEntertainmentReady(const QString& apiVersion);
bool isAPIv2Ready (int swVersion);
int getFirmwareVerion() { return _deviceFirmwareVersion; }
void setBridgeDetails( const QJsonDocument &doc, bool isLogging = false );
void setBaseApiEnvironment(bool apiV2 = true, const QString& path = "");
QJsonDocument getGroupDetails( const QString& groupId );
QJsonDocument setGroupState( const QString& groupId, bool state);
bool isStreamOwner(const QString &streamOwner) const;
bool initDevicesMap();
bool initLightsMap();
bool initGroupsMap();
bool initEntertainmentSrvsMap();
void log(const char* msg, const char* type, ...) const;
bool configureSsl();
const int * getCiphersuites() const override;
///REST-API wrapper
ProviderRestApi* _restApi;
int _apiPort;
/// User name for the API ("newdeveloper")
QString _authToken;
QString _applicationID;
bool _useHueEntertainmentAPI;
bool _useEntertainmentAPI;
bool _useApiV2;
bool _isAPIv2Ready;
QJsonDocument getGroupState( int groupId );
QJsonDocument setGroupState( int groupId, bool state);
bool isStreamOwner(const QString &streamOwner) const;
bool initMaps();
void log(const char* msg, const char* type, ...) const;
const int * getCiphersuites() const override;
bool _isDiyHue;
private:
@ -364,16 +393,25 @@ private:
///
/// @return A JSON structure holding a list of devices found
///
QJsonArray discover();
QJsonArray discoverSsdp();
QJsonDocument getAllBridgeInfos();
void setBridgeConfig( const QJsonDocument &doc );
QJsonDocument retrieveDeviceDetails(const QString& deviceId = "");
QJsonDocument retrieveLightDetails(const QString& lightId = "");
QJsonDocument retrieveGroupDetails(const QString& groupId = "");
QJsonDocument retrieveEntertainmentSrvDetails(const QString& deviceId = "");
bool retrieveApplicationId();
void setDevicesMap( const QJsonDocument &doc );
void setLightsMap( const QJsonDocument &doc );
void setGroupMap( const QJsonDocument &doc );
void setEntertainmentSrvMap( const QJsonDocument &doc );
//Philips Hue Bridge details
QString _deviceName;
QString _deviceBridgeId;
QString _deviceModel;
QString _deviceFirmwareVersion;
int _deviceFirmwareVersion;
QString _deviceAPIVersion;
uint _api_major;
@ -382,8 +420,12 @@ private:
bool _isHueEntertainmentReady;
QMap<int,QJsonObject> _lightsMap;
QMap<int,QJsonObject> _groupsMap;
QMap<QString,QJsonObject> _devicesMap;
QMap<QString,QJsonObject> _lightsMap;
QMap<QString,QJsonObject> _groupsMap;
QMap<QString,QJsonObject> _entertainmentMap;
int _lightsCount;
};
/**
@ -440,7 +482,7 @@ public:
///
/// @return Number of device's LEDs
///
unsigned int getLightsCount() const { return _lightsCount; }
int getLightsCount() const { return _lightsCount; }
void setOnOffState(PhilipsHueLight& light, bool on, bool force = false);
void setTransitionTime(PhilipsHueLight& light);
@ -547,18 +589,18 @@ private:
bool setLights();
/// creates new PhilipsHueLight(s) based on user lightid with bridge feedback
/// creates new PhilipsHueLight(s) based on user lightId with bridge feedback
///
/// @param map Map of lightid/value pairs of bridge
/// @param map Map of lightId/value pairs of bridge
///
bool updateLights(const QMap<int, QJsonObject> &map);
bool updateLights(const QMap<QString, QJsonObject> &map);
///
/// @brief Set the number of LEDs supported by the device.
///
/// @rparam[in] Number of device's LEDs
//
void setLightsCount( unsigned int lightsCount);
void setLightsCount(int lightsCount);
bool openStream();
bool getStreamGroupState();
@ -566,10 +608,8 @@ private:
bool startStream();
bool stopStream();
void writeStream(bool flush = false);
int writeSingleLights(const std::vector<ColorRgb>& ledValues);
QByteArray prepareStreamData() const;
int writeStreamData(const std::vector<ColorRgb>& ledValues, bool flush = false);
///
bool _switchOffOnBlack;
@ -582,12 +622,15 @@ private:
bool _isInitLeds;
/// Array of the light ids.
std::vector<int> _lightIds;
QStringList _lightIds;
/// Array to save the lamps.
std::vector<PhilipsHueLight> _lights;
int _lightsCount;
int _groupId;
int _channelsCount;
QString _groupId;
QString _groupName;
QString _streamOwner;
int _blackLightsTimeout;
double _blackLevel;
@ -595,15 +638,5 @@ private:
int _onBlackTimeToPowerOn;
bool _candyGamma;
// TODO: Check what is the correct class
uint32_t _handshake_timeout_min;
uint32_t _handshake_timeout_max;
bool _stopConnection;
QString _groupName;
QString _streamOwner;
qint64 _lastConfirm;
int _lastId;
bool _groupStreamState;
};

View File

@ -301,7 +301,7 @@ bool LedDeviceWled::isReadyForSegmentStreaming(semver::version& version) const
}
else
{
Error(_log, "Version provided to test for streaming readiness is not valid ");
Error(_log, "Version provided to test for segment streaming readiness is not valid ");
}
return isReady;
}
@ -325,7 +325,7 @@ bool LedDeviceWled::isReadyForDDPStreaming(semver::version& version) const
}
else
{
Error(_log, "Version provided to test for streaming readiness is not valid ");
Error(_log, "Version provided to test for DDP streaming readiness is not valid ");
}
return isReady;
}
@ -352,12 +352,12 @@ bool LedDeviceWled::powerOn()
}
else
{
QJsonArray propertiesSegments = _originalStateProperties[STATE_SEG].toArray();
const QJsonArray propertiesSegments = _originalStateProperties[STATE_SEG].toArray();
bool isStreamSegmentIdFound { false };
QJsonArray segments;
for (const auto& segmentItem : qAsConst(propertiesSegments))
for (const auto& segmentItem : propertiesSegments)
{
QJsonObject segmentObj = segmentItem.toObject();
@ -505,9 +505,9 @@ bool LedDeviceWled::restoreState()
if (_isStreamToSegment)
{
QJsonArray propertiesSegments = _originalStateProperties[STATE_SEG].toArray();
const QJsonArray propertiesSegments = _originalStateProperties[STATE_SEG].toArray();
QJsonArray segments;
for (const auto& segmentItem : qAsConst(propertiesSegments))
for (const auto& segmentItem : propertiesSegments)
{
QJsonObject segmentObj = segmentItem.toObject();

View File

@ -2,11 +2,18 @@
#include "ProviderRestApi.h"
// Qt includes
#include <QObject>
#include <QEventLoop>
#include <QNetworkReply>
#include <QByteArray>
#include <QJsonObject>
#include <QList>
#include <QHash>
#include <QFile>
#include <QSslSocket>
//std includes
#include <iostream>
#include <chrono>
@ -30,12 +37,12 @@ ProviderRestApi::ProviderRestApi(const QString& scheme, const QString& host, int
: _log(Logger::getInstance("LEDDEVICE"))
, _networkManager(nullptr)
, _requestTimeout(DEFAULT_REST_TIMEOUT)
,_isSeflSignedCertificateAccpeted(false)
{
_networkManager = new QNetworkAccessManager();
#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0))
_networkManager->setRedirectPolicy(QNetworkRequest::NoLessSafeRedirectPolicy);
#endif
_apiUrl.setScheme(scheme);
_apiUrl.setHost(host);
_apiUrl.setPort(port);
@ -46,7 +53,7 @@ ProviderRestApi::ProviderRestApi(const QString& scheme, const QString& host, int
: ProviderRestApi(scheme, host, port, "") {}
ProviderRestApi::ProviderRestApi(const QString& host, int port, const QString& basePath)
: ProviderRestApi("http", host, port, basePath) {}
: ProviderRestApi((port == 443) ? "https" : "http", host, port, basePath) {}
ProviderRestApi::ProviderRestApi(const QString& host, int port)
: ProviderRestApi(host, port, "") {}
@ -59,18 +66,33 @@ ProviderRestApi::~ProviderRestApi()
delete _networkManager;
}
void ProviderRestApi::setScheme(const QString& scheme)
{
_apiUrl.setScheme(scheme);
}
void ProviderRestApi::setUrl(const QUrl& url)
{
_apiUrl = url;
_basePath = url.path();
}
void ProviderRestApi::setBasePath(const QStringList& pathElements)
{
setBasePath(pathElements.join(ONE_SLASH));
}
void ProviderRestApi::setBasePath(const QString& basePath)
{
_basePath.clear();
appendPath(_basePath, basePath);
}
void ProviderRestApi::clearBasePath()
{
_basePath.clear();
}
void ProviderRestApi::setPath(const QStringList& pathElements)
{
_path.clear();
@ -83,6 +105,11 @@ void ProviderRestApi::setPath(const QString& path)
appendPath(_path, path);
}
void ProviderRestApi::clearPath()
{
_path.clear();
}
void ProviderRestApi::appendPath(const QString& path)
{
appendPath(_path, path);
@ -204,6 +231,7 @@ httpResponse ProviderRestApi::executeOperation(QNetworkAccessManager::Operation
QDateTime start = QDateTime::currentDateTime();
QString opCode;
QNetworkReply* reply;
switch (operation) {
case QNetworkAccessManager::GetOperation:
opCode = "GET";
@ -255,11 +283,11 @@ httpResponse ProviderRestApi::getResponse(QNetworkReply* const& reply)
HttpStatusCode httpStatusCode = static_cast<HttpStatusCode>(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt());
response.setHttpStatusCode(httpStatusCode);
response.setNetworkReplyError(reply->error());
response.setHeaders(reply->rawHeaderPairs());
if (reply->error() == QNetworkReply::NoError)
{
QByteArray replyData = reply->readAll();
if (!replyData.isEmpty())
{
QJsonParseError error;
@ -284,40 +312,41 @@ httpResponse ProviderRestApi::getResponse(QNetworkReply* const& reply)
else
{
QString errorReason;
if (httpStatusCode > 0) {
QString httpReason = reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
QString advise;
switch ( httpStatusCode ) {
case HttpStatusCode::BadRequest:
advise = "Check Request Body";
break;
case HttpStatusCode::UnAuthorized:
advise = "Check Authentication Token (API Key)";
break;
case HttpStatusCode::Forbidden:
advise = "No permission to access the given resource";
break;
case HttpStatusCode::NotFound:
advise = "Check Resource given";
break;
default:
advise = httpReason;
break;
}
errorReason = QString ("[%3 %4] - %5").arg(httpStatusCode).arg(httpReason, advise);
if (reply->error() == QNetworkReply::OperationCanceledError)
{
errorReason = "Network request timeout error";
}
else
{
if (reply->error() == QNetworkReply::OperationCanceledError)
{
errorReason = "Network request timeout error";
qDebug() << "httpStatusCode: "<< httpStatusCode;
if (httpStatusCode > 0) {
QString httpReason = reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
QString advise;
switch ( httpStatusCode ) {
case HttpStatusCode::BadRequest:
advise = "Check Request Body";
break;
case HttpStatusCode::UnAuthorized:
advise = "Check Authentication Token (API Key)";
break;
case HttpStatusCode::Forbidden:
advise = "No permission to access the given resource";
break;
case HttpStatusCode::NotFound:
advise = "Check Resource given";
break;
default:
advise = httpReason;
break;
}
errorReason = QString ("[%3 %4] - %5").arg(httpStatusCode).arg(httpReason, advise);
}
else
{
errorReason = reply->errorString();
}
}
response.setError(true);
response.setErrorReason(errorReason);
}
@ -344,3 +373,121 @@ void ProviderRestApi::setHeader(const QByteArray &headerName, const QByteArray &
{
_networkRequestHeaders.setRawHeader(headerName, headerValue);
}
void httpResponse::setHeaders(const QList<QNetworkReply::RawHeaderPair>& pairs)
{
_responseHeaders.clear();
for (const auto &item: pairs)
{
_responseHeaders[item.first] = item.second;
}
}
QByteArray httpResponse::getHeader(const QByteArray header) const
{
return _responseHeaders.value(header);
}
bool ProviderRestApi::setCaCertificate(const QString& caFileName)
{
bool rc {false};
/// Add our own CA to the default SSL configuration
QSslConfiguration configuration = QSslConfiguration::defaultConfiguration();
QFile caFile (caFileName);
if (!caFile.open(QIODevice::ReadOnly))
{
Error(_log,"Unable to open CA-Certificate file: %s", QSTRING_CSTR(caFileName));
return false;
}
QSslCertificate cert (&caFile);
caFile.close();
QList<QSslCertificate> allowedCAs;
allowedCAs << cert;
configuration.setCaCertificates(allowedCAs);
QSslConfiguration::setDefaultConfiguration(configuration);
#ifndef QT_NO_SSL
if (QSslSocket::supportsSsl())
{
QObject::connect( _networkManager, &QNetworkAccessManager::sslErrors, this, &ProviderRestApi::onSslErrors, Qt::UniqueConnection );
_networkManager->connectToHostEncrypted(_apiUrl.host(), _apiUrl.port(), configuration);
rc = true;
}
#endif
return rc;
}
void ProviderRestApi::acceptSelfSignedCertificates(bool isAccepted)
{
_isSeflSignedCertificateAccpeted = isAccepted;
}
void ProviderRestApi::setAlternateServerIdentity(const QString& serverIdentity)
{
_serverIdentity = serverIdentity;
}
QString ProviderRestApi::getAlternateServerIdentity() const
{
return _serverIdentity;
}
bool ProviderRestApi::checkServerIdentity(const QSslConfiguration& sslConfig) const
{
bool isServerIdentified {false};
// Perform common name validation
QSslCertificate serverCertificate = sslConfig.peerCertificate();
QStringList commonName = serverCertificate.subjectInfo(QSslCertificate::CommonName);
if ( commonName.contains(getAlternateServerIdentity(), Qt::CaseInsensitive) )
{
isServerIdentified = true;
}
return isServerIdentified;
}
void ProviderRestApi::onSslErrors(QNetworkReply* reply, const QList<QSslError>& errors)
{
int ignoredErrorCount {0};
for (const QSslError &error : errors)
{
bool ignoreSslError{false};
switch (error.error()) {
case QSslError::HostNameMismatch :
if (checkServerIdentity(reply->sslConfiguration()) )
{
ignoreSslError = true;
}
break;
case QSslError::SelfSignedCertificate :
if (_isSeflSignedCertificateAccpeted)
{
ignoreSslError = true;
}
break;
default:
break;
}
if (ignoreSslError)
{
++ignoredErrorCount;
}
else
{
Debug (_log,"SSL Error occured: [%d] %s ",error.error(), QSTRING_CSTR(error.errorString()));
}
}
if (ignoredErrorCount == errors.size())
{
reply->ignoreSslErrors();
}
}

View File

@ -10,12 +10,13 @@
#include <QUrlQuery>
#include <QJsonDocument>
#include <QFile>
#include <QBasicTimer>
#include <QTimerEvent>
#include <chrono>
constexpr std::chrono::milliseconds DEFAULT_REST_TIMEOUT{ 1000 };
constexpr std::chrono::milliseconds DEFAULT_REST_TIMEOUT{ 2000 };
//Set QNetworkReply timeout without external timer
//https://stackoverflow.com/questions/37444539/how-to-set-qnetworkreply-timeout-without-external-timer
@ -28,7 +29,7 @@ public:
enum HandleMethod { Abort, Close };
ReplyTimeout(QNetworkReply* reply, const int timeout, HandleMethod method = Abort) :
QObject(reply), m_method(method), m_timedout(false)
QObject(reply), m_method(method), m_timedout(false)
{
Q_ASSERT(reply);
if (reply && reply->isRunning()) {
@ -87,6 +88,10 @@ public:
QJsonDocument getBody() const { return _responseBody; }
void setBody(const QJsonDocument& body) { _responseBody = body; }
QByteArray getHeader(const QByteArray header) const;
void setHeaders(const QList<QNetworkReply::RawHeaderPair>& pairs);
QString getErrorReason() const { return _errorReason; }
void setErrorReason(const QString& errorReason) { _errorReason = errorReason; }
@ -99,6 +104,8 @@ public:
private:
QJsonDocument _responseBody {};
QHash<QByteArray, QByteArray> _responseHeaders;
bool _hasError = false;
QString _errorReason;
@ -131,6 +138,7 @@ class ProviderRestApi : public QObject
public:
///
/// @brief Constructor of the REST-API wrapper
///
ProviderRestApi();
@ -176,6 +184,20 @@ public:
///
virtual ~ProviderRestApi() override;
///
/// @brief Set the API's scheme
///
/// @param[in] scheme
///
void setScheme(const QString& scheme);
///
/// @brief Get the API's scheme
///
/// return schme
///
QString getScheme() { return _apiUrl.scheme(); }
///
/// @brief Set an API's host
///
@ -190,6 +212,13 @@ public:
///
void setPort(const int port) { _apiUrl.setPort(port); }
///
/// @brief Get the API's port
///
/// return port
///
int getPort() { return _apiUrl.port(); }
///
/// @brief Set an API's url
///
@ -204,6 +233,13 @@ public:
///
QUrl getUrl() const;
///
/// @brief Set an API's base path (the stable path element before addressing resources)
///
/// @param[in] pathElements to form a path, e.g. (clip,v2,resource) results in "/clip/v2/resource"
///
void setBasePath(const QStringList& pathElements);
///
/// @brief Set an API's base path (the stable path element before addressing resources)
///
@ -211,6 +247,11 @@ public:
///
void setBasePath(const QString& basePath);
///
/// @brief Clear an API's base path (the stable path element before addressing resources)
///
void clearBasePath();
///
/// @brief Set an API's path to address resources
///
@ -218,12 +259,18 @@ public:
///
void setPath(const QString& path);
///
/// @brief Set an API's path to address resources
///
/// @param[in] pathElements to form a path, e.g. (lights,1,state) results in "/lights/1/state/"
///
void setPath(const QStringList& pathElements);
///
/// @brief Clear an API's path
///
void clearPath();
///
/// @brief Append an API's path element to path set before
///
@ -252,6 +299,10 @@ public:
///
void setQuery(const QUrlQuery& query);
QString getBasePath() {return _basePath;}
QString getPath() {return _path;}
///
/// @brief Execute GET request
///
@ -359,6 +410,14 @@ public:
/// @param[in] timeout in milliseconds.
void setTransferTimeout(std::chrono::milliseconds timeout = DEFAULT_REST_TIMEOUT) { _requestTimeout = timeout; }
bool setCaCertificate(const QString& caFileName);
void acceptSelfSignedCertificates(bool accept);
void setAlternateServerIdentity(const QString& serverIdentity);
QString getAlternateServerIdentity() const;
///
/// @brief Set the common logger for LED-devices.
///
@ -366,6 +425,10 @@ public:
///
void setLogger(Logger* log) { _log = log; }
protected slots:
/// Handle the SSLErrors
void onSslErrors(QNetworkReply* reply, const QList<QSslError>& errors);
private:
///
@ -379,9 +442,11 @@ private:
httpResponse executeOperation(QNetworkAccessManager::Operation op, const QUrl& url, const QByteArray& body = {});
bool checkServerIdentity(const QSslConfiguration& sslConfig) const;
Logger* _log;
// QNetworkAccessManager object for sending REST-requests.
/// QNetworkAccessManager object for sending REST-requests.
QNetworkAccessManager* _networkManager;
std::chrono::milliseconds _requestTimeout;
@ -394,6 +459,9 @@ private:
QUrlQuery _query;
QNetworkRequest _networkRequestHeaders;
QString _serverIdentity;
bool _isSeflSignedCertificateAccpeted;
};
#endif // PROVIDERRESTKAPI_H

View File

@ -150,6 +150,11 @@ const int *ProviderUdpSSL::getCiphersuites() const
return mbedtls_ssl_list_ciphersuites();
}
void ProviderUdpSSL::setPSKidentity(const QString& pskIdentity)
{
_psk_identity = pskIdentity;
}
bool ProviderUdpSSL::initNetwork()
{
if ((!_isDeviceReady || _streamPaused) && _streamReady)
@ -334,6 +339,11 @@ void ProviderUdpSSL::freeSSLConnection()
}
}
void ProviderUdpSSL::writeBytes(QByteArray data, bool flush)
{
writeBytes(static_cast<uint>(data.size()), reinterpret_cast<unsigned char*>(data.data()), flush);
}
void ProviderUdpSSL::writeBytes(unsigned int size, const uint8_t* data, bool flush)
{
if (!_streamReady || _streamPaused)

View File

@ -100,6 +100,14 @@ protected:
///
void stopConnection();
///
/// Writes the given bytes/bits to the UDP-device and sleeps the latch time to ensure that the
/// values are latched.
///
/// @param[in] data The data
///
void writeBytes(QByteArray data, bool flush = false);
///
/// Writes the given bytes/bits to the UDP-device and sleeps the latch time to ensure that the
/// values are latched.
@ -116,6 +124,8 @@ protected:
///
virtual const int * getCiphersuites() const;
void setPSKidentity(const QString& pskIdentity);
private:
bool initConnection();

View File

@ -159,12 +159,10 @@ QJsonObject LedDeviceWS281x::discover(const QJsonObject& /*params*/)
QJsonArray deviceList;
if (SysInfo::isUserAdmin())
{
//Indicate the general availability of the device, if hyperion is run under root
deviceList << QJsonObject ({{"found",true}});
devicesDiscovered.insert("devices", deviceList);
}
//Indicate the general availability of the device, if hyperion is run under root
devicesDiscovered.insert("isUserAdmin", SysInfo::isUserAdmin());
devicesDiscovered.insert("devices", deviceList);
DebugIf(verbose,_log, "devicesDiscovered: [%s]", QString(QJsonDocument(devicesDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData());

View File

@ -35,26 +35,45 @@
},
"propertyOrder": 4
},
"useAPIv2": {
"type": "boolean",
"format": "checkbox",
"title": "edt_dev_spec_useAPIv2_title",
"default": false,
"options": {
"hidden": true
},
"access": "expert",
"propertyOrder": 5
},
"useEntertainmentAPI": {
"type": "boolean",
"format": "checkbox",
"title": "edt_dev_spec_useEntertainmentAPI_title",
"default": true,
"propertyOrder": 5
"options": {
"hidden": true
},
"propertyOrder": 6
},
"switchOffOnBlack": {
"type": "boolean",
"format": "checkbox",
"title": "edt_dev_spec_switchOffOnBlack_title",
"default": false,
"propertyOrder": 6
"options": {
"dependencies": {
"useAPIv2": false
}
},
"propertyOrder": 7
},
"restoreOriginalState": {
"type": "boolean",
"format": "checkbox",
"title": "edt_dev_spec_restoreOriginalState_title",
"default": false,
"propertyOrder": 7
"propertyOrder": 8
},
"blackLevel": {
"type": "number",
@ -64,7 +83,12 @@
"step": 0.01,
"minimum": 0.001,
"maximum": 1.0,
"propertyOrder": 8
"options": {
"dependencies": {
"useAPIv2": false
}
},
"propertyOrder": 9
},
"onBlackTimeToPowerOff": {
"type": "integer",
@ -76,7 +100,12 @@
"maximum": 100000,
"default": 600,
"required": true,
"propertyOrder": 9
"options": {
"dependencies": {
"useAPIv2": false
}
},
"propertyOrder": 10
},
"onBlackTimeToPowerOn": {
"type": "integer",
@ -88,14 +117,24 @@
"maximum": 100000,
"default": 300,
"required": true,
"propertyOrder": 9
"options": {
"dependencies": {
"useAPIv2": false
}
},
"propertyOrder": 11
},
"candyGamma": {
"type": "boolean",
"format": "checkbox",
"title": "edt_dev_spec_candyGamma_title",
"default": true,
"propertyOrder": 10
"options": {
"dependencies": {
"useAPIv2": false
}
},
"propertyOrder": 12
},
"lightIds": {
"type": "array",
@ -112,20 +151,23 @@
"useEntertainmentAPI": false
}
},
"propertyOrder": 11
"propertyOrder": 13
},
"groupId": {
"type": "number",
"format": "stepper",
"step": 1,
"type": "string",
"title": "edt_dev_spec_groupId_title",
"default": 0,
"default": "",
"options": {
"dependencies": {
"useEntertainmentAPI": true
}
},
"propertyOrder": 12
"options": {
"dependencies": {
"useAPIv2": false
}
},
"propertyOrder": 14
},
"brightnessFactor": {
"type": "number",
@ -136,7 +178,12 @@
"minimum": 0.5,
"maximum": 10.0,
"access": "advanced",
"propertyOrder": 13
"options": {
"dependencies": {
"useAPIv2": false
}
},
"propertyOrder": 15
},
"handshakeTimeoutMin": {
"type": "number",
@ -154,7 +201,7 @@
"useEntertainmentAPI": true
}
},
"propertyOrder": 14
"propertyOrder": 16
},
"handshakeTimeoutMax": {
"type": "number",
@ -172,7 +219,7 @@
"useEntertainmentAPI": true
}
},
"propertyOrder": 15
"propertyOrder": 17
},
"verbose": {
"type": "boolean",
@ -180,7 +227,7 @@
"title": "edt_dev_spec_verbose_title",
"default": false,
"access": "expert",
"propertyOrder": 16
"propertyOrder": 18
},
"transitiontime": {
"type": "number",
@ -195,24 +242,29 @@
"useEntertainmentAPI": false
}
},
"propertyOrder": 17
"propertyOrder": 19
},
"blackLightsTimeout": {
"type": "number",
"title": "edt_dev_spec_blackLightsTimeout_title",
"default": 5000,
"options": {
"hidden": true
"dependencies": {
"useAPIv2": false
}
},
"propertyOrder": 18
"propertyOrder": 20
},
"brightnessThreshold": {
"type": "number",
"title": "edt_dev_spec_brightnessThreshold_title",
"default": 0.0001,
"options": {
"hidden": true
"dependencies": {
"useAPIv2": false
}
},
"propertyOrder": 19
"propertyOrder": 21
},
"brightnessMin": {
"type": "number",
@ -223,9 +275,11 @@
"maximum": 1.0,
"access": "advanced",
"options": {
"hidden": true
"dependencies": {
"useAPIv2": false
}
},
"propertyOrder": 20
"propertyOrder": 22
},
"brightnessMax": {
"type": "number",
@ -236,9 +290,11 @@
"maximum": 1.0,
"access": "advanced",
"options": {
"hidden": true
"dependencies": {
"useAPIv2": false
}
},
"propertyOrder": 21
"propertyOrder": 23
}
},
"additionalProperties": true

View File

@ -182,6 +182,7 @@ bool MdnsBrowser::resolveAddress(Logger* log, const QString& hostname, QHostAddr
}
else
{
QObject::disconnect(&MdnsBrowser::getInstance(), &MdnsBrowser::addressResolved, nullptr, nullptr);
Error(log, "Resolved mDNS hostname [%s] timed out", QSTRING_CSTR(hostname));
}
}

View File

@ -65,7 +65,7 @@ void Logger::deleteInstance(const QString & name, const QString & subName)
if (name.isEmpty())
{
for (auto *logger : qAsConst(LoggerMap)) {
for (auto *logger : std::as_const(LoggerMap)) {
delete logger;
}

View File

@ -1,4 +1,5 @@
// stdlib includes
#include <limits>
#include <iterator>
#include <algorithm>
#include <cmath>
@ -58,13 +59,13 @@ QPair<bool, bool> QJsonSchemaChecker::validate(const QJsonObject& value, bool ig
QJsonObject QJsonSchemaChecker::getAutoCorrectedConfig(const QJsonObject& value, bool ignoreRequired)
{
_ignoreRequired = ignoreRequired;
QStringList sequence = QStringList() << "remove" << "modify" << "create";
const QStringList sequence = QStringList() << "remove" << "modify" << "create";
_error = false;
_schemaError = false;
_messages.clear();
_autoCorrected = value;
for (const QString& correct : qAsConst(sequence))
for (const QString& correct : sequence)
{
_correct = correct;
_currentPath.clear();

View File

@ -0,0 +1,14 @@
-----BEGIN CERTIFICATE-----
MIICMjCCAdigAwIBAgIUO7FSLbaxikuXAljzVaurLXWmFw4wCgYIKoZIzj0EAwIw
OTELMAkGA1UEBhMCTkwxFDASBgNVBAoMC1BoaWxpcHMgSHVlMRQwEgYDVQQDDAty
b290LWJyaWRnZTAiGA8yMDE3MDEwMTAwMDAwMFoYDzIwMzgwMTE5MDMxNDA3WjA5
MQswCQYDVQQGEwJOTDEUMBIGA1UECgwLUGhpbGlwcyBIdWUxFDASBgNVBAMMC3Jv
b3QtYnJpZGdlMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEjNw2tx2AplOf9x86
aTdvEcL1FU65QDxziKvBpW9XXSIcibAeQiKxegpq8Exbr9v6LBnYbna2VcaK0G22
jOKkTqOBuTCBtjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNV
HQ4EFgQUZ2ONTFrDT6o8ItRnKfqWKnHFGmQwdAYDVR0jBG0wa4AUZ2ONTFrDT6o8
ItRnKfqWKnHFGmShPaQ7MDkxCzAJBgNVBAYTAk5MMRQwEgYDVQQKDAtQaGlsaXBz
IEh1ZTEUMBIGA1UEAwwLcm9vdC1icmlkZ2WCFDuxUi22sYpLlwJY81Wrqy11phcO
MAoGCCqGSM49BAMCA0gAMEUCIEBYYEOsa07TH7E5MJnGw557lVkORgit2Rm1h3B2
sFgDAiEA1Fj/C3AN5psFMjo0//mrQebo0eKd3aWRx+pQY08mk48=
-----END CERTIFICATE-----

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.1.0)
cmake_minimum_required(VERSION 3.5.0)
project(hyperion-aml)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network Widgets REQUIRED)

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.1.0)
cmake_minimum_required(VERSION 3.5.0)
project(hyperion-dispmanx)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network Widgets REQUIRED)

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.1.0)
cmake_minimum_required(VERSION 3.5.0)
project(hyperion-framebuffer)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network Widgets REQUIRED)

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.1.0)
cmake_minimum_required(VERSION 3.5.0)
project(hyperion-osx)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Gui Network Widgets REQUIRED)

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.1.0)
cmake_minimum_required(VERSION 3.5.0)
project(hyperion-qt)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Gui Network Widgets REQUIRED)

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.1.0)
cmake_minimum_required(VERSION 3.5.0)
project(hyperion-remote)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network Widgets REQUIRED)

View File

@ -57,9 +57,9 @@ void showHelp(Option & option){
int getInstaneIdbyName(const QJsonObject & reply, const QString & name){
if(reply.contains("instance")){
QJsonArray list = reply.value("instance").toArray();
const QJsonArray list = reply.value("instance").toArray();
for ( const auto &entry : qAsConst(list) ) {
for ( const auto &entry : list ) {
const QJsonObject obj = entry.toObject();
if(obj["friendly_name"] == name && obj["running"].toBool())
{

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.1.0)
cmake_minimum_required(VERSION 3.5.0)
project(hyperion-v4l2)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network Widgets REQUIRED)

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.1.0)
cmake_minimum_required(VERSION 3.5.0)
project(hyperion-x11)
find_package(X11 REQUIRED)

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.1.0)
cmake_minimum_required(VERSION 3.5.0)
project(hyperion-xcb)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network Widgets REQUIRED)

View File

@ -160,7 +160,7 @@ if (APPLE)
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/cmake/osxbundle/Info.plist.in
MACOSX_BUNDLE_BUNDLE_NAME "Hyperion"
MACOSX_BUNDLE_BUNDLE_VERSION ${HYPERION_VERSION}
MACOSX_BUNDLE_COPYRIGHT "Copyright(c) 2014-2022 Hyperion Project"
MACOSX_BUNDLE_COPYRIGHT "Copyright(c) 2014-2023 Hyperion Project"
MACOSX_BUNDLE_GUI_IDENTIFIER "com.hyperion-project.${PROJECT_NAME}"
MACOSX_BUNDLE_ICON_FILE "Hyperion.icns"
MACOSX_BUNDLE_INFO_STRING "${PROJECT_NAME} ${HYPERION_VERSION}"

View File

@ -268,7 +268,7 @@ SuspendHandlerLinux::SuspendHandlerLinux()
QDBusConnection systemBus = QDBusConnection::systemBus();
if (!systemBus.isConnected())
{
Error(Logger::getInstance("DAEMON"), "Suspend/resume handler - System bus is not connected");
Info(Logger::getInstance("DAEMON"), "The suspend/resume feature is not supported by your system configuration");
}
else
{
@ -288,7 +288,7 @@ SuspendHandlerLinux::SuspendHandlerLinux()
QDBusConnection sessionBus = QDBusConnection::sessionBus();
if (!sessionBus.isConnected())
{
Error(Logger::getInstance("DAEMON"), "Lock/unlock handler- Session bus is not connected");
Info(Logger::getInstance("DAEMON"), "The lock/unlock feature is not supported by your system configuration");
}
else
{

View File

@ -15,4 +15,5 @@ void CreateConsole()
freopen_s(&fDummy, "CONOUT$", "w", stderr);
freopen_s(&fDummy, "CONIN$", "r", stdin);
SetConsoleTitle(TEXT("Hyperion"));
SetConsoleOutputCP(CP_UTF8);
}

View File

@ -268,9 +268,9 @@ int main(int argc, char** argv)
if (directory.exists() && destDir.exists())
{
std::cout << "Extract to folder: " << destDir.absolutePath().toStdString() << std::endl;
QStringList filenames = directory.entryList(QStringList() << "*", QDir::Files, QDir::Name | QDir::IgnoreCase);
const QStringList filenames = directory.entryList(QStringList() << "*", QDir::Files, QDir::Name | QDir::IgnoreCase);
QString destFileName;
for (const QString & filename : qAsConst(filenames))
for (const QString & filename : filenames)
{
destFileName = destDir.dirName()+"/"+filename;
if (QFile::exists(destFileName))

View File

@ -24,7 +24,7 @@ int main()
return -1;
}
const LedString ledString = hyperion::createLedString(config["leds"].toArray(), hyperion::createColorOrder(config["device"].toObject()));
const LedString ledString = LedString::createLedString(config["leds"].toArray(), hyperion::createColorOrder(config["device"].toObject()));
const ColorRgb testColor = {64, 123, 12};