diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 098e5fc1..a23b8eb4 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -193,30 +193,3 @@ jobs: with: name: windows path: windows - -###################### -#### Documentation ### -###################### - - docs: - name: Documentation - runs-on: ubuntu-latest - defaults: - run: - working-directory: docs - steps: - - name: Checkout - uses: actions/checkout@v2 - - # Install dependencies - - name: Setup node 12 - uses: actions/setup-node@v1 - with: - node-version: '12' - - # Build Docs - - name: Build docs - run: | - npm install -g yarn - yarn install - yarn docs:build diff --git a/.github/workflows/push-master.yml b/.github/workflows/push-master.yml index 4e8e5fc4..6a1c61c1 100644 --- a/.github/workflows/push-master.yml +++ b/.github/workflows/push-master.yml @@ -151,43 +151,6 @@ jobs: with: path: build/Hyperion-* -###################### -#### Documentation ### -###################### - - Docs: - name: Documentation - runs-on: ubuntu-latest - defaults: - run: - working-directory: docs - steps: - - name: Checkout - uses: actions/checkout@v2 - - # Install dependencies - - name: Setup node 12 - uses: actions/setup-node@v1 - with: - node-version: '12' - - # Build Docs - - name: Build docs - run: | - cd docs - npm install -g yarn - yarn install - yarn docs:build - - # Deploy to gh-pages (only on tagged commit) - - name: Deploy to gh-pages - if: startsWith(github.event.ref, 'refs/tags') - uses: peaceiris/actions-gh-pages@v3 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./docs/dist - cname: docs.hyperion-project.org - ################################ ###### Publish Releases ######## ################################ @@ -195,7 +158,7 @@ jobs: publish: name: Publish Releases if: startsWith(github.event.ref, 'refs/tags') - needs: [Linux, macOS, windows, Docs] + needs: [Linux, macOS, windows] runs-on: ubuntu-latest steps: - name: Checkout diff --git a/.gitignore b/.gitignore index ea25d9d4..40563443 100644 --- a/.gitignore +++ b/.gitignore @@ -27,8 +27,11 @@ libsrc/flatbufserver/hyperion_request_generated.h *.kdev* # Visual Studio 2015/2017/2019 cache/options directory -.vs/ +# Ignore +.vs/* CMakeSettings.json +# Allow +!.vs/launch.vs.json # LedDevice 'File' output NULL diff --git a/CHANGELOG.md b/CHANGELOG.md index 411fe242..8b9137a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,11 +10,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- WLED: Support of ["live" property] (https://github.com/Aircoookie/WLED/issues/1308), addresses #1095 +- WLED: Support storing/restoring state, fixes #1101 +- LED-Devices: Allow to get properties for Atmo and Karatedevices to limit LED numbers configurable +- LED-Devices: Add timeouts for REST-API calls + ### Changed - Updated dependency rpi_ws281x to latest upstream +- Fix High CPU load (RPI3B+) (#1013) +- Nanoleaf: Consider Nanoleaf-Shape Controlers +- LED-Devices: Show HW-Ledcount in all setting levels + +- Documentation: Add link to [Hyperion-py](https://github.com/dermotduffy/hyperion-py) ### Fixed +- Fix issue #1127: LED-Devices: Correct total packet count in tpm2net implementation +- LED-Hue: Proper black in Entertainement mode if min brightness is set +- LED-Hue: Minor fix of setColor command +- Nanoleaf: Fix,if external control mode cannot be set + ### Removed ## [2.0.0-alpha.9](https://github.com/hyperion-project/hyperion.ng/releases/tag/2.0.0-alpha.9) - 2020-11-18 diff --git a/CompileHowto.md b/CompileHowto.md index 5b662e83..978a65a0 100644 --- a/CompileHowto.md +++ b/CompileHowto.md @@ -1,3 +1,4 @@ + # 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. @@ -7,58 +8,67 @@ 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 ``` **Raspbian 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 rpi-raspbian -t buster ``` ## 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 ``` **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 ``` **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 ``` **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 ``` **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 ``` **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 ``` +## 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 +-c: do incremental compiles, Note: you need to keep the image and tag stable +**Compile code in $HYPERION_HOME incrementally for Raspberry Pi 2/3/4 (Debian Buster)** +```console +cd $HYPERION_HOME +./bin/scripts/docker-compile.sh -l -c -i armv7l -t buster +``` # The usual way ## Debian/Ubuntu/Win10LinuxSubsystem -``` +```console sudo apt-get update sudo apt-get install git cmake build-essential qtbase5-dev libqt5serialport5-dev libqt5sql5-sqlite libqt5svg5-dev libqt5x11extras5-dev libusb-1.0-0-dev python3-dev 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 libjpeg-dev libturbojpeg0-dev libssl-dev zlib1g-dev ``` **on RPI you need the videocore IV headers** -``` +```console sudo apt-get install libraspberrypi-dev ``` **OSMC on Raspberry Pi** -``` +```console sudo apt-get install rbp-userland-dev-osmc ``` @@ -71,7 +81,7 @@ See [AUR](https://aur.archlinux.org/packages/?O=0&SeB=nd&K=hyperion&outdated=&SB ## Fedora The following dependencies are needed to build hyperion.ng on fedora. -``` +```console sudo dnf -y groupinstall "Development Tools" sudo dnf install python3-devel qt-devel qt5-qtbase-devel qt5-qtserialport-devel libjpeg-devel xrandr xcb-util-image-devel qt5-qtx11extras-devel turbojpeg-devel libusb-devel avahi-libs avahi-compat-libdns_sd-devel xcb-util-devel dbus-devel openssl-devel fedora-packager rpmdevtools gcc libcec-devel ``` @@ -81,13 +91,8 @@ After installing the dependencies, you can continue with the compile instruction To install on OS X you either need Homebrew or Macport but Homebrew is the recommended way to install the packages. To use Homebrew XCode is required as well, use `brew doctor` to check your install. First you need to install the dependencies: -``` -brew install qt5 -brew install python3 -brew install cmake -brew install libusb -brew install doxygen -brew install zlib +```console +brew install qt5 python3 cmake libusb doxygen zlib ``` ## Windows (WIP) @@ -110,17 +115,17 @@ We assume a 64bit Windows 10. Install the following; # Compiling and installing Hyperion -### The general quick way (without big comments) +## The general quick way (without big comments) -complete automated process for Mac/Linux: -```bash +**complete automated process for Mac/Linux:** +```console wget -qO- https://raw.githubusercontent.com/hyperion-project/hyperion.ng/master/bin/compile.sh | sh ``` -some more detailed way: (or more or less the content of the script above) -be sure you fulfill the prerequisites above. +**some more detailed way: (or more or less the content of the script above)** -```bash +```console +# be sure you fulfill the prerequisites above git clone --recursive https://github.com/hyperion-project/hyperion.ng.git hyperion cd hyperion mkdir build @@ -138,92 +143,94 @@ bin/hyperiond # webui is located on localhost:8090 or 8091 ``` +## The detailed way (with many comments) -### Download +**Download:** Creates hyperion directory and checkout the code from github - -``` +```console export HYPERION_DIR="hyperion" git clone --recursive --depth 1 https://github.com/hyperion-project/hyperion.ng.git "$HYPERION_DIR" ``` -### Preparations +**Preparations:** Change into hyperion folder and create a build folder -``` +```console cd "$HYPERION_DIR" mkdir build cd build ``` -### Generate the make files: - +**Generate the make files:** To generate make files with automatic platform detection and default settings: - -This should fit to *RPI, x86, amlogic/wetek* -``` +This should fit to *RPI, x86, amlogic/wetek: +```console cmake -DCMAKE_BUILD_TYPE=Release .. ``` *Developers on x86* linux should use: -``` +```console cmake -DPLATFORM=x11-dev -DCMAKE_BUILD_TYPE=Release .. ``` To use framebuffer instead of dispmanx (for example on the *cubox-i*): -``` +```console cmake -DENABLE_FB=ON -DCMAKE_BUILD_TYPE=Release .. ``` To generate make files on OS X: Platform should be auto detected and refer to osx, you can also force osx: -``` +```console cmake -DPLATFORM=osx -DCMAKE_BUILD_TYPE=Release .. ``` +In case you would like to build with a dedicated Qt version, provide the version's location via the CMAKE_PREFIX_PATH: +```console +cmake -DCMAKE_PREFIX_PATH=/opt/Qt/5.15.2/gcc_64 -DCMAKE_BUILD_TYPE=Release .. +``` + To generate files on Windows (Release+Debug capable): Platform should be auto detected and refer to windows, you can also force windows: -```sh +```posh # You might need to setup MSVC env first call "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvars64.bat" cmake -DPLATFORM=windows -G "Visual Studio 16 2019" .. ``` -### Run make to build Hyperion +**Run make to build Hyperion:** The `-j $(nproc)` specifies the amount of CPU cores to use. -```bash +```console make -j $(nproc) ``` On a mac you can use ``sysctl -n hw.ncpu`` to get the number of available CPU cores to use. -```bash +```console make -j $(sysctl -n hw.ncpu) ``` -On Windows run -```bash +On Windows run: +```posh cmake --build . --config Release -- -maxcpucount ``` Maintainer: To build installer, install [NSIS](https://nsis.sourceforge.io/Main_Page) and set env `VCINSTALLDIR="C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC"` -### Install hyperion into your system - +**Install hyperion into your system:** Copy all necessary files to ``/usr/local/share/hyperion`` -```bash +```console sudo make install/strip ``` If you want to install into another location call this before installing -```bash +```console cmake -DCMAKE_INSTALL_PREFIX=/home/pi/apps .. ``` This will install to ``/home/pi/apps/share/hyperion`` -### Integrating hyperion into your system +**Integrating hyperion into your system:** ... ToDo diff --git a/CrossCompileHowto.md b/CrossCompileHowto.md deleted file mode 100644 index 4617370a..00000000 --- a/CrossCompileHowto.md +++ /dev/null @@ -1,93 +0,0 @@ -# Cross-Compile Hyperion-NG -Leverage the power of a host environment (here Ubuntu) compiling for a target platform (here Raspberry Pi). -Use a clean Raspbian Stretch Lite (on target) and Ubuntu 18/19 (on host) to execute the steps outlined below. -## On the Target system (here Raspberry Pi) -Install required additional packages. -``` -sudo apt-get install qtbase5-dev libqt5serialport5-dev libqt5svg5-dev libusb-1.0-0-dev python3-dev libcec-dev libxcb-util0-dev libxcb-randr0-dev libxrandr-dev libxrender-dev libavahi-core-dev libavahi-compat-libdnssd-dev libjpeg-dev libturbojpeg0-dev libqt5sql5-sqlite aptitude qt5-default rsync libssl-dev zlib1g-dev -``` -## On the Host system (here Ubuntu) -Update the Ubuntu environment to the latest stage and install required additional packages. -``` -sudo apt-get update -sudo apt-get upgrade -sudo apt-get -qq -y install git rsync cmake build-essential qtbase5-dev libqt5serialport5-dev libqt5svg5-dev libqt5sql5-sqlite 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 libjpeg-dev libturbojpeg0-dev libssl-dev zlib1g-dev -``` - -Refine the target IP or hostname, plus userID as required and set-up cross-compilation environment: -``` -export TARGET_IP=x.x.x.x -export TARGET_USER=pi -``` -``` -export CROSSROOT="$HOME/crosscompile" -export RASCROSS_DIR="$CROSSROOT/raspberrypi" -export ROOTFS_DIR="$RASCROSS_DIR/rootfs" -export TOOLCHAIN_DIR="$RASCROSS_DIR/tools" -export QT5_DIR="$CROSSROOT/Qt5" -export HYPERION_DIR="$HOME/hyperion.ng" -``` -Get native files from target platform into the host-environment: -``` -mkdir -p "$ROOTFS_DIR/lib" -mkdir -p "$ROOTFS_DIR/usr" -rsync -rl --delete-after --copy-unsafe-links $TARGET_USER@$TARGET_IP:/lib "$ROOTFS_DIR" -rsync -rl --delete-after --copy-unsafe-links $TARGET_USER@$TARGET_IP:/usr/include "$ROOTFS_DIR/usr" -rsync -rl --delete-after --copy-unsafe-links $TARGET_USER@$TARGET_IP:/usr/lib "$ROOTFS_DIR/usr" -``` - -### Raspberry Pi specific steps -Get Raspberry Pi firmware: -``` -mkdir -p "$RASCROSS_DIR/firmware" -git clone --depth 1 https://github.com/raspberrypi/firmware.git "$RASCROSS_DIR/firmware" -ln -s "$RASCROSS_DIR/firmware/hardfp/opt" "$ROOTFS_DIR/opt" -``` -Get toolchain files which allows to build ARM executables on x86 platforms: -``` -mkdir -p "$TOOLCHAIN_DIR" -cd $TOOLCHAIN_DIR -wget -c https://releases.linaro.org/components/toolchain/binaries/7.4-2019.02/arm-linux-gnueabihf/gcc-linaro-7.4.1-2019.02-x86_64_arm-linux-gnueabihf.tar.xz --no-check-certificate -tar -xvf gcc-linaro-7.4.1-2019.02-x86_64_arm-linux-gnueabihf.tar.xz - -``` -### Install the Qt5 framework -``` -mkdir -p "$QT5_DIR" -cd "$QT5_DIR" -wget -c https://download.qt.io/new_archive/qt/5.7/5.7.1/qt-opensource-linux-x64-5.7.1.run -chmod +x $QT5_DIR/*.run -``` -Display absolute installation directory to be used in Qt5 installer: -``` -echo $HOME/crosscompile/Qt5 -``` -Start the Qt5 installation. -Follow the dialogs and install in absolute directory of ```$HOME/crosscompile/Qt5``` (copy from above) -``` -./qt-opensource-linux-x64-5.7.1.run -``` -### Get the Hyperion-NG source files -``` -git clone --recursive https://github.com/hyperion-project/hyperion.ng.git "$HYPERION_DIR" -``` -### Get required submodules for Hyperion -``` -cd "$HYPERION_DIR" -git fetch --recurse-submodules -j2 -``` -### Compile Hyperion-NG -``` -cd "$HYPERION_DIR" -chmod +x "$HYPERION_DIR/bin/"*.sh -./bin/create_all_releases.sh -``` -### Transfer output packages to target platform and install Hyperion-NG -Output packages for target platform (.deb, .tar.gz, .sh) can be found here: -``` -$HYPERION_DIR/deploy/rpi -``` -# Install Hyperion-NG on target platform -t.b.d. - - diff --git a/assets/firmware/arduino/adalight/adalight.ino b/assets/firmware/arduino/adalight/adalight.ino index 30a41c2a..5172129a 100644 --- a/assets/firmware/arduino/adalight/adalight.ino +++ b/assets/firmware/arduino/adalight/adalight.ino @@ -139,7 +139,7 @@ void setup() { } int ledCount = MAX_LEDS; - if (ANALOG_MODE == ANALOG_MODE_LAST_LED) { + if (ANALOG_OUTPUT_ENABLED == true && ANALOG_MODE == ANALOG_MODE_LAST_LED) { ledCount--; } @@ -170,7 +170,7 @@ void setup() { showColor(CRGB(0, 0, 0)); Serial.print("Ada\n"); // Send "Magic Word" string to host - + Serial.println("Ada: LED num: " + String(FastLED.size())); //Return number of LEDs configured boolean transmissionSuccess; unsigned long sum_r, sum_g, sum_b; @@ -254,4 +254,3 @@ void setup() { void loop() { // Not used. See note in setup() function. } - diff --git a/assets/webconfig/content/support.html b/assets/webconfig/content/support.html index ddc2dfed..c998e00d 100644 --- a/assets/webconfig/content/support.html +++ b/assets/webconfig/content/support.html @@ -3,110 +3,24 @@
-
-

Spread the word

- -
- -

Facebook

-

Share our Hyperion Facebook page and get a notice when new updates are released

-
-
- -
- -

Twitter

-

Share and follow on Twitter, be always up to date with latest post about the Hyperion development

-
-
- -
- -

Google+

-

Circle us on Google +!

-
-
- -
- -

Youtube

-

Bored from pictures? Checkout our Youtube channel!

-
-
- -
- -

Instagram

-

-
-
-
-
-

Information and help ressources

- +

Webpage

Home of Hyperion

- +
-

Wiki

+

Documentation

The A to Z source for almost everything Hyperion related

- +

Forum

diff --git a/assets/webconfig/i18n/de.json b/assets/webconfig/i18n/de.json index 875b3646..a623216b 100644 --- a/assets/webconfig/i18n/de.json +++ b/assets/webconfig/i18n/de.json @@ -874,7 +874,7 @@ "wiz_cc_chooseid": "Wähle einen Namen für dieses Farb-Profil.", "wiz_cc_intro1": "Der Assistent wird dich durch die Kalibrierung deiner LEDs leiten. Sofern du Kodi nutzt, können die Bilder und Testvideos direkt an Kodi geschickt werden. Andernfalls musst du das Material selbst herunterladen und anwenden.", "wiz_cc_kodicon": "Kodi Webserver gefunden, fahre mit Kodi-Unterstützung fort.", - "wiz_cc_kodidiscon": "Kodi Webserver nicht gefunden, fahre ohne Kodi-Unterstützung fort.", + "wiz_cc_kodidiscon": "Kodi Webserver nicht gefunden, fahre ohne Kodi-Unterstützung fort (prüfe, ob Fernsteuerung durch Programme auf anderen Rechnern erlaubt ist).", "wiz_cc_kodidisconlink": "Download Link Bilder:", "wiz_cc_kodimsg_start": "Test bestanden - Zeit zu beginnen", "wiz_cc_kodishould": "Kodi sollte jetzt folgendes Bild anzeigen: $1", diff --git a/assets/webconfig/i18n/en.json b/assets/webconfig/i18n/en.json index ffca1c9c..df528fa2 100644 --- a/assets/webconfig/i18n/en.json +++ b/assets/webconfig/i18n/en.json @@ -291,6 +291,7 @@ "edt_conf_enum_logverbose": "Verbose", "edt_conf_enum_logwarn": "Warning", "edt_conf_enum_multicolor_mean": "Multicolor", + "edt_conf_enum_please_select": "Please Select", "edt_conf_enum_rbg": "RBG", "edt_conf_enum_rgb": "RGB", "edt_conf_enum_right_left": "Right to left", @@ -844,6 +845,8 @@ "remote_maptype_label_multicolor_mean": "Multicolor", "remote_maptype_label_unicolor_mean": "Unicolor", "remote_optgroup_syseffets": "Provided Effects", + "remote_optgroup_templates_custom": "User Templates", + "remote_optgroup_templates_system": "System Templates", "remote_optgroup_usreffets": "User Effects", "remote_videoMode_2D": "2D", "remote_videoMode_3DSBS": "3DSBS", @@ -870,7 +873,7 @@ "support_label_webpagetitle": "Webpage", "support_label_webrestitle": "Information and help resources", "support_label_wikitext": "The A to Z source for almost everything Hyperion related", - "support_label_wikititle": "Wiki", + "support_label_wikititle": "Documentation", "support_label_yttext": "Bored from pictures? Check out our YouTube channel!", "update_button_changelog": "Full changelog", "update_button_install": "Install", @@ -891,7 +894,7 @@ "wiz_cc_chooseid": "Define a name for this color profile.", "wiz_cc_intro1": "This wizard will guide you through your led calibration. If you are using Kodi, the calibration pictures and videos can be sent directly to it. Prerequisite: You need to enable \"Allow remote control from applications on other systems\" in Kodi.
Alternatively, you might want downloading these files yourself and display them when the wizard asks you to adjust the setting.", "wiz_cc_kodicon": "Kodi found, proceed with Kodi support.", - "wiz_cc_kodidiscon": "Kodi not found, proceed without Kodi support.", + "wiz_cc_kodidiscon": "Kodi not found, proceed without Kodi support (please check, if remote control by other systems is activated).", "wiz_cc_kodidisconlink": "Download link pictures:", "wiz_cc_kodimsg_start": "Test success - time to proceed!", "wiz_cc_kodishould": "Kodi should show the following picture: $1", diff --git a/assets/webconfig/js/content_effectsconfigurator.js b/assets/webconfig/js/content_effectsconfigurator.js index feea705c..674882b5 100644 --- a/assets/webconfig/js/content_effectsconfigurator.js +++ b/assets/webconfig/js/content_effectsconfigurator.js @@ -1,204 +1,246 @@ -$(document).ready( function() { - performTranslation(); - var oldDelList = []; - var effectName = ""; - var imageData = ""; - var effects_editor = null; - var effectPy = ""; - var testrun; +$(document).ready(function () { + performTranslation(); + var oldDelList = []; + var effectName = ""; + var imageData = ""; + var effects_editor = null; + var effectPyScript = ""; + var testrun; - if(window.showOptHelp) - createHintH("intro", $.i18n('effectsconfigurator_label_intro'), "intro_effc"); + if (window.showOptHelp) + createHintH("intro", $.i18n('effectsconfigurator_label_intro'), "intro_effc"); - function updateDelEffectlist(){ - var newDelList = window.serverInfo.effects; - if(newDelList.length != oldDelList.length) - { - $('#effectsdellist').html(""); - var usrEffArr = []; - var sysEffArr = []; - for(var idx=0; idx 0) { + var usrEffGrp = createSelGroup($.i18n('remote_optgroup_usreffets')); + for (var idx = 0; idx < usrEffArr.length; idx++) + { + usrEffGrp.appendChild(createSelOpt('ext_' + newDelList[usrEffArr[idx]].name, newDelList[usrEffArr[idx]].name)); + } + $('#effectsdellist').append(usrEffGrp); + } + + var sysEffGrp = createSelGroup($.i18n('remote_optgroup_syseffets')); + for (var idx = 0; idx < sysEffArr.length; idx++) + { + sysEffGrp.appendChild(createSelOpt('int_' + newDelList[sysEffArr[idx]].name, newDelList[sysEffArr[idx]].name)); + } + $('#effectsdellist').append(sysEffGrp); + + $("#effectsdellist").trigger("change"); + + oldDelList = newDelList; + } + } + + function triggerTestEffect() { + testrun = true; + + var args = effects_editor.getEditor('root.args'); + requestTestEffect(effectName, effectPyScript, JSON.stringify(args.getValue()), imageData); + }; + + // Specify upload handler for image files + JSONEditor.defaults.options.upload = function (type, file, cbs) { + var fileReader = new FileReader(); + + //check file + if (!file.type.startsWith('image')) { + imageData = ""; + cbs.failure('File upload error'); + // TODO clear file dialog. + showInfoDialog('error', "", $.i18n('infoDialog_writeimage_error_text', file.name)); + return; + } + + fileReader.onload = function () { + imageData = this.result.split(',')[1]; + cbs.success(file.name); + }; + + fileReader.readAsDataURL(file); + }; + + $("#effectslist").off().on("change", function (event) { + if (effects_editor != null) + effects_editor.destroy(); + + for (var idx = 0; idx < effects.length; idx++) { + if (effects[idx].script == this.value) { + effects_editor = createJsonEditor('editor_container', { + args: effects[idx].schemaContent, + }, false, true, false); + + effectPyScript = effects[idx].script; + + imageData = ""; + $("#name-input").trigger("change"); + + var desc = $.i18n(effects[idx].schemaContent.title + '_desc'); + if (desc === effects[idx].schemaContent.title + '_desc') { + desc = "" + } + + $("#eff_desc").html(createEffHint($.i18n(effects[idx].schemaContent.title), desc)); + break; + } + } + + effects_editor.on('change', function () { + if ($("#btn_cont_test").hasClass("btn-success") && effects_editor.validate().length == 0 && effectName != "") { + triggerTestEffect(); + } + if (effects_editor.validate().length == 0 && effectName != "") { + $('#btn_start_test').attr('disabled', false); + !window.readOnlyMode ? $('#btn_write').attr('disabled', false) : $('#btn_write').attr('disabled', true); + } + else { + $('#btn_start_test, #btn_write').attr('disabled', true); + } + }); + }); + + // disable or enable control elements + $("#name-input").on('change keyup', function (event) { + effectName = $(this).val(); + if ($(this).val() == '') { + effects_editor.disable(); + $("#eff_footer").children().attr('disabled', true); + } else { + effects_editor.enable(); + $("#eff_footer").children().attr('disabled', false); + !window.readOnlyMode ? $('#btn_write').attr('disabled', false) : $('#btn_write').attr('disabled', true); + } + }); + + // Save Effect + $('#btn_write').off().on('click', function () { + requestWriteEffect(effectName, effectPyScript, JSON.stringify(effects_editor.getValue()), imageData); + $(window.hyperion).one("cmd-create-effect", function (event) { + if (event.response.success) + showInfoDialog('success', "", $.i18n('infoDialog_effconf_created_text', effectName)); }); - // Save Effect - $('#btn_write').off().on('click',function() { - requestWriteEffect(effectName,effectPy,JSON.stringify(effects_editor.getValue()),imageData); - $(window.hyperion).one("cmd-create-effect", function(event) { - if (event.response.success) - showInfoDialog('success', "", $.i18n('infoDialog_effconf_created_text', effectName)); - }); + if (testrun) + setTimeout(requestPriorityClear, 100); + }); - if (testrun) - setTimeout(requestPriorityClear,100); + // Start test + $('#btn_start_test').off().on('click', function () { + triggerTestEffect(); + }); - }); + // Stop test + $('#btn_stop_test').off().on('click', function () { + requestPriorityClear(); + testrun = false; + }); - // Start test - $('#btn_start_test').off().on('click',function() { - triggerTestEffect(); - }); + // Continuous test + $('#btn_cont_test').off().on('click', function () { + toggleClass('#btn_cont_test', "btn-success", "btn-danger"); + }); - // Stop test - $('#btn_stop_test').off().on('click',function() { - requestPriorityClear(); - testrun = false; - }); + // Delete Effect + $('#btn_delete').off().on('click', function () { + var name = $("#effectsdellist").val().split("_")[1]; + requestDeleteEffect(name); + $(window.hyperion).one("cmd-delete-effect", function (event) { + if (event.response.success) + showInfoDialog('success', "", $.i18n('infoDialog_effconf_deleted_text', name)); + }); + }); - // Continuous test - $('#btn_cont_test').off().on('click',function() { - toggleClass('#btn_cont_test', "btn-success", "btn-danger"); - }); + // Disable or enable Delete Effect Button + $('#effectsdellist').off().on('change', function () { + $(this).val() == null ? $('#btn_edit, #btn_delete').prop('disabled', true) : ""; + $(this).val().startsWith("int_") ? $('#btn_delete').prop('disabled', true) : $('#btn_delete').prop('disabled', false); + }); - // Delete Effect - $('#btn_delete').off().on('click',function() { - var name = $("#effectsdellist").val().split("_")[1]; - requestDeleteEffect(name); - $(window.hyperion).one("cmd-delete-effect", function(event) { - if (event.response.success) - showInfoDialog('success', "", $.i18n('infoDialog_effconf_deleted_text', name)); - }); - }); + // Load Effect + $('#btn_edit').off().on('click', function () { - // disable or enable Delete Effect Button - $('#effectsdellist').off().on('change', function(){ - $(this).val() == null ? $('#btn_edit, #btn_delete').prop('disabled',true) : ""; - $(this).val().startsWith("int_") ? $('#btn_delete').prop('disabled',true) : $('#btn_delete').prop('disabled',false); - }); + var name = $("#effectsdellist").val().replace("ext_", ""); + if (name.startsWith("int_")) { + name = name.split("_").pop(); + $("#name-input").val("My Modded Effect"); + } + else { + name = name.split("_").pop(); + $("#name-input").val(name); + } - // Load Effect - $('#btn_edit').off().on('click', function(){ - var name = $("#effectsdellist").val().replace("ext_",""); + var efx = window.serverInfo.effects; + for (var i = 0; i < efx.length; i++) { + if (efx[i].name == name) { + var py = efx[i].script; + $("#effectslist").val(py).trigger("change"); - if(name.startsWith("int_")) - { name = name.split("_").pop(); - $("#name-input").val("My Modded Effect"); - } - else - { - name = name.split("_").pop(); - $("#name-input").val(name); - } + for (var key in efx[i].args) { + var ed = effects_editor.getEditor('root.args.' + [key]); + if (ed) + ed.setValue(efx[i].args[key]); + } + break; + } + } + }); - var efx = window.serverInfo.effects; - for(var i = 0; i 0) { + var custTmplGrp = createSelGroup($.i18n('remote_optgroup_templates_custom')); + for (var idx = 0; idx < custTemplatesIDs.length; idx++) + { + custTmplGrp.appendChild(createSelOpt(effects[custTemplatesIDs[idx]].script, $.i18n(effects[custTemplatesIDs[idx]].schemaContent.title))); + } + $('#effectslist').append(custTmplGrp); + } - //interval update - $(window.hyperion).on("cmd-effects-update", function(event){ - window.serverInfo.effects = event.response.data.effects - updateDelEffectlist(); - }); + var sysTmplGrp = createSelGroup($.i18n('remote_optgroup_templates_system')); + for (var idx = 0; idx < sysTemplatesIDs.length; idx++) + { + sysTmplGrp.appendChild(createSelOpt(effects[sysTemplatesIDs[idx]].script, $.i18n(effects[sysTemplatesIDs[idx]].schemaContent.title))); + } + $('#effectslist').append(sysTmplGrp); - removeOverlay(); + $("#effectslist").trigger("change"); + + updateDelEffectlist(); + + //interval update + $(window.hyperion).on("cmd-effects-update", function (event) { + window.serverInfo.effects = event.response.data.effects + updateDelEffectlist(); + }); + + removeOverlay(); }); + diff --git a/assets/webconfig/js/content_grabber.js b/assets/webconfig/js/content_grabber.js index dbf1c49f..3dc25cb1 100755 --- a/assets/webconfig/js/content_grabber.js +++ b/assets/webconfig/js/content_grabber.js @@ -11,12 +11,12 @@ $(document).ready(function () { $('#conf_cont_instCapt').append(createOptPanel('fa-camera', $.i18n("edt_conf_instCapture_heading_title"), 'editor_container_instCapt', 'btn_submit_instCapt')); $('#conf_cont_instCapt').append(createHelpTable(window.schema.instCapture.properties, $.i18n("edt_conf_instCapture_heading_title"))); - // Framegrabber + // Screen-Grabber $('#conf_cont').append(createRow('conf_cont_screen')); $('#conf_cont_screen').append(createOptPanel('fa-camera', $.i18n("edt_conf_fg_heading_title"), 'editor_container_screengrabber', 'btn_submit_screengrabber')); $('#conf_cont_screen').append(createHelpTable(window.schema.framegrabber.properties, $.i18n("edt_conf_fg_heading_title"))); - // V4L2 - hide if not available + // Video-Grabber - hide if not available if (VIDEOGRABBER_AVAIL) { $('#conf_cont').append(createRow('conf_cont_video')); $('#conf_cont_video').append(createOptPanel('fa-camera', $.i18n("edt_conf_v4l2_heading_title"), 'editor_container_videograbber', 'btn_submit_videograbber')); @@ -36,7 +36,7 @@ $(document).ready(function () { instCapture: window.schema.instCapture }, true, true); - // Hide V4L2 elements, if not available + // Hide Video-Grabber elements, if not available if (!VIDEOGRABBER_AVAIL) { $('[data-schemapath*="root.instCapture.v4lEnable' + '"]').hide(); $('[data-schemapath*="root.instCapture.v4lPriority' + '"]').hide(); @@ -67,6 +67,15 @@ $(document).ready(function () { conf_editor_instCapt.validate().length || window.readOnlyMode ? $('#btn_submit_instCapt').attr('disabled', true) : $('#btn_submit_instCapt').attr('disabled', false); }); + + conf_editor_instCapt.watch('root.instCapture.systemEnable', () => { + var systemEnable = conf_editor_instCapt.getEditor("root.instCapture.systemEnable").getValue(); + if (systemEnable) { + discoverInputSources("screen"); + } + + }); + conf_editor_instCapt.watch('root.instCapture.v4lEnable', () => { if (VIDEOGRABBER_AVAIL) { var videoEnable = conf_editor_instCapt.getEditor("root.instCapture.v4lEnable").getValue(); @@ -131,43 +140,18 @@ $(document).ready(function () { updateJsonEditorRange(editor.getEditor(path), 'cropBottom', 0, height); } - // Framegrabber + // Screen-Grabber conf_editor_screen = createJsonEditor('editor_container_screengrabber', { framegrabber: window.schema.framegrabber }, true, true); conf_editor_screen.on('ready', function () { - var availableGrabbers = window.serverInfo.grabbers.available; - var screenGrabberOptions = conf_editor_screen.getEditor('root.framegrabber'); - var orginalGrabberTypes = screenGrabberOptions.schema.properties.type.enum; - var orginalGrabberTitles = screenGrabberOptions.schema.properties.type.options.enum_titles; - var enumVals = []; - var enumTitelVals = []; - var enumDefaultVal = ""; - - for (var i = 0; i < orginalGrabberTypes.length; i++) { - var grabberType = orginalGrabberTypes[i]; - if ($.inArray(grabberType, availableGrabbers) != -1) { - enumVals.push(grabberType); - enumTitelVals.push(orginalGrabberTitles[i]); - } + var screenEnable = conf_editor_instCapt.getEditor("root.instCapture.systemEnable").getValue(); + if (screenEnable) { + discoverInputSources("screen"); } - var activeGrabbers = window.serverInfo.grabbers.active.map(v => v.toLowerCase()); - - // Select first active platform grabber - for (var i = 0; i < enumVals.length; i++) { - var grabberType = enumVals[i]; - if ($.inArray(grabberType, activeGrabbers) != -1) { - enumDefaultVal = grabberType; - break; - } - } - updateJsonEditorSelection(screenGrabberOptions, "type", {}, enumVals, enumTitelVals, enumDefaultVal); - }); - - conf_editor_screen.on('ready', function () { updateCropForWidth(conf_editor_screen, "root.framegrabber"); updateCropForHeight(conf_editor_screen, "root.framegrabber"); }); @@ -181,6 +165,182 @@ $(document).ready(function () { filterScreenInputOptions(selectedType); }); + conf_editor_screen.watch('root.framegrabber.available_devices', () => { + var deviceSelected = conf_editor_screen.getEditor("root.framegrabber.available_devices").getValue(); + if (deviceSelected === "NONE" || deviceSelected === "") { + $('#btn_submit_screengrabber').attr('disabled', true); + } + else { + var addSchemaElements = {}; + var enumVals = []; + var enumTitelVals = []; + var enumDefaultVal = ""; + + var deviceProperties = getPropertiesOfDevice(deviceSelected); + + //Update hidden input element + conf_editor_screen.getEditor("root.framegrabber.device").setValue(deviceProperties.device); + + var video_inputs = deviceProperties.video_inputs; + if (video_inputs.length <= 1) { + addSchemaElements.access = "expert"; + } + + for (const video_input of video_inputs) { + enumVals.push(video_input.inputIdx); + enumTitelVals.push(video_input.name); + } + + if (enumVals.length > 0) { + if (deviceSelected === configuredDevice) { + var configuredVideoInput = window.serverConfig.framegrabber.input; + if ($.inArray(configuredVideoInput, enumVals) != -1) { + enumDefaultVal = configuredVideoInput; + } + } + updateJsonEditorSelection(conf_editor_screen.getEditor('root.framegrabber'), + 'device_inputs', addSchemaElements, enumVals, enumTitelVals, enumDefaultVal, false); + } + + if (!window.readOnlyMode) { + $('#btn_submit_screengrabber').attr('disabled', false); + } + } + }); + + conf_editor_screen.watch('root.framegrabber.device_inputs', () => { + var deviceSelected = conf_editor_screen.getEditor("root.framegrabber.available_devices").getValue(); + var videoInputSelected = conf_editor_screen.getEditor("root.framegrabber.device_inputs").getValue(); + + //Update hidden input element + conf_editor_screen.getEditor("root.framegrabber.input").setValue(parseInt(videoInputSelected)); + + var addSchemaElements = {}; + var enumVals = []; + var enumTitelVals = []; + var enumDefaultVal = ""; + + var deviceProperties = getPropertiesOfDevice(deviceSelected); + + var formats = deviceProperties.video_inputs[videoInputSelected].formats; + var formatIdx = 0; + /* + if (formatSelected !== "NONE") { + formatIdx = formats.findIndex(x => x.format === formatSelected); + } + */ + + var resolutions = formats[formatIdx].resolutions; + if (resolutions.length <= 1) { + addSchemaElements.access = "advanced"; + } else { + resolutions.sort(compareTwoValues('width', 'height', 'asc')); + } + + for (var i = 0; i < resolutions.length; i++) { + enumVals.push(i); + var resolutionText = resolutions[i].width + "x" + resolutions[i].height; + enumTitelVals.push(resolutionText); + } + + if (enumVals.length > 0) { + if (deviceSelected === configuredDevice) { + var configuredResolutionText = window.serverConfig.framegrabber.width + "x" + window.serverConfig.framegrabber.height; + var idx = $.inArray(configuredResolutionText, enumTitelVals) + if (idx != -1) { + enumDefaultVal = idx; + } + } + + updateJsonEditorSelection(conf_editor_screen.getEditor('root.framegrabber'), + 'resolutions', addSchemaElements, enumVals, enumTitelVals, enumDefaultVal, false); + } + + if (!window.readOnlyMode) { + $('#btn_submit_videograbber').attr('disabled', false); + } + }); + + conf_editor_screen.watch('root.framegrabber.resolutions', () => { + var deviceSelected = conf_editor_screen.getEditor("root.framegrabber.available_devices").getValue(); + var videoInputSelected = conf_editor_screen.getEditor("root.framegrabber.device_inputs").getValue(); + var resolutionSelected = conf_editor_screen.getEditor("root.framegrabber.resolutions").getValue(); + + var addSchemaElements = {}; + var enumVals = []; + var enumDefaultVal = ""; + + var deviceProperties = getPropertiesOfDevice(deviceSelected); + + var formats = deviceProperties.video_inputs[videoInputSelected].formats; + var formatIdx = 0; + /* + if (formatSelected !== "NONE") { + formatIdx = formats.findIndex(x => x.format === formatSelected); + } + */ + + //Update hidden resolution related elements + var width = parseInt(formats[formatIdx].resolutions[resolutionSelected].width); + conf_editor_screen.getEditor("root.framegrabber.width").setValue(width); + + var height = parseInt(formats[formatIdx].resolutions[resolutionSelected].height); + conf_editor_screen.getEditor("root.framegrabber.height").setValue(height); + + //Update crop rage depending on selected resolution + updateCropForWidth(conf_editor_screen, "root.framegrabber"); + updateCropForHeight(conf_editor_screen, "root.framegrabber"); + + var fps = formats[formatIdx].resolutions[resolutionSelected].fps; + if (!fps) { + enumVals.push("NONE"); + addSchemaElements.options = { "hidden": true }; + } else { + fps.sort((a, b) => a - b); + for (var i = 0; i < fps.length; i++) { + enumVals.push(fps[i]); + } + } + + if (enumVals.length <= 1) { + addSchemaElements.access = "expert"; + } + + if (enumVals.length > 0) { + if (deviceSelected === configuredDevice) { + var configuredFps = window.serverConfig.framegrabber.fps; + if ($.inArray(configuredFps, enumVals) != -1) { + enumDefaultVal = configuredFps; + } + } + updateJsonEditorSelection(conf_editor_screen.getEditor('root.framegrabber'), + 'framerates', addSchemaElements, enumVals, [], enumDefaultVal, false); + } + + if (!window.readOnlyMode) { + $('#btn_submit_screengrabber').attr('disabled', false); + } + }); + + conf_editor_screen.watch('root.framegrabber.framerates', () => { + //Update hidden fps element + var fps = 0; + var framerates = conf_editor_screen.getEditor("root.framegrabber.framerates").getValue(); + if (framerates !== "NONE") { + fps = parseInt(framerates); + } + + //Show Frameskipping only when more than 2 fps + if (fps > 2 && storedAccess === "expert") { + showVideoInputOptions(["fpsSoftwareDecimation"], true); + } + else { + showVideoInputOptions(["fpsSoftwareDecimation"], false); + } + conf_editor_screen.getEditor("root.framegrabber.fps").setValue(fps); + }); + + conf_editor_screen.watch('root.framegrabber.width', () => { updateCropForWidth(conf_editor_screen, "root.framegrabber"); }); @@ -227,7 +387,13 @@ $(document).ready(function () { }; $('#btn_submit_screengrabber').off().on('click', function () { - requestWriteConfig(conf_editor_screen.getValue()); + var saveOptions = conf_editor_screen.getValue(); + + var instCaptOptions = window.serverConfig.instCapture; + instCaptOptions.systemEnable = true; + saveOptions.instCapture = instCaptOptions; + + requestWriteConfig(saveOptions); }); // External Input Sources (Video-Grabbers) @@ -251,8 +417,16 @@ $(document).ready(function () { conf_editor_video.on('change', function () { var deviceSelected = conf_editor_video.getEditor("root.grabberV4L2.available_devices").getValue(); if (!conf_editor_video.validate().length) { - if (deviceSelected !== "NONE") { - window.readOnlyMode ? $('#btn_submit_videograbber').attr('disabled', true) : $('#btn_submit_videograbber').attr('disabled', false); + + switch (deviceSelected) { + case "SELECT": + showAllVideoInputOptions(conf_editor_video, "grabberV4L2", false); + break; + case "NONE": + break; + default: + window.readOnlyMode ? $('#btn_submit_videograbber').attr('disabled', true) : $('#btn_submit_videograbber').attr('disabled', false); + break; } } else { @@ -262,7 +436,7 @@ $(document).ready(function () { conf_editor_video.watch('root.grabberV4L2.available_devices', () => { var deviceSelected = conf_editor_video.getEditor("root.grabberV4L2.available_devices").getValue(); - if (deviceSelected === "NONE" || deviceSelected === "") { + if (deviceSelected === "NONE" || deviceSelected === "SELECT" || deviceSelected === "") { $('#btn_submit_videograbber').attr('disabled', true); } else { @@ -293,6 +467,7 @@ $(document).ready(function () { enumDefaultVal = configuredVideoInput; } } + updateJsonEditorSelection(conf_editor_video.getEditor('root.grabberV4L2'), 'device_inputs', addSchemaElements, enumVals, enumTitelVals, enumDefaultVal, false); } @@ -389,7 +564,7 @@ $(document).ready(function () { var resolutions = formats[formatIdx].resolutions; if (resolutions.length <= 1) { - addSchemaElements.access = "expert"; + addSchemaElements.access = "advanced"; } else { resolutions.sort(compareTwoValues('width', 'height', 'asc')); } @@ -497,8 +672,13 @@ $(document).ready(function () { }); $('#btn_submit_videograbber').off().on('click', function () { - var v4l2Options = conf_editor_video.getValue(); - requestWriteConfig(v4l2Options); + var saveOptions = conf_editor_video.getValue(); + + var instCaptOptions = window.serverConfig.instCapture; + instCaptOptions.v4lEnable = true; + saveOptions.instCapture = instCaptOptions; + + requestWriteConfig(saveOptions); }); } @@ -514,35 +694,69 @@ $(document).ready(function () { removeOverlay(); - // build dynamic enum - var updateVideoSourcesList = function (type, discoveryInfo) { + // build dynamic screen input enum + var updateScreenSourcesList = function (type, discoveryInfo) { var enumVals = []; var enumTitelVals = []; var enumDefaultVal = ""; + if (jQuery.isEmptyObject(discoveryInfo)) { + enumVals.push("NONE"); + enumTitelVals.push($.i18n('edt_conf_grabber_discovered_none')); + + conf_editor_screen.getEditor('root.framegrabber').disable(); + showAllVideoInputOptions(conf_editor_screen, "framegrabber", false); + } + else { + for (const device of discoveryInfo) { + enumVals.push(device.device_name); + } + conf_editor_screen.getEditor('root.framegrabber').enable(); + } + + if (enumVals.length > 0) { + configuredDevice = window.serverConfig.framegrabber.available_devices; + if ($.inArray(configuredDevice, enumVals) != -1) { + enumDefaultVal = configuredDevice; + } + + updateJsonEditorSelection(conf_editor_screen.getEditor('root.framegrabber'), + 'available_devices', {}, enumVals, enumTitelVals, enumDefaultVal, false); + } + } + + // build dynamic video input enum + var updateVideoSourcesList = function (type, discoveryInfo) { + var enumVals = []; + var enumTitelVals = []; + var enumDefaultVal = ""; + var addSelect = false; + if (jQuery.isEmptyObject(discoveryInfo)) { enumVals.push("NONE"); enumTitelVals.push($.i18n('edt_conf_grabber_discovered_none')); conf_editor_video.getEditor('root.grabberV4L2').disable(); - showAllVideoInputOptions(false); + showAllVideoInputOptions(conf_editor_video, "grabberV4L2", false); } else { for (const device of discoveryInfo) { enumVals.push(device.device_name); } conf_editor_video.getEditor('root.grabberV4L2').enable(); - } - - if (enumVals.length > 0) { configuredDevice = window.serverConfig.grabberV4L2.available_devices; + if ($.inArray(configuredDevice, enumVals) != -1) { enumDefaultVal = configuredDevice; } - - updateJsonEditorSelection(conf_editor_video.getEditor('root.grabberV4L2'), - 'available_devices', {}, enumVals, enumTitelVals, enumDefaultVal, false); + else { + addSelect = true; + showAllVideoInputOptions(conf_editor_video, "grabberV4L2", false); + } } + + updateJsonEditorSelection(conf_editor_video.getEditor('root.grabberV4L2'), + 'available_devices', {}, enumVals, enumTitelVals, enumDefaultVal, addSelect); } async function discoverInputSources(type, params) { @@ -557,9 +771,18 @@ $(document).ready(function () { "video_sources": [] } } + + //console.log("discoveryResult", discoveryResult); discoveredInputSources = discoveryResult.video_sources; - updateVideoSourcesList(type, discoveredInputSources); + switch (type) { + case "screen": + updateScreenSourcesList(type, discoveredInputSources); + break; + case "video": + updateVideoSourcesList(type, discoveredInputSources); + break; + } } function getPropertiesOfDevice(deviceName) { @@ -573,20 +796,20 @@ $(document).ready(function () { return deviceProperties; } - function showVideoInputOptions(elements, state) { + function showVideoInputOptions(path, elements, state) { for (var i = 0; i < elements.length; i++) { - $('[data-schemapath*="root.grabberV4L2.' + elements[i] + '"]').toggle(state); + $('[data-schemapath*="'+ path + '.' + elements[i] + '"]').toggle(state); } } - function showAllVideoInputOptions(state) { + function showAllVideoInputOptions(editor, item, state) { var elements = []; - for (var key in conf_editor_video.schema.properties.grabberV4L2.properties) { + for (var key in editor.schema.properties[item].properties) { if (key !== "available_devices") { elements.push(key); } } - showVideoInputOptions(elements, state); + showVideoInputOptions("root." + item, elements, state); } }); diff --git a/assets/webconfig/js/ui_utils.js b/assets/webconfig/js/ui_utils.js index eea7460a..ae348c02 100644 --- a/assets/webconfig/js/ui_utils.js +++ b/assets/webconfig/js/ui_utils.js @@ -53,7 +53,7 @@ function updateSessions() { if (sess && sess.length) { window.wSess = []; for (var i = 0; i < sess.length; i++) { - if (sess[i].type == "_hyperiond-http._tcp.") { + if (sess[i].type == "_http._tcp." || sess[i].type == "_https._tcp." || sess[i].type == "_hyperiond-http._tcp.") { window.wSess.push(sess[i]); } } @@ -461,7 +461,7 @@ function createJsonEditor(container, schema, setconfig, usePanel, arrayre) { return editor; } -function updateJsonEditorSelection(editor, key, addElements, newEnumVals, newTitelVals, newDefaultVal, addCustom) { +function updateJsonEditorSelection(editor, key, addElements, newEnumVals, newTitelVals, newDefaultVal, addSelect, addCustom, addCustomAsFirst, customText) { var orginalProperties = editor.schema.properties[key]; var newSchema = []; @@ -494,8 +494,22 @@ function updateJsonEditorSelection(editor, key, addElements, newEnumVals, newTit } if (addCustom) { - newEnumVals.push("custom"); - newTitelVals.push("edt_conf_enum_custom"); + + if (newTitelVals.length === 0) { + newTitelVals = [...newEnumVals]; + } + + if (!!!customText) { + customText = "edt_conf_enum_custom"; + } + + if (addCustomAsFirst) { + newEnumVals.unshift("CUSTOM"); + newTitelVals.unshift(customText); + } else { + newEnumVals.push("CUSTOM"); + newTitelVals.push(customText); + } if (newSchema[key].options.infoText) { var customInfoText = newSchema[key].options.infoText + "_custom"; @@ -503,6 +517,12 @@ function updateJsonEditorSelection(editor, key, addElements, newEnumVals, newTit } } + if (addSelect) { + newEnumVals.unshift("SELECT"); + newTitelVals.unshift("edt_conf_enum_please_select"); + newDefaultVal = "SELECT"; + } + if (newEnumVals) { newSchema[key]["enum"] = newEnumVals; } diff --git a/bin/scripts/docker-compile.sh b/bin/scripts/docker-compile.sh index 3ff06ad7..eb9a24bc 100644 --- a/bin/scripts/docker-compile.sh +++ b/bin/scripts/docker-compile.sh @@ -10,32 +10,44 @@ BUILD_TYPE="Release" # the docker image at GitHub Container Registry BUILD_IMAGE="x86_64" # the docker tag at GitHub Container Registry -BUILD_TAG="stretch" +BUILD_TAG="buster" # build packages (.deb .zip ...) BUILD_PACKAGES=true # packages string inserted to cmake cmd PACKAGES="" +#Run build using GitHub code files +BUILD_LOCAL=0 +#Build from scratch +BUILD_INCREMENTAL=0 +#Verbose output +_VERBOSE=0 # get current path to this script, independent of calling pushd . > /dev/null -SCRIPT_PATH="${BASH_SOURCE[0]}" -if ([ -h "${SCRIPT_PATH}" ]); then - while([ -h "${SCRIPT_PATH}" ]); do cd `dirname "$SCRIPT_PATH"`; - SCRIPT_PATH=`readlink "${SCRIPT_PATH}"`; done +BASE_PATH="${BASH_SOURCE[0]}" +if ([ -h "${BASE_PATH}" ]); then + while([ -h "${BASE_PATH}" ]); do cd `dirname "${BASE_PATH}"`; + BASE_PATH=`readlink "${BASE_PATH}"`; done fi -cd `dirname ${SCRIPT_PATH}` > /dev/null -SCRIPT_PATH=`pwd`; +cd `dirname ${BASE_PATH}` > /dev/null +BASE_PATH=`pwd`; popd > /dev/null +BASE_PATH=`pwd`;function log () { + if [[ $_V -eq 1 ]]; then + echo "$@" + fi +} + set +e -$DOCKER ps >/dev/null 2>&1 +${DOCKER} ps >/dev/null 2>&1 if [ $? != 0 ]; then DOCKER="sudo docker" fi # check if docker is available -if ! $DOCKER ps >/dev/null; then +if ! ${DOCKER} ps >/dev/null; then echo "Error connecting to docker:" - $DOCKER ps + ${DOCKER} ps printHelp exit 1 fi @@ -46,7 +58,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 Stretch (x86_64). +## 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) ## ## Homepage: https://www.hyperion-project.org @@ -54,15 +66,25 @@ echo "######################################################## ######################################################## # These are possible arguments to modify the script behaviour with their default values # -# docker-compile.sh -h # Show this help message -# docker-compile.sh -i x86_64 # The docker image, one of x86_64 | armv6l | armv7l | rpi-raspbian -# docker-compile.sh -t stretch # The docker tag, stretch or buster -# docker-compile.sh -b Release # cmake Release or Debug build -# docker-compile.sh -p true # If true build packages with CPack +# docker-compile.sh -h # Show this help message +# docker-compile.sh -i x86_64 # The docker image, one of x86_64 | armv6l | armv7l | rpi-raspbian +# docker-compile.sh -t stretch # The docker tag, stretch or buster +# docker-compile.sh -b Release # cmake Release or Debug build +# docker-compile.sh -p true # If true, build packages with CPack +# docker-compile.sh -l # Run build using local code files +# docker-compile.sh -c # Run incremental build, i.e. do not delete files created during previous build # More informations to docker tags at: https://github.com/Hyperion-Project/hyperion.docker-ci" } -while getopts i:t:b:p:h option +function log () { + if [[ $_VERBOSE -eq 1 ]]; then + echo "$@" + fi +} + +echo "Compile Hyperion using a Docker container" + +while getopts i:t:b:p:lcvh option do case "${option}" in @@ -70,51 +92,83 @@ do t) BUILD_TAG=${OPTARG};; b) BUILD_TYPE=${OPTARG};; p) BUILD_PACKAGES=${OPTARG};; + l) BUILD_LOCAL=1;; + c) BUILD_INCREMENTAL=1;; + v) _VERBOSE=1;; h) printHelp; exit 0;; esac done # determine package creation -if [ $BUILD_PACKAGES == "true" ]; then +if [ ${BUILD_PACKAGES} == "true" ]; then PACKAGES="package" fi -echo "---> Initialize with IMAGE:TAG=${BUILD_IMAGE}:${BUILD_TAG}, BUILD_TYPE=${BUILD_TYPE}, BUILD_PACKAGES=${BUILD_PACKAGES}" +echo "---> Initialize with IMAGE:TAG=${BUILD_IMAGE}:${BUILD_TAG}, BUILD_TYPE=${BUILD_TYPE}, BUILD_PACKAGES=${BUILD_PACKAGES}, BUILD_LOCAL=${BUILD_LOCAL}, BUILD_INCREMENTAL=${BUILD_INCREMENTAL}" + +CODE_PATH=${BASE_PATH}; +BUILD_DIR="build-${BUILD_IMAGE}-${BUILD_TAG}" +BUILD_PATH="${BASE_PATH}/${BUILD_DIR}" +DEPLOY_DIR="deploy/${BUILD_IMAGE}/${BUILD_TAG}" +DEPLOY_PATH="${BASE_PATH}/${DEPLOY_DIR}" + +log "---> BASE_PATH = ${BASE_PATH}" +log "---> BUILD_DIR = ${BUILD_DIR}" +log "---> BUILD_PATH = ${BUILD_PATH}" +log "---> DEPLOY_DIR = ${DEPLOY_DIR}" +log "---> DEPLOY_PATH = ${DEPLOY_PATH}" # cleanup deploy folder, create folder for ownership -sudo rm -fr $SCRIPT_PATH/deploy >/dev/null 2>&1 -mkdir $SCRIPT_PATH/deploy >/dev/null 2>&1 +sudo rm -fr ${DEPLOY_PATH} >/dev/null 2>&1 +mkdir -p ${DEPLOY_PATH} >/dev/null 2>&1 # get Hyperion source, cleanup previous folder +if [ ${BUILD_LOCAL} == 0 ]; then +CODE_PATH="${CODE_PATH}/hyperion/" echo "---> Downloading Hyperion source code from ${GIT_REPO_URL}" -sudo rm -fr $SCRIPT_PATH/hyperion >/dev/null 2>&1 -git clone --recursive --depth 1 -q $GIT_REPO_URL $SCRIPT_PATH/hyperion || { echo "---> Failed to download Hyperion source code! Abort"; exit 1; } +sudo rm -fr ${CODE_PATH} >/dev/null 2>&1 +git clone --recursive --depth 1 -q ${GIT_REPO_URL} ${CODE_PATH} || { echo "---> Failed to download Hyperion source code! Abort"; exit 1; } +fi + +#Remove previous build area, if no incremental build +if [ ${BUILD_INCREMENTAL} != 1 ]; then +sudo rm -fr ${BASE_PATH}/${BUILD_PATH} >/dev/null 2>&1 +fi +mkdir -p ${BASE_PATH}/${BUILD_PATH} >/dev/null 2>&1 + +echo "---> Compiling Hyperion from source code at ${CODE_PATH}" # Steps: # Update lokal docker image # Remove container after stop -# Mount /deploy to /deploy +# Mount deploment path to /deploy # Mount source dir to /source # Use target docker image # execute inside container all commands on bash echo "---> Startup docker..." $DOCKER run --rm \ - -v "${SCRIPT_PATH}/deploy:/deploy" \ - -v "${SCRIPT_PATH}/hyperion:/source:ro" \ - $REGISTRY_URL/$BUILD_IMAGE:$BUILD_TAG \ - /bin/bash -c "mkdir hyperion && cp -r /source/. /hyperion && - cd /hyperion && mkdir build && cd build && + -v "${DEPLOY_PATH}:/deploy" \ + -v "${CODE_PATH}/:/source:rw" \ + ${REGISTRY_URL}/${BUILD_IMAGE}:${BUILD_TAG} \ + /bin/bash -c "mkdir -p /source/${BUILD_DIR} && cd /source/${BUILD_DIR} && cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE} .. || exit 2 && make -j $(nproc) ${PACKAGES} || exit 3 && - echo '---> Copy binaries and packages to host folder: ${SCRIPT_PATH}/deploy' && - cp -v /hyperion/build/bin/h* /deploy/ 2>/dev/null || : && - cp -v /hyperion/build/Hyperion-* /deploy/ 2>/dev/null || : && + echo '---> Copying packages to host folder: ${DEPLOY_PATH}' && + cp -v /source/${BUILD_DIR}/Hyperion-* /deploy 2>/dev/null || : && exit 0; exit 1 " || { echo "---> Hyperion compilation failed! Abort"; exit 4; } # overwrite file owner to current user -sudo chown -fR $(stat -c "%U:%G" $SCRIPT_PATH/deploy) $SCRIPT_PATH/deploy +sudo chown -fR $(stat -c "%U:%G" ${BASE_PATH}) ${BUILD_PATH} +sudo chown -fR $(stat -c "%U:%G" ${BASE_PATH}) ${DEPLOY_PATH} -echo "---> Script finished, view folder ${SCRIPT_PATH}/deploy for compiled packages and binaries" +if [ ${BUILD_LOCAL} == 1 ]; then + echo "---> Find compiled binaries in: ${BUILD_PATH}/bin" +fi + +if [ ${BUILD_PACKAGES} == "true" ]; then + echo "---> Find deployment packages in: ${DEPLOY_PATH}" +fi + echo "---> Script finished" exit 0 diff --git a/cmake/Dependencies.cmake b/cmake/Dependencies.cmake index d291b8e8..b83a9c20 100644 --- a/cmake/Dependencies.cmake +++ b/cmake/Dependencies.cmake @@ -339,30 +339,6 @@ macro(DeployWindows TARGET) ) endforeach() - if (ENABLE_DX) - # Download DirectX End-User Runtimes (June 2010) - set(url "https://download.microsoft.com/download/8/4/A/84A35BF1-DAFE-4AE8-82AF-AD2AE20B6B14/directx_Jun2010_redist.exe") - if(NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/dx_redist.exe") - file(DOWNLOAD "${url}" "${CMAKE_CURRENT_BINARY_DIR}/dx_redist.exe" - STATUS result - ) - - # Check if the download is successful - list(GET result 0 result_code) - if(NOT result_code EQUAL 0) - list(GET result 1 reason) - message(FATAL_ERROR "Could not download DirectX End-User Runtimes: ${reason}") - endif() - endif() - - # Copy DirectX End-User Runtimes to 'hyperion' - install( - FILES ${CMAKE_CURRENT_BINARY_DIR}/dx_redist.exe - DESTINATION "bin" - COMPONENT "Hyperion" - ) - endif (ENABLE_DX) - else() # Run CMake after target was built add_custom_command( diff --git a/config/hyperion.config.json.default b/config/hyperion.config.json.default index 040187eb..6994ba71 100644 --- a/config/hyperion.config.json.default +++ b/config/hyperion.config.json.default @@ -62,7 +62,7 @@ "grabberV4L2" : { - "device" : "auto", + "device" : "none", "input" : 0, "encoding" : "NO_CHANGE", "width" : 0, @@ -93,16 +93,16 @@ "framegrabber" : { - "type" : "auto", + "device" : "auto", + "input" : 0, "width" : 80, "height" : 45, - "frequency_Hz" : 10, + "fps" : 10, "pixelDecimation" : 8, "cropLeft" : 0, "cropRight" : 0, "cropTop" : 0, - "cropBottom" : 0, - "display" : 0 + "cropBottom" : 0 }, "blackborderdetector" : diff --git a/dependencies/CMakeLists-mbedtls.txt.in b/dependencies/CMakeLists-mbedtls.txt.in index 12888d5b..cb81adc8 100644 --- a/dependencies/CMakeLists-mbedtls.txt.in +++ b/dependencies/CMakeLists-mbedtls.txt.in @@ -14,7 +14,7 @@ include(ExternalProject) ExternalProject_Add( mbedtls GIT_REPOSITORY "https://github.com/ARMmbed/mbedtls.git" - GIT_TAG origin/master + GIT_TAG "v2.25.0" # Reset to origin/master if issue https://github.com/ARMmbed/mbedtls/issues/4233 if fixed BUILD_ALWAYS OFF DOWNLOAD_DIR "${DOWNLOAD_DIR}" SOURCE_DIR "${SOURCE_DIR}" diff --git a/dependencies/CMakeLists.txt b/dependencies/CMakeLists.txt index 318787de..f37aa83a 100644 --- a/dependencies/CMakeLists.txt +++ b/dependencies/CMakeLists.txt @@ -233,7 +233,7 @@ if (NOT USE_SYSTEM_MBEDTLS_LIBS) FetchContent_Declare( mbedtls GIT_REPOSITORY https://github.com/ARMmbed/mbedtls.git - GIT_TAG origin/master + GIT_TAG "v2.25.0" # Reset to origin/master if issue https://github.com/ARMmbed/mbedtls/issues/4233 if fixed BUILD_ALWAYS OFF GIT_PROGRESS 1 DOWNLOAD_DIR "${MBEDTLS_DOWNLOAD_DIR}" diff --git a/docs/development/LedDevice_Flows.drawio b/development/LedDevice_Flows.drawio similarity index 100% rename from docs/development/LedDevice_Flows.drawio rename to development/LedDevice_Flows.drawio diff --git a/docs/development/LedDevice_Flows.png b/development/LedDevice_Flows.png similarity index 100% rename from docs/development/LedDevice_Flows.png rename to development/LedDevice_Flows.png diff --git a/docs/.gitignore b/docs/.gitignore deleted file mode 100644 index f06235c4..00000000 --- a/docs/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules -dist diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index 87d20045..00000000 --- a/docs/README.md +++ /dev/null @@ -1,24 +0,0 @@ -## Documentation -This folder contains the Hyperion documentation build files. It's written in Markdown with [VuePress](https://vuepress.vuejs.org/) as static site generator. - -### Development -To edit or translate the documentation, it's not necessarily required to follow these steps (As we use Markdown). But if you want to check the results, please do so. - - Install latest [Node.js LTS](https://nodejs.org/en/) - - Open console - - Install Yarn `npm install -g yarn` (If this does not work - logout/login) - - Navigate with console to this directory - - Do `yarn install` - - Now you can start dev server with `yarn docs:dev` - - Open Browser and go to address `localhost:8080` - -#### Notes - - If you want to view the deployable site locally run `yarn docs:serve` - - Do not rename files and folders while translating - - Copy/paste and translate also `.vuepress/config.js` at `themeConfig.locales` - - Changes in `.vuepress/config.js` may lead to a bugged dev server. Restart. - - To modify the sidebar pages checkout `.vuepress/config.js` at `themeConfig.sidebar` - -### Production -To get a deployable version run - - `yarn docs:build` (while inside this folder) - - Files will be in `dist` folder \ No newline at end of file diff --git a/docs/docs/.vuepress/components/ImageWrap.vue b/docs/docs/.vuepress/components/ImageWrap.vue deleted file mode 100644 index a3fc3104..00000000 --- a/docs/docs/.vuepress/components/ImageWrap.vue +++ /dev/null @@ -1,18 +0,0 @@ - - - - - \ No newline at end of file diff --git a/docs/docs/.vuepress/components/MainSection.vue b/docs/docs/.vuepress/components/MainSection.vue deleted file mode 100644 index 6e28ddd0..00000000 --- a/docs/docs/.vuepress/components/MainSection.vue +++ /dev/null @@ -1,49 +0,0 @@ - - - - - \ No newline at end of file diff --git a/docs/docs/.vuepress/config.js b/docs/docs/.vuepress/config.js deleted file mode 100644 index 873e1d65..00000000 --- a/docs/docs/.vuepress/config.js +++ /dev/null @@ -1,290 +0,0 @@ -module.exports = { - head: [ - ['link', { rel: 'icon', type: 'image/png', sizes: '16x16', href: '/icons/favicon-16x16.png' }], - ['link', { rel: 'icon', type: 'image/png', sizes: '32x32', href: '/icons/favicon-32x32.png' }], - ['link', { rel: 'icon', type: 'image/png', sizes: '96x96', href: '/icons/favicon-96x96.png' }], - ['link', { rel: 'icon', type: 'image/png', sizes: '128x128', href: '/icons/favicon-128x128.png' }], - ['link', { rel: 'icon', type: 'image/ico', href: '/icons/favicon.ico' }], - // iPhone XR - ['link', { rel: "apple-touch-startup-image", media: "(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2)", href: "/icons/apple-launch-828x1792.png" }], - // iPhone X, XS - ['link', { rel: "apple-touch-startup-image", media: "(device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3)", href: "/icons/apple-launch-1125x2436.png" }], - // iPhone XS Max - ['link', { rel: "apple-touch-startup-image", media: "(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3)", href: "/icons/apple-launch-1242x2688.png" }], - // iPhone 8, 7, 6s, 6 - ['link', { rel: "apple-touch-startup-image", media: "(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2)", href: "/icons/apple-launch-750x1334.png" }], - // iPhone 8 Plus, 7 Plus, 6s Plus, 6 Plus - ['link', { rel: "apple-touch-startup-image", media: "(device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3)", href: "/icons/apple-launch-1242x2208.png" }], - // iPhone 5 - ['link', { rel: "apple-touch-startup-image", media: "(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2)", href: "/icons/apple-launch-640x1136.png" }], - // iPad Mini, Air, 9.7 - ['link', { rel: "apple-touch-startup-image", media: "(device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2)", href: "/icons/apple-launch-1536x2048.png" }], - // iPad Pro 10.5 - ['link', { rel: "apple-touch-startup-image", media: "(device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2)", href: "/icons/apple-launch-1668x2224.png" }], - // iPad Pro 11 - ['link', { rel: "apple-touch-startup-image", media: "(device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2)", href: "/icons/apple-launch-1668x2388.png" }], - // iPad Pro 12.9" - ['link', { rel: "apple-touch-startup-image", media: "(device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2)", href: "/icons/apple-launch-2048x2732.png" }], - - // PWA - ['link', { rel: 'manifest', href: '/manifest.json' }], - ['meta', { name: 'theme-color', content: '#2b81a0' }], // ??? - ['meta', { name: 'apple-mobile-web-app-capable', content: 'yes' }], - ['meta', { name: 'apple-mobile-web-app-status-bar-style', content: 'black' }], - ['meta', { name: 'apple-mobile-web-app-title', content: 'Hyperion Documentation' }], - ['link', { rel: 'apple-touch-icon', sizes: '120x120', href: '/icons/apple-icon-120x120.png' }], - ['link', { rel: 'apple-touch-icon', sizes: '152x152', href: '/icons/apple-icon-152x152.png' }], - ['link', { rel: 'apple-touch-icon', sizes: '167x167', href: '/icons/apple-icon-167x167.png' }], - ['link', { rel: 'apple-touch-icon', sizes: '180x180', href: '/icons/apple-icon-180x180.png' }], - ['link', { rel: 'mask-icon', href: '/icons/safari-pinned-tab.svg', color: '#fff' }], - ['meta', { name: 'msapplication-TileImage', content: '/icons/ms-icon-144x144.png' }], // probably invert - ['meta', { name: 'msapplication-TileColor', content: '#2b81a0' }] // might not match with icon - ], - dest: "./dist", - title: "Hyperion", - // removing this sections disables lang selector. But everything else works. Featue Request to merge with themeConfig.locales? - locales: { - "/": { - lang: 'en-US', - // Description of page does not work inside themeConfig - description: 'Hyperion Ambient Light documentation' - }, - "/de/": { - lang: 'de-DE', - description: 'Hyperion Ambient Light Dokumentation' - } - }, - themeConfig: { - /* algolia: { - apiKey: '', - indexName: '' - }, - - */ - sidebarDepth: 3, - smoothScroll: true, - logo: '/hyperion-logo.png', - locales: { - '/': { - // text for the language dropdown - selectText: 'Languages', - // label for this locale in the language dropdown - label: 'English', - // Aria Label for locale in the dropdown - ariaLabel: 'Languages', - // text for last updated - lastUpdated: 'Last Updated', - // Seach placeholder - searchPlaceholder: 'Search...', - // Customising the header label - repoLabel: 'Contribute', - // custom text for edit link. Defaults to "Edit this page" - editLinkText: 'Edit this page on GitHub', - // config for Service Worker - serviceWorker: { - updatePopup: { - message: "New content is available.", - buttonText: "Refresh" - } - }, - // The top navbar - nav: [ - { text: 'Home', link: '/' }, - { text: 'User', link: '/en/user/' }, - { text: 'Effects', link: '/en/effects/' }, - { text: 'Json API', link: '/en/json/' } - // { text: 'Addons API', link: '/en/addons/' } - ], - sidebar: { - '/en/user/': getUserSidebar('General', 'Advanced'), - '/en/effects/': getEffectsSidebar('Effects', 'Effects UI'), - '/en/json/': getJsonSidebar('JSON', 'Misc'), - '/en/api/': getApiSidebar('Go back to') - // '/en/addons/': getAddonsSidebar('Addons', 'Addons UI') - } - }, - '/de/': { - selectText: 'Sprachen', - label: 'Deutsch', - searchPlaceholder: 'Wer sucht...', - lastUpdated: 'Zuletzt Aktualisiert', - repoLabel: 'Mach mit', - editLinkText: 'Editiere diese Seite auf Github', - serviceWorker: { - updatePopup: { - message: "Neuer Inhalt ist verfügbar.", - buttonText: "Aktualisieren" - } - }, - nav: [ - { text: 'Startseite', link: '/de/' } - //{ text: 'Benutzer', link: '/de/user/' } - //{ text: 'Effects', link: '/en/effects/' }, - //{ text: 'Json API', link: '/en/json/' } - // { text: 'Addons API', link: '/en/addons/' } - ], - // '/de/user/': getUserSidebar('Allgemein', 'Erweitert'), - // '/de/effects/': getEffectsSidebar('Effekte', 'Effekt UI'), - // '/de/json/': getJsonSidebar('JSON', 'Misc'), - // '/de/api/': getApiSidebar('Gehe zurück zu') - // '/en/addons/': getAddonsSidebar('Addons', 'Addons UI') - } - }, - // Customising the header label - // Defaults to "GitHub"/"GitLab"/"Bitbucket" depending on `themeConfig.repo` - repoLabel: 'Contribute', - // Optional options for generating "Edit this page" link - // if your docs are in a different repo from your main project: - docsRepo: 'hyperion-project/hyperion.ng', - // if your docs are not at the root of the repo: - docsDir: 'docs/docs', - // if your docs are in a specific branch (defaults to 'master'): - docsBranch: 'master', - // defaults to false, set to true to enable - editLinks: true, - // default value is true. Allows to hide next page links on all pages - nextLinks: true, - // default value is true. Allows to hide prev page links on all pages - prevLinks: true, - // custom text for edit link. Defaults to "Edit this page" - //editLinkText: 'Edit this page on GitHub' - }, - plugins: [ - - // https://vuepress.github.io/en/plugins/medium-zoom/ - [ - 'vuepress-plugin-medium-zoom', - { - selector: '.zoomable', - delay: 1000, - options: { - margin: 24, - background: '#000000bf', - scrollOffset: 0, - } - } - ], - // https://vuepress.github.io/en/plugins/redirect - [ - 'vuepress-plugin-redirect', - { - locales: true - } - ], - // https://vuepress.vuejs.org/plugin/official/plugin-pwa.html#install - [ - '@vuepress/pwa', { - serviceWorker: true, - updatePopup: true - } - ], - // https://v1.vuepress.vuejs.org/plugin/official/plugin-back-to-top.html - [ - '@vuepress/back-to-top' - ], - [ - 'vuepress-plugin-serve' - ] - ] -} - -function getUserSidebar (groupA, groupB) { - return [ - { - title: groupA, - collapsable: false, - children: [ - '', - 'Installation', - 'Configuration', - 'LedDevices', - 'HyperBian', - ] - }, - { - title: groupB, - collapsable: false, - children: [ - 'advanced/Advanced', - 'advanced/Support', - ] - } - ] -} - -function getEffectsSidebar (groupA, groupB) { - return [{ - title: groupA, - collapsable: false, - children: [ - '', - 'API', - 'OurFirstEffect', - ] - }, - { - title: groupB, - collapsable: false, - children: [ - '../api/Ui' - ] - } - ] -} - -function getJsonSidebar (groupA, groupB) { - return [{ - title: groupA, - collapsable: false, - children: [ - '', - 'ServerInfo', - 'Control', - 'Authorization', - 'Subscribe', - ] - }, - { - title: groupB, - collapsable: false, - children: [ - '../api/Detect', - '../api/Guidelines' - ] - } - ] -} - -function getApiSidebar (groupA) { - return [ - { - title: groupA, - collapsable: false, - children: [ - '../effects/', - '../json/' - ] - } - ] -} - -function getAddonsSidebar (groupA, groupB) { - return [{ - title: groupA, - collapsable: false, - children: [ - '', - 'API', - 'OurFirstAddon', - ] - }, - { - title: groupB, - collapsable: false, - children: [ - '../api/Ui' - ] - } - ] -} - diff --git a/docs/docs/.vuepress/public/hyperion-logo.png b/docs/docs/.vuepress/public/hyperion-logo.png deleted file mode 100644 index 1d3036ce..00000000 Binary files a/docs/docs/.vuepress/public/hyperion-logo.png and /dev/null differ diff --git a/docs/docs/.vuepress/public/icons/apple-icon-120x120.png b/docs/docs/.vuepress/public/icons/apple-icon-120x120.png deleted file mode 100644 index 169bb6d5..00000000 Binary files a/docs/docs/.vuepress/public/icons/apple-icon-120x120.png and /dev/null differ diff --git a/docs/docs/.vuepress/public/icons/apple-icon-152x152.png b/docs/docs/.vuepress/public/icons/apple-icon-152x152.png deleted file mode 100644 index ca8c49d0..00000000 Binary files a/docs/docs/.vuepress/public/icons/apple-icon-152x152.png and /dev/null differ diff --git a/docs/docs/.vuepress/public/icons/apple-icon-167x167.png b/docs/docs/.vuepress/public/icons/apple-icon-167x167.png deleted file mode 100644 index 2f5c0dfc..00000000 Binary files a/docs/docs/.vuepress/public/icons/apple-icon-167x167.png and /dev/null differ diff --git a/docs/docs/.vuepress/public/icons/apple-icon-180x180.png b/docs/docs/.vuepress/public/icons/apple-icon-180x180.png deleted file mode 100644 index 11007fe9..00000000 Binary files a/docs/docs/.vuepress/public/icons/apple-icon-180x180.png and /dev/null differ diff --git a/docs/docs/.vuepress/public/icons/apple-launch-1125x2436.png b/docs/docs/.vuepress/public/icons/apple-launch-1125x2436.png deleted file mode 100644 index b9cef742..00000000 Binary files a/docs/docs/.vuepress/public/icons/apple-launch-1125x2436.png and /dev/null differ diff --git a/docs/docs/.vuepress/public/icons/apple-launch-1242x2208.png b/docs/docs/.vuepress/public/icons/apple-launch-1242x2208.png deleted file mode 100644 index 2e6e322d..00000000 Binary files a/docs/docs/.vuepress/public/icons/apple-launch-1242x2208.png and /dev/null differ diff --git a/docs/docs/.vuepress/public/icons/apple-launch-1242x2688.png b/docs/docs/.vuepress/public/icons/apple-launch-1242x2688.png deleted file mode 100644 index 96fbd2a4..00000000 Binary files a/docs/docs/.vuepress/public/icons/apple-launch-1242x2688.png and /dev/null differ diff --git a/docs/docs/.vuepress/public/icons/apple-launch-1536x2048.png b/docs/docs/.vuepress/public/icons/apple-launch-1536x2048.png deleted file mode 100644 index 98a9928d..00000000 Binary files a/docs/docs/.vuepress/public/icons/apple-launch-1536x2048.png and /dev/null differ diff --git a/docs/docs/.vuepress/public/icons/apple-launch-1668x2224.png b/docs/docs/.vuepress/public/icons/apple-launch-1668x2224.png deleted file mode 100644 index d0549a00..00000000 Binary files a/docs/docs/.vuepress/public/icons/apple-launch-1668x2224.png and /dev/null differ diff --git a/docs/docs/.vuepress/public/icons/apple-launch-1668x2388.png b/docs/docs/.vuepress/public/icons/apple-launch-1668x2388.png deleted file mode 100644 index 8158e92e..00000000 Binary files a/docs/docs/.vuepress/public/icons/apple-launch-1668x2388.png and /dev/null differ diff --git a/docs/docs/.vuepress/public/icons/apple-launch-2048x2732.png b/docs/docs/.vuepress/public/icons/apple-launch-2048x2732.png deleted file mode 100644 index fecd09c8..00000000 Binary files a/docs/docs/.vuepress/public/icons/apple-launch-2048x2732.png and /dev/null differ diff --git a/docs/docs/.vuepress/public/icons/apple-launch-640x1136.png b/docs/docs/.vuepress/public/icons/apple-launch-640x1136.png deleted file mode 100644 index b5042c27..00000000 Binary files a/docs/docs/.vuepress/public/icons/apple-launch-640x1136.png and /dev/null differ diff --git a/docs/docs/.vuepress/public/icons/apple-launch-750x1334.png b/docs/docs/.vuepress/public/icons/apple-launch-750x1334.png deleted file mode 100644 index 9e66b4e8..00000000 Binary files a/docs/docs/.vuepress/public/icons/apple-launch-750x1334.png and /dev/null differ diff --git a/docs/docs/.vuepress/public/icons/apple-launch-828x1792.png b/docs/docs/.vuepress/public/icons/apple-launch-828x1792.png deleted file mode 100644 index 59925e08..00000000 Binary files a/docs/docs/.vuepress/public/icons/apple-launch-828x1792.png and /dev/null differ diff --git a/docs/docs/.vuepress/public/icons/favicon-128x128.png b/docs/docs/.vuepress/public/icons/favicon-128x128.png deleted file mode 100644 index 16b685c7..00000000 Binary files a/docs/docs/.vuepress/public/icons/favicon-128x128.png and /dev/null differ diff --git a/docs/docs/.vuepress/public/icons/favicon-16x16.png b/docs/docs/.vuepress/public/icons/favicon-16x16.png deleted file mode 100644 index 52d72f5d..00000000 Binary files a/docs/docs/.vuepress/public/icons/favicon-16x16.png and /dev/null differ diff --git a/docs/docs/.vuepress/public/icons/favicon-32x32.png b/docs/docs/.vuepress/public/icons/favicon-32x32.png deleted file mode 100644 index 9e0a32b8..00000000 Binary files a/docs/docs/.vuepress/public/icons/favicon-32x32.png and /dev/null differ diff --git a/docs/docs/.vuepress/public/icons/favicon-96x96.png b/docs/docs/.vuepress/public/icons/favicon-96x96.png deleted file mode 100644 index e06ea630..00000000 Binary files a/docs/docs/.vuepress/public/icons/favicon-96x96.png and /dev/null differ diff --git a/docs/docs/.vuepress/public/icons/favicon.ico b/docs/docs/.vuepress/public/icons/favicon.ico deleted file mode 100644 index 92311b0c..00000000 Binary files a/docs/docs/.vuepress/public/icons/favicon.ico and /dev/null differ diff --git a/docs/docs/.vuepress/public/icons/icon-128x128.png b/docs/docs/.vuepress/public/icons/icon-128x128.png deleted file mode 100644 index 16b685c7..00000000 Binary files a/docs/docs/.vuepress/public/icons/icon-128x128.png and /dev/null differ diff --git a/docs/docs/.vuepress/public/icons/icon-192x192.png b/docs/docs/.vuepress/public/icons/icon-192x192.png deleted file mode 100644 index b6cd4aad..00000000 Binary files a/docs/docs/.vuepress/public/icons/icon-192x192.png and /dev/null differ diff --git a/docs/docs/.vuepress/public/icons/icon-256x256.png b/docs/docs/.vuepress/public/icons/icon-256x256.png deleted file mode 100644 index 9ba11917..00000000 Binary files a/docs/docs/.vuepress/public/icons/icon-256x256.png and /dev/null differ diff --git a/docs/docs/.vuepress/public/icons/icon-384x384.png b/docs/docs/.vuepress/public/icons/icon-384x384.png deleted file mode 100644 index 852ae387..00000000 Binary files a/docs/docs/.vuepress/public/icons/icon-384x384.png and /dev/null differ diff --git a/docs/docs/.vuepress/public/icons/icon-512x512.png b/docs/docs/.vuepress/public/icons/icon-512x512.png deleted file mode 100644 index 69ac0340..00000000 Binary files a/docs/docs/.vuepress/public/icons/icon-512x512.png and /dev/null differ diff --git a/docs/docs/.vuepress/public/icons/ms-icon-144x144.png b/docs/docs/.vuepress/public/icons/ms-icon-144x144.png deleted file mode 100644 index 1bbbaf7a..00000000 Binary files a/docs/docs/.vuepress/public/icons/ms-icon-144x144.png and /dev/null differ diff --git a/docs/docs/.vuepress/public/icons/safari-pinned-tab.svg b/docs/docs/.vuepress/public/icons/safari-pinned-tab.svg deleted file mode 100644 index ed54571e..00000000 --- a/docs/docs/.vuepress/public/icons/safari-pinned-tab.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/docs/docs/.vuepress/public/images/en/avahi-browse.jpg b/docs/docs/.vuepress/public/images/en/avahi-browse.jpg deleted file mode 100644 index 54097bbc..00000000 Binary files a/docs/docs/.vuepress/public/images/en/avahi-browse.jpg and /dev/null differ diff --git a/docs/docs/.vuepress/public/images/en/http_jsonrpc.jpg b/docs/docs/.vuepress/public/images/en/http_jsonrpc.jpg deleted file mode 100644 index 6e1f25bf..00000000 Binary files a/docs/docs/.vuepress/public/images/en/http_jsonrpc.jpg and /dev/null differ diff --git a/docs/docs/.vuepress/public/images/en/owneff_1.jpg b/docs/docs/.vuepress/public/images/en/owneff_1.jpg deleted file mode 100644 index 21580cf2..00000000 Binary files a/docs/docs/.vuepress/public/images/en/owneff_1.jpg and /dev/null differ diff --git a/docs/docs/.vuepress/public/images/en/owneff_2.jpg b/docs/docs/.vuepress/public/images/en/owneff_2.jpg deleted file mode 100644 index f68d9a77..00000000 Binary files a/docs/docs/.vuepress/public/images/en/owneff_2.jpg and /dev/null differ diff --git a/docs/docs/.vuepress/public/images/en/owneff_3.gif b/docs/docs/.vuepress/public/images/en/owneff_3.gif deleted file mode 100644 index 9918f4a3..00000000 Binary files a/docs/docs/.vuepress/public/images/en/owneff_3.gif and /dev/null differ diff --git a/docs/docs/.vuepress/public/images/en/owneff_4.gif b/docs/docs/.vuepress/public/images/en/owneff_4.gif deleted file mode 100644 index 49ad9e82..00000000 Binary files a/docs/docs/.vuepress/public/images/en/owneff_4.gif and /dev/null differ diff --git a/docs/docs/.vuepress/public/images/en/user_bbmodes.jpg b/docs/docs/.vuepress/public/images/en/user_bbmodes.jpg deleted file mode 100644 index bb363b9c..00000000 Binary files a/docs/docs/.vuepress/public/images/en/user_bbmodes.jpg and /dev/null differ diff --git a/docs/docs/.vuepress/public/images/en/user_config_access.jpg b/docs/docs/.vuepress/public/images/en/user_config_access.jpg deleted file mode 100644 index 6d618547..00000000 Binary files a/docs/docs/.vuepress/public/images/en/user_config_access.jpg and /dev/null differ diff --git a/docs/docs/.vuepress/public/images/en/user_config_dash.jpg b/docs/docs/.vuepress/public/images/en/user_config_dash.jpg deleted file mode 100644 index 244f8087..00000000 Binary files a/docs/docs/.vuepress/public/images/en/user_config_dash.jpg and /dev/null differ diff --git a/docs/docs/.vuepress/public/images/en/user_config_lang.jpg b/docs/docs/.vuepress/public/images/en/user_config_lang.jpg deleted file mode 100644 index 5d9cc277..00000000 Binary files a/docs/docs/.vuepress/public/images/en/user_config_lang.jpg and /dev/null differ diff --git a/docs/docs/.vuepress/public/images/en/user_gammacurve.png b/docs/docs/.vuepress/public/images/en/user_gammacurve.png deleted file mode 100644 index 2a8b4127..00000000 Binary files a/docs/docs/.vuepress/public/images/en/user_gammacurve.png and /dev/null differ diff --git a/docs/docs/.vuepress/public/images/en/user_hyperbian_ssh.jpg b/docs/docs/.vuepress/public/images/en/user_hyperbian_ssh.jpg deleted file mode 100644 index 641ddc97..00000000 Binary files a/docs/docs/.vuepress/public/images/en/user_hyperbian_ssh.jpg and /dev/null differ diff --git a/docs/docs/.vuepress/public/images/en/user_hyperbian_wpa_suppli1.jpg b/docs/docs/.vuepress/public/images/en/user_hyperbian_wpa_suppli1.jpg deleted file mode 100644 index aa9cfdd7..00000000 Binary files a/docs/docs/.vuepress/public/images/en/user_hyperbian_wpa_suppli1.jpg and /dev/null differ diff --git a/docs/docs/.vuepress/public/images/en/user_hyperbian_wpa_suppli2.jpg b/docs/docs/.vuepress/public/images/en/user_hyperbian_wpa_suppli2.jpg deleted file mode 100644 index 389a28c3..00000000 Binary files a/docs/docs/.vuepress/public/images/en/user_hyperbian_wpa_suppli2.jpg and /dev/null differ diff --git a/docs/docs/.vuepress/public/images/en/user_hyperbian_wpa_suppli3.jpg b/docs/docs/.vuepress/public/images/en/user_hyperbian_wpa_suppli3.jpg deleted file mode 100644 index c8ff6082..00000000 Binary files a/docs/docs/.vuepress/public/images/en/user_hyperbian_wpa_suppli3.jpg and /dev/null differ diff --git a/docs/docs/.vuepress/public/images/en/user_ledlayout.jpg b/docs/docs/.vuepress/public/images/en/user_ledlayout.jpg deleted file mode 100644 index 0893e013..00000000 Binary files a/docs/docs/.vuepress/public/images/en/user_ledlayout.jpg and /dev/null differ diff --git a/docs/docs/.vuepress/public/images/en/user_ledlayout1.jpg b/docs/docs/.vuepress/public/images/en/user_ledlayout1.jpg deleted file mode 100644 index 8cb05252..00000000 Binary files a/docs/docs/.vuepress/public/images/en/user_ledlayout1.jpg and /dev/null differ diff --git a/docs/docs/.vuepress/public/images/en/user_ledlayout2.jpg b/docs/docs/.vuepress/public/images/en/user_ledlayout2.jpg deleted file mode 100644 index 290b7733..00000000 Binary files a/docs/docs/.vuepress/public/images/en/user_ledlayout2.jpg and /dev/null differ diff --git a/docs/docs/.vuepress/public/images/en/user_ledlayout3.jpg b/docs/docs/.vuepress/public/images/en/user_ledlayout3.jpg deleted file mode 100644 index 4acbe6b7..00000000 Binary files a/docs/docs/.vuepress/public/images/en/user_ledlayout3.jpg and /dev/null differ diff --git a/docs/docs/.vuepress/public/manifest.json b/docs/docs/.vuepress/public/manifest.json deleted file mode 100644 index 42c1042c..00000000 --- a/docs/docs/.vuepress/public/manifest.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "Hyperion Documentation", - "short_name": "Hyperion Documentation", - "start_url": ".", - "display": "standalone", - "background_color": "#fff", - "theme_color": "#2b81a0", - "description": "All you want to know about Hyperion", - "icons": [ - { - "src": "icons/icon-128x128.png", - "sizes": "128x128", - "type": "image/png" - }, - { - "src": "icons/icon-192x192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "icons/icon-256x256.png", - "sizes": "256x256", - "type": "image/png" - }, - { - "src": "icons/icon-384x384.png", - "sizes": "384x384", - "type": "image/png" - }, - { - "src": "icons/icon-512x512.png", - "sizes": "512x512", - "type": "image/png" - } - ] -} \ No newline at end of file diff --git a/docs/docs/.vuepress/styles/index.styl b/docs/docs/.vuepress/styles/index.styl deleted file mode 100644 index 1f94b88a..00000000 --- a/docs/docs/.vuepress/styles/index.styl +++ /dev/null @@ -1,48 +0,0 @@ -// global css as stylus -.text-center - text-align center - -.sub-text - color rgb(94, 94, 94) - font-size 90% - -.cursor-pointer - cursor: pointer - -.dark - color white - .sub-text - opacity 0.8 - color: white - -.flex - display: flex - flex-wrap: wrap - -.flex-center - justify-content center - -.no-decoration - text-decoration none - -.main-section-disabled - background-color grey !important - color lightgrey !important - cursor not-allowed !important - pointer-events none - -// hide Hyperion TITLE -.site-name - display none !important - -.no-mp - margin 0 !important - padding 0 !important - -// ImageWrap component -.img-margin - margin 10px 5px - p - margin 0 -.img-shadow - box-shadow 1px 1px 5px 0 rgba(0,0,0,0.4) \ No newline at end of file diff --git a/docs/docs/.vuepress/styles/palette.styl b/docs/docs/.vuepress/styles/palette.styl deleted file mode 100644 index 5f5df4b8..00000000 --- a/docs/docs/.vuepress/styles/palette.styl +++ /dev/null @@ -1,9 +0,0 @@ -// default styles: DO NOT ADD custom global css here, use index.styl instead -// original $accentColor = #3eaf7c -$accentColor = #2b819a - -// default values 10.2019 -// $accentColor = #3eaf7c -// $textColor = #2c3e50 -// $borderColor = #eaecef -// $codeBgColor = #282c34 \ No newline at end of file diff --git a/docs/docs/README.md b/docs/docs/README.md deleted file mode 100644 index c49b7287..00000000 --- a/docs/docs/README.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -sidebar: false ---- - -Hyperion Logo - -Welcome in the colorful world of Hyperion. Please choose the documentation you want to view. - -
- - - -
- -::: tip -You can select another translation at the top. -::: \ No newline at end of file diff --git a/docs/docs/de/README.md b/docs/docs/de/README.md deleted file mode 100644 index 287f8b57..00000000 --- a/docs/docs/de/README.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -sidebar: false ---- - -Hyperion Logo - -Willkommen in der bunten Welt von Hyperion. Bitte wähle aus, welche Dokumentation du einsehen möchtest. - -
- - - -
- -::: warning Unvollständig -Leider ist die Dokumentation in der ausgewählten Sprache nicht vollständig verfügbar. Wenn du mithelfen möchtest dies zu ändern, geht es [hier weiter](https://github.com/hyperion-project/hyperion.ng/blob/master/docs/README.md). -::: \ No newline at end of file diff --git a/docs/docs/en/addons/API.md b/docs/docs/en/addons/API.md deleted file mode 100644 index 9a9a979b..00000000 --- a/docs/docs/en/addons/API.md +++ /dev/null @@ -1,210 +0,0 @@ - -# Addon API -Overview of the API. Get access to these functions by importing the `hapi` module `import hapi`. -| Function | Returns | Comment | -| ------------------------- | ------- | --------------------------------------------------------------------------------------------------- | -| hapi.abort() | bool | Check if we should abort the script, True on abort request else false | -| hapi.log() | - | Print a log message to the Hyperion log. See [hapi.log()](#hapi-log) | -| hapi.registerCallback() | - | Register a function with a callback function. See [hapi.registerCallback()](#hapi-registercallback) | -| hapi.unregisterCallback() | - | Unregister a function from callback. See [hapi.unregisterCallback()](#hapi-unregistercallback) | -| hapi.getComponentState() | int | Get current state of a component. See [hapi.getComponentState()](#hapi-getcomponentstate ) | -| hapi.setComponentState() | bool | Enable or disable a component. See [hapi.setComponentState()](#hapi-setcomponentstate) | -| hapi.getSettings() | data | Get the current user settings for your addon. See [hapi.getSettings()](#hapi-getsettings) | -| hapi.setColor() | - | Set a color. See [hapi.setColor()](#hapi-setcolor) | -| hapi.setEffect() | int | Start effect by name. See [hapi.setEffect()](#hapi-seteffect ) | -| hapi.getPriorityInfo() | dict | Get info about a priority. See [hapi.getPriorityInfo()](#hapi-getpriorityinfo) | -| hapi.getAllPriorities() | list | Get all registered priorities. See [hapi.getAllPriorities()](#hapi-getallpriorities) | -| hapi.getVisiblePriority() | int | Get current visible priority. See [hapi.getVisiblePriority()](#hapi-getvisiblepriority) | -| hapi.setVisiblePriority() | bool | Select a specific priority. See [hapi.setVisiblePriority()](#hapi-setvisiblepriority) | -| hapi.getAdjustmentList() | list | Get a list of all adjustment ids. See [hapi.getAdjustmentList()](#hapi-getadjustmentlist) | -| hapi.getBrightness() | int | Get current brightness. See [hapi.getBrightness()](#hapi-getbrightness) | -| hapi.setBrightness() | bool | Set new brightness. See [hapi.setBrightness()](#hapi-setbrightness) | - -## Data transformation cheatsheet -As we need to transform "UI elements"-data from `json` to `python`, here a cheatsheet how the transformation is done. - -| Json | Python | -| :-----: | :----: | -| boolean | int | -| integer | int | -| number | float | -| string | str | -| array | list | -| object | dict | - -## Methods - -### hapi.log() -Write a message to the Hyperion log. Your addon name will be automatically prepended to all messages! -`hapi.log(msg, lvl)` -| Argument | Type | Comment | -| msg | str | The message you want to print as string | -| lvl | enum | Optional: Print message with a specific log lvl. `LOG_INFO` = Info, `LOG_WARNING` = Warning, `LOG_ERROR` = Error, `LOG_DEBUG` = Debug. **Defaults to Debug** | - -### hapi.registerCallback() -To listen for specific Hyperion events you can register callbacks. -`hapi.registerCallback(callbackType, connectFunction)` -| Argument | Type | Comment | -| ----------------------------------------- | ---- | --------------------------------------------------------------------------------------------------- | -| callbackType | Enum | Callbacks: `ON_COMP_STATE_CHANGED`, `ON_SETTINGS_CHANGED`, `ON_VISIBLE_PRIORITY_CHANGED` | -| connectFunction | - | A previously defined function which will be used to deliver the callback | -| callbackType: ON_COMP_STATE_CHANGED | - | When comp state changes, arg1 `comp` component as str, arg2 `newState` as int | -| callbackType: ON_SETTINGS_CHANGED | - | When user saved new settings, reload settings [hapi.getSettings()](#hapi.getsettings) | -| callbackType: ON_VISIBLE_PRIORITY_CHANGED | - | Is called whenever the visible priority changes, argument `priority` of type int (the new priority) | -``` python -# Example implementation with log output -import hapi - -def onCompStateChanged(comp, newState): - hapi.log("The component "+comp+" changed state to:"+str(newState)) - -def onSettingsChanged(): - hapi.log("New settings! Do something!") - -def onVsibilePriorityChanged(newPriority): - hapi.log("The new visible priority is: "+str(newPriority)) - -hapi.registerCallback(ON_COMP_STATE_CHANGED, onCompStateChanged) -hapi.registerCallback(ON_SETTINGS_CHANGED, onSettingsChanged) -hapi.registerCallback(ON_VISIBLE_PRIORITY_CHANGED, onVsibilePriorityChanged) -``` - -### hapi.unregisterCallback() -You can also unregister a callbackType again. You can register and unregister as often you need it. Usually you won't need it, but for completion here it is! After unregister the connected function does no longer react upon callbacks -`hapi.unregisterCallback(callbackType)` -| Argument | Type | Comment | -| ------------ | ---- | ------------------------------------------------------------------------------------ | -| callbackType | Enum | One of `ON_COMP_STATE_CHANGED`, `ON_SETTINGS_CHANGED`, `ON_VISIBLE_PRIORITY_CHANGED` | - -### hapi.getComponentState() -Get the current state of a component. -`hapi.getComponentState(comp)` -| Argument | Type | Comment | -| -------- | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| comp | int | The component ID one of `COMP_ALL COMP_SMOOTHING COMP_BLACKBORDER COMP_LEDDEVICE COMP_GRABBER COMP_V4L`, prefixed with `COMP_`. See explanation here [Component IDs explained](/en/json/control#components-ids-explained) | -| @return | int | `True` if enabled, `False` if disabled, `-1` if not found | - - -### hapi.setComponentState() -Set a Hyperion component to a new state. This method writes a debug message on each call! -`hapi.setComponentState(comp, enable)` -| Argument | Type | Comment | -| -------- | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| comp | int | The component ID one of `COMP_ALL COMP_SMOOTHING COMP_BLACKBORDER COMP_LEDDEVICE COMP_GRABBER COMP_V4L`, prefixed with `COMP_`. See explanation here [Component IDs explained](/en/json/control#components-ids-explained) | -| enable | int | True to enable it, False to disable it | -| @return | bool | True if the requested component was found else false | - -### hapi.getSettings() -Get the current user settings data for your addon. The returned data contains all settings that has been transformed from JSON to python data types. See the table below how they are transformed. -`hapi.getSettings()` -| Json | Python | -| :-----: | :----: | -| boolean | int | -| integer | int | -| number | float | -| string | str | -| array | tuple | -| object | dict | - -**Basics** \ -The root data type is usually of type object which will be transformed to a python dict, so we use the dict syntax to get the value. The fallback parameter should be defined wisely, if the value is not found it will be used instead. -``` python -import hapi -# Get a bool value of a dict -myBoolValue = MySettings.get('MyBoolOption', True) - -# Get a int value of a dict -myIntValue = MySettings.get('MyIntOption', 20) - -# Get a float value of a dict -myFloatValue = MySettings.get('MyFloatOption', 15.7) - -# Get a string value of a dict -myStringValue = MySettings.get('MyStringOption', 'MyFallbackString') - -# Get a tuple of a dict -# Two RGB colors would look like the following. A tuple that contains 2 other tuples where each contains 3 int values -myListValue = MySettings.get('MyListOption', ()) - -# Here a colorpicker example -myColorValue = MySettings.get('MyColorPicker', (255,0,0)) -# Here an array(tuple) of multiple colorpickers -myColorValues = MySettings.get('MyColorPickers', ((255,0,0),(0,255,0)) ) -``` - -### hapi.setColor() -Set a RGB color value with timeout at the given priority. -`hapi.setColor(red, green, blue, timeout, priority)` -| Argument | Type | Comment | -| -------- | ---- | ---------------------------------------------------------------------- | -| red | int | Red 0-255 | -| green | int | Green 0-255 | -| blue | int | Blue 0-255 | -| timeout | int | Optional: Set a specific timeout in ms. Defaults to -1 (endless) | -| priority | int | Optional: Set the color at a specific priority channel. Defaults to 50 | - -### hapi.setEffect() -Start an effect by name with timeout at the given priority. -`hapi.setEffect(effectName, timeout, priority)` -| Argument | Type | Comment | -| ---------- | ---- | ---------------------------------------------------------------------- | -| effectName | str | The name of the effect | -| timeout | int | Optional: Set a specific timeout in ms. Defaults to -1 (endless) | -| priority | int | Optional: Set the color at a specific priority channel. Defaults to 50 | -| @return | int | `0` on success, `-1` on failure (eg not found) | - -### hapi.getPriorityInfo() -Get priority info for the given priority. -`hapi.getPriorityInfo(priority)` -| Argument | Type | Comment | -| -------- | ---- | ------------------------------------------------------------------------------------------------------------ | -| priority | int | The priority you want information for | -| @return | dict | A dict with fields `priority` as int, `timeout` as int, `component` as str, `origin` as str, `owner` as str. | - -### hapi.getAllPriorities() -Get all registered priorities. -`hapi.getAllPriorities()` -| Argument | Type | Comment | -| :------: | :---: | :-------------------------------------------------------------------------: | -| @return | tuple | A tuple of all priorities that has been registered (type int) `(1,240,255)` | - - -### hapi.getVisiblePriority() -Get the current visible priority. -`hapi.getVisiblePriority()` -| Argument | Type | Comment | -| -------- | ---- | ------------ | -| @return | int | The priority | - -### hapi.setVisiblePriority() -Set a specific priority to visible. Returns `True` on success or `False` if not found. -`hapi.setVisiblePriority(priority)` -| Argument | Type | Comment | -| -------- | ---- | ---------------------------------------------------- | -| priority | int | The priority to set | -| @return | bool | `True` on success, `False` on failure (eg not found) | - - -### hapi.getAdjustmentList() -Returns a list of all available adjustment ids. These ids are used to apply changes to different calibration profiles. -`hapi.getAdjustmentList()` -| Argument | Type | Comment | -| -------- | ---- | ---------------------- | -| @return | list | List of adjustment ids | - -### hapi.getBrightness() -Get the brightness of a given adjustment id. If no id is provided it will return the brightness of primary adjustment (e.g. first). See also [hapi.getAdjustmentList()](#hapi-getadjustmentlist). -`hapi.getBrightness(id)` -| Argument | Type | Comment | -| -------- | ---- | ----------------------------------------------------------------------------------------------------------------------- | -| id | str | Optional: Get the brightness of a specific adjustment id, if not given it will return the primary adjustment brightness | -| @return | int | The brightness between `0` and `100` (considered as %). Returns `-1` if the adjustment id is not found | - -### hapi.setBrightness() -Set the brightness for the given adjustment id. If no id is provided it will set all available adjustment ids to the given brightness. See also getAdjustmentList() -`hapi.setBrightness(brightness, id)` -| Argument | Type | Comment | -| :--------: | :---: | :-----------------------------------------------------------------------------------------------------: | -| brightness | int | The brightness value between `0` and `100` | -| id | str | Optional: Target a specific adjustment id, if not set it will apply the brightness to all available ids | -| @return | bool | `True` on success, `False` on failure (eg given adjustment id not found) | diff --git a/docs/docs/en/addons/OurFirstAddon.md b/docs/docs/en/addons/OurFirstAddon.md deleted file mode 100644 index 646d149b..00000000 --- a/docs/docs/en/addons/OurFirstAddon.md +++ /dev/null @@ -1,87 +0,0 @@ -# Our first addon -You want to write an addon? You have no clue about everything? Perfect, the next steps will explain you everything you need to know. Also Python beginners are invited. Let's start with the addon types. - -[[toc]] - -## Addon types -Currently there are 2 types of Addons. - * Service - * Module - -A service addon runs usually the whole time (if enabled), it starts and stops with the execution of Hyperion. Additional it has settings that can be configured from the user to fit their needs. This can be an IP address to another service, a time to trigger, or anything else that you will discover from the Addon API - -A module provides utility methods which can be imported from a service addon to be used. Examples are Python packages from the PyPi repository like httplib2, which makes the developer life easier when working with HTTP requests. Instead implementing everything on your own you can rely on the work of others with well tested modules from the Python community. You can also create modules on your own if you think the code can be reused in other service addons. - -## Development setup -All you need is: - * An installed and running Hyperion. You need access to the filesystem where Hyperion has been installed - * An editor to write code (recommended [Visual Studio Code](https://code.visualstudio.com/)) for Windows/Linux/Mac) - -### Folder layout -The follow files are part of an addon. -| File | language | Comment | -| ------------------- | -------------------------------------- | --------------------------------------------------------------------------- | -| service.py | [Python](https://www.python.org/) | Required for `service` addons. Entry point, this is where your code goes to | -| addon.json | [JSON](http://www.json.org/) | The meta data file required for all addons | -| settingsSchema.json | [JSON Schema](http://json-schema.org/) | Required for `service` addons. Options UI. [Read more](/en/api/ui.md) | -| lib | Folder | Required for `module` addons. Entry point for modules | - -### Create a new service Addon -To create a service addon you need to follow a simple structure. - - Navigate to ~/.hyperion/addons (folder in your home directory) - - Think about a short "id", this id needs to be unique and should just contain letters (English), lowercase no whitespace Example: `kodicon` `plexcon` `timer` `cec` - - Create a folder with your id and prepend `service.`. Example: `service.kodicon` `service.timer` `service.cec` - - Inside this folder create a file called `service.py`, this is where your addon code goes to - - Create a file called `settingsSchema.json`, this will represent our options - - Create a new file called `addon.json` and add [metadata](#metadata|) - - That's it! - -::: tip -A prepared service playground addon can be downloaded from the repository. This shows the basic usage of the API but also how option UI works -::: - -### Metadata -The metadata file called addon.json is a description of your addon to declare name, version, dependencies, support URL, sourcecode URL and more. This file is parsed by Hyperion to provide users required informations and download updates accordingly. - -| Property | Type | Comment | -| ------------ | ------ | ---------------------------------------------------------------------- | -| name | String | User friendly name of your addon | -| description | String | What does this addon as a brief overview | -| id | String | The unique id | -| version | String | The current version of your addon. [Semver 2.0.0](https://semver.org/) | -| category | Array | Add the addon to a category. Available `utility` | -| dependencies | Object | You can depend on modules / a specific minimum Hyperion version. | -| changelog | Array | Array of Objects with notes | -| provider | String | Author of this addon | -| support | String | A URL for support. | -| source | String | A URL where the source code is hosted | -| licence | String | Licence type, can be MIT, GPL, LGPL | - -Here a version for copy and paste -``` json -{ - "name":"My addon Name", - "description" : "What does my addon as a brief overview", - "id":"service.myid", - "version" : "0.1.0", - "category" : "utility", - "dependencies" :{"hyperion" : "2.0.0"}, - "changelog" : [{"0.1.0 Crunchy Cudator":"-New featrues -bugfixs -other stuff"}], - "provider":"hyperion-project", - "support":"URL to hyperion-project.org Forum thread", - "source" :"URL to source code", - "licence" : "MIT" -} -``` - -### Addon categories -Addons can be assigned to a category for better sorting. Select the best matching - * **utility** A utility is usually a smaller addon, which does very basic tasks. It doesn't connect to another software. For example the Wake On LAN addon is a utility. - * **integration** A integration addon interfaces with another software to listen for specific API events which triggers now actions on the Hyperion side or vice versa. Example is the Kodi addon - * You can suggest new categories! - -### Development -Enough preparation stuff, let's start! \ -It's highly recommended to work/read once through a Python tutorial which explains you the principals of Python if you are new to Python. - * New to Python? No problem, here is a interactive tutorial where you can read, write and execute your first python scripts inside your browser [learnpython](https://www.learnpython.org/), available in 7 languages! - * Good beginner guide: [Python course EN](https://www.python-course.eu/python3_interactive.php). [Python Kurs DE](https://www.python-kurs.eu/python3_interaktiv.php). It's not necessary (nor possible) to understand everything, but the first pages are very helpful as a start! diff --git a/docs/docs/en/addons/README.md b/docs/docs/en/addons/README.md deleted file mode 100644 index f328fdbe..00000000 --- a/docs/docs/en/addons/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# Addons -Hyperion has an addon engine that allows you to extend the functionality of Hyperion. It is written in Python and has a specific task like connecting to a third party software and listen for events to apply actions based on addon settings at the Hyperion API. - -[[toc]] - -## API -An API documentation is available here: [Addon API](/en/addons/api.md) - -## Our first Addon -A guide for people that want to learn and write something: [Our first Addon](/en/addons/OurFirstAddon.md) \ No newline at end of file diff --git a/docs/docs/en/api/Detect.md b/docs/docs/en/api/Detect.md deleted file mode 100644 index 4b20fd89..00000000 --- a/docs/docs/en/api/Detect.md +++ /dev/null @@ -1,57 +0,0 @@ -# Detect Hyperion -Hyperion announces it's services on the network, via ZeroConf and SSDP. - -[[toc]] - -## SSDP -**S**imple**S**ervice**D**iscovery**P**rotocol -([SSDP](https://en.wikipedia.org/wiki/Simple_Service_Discovery_Protocol)) is the -discovery subset of UPnP. The implementation is lighter than ZeroConf as it just needs a -UDP Socket without any further dependencies. - - -### SSDP-Client Library -Here are some example client libraries for different programming languages (many others available): - * [NodeJS](https://github.com/diversario/node-ssdp#usage---client) - * [Java](https://github.com/resourcepool/ssdp-client#jarpic-client) - -### Usage -With a given SSDP-client library, you can use the following USN / service type: - -`urn:hyperion-project.org:device:basic:1` - -Some headers from the response will include: - * **Location**: The URL of the webserver - * **USN**: The unique id for this Hyperion instance, it will remain the same after system restarts or Hyperion updates - * **HYPERION-FBS-PORT**: The port of the flatbuffers server - * **HYPERION-JSS-PORT**: The port of the JsonServer - * **HYPERION-NAME**: The user defined name for this server - -As the data changes (e.g. network adapter IP address change), new updates will be automatically announced. - -## Zeroconf -Also known as [Apple Bonjour](https://en.wikipedia.org/wiki/Bonjour_(software)) or [Avahi](https://en.wikipedia.org/wiki/Avahi_(software)). Hyperion is detectable through zeroconf. - -**Hyperion publishes the following informations:** - * **_hyperiond-http._tcp**: Hyperion Webserver (HTTP+Websocket) - * **_hyperiond-json._tcp**: Hyperion JSON Server (TcpSocket) - * **_hyperiond-flatbuf._tcp**: Hyperion Flatbuffers server (Google Flatbuffers) - -You get the IP address, hostname, port and the Hyperion instance name (before the @ for -the full name). As this works realtime you can always have an up to date list of available -Hyperion servers. - -### TXT RECORD -Each published entry contains at least the following data in the txt field: - * **id**: A static unique id to identify an Hyperion instance. - * **version**: Hyperion version. - - -### Test Clients -There are several clients available for testing like the -[avahi-browse](http://manpages.ubuntu.com/manpages/bionic/man1/avahi-browse.1.html) a -commandline tool for Ubuntu/Debian. Example command -``` bash -sudo apt-get install avahi-browse && avahi-browse -r _hyperiond-http._tcp -``` - \ No newline at end of file diff --git a/docs/docs/en/api/Guidelines.md b/docs/docs/en/api/Guidelines.md deleted file mode 100644 index f37aa4a7..00000000 --- a/docs/docs/en/api/Guidelines.md +++ /dev/null @@ -1,23 +0,0 @@ -# Guidelines -Improve the user experience with Hyperion by following these guidelines. - -[[toc]] - -## Priority Guidelines -Please adhere to the following priority guidelines to avoid user confusion and ensure -the best user experience possible: - -The user expects that an effect or color should be higher in priority (lower in value) -than capturing, as colors/effects are usually run intermittently. - -| Type | Priority/Range | Recommended | Comment | -| :---------------------: | :------------: | :---------: | :----------------------------------------: | -| Boot Effect/Color | 0 | - | Blocked | -| Web Configuration | 1 | - | | -| **Remote Control** | **2-99** | **50** | Set effect/color/single image | -| **Image Streaming** | **100-199** | **150** | For image streams (Flatbuffer/Protobuffer) | -| Boblight | 201 | - | | -| USB Capture | 240 | - | | -| Platform Capture | 250 | - | | -| Background Effect/Color | 254 | - | | -| Reserved | 255 | - | | \ No newline at end of file diff --git a/docs/docs/en/api/Ui.md b/docs/docs/en/api/Ui.md deleted file mode 100644 index bb345c39..00000000 --- a/docs/docs/en/api/Ui.md +++ /dev/null @@ -1,250 +0,0 @@ -# Graphical User Interface -We use a JSON schema to create a user-friendly GUI and validate the input to prevent wrong or unwanted data that will be consumed by your python file. Each python file requires a GUI schema. - -::: tip -If you have never written JSON syntax, we recommend a short introduction. [Here](https://www.digitalocean.com/community/tutorials/an-introduction-to-json) and/or [Here (technical)](http://www.json.org/) -::: - -[[toc]] - -## UI elements -Each UI element has a specific schema. The schema allows you to give the element a label and validate user input by providing for example a minimum and a maximum number for an element of type number. A minimum count of colors, a default value (required!) or even to show/hide an element based on the value of another element. - -### Checkbox -Show a checkbox. -``` json - "swirl_enabled" :{ - "type" : "boolean", - "title" : "edt_eff_swirl_enabled", - "default" : false - } -``` -The option `swirl_enabled` will be of type boolean with title `edt_eff_swirl_enabled` ([Titles will be translated](#translation)). The `default` sets the option to the defined default value, required!. - -### String -An input field which accepts all kind of characters -``` json - "swirl_name" :{ - "type" : "string", - "title" : "edt_eff_swirl_name", - "default" : "A cool placeholder name" - } -``` -The option `swirl_name` will be of type string with title `edt_eff_swirl_name` ([Titles will be translated](#translation)). The `default` sets the option to the defined default value, required!. \ -**Optional** - * Add `"minLength" : 5` to force a minimum length of 5. Be aware that the default value matches - * Add `"maxLength" : 9` to force a maximum length of 9. Be aware that the default value matches - * Add `"enum" : ["Amazing1","Amazing","Amazing3"]` Renders the input as a select box where the user can choose one of the defined options. - -### Integer -An input field for integer -``` json - "swirl_count" :{ - "type" : "integer", - "title" : "edt_eff_swirl_count", - "default" : 5 - } -``` -The option `swirl_count` will be of type integer with title `edt_eff_swirl_count` ([Titles will be translated](#translation)). The `default` sets the option to the defined default value, required!. \ -**Optional** - * Add `"minimum" : 5` to force a minimum value in case it shouldn't be lower - * Add `"maximum" : 9` to force a maximum value in case it shouldn't be higher - * Add `"step" : 2,` to define a alternate stepping of value. If not given, defaults to `1`. This doesn't prevent values which are "outside" of the step, it's more a helper if you use up/down keys and higher or smaller steps are wanted. - - -### Number -A input field for numbers (float) -``` json - "swirl_spread" : - { - "type" : "number", - "title" : "edt_eff_swirl_spread", - "default" : 7.0 - } -``` -The option `swirl_spread` will be of type number (float) with title `edt_eff_swirl_spread` ([Titles will be translated](#translation)). The `default` sets the option to the defined default value, required!. \ -**Optional** - * Add `"minimum" : 5.0` to force a minimum value in case it shouldn't be lower - * Add `"maximum" : 9.6` to force a maximum value in case it shouldn't be higher - * Add `"step" : 0.1,` to define a alternate stepping of value. If not given, defaults to `1.0`. This doesn't prevent values which are "outside" of the step, it's more a helper if you use up/down keys and higher or smaller steps are wanted. - -### Select -Create a select element, where you can select one of the `enum` items. Default is required! -``` json - "candles": { - "type": "string", - "title":"edt_eff_whichleds", - "enum" : ["all","all-together","list"], - "default" : "all" - } -``` - -### Array -Creates an array input with the given properties at `items`. You can nest inside all kind of options -``` json - "countries": { - "type": "array", - "uniqueItems": true, - "title" : "edt_eff_countries", - "items": { - "type": "string", - "title": "edt_eff_country" - }, - "default":["de","at"] - } -``` -The option `countries` will be of type array (in python it's a python tuple) (shown as array where you can add or remove properties, in this case a string input field with the title `edt_eff_country"`) with the title `edt_eff_swirl_countries` ([Titles will be translated](#translation)). The `default` sets the option to the defined default value. Required! \ -**Optional** - * Add `"uniqueItems": true` if you want to make sure that each item is unique - * Add `"minItems": 2` to force a minimum items count of the array - * Add `"maxItems": 6` to force a maximum items count of the array - -### Array - Multiselect -Create a selection where multiple elements from `ènum` can be selected. Default value is not required. -``` json - "countries": { - "type": "array", - "title" : "edt_eff_countries", - "uniqueItems": true, - "items": { - "type": "string", - "enum": ["de","at","fr","be","it","es","bg","ee","dk","fi","hu","ie","lv","lt","lu","mt","nl","pl","pt","ro","sl","se","ch"] - }, - "default":["de","at"], - "propertyOrder" : 1 - }, -``` - -### Array - Colorpicker RGB -Creates a RGB colorpicker. -``` json - "color" : { - "type": "array", - "title" : "edt_eff_color", - "format":"colorpicker", - "default" : [255,0,0], - "items":{ - "type":"integer", - "minimum": 0, - "maximum": 255 - }, - "minItems": 3, - "maxItems": 3 - } -``` -The option `color` will be of type array (shown as RGB colorpicker) with the title `edt_eff_color` ([Titles will be translated](#translation)). This colorpicker will be set to initial red. - -### Array - Colorpicker RGBA -Creates a RGBA colorpicker. Think twice brefore you provide a RGBA picker, the use case is limited. -``` json - "color" : { - "type": "array", - "title" : "edt_eff_color", - "format":"colorpickerRGBA", - "default" : [255,0,0,0.5], - "minItems": 4, - "maxItems": 4 - } -``` -The option `color` will be of type array (shown as RGBA colorpicker) with the title `edt_eff_color` ([Titles will be translated](#translation)). This colorpicker will be set to red with 50% alpha initial. Required to add a default color. - -## More beautification -To organize your UI better and make it prettier we provide a set of additional keywords. - -### Dependencies -Hide/Show a specific option based on the value of another option -``` json{12} - "enable-second": { - "type": "boolean", - "title":"edt_eff_enableSecondSwirl", - "default": false, - "propertyOrder" : 1 - }, - "random-center2": { - "type": "boolean", - "title":"edt_eff_randomCenter", - "default": false, - "options": { - "dependencies": { - "enable-second": true - } - } - } -``` -The option `random-center2` is NOT shown until the option `enable-second` is set to true. This also works with numbers, integers and strings. - -### Order -As each option is a Object and the sort order for Objects is random you need to set an order on your own. Add a `propertyOrder` key. -``` json{5,11} - "enable-second": { - "type": "boolean", - "title":"edt_eff_enableSecondSwirl", - "default": false, - "propertyOrder" : 1 - }, - "random-center2": { - "type": "boolean", - "title":"edt_eff_randomCenter", - "default": false, - "propertyOrder" : 2 - } -``` -The option `enable-second` will be first, `random-center2` second. - -### Field appends -You want a specific unit at the end of a field like "s", "ms" or "percent"? Just add a `append` with the wanted unit. -``` json{5} - "interval": { - "type": "integer", - "title":"edt_eff_interval", - "default": 5, - "append" : "edt_append_s", - "propertyOrder" : 1 - } -``` -This will add a "s" for seconds to the input field. Please note it will be also translated, so check the translation file if your unit is already available. Add a new one if required. - -### Smoothing control (only for effects) -Since v2 effects are no longer smoothed, it is possible to enable and manipulate smoothing if required. Add the following to the schema. -``` json -"smoothing-custom-settings":{ - "type":"boolean", - "title":"edt_eff_smooth_custom", - "default":false, - "propertyOrder":1 -}, -"smoothing-time_ms":{ - "type":"integer", - "title":"edt_eff_smooth_time_ms", - "minimum":25, - "maximum":600, - "default":200, - "append":"edt_append_ms", - "options":{ - "dependencies":{ - "smoothing-custom-settings":true - } - }, - "propertyOrder":2 -}, -"smoothing-updateFrequency":{ - "type":"number", - "title":"edt_eff_smooth_updateFrequency", - "minimum":1.0, - "maximum":100.0, - "default":25.0, - "append":"edt_append_hz", - "options":{ - "dependencies":{ - "smoothing-custom-settings":true - } - }, - "propertyOrder":3 -} -``` - -### Translation -**only for effects - plugins will follow** \ -To translate the effect options to a language we use placeholders that are translated during runtime into the target language. -It will usually look like this -`edt_eff_smooth` Available phrases begins with `edt_eff_` they are shared across all effects to prevent duplicates. Please search the [translation file](https://github.com/hyperion-project/hyperion.ng/blob/master/assets/webconfig/i18n/en.json) for a matching translation. If you don't find a matching phrase please add it. diff --git a/docs/docs/en/effects/API.md b/docs/docs/en/effects/API.md deleted file mode 100644 index 30e71a44..00000000 --- a/docs/docs/en/effects/API.md +++ /dev/null @@ -1,276 +0,0 @@ -# Effect Engine API -All available functions for usage. - -## API Overview -| Function | Returns | Comment | -| ------------------------------- | ----- | -------- | -| hyperion.ledCount | Integer | Get the current led count from the led layout | -| hyperion.latchTime | Integer | Get the current active latchtime in ms. | -| hyperion.imageWidth() | Integer | Get the current image width, calculate positions for elements at the [coordinate system](http://doc.qt.io/qt-5/coordsys.html#rendering) | -| hyperion.imageHeight() | Integer | Get the current image height,calculate positions for elements at the [coordinate system](http://doc.qt.io/qt-5/coordsys.html#rendering) | -| hyperion.imageCRotate() | - | Rotates the coordinate system at the center (0,0) by the given angle. See [hyperion.imageCRotate()](#hyperion-imagecrotate) | -| hyperion.imageCOffset() | - | Add a offset to the coordinate system. See [hyperion.imageCOffset()](#hyperion-imagecoffset) | -| hyperion.imageCShear() | - | Shear the coordinate system. See [hyperion.imageCShear()](#hyperion-imagecshear) | -| hyperion.imageResetT() | - | Resets all coordination system modifications done with hyperion.imageCRotate(), hyperion.imageCOffset(), hyperion.imageCShear() | -| hyperion.imageMinSize() | - | See [hyperion.imageMinSize()](#hyperion-imageminsize)| -| hyperion.abort() | Boolean | If true, hyperion requests an effect abort, used in a while loop to repeat effect calculations and writing | -| hyperion.imageConicalGradient() | - | See [hyperion.imageConicalGradient()](#hyperion-imageconicalgradient) | -| hyperion.imageRadialGradient() | - | See [hyperion.imageRadialGradient()](#hyperion-imageradialgradient)| -| hyperion.imageLinearGradient() | - | See [hyperion.imageLinearGradient()](#hyperion-imagelineargradient)| -| hyperion.imageDrawLine() | - | See [hyperion.imageDrawLine()](#hyperion-imagedrawline) | -| hyperion.imageDrawPoint() | - | See [hyperion.imageDrawPoint()](#hyperion-imagedrawpoint) | -| hyperion.imageDrawPolygon() | - | See [hyperion.imageDrawPolygon()](#hyperion-imagedrawpolygon) | -| hyperion.imageDrawPie() | - | See [hyperion.imageDrawPie()](#hyperion-imagedrawpie) | -| hyperion.imageDrawRect() | - | See [hyperion.imageDrawRect()](#hyperion-imagedrawrect) | -| hyperion.imageSolidFill() | - | See [hyperion.imageSolidFill()](#hyperion-imagesolidfill) | -| hyperion.imageShow() | - | Hyperion shows the image you created with other `hyperion.image*` functions before. This is always the last step after you created the image with other hyperion.image* function | -| hyperion.imageSetPixel() | - | See [hyperion.imageSetPixel()](#hyperion-imagesetpixel) | -| hyperion.imageGetPixel() | Tuple | A [Python tuple](https://www.tutorialspoint.com/python/python_tuples.htm) RGB values for the requested position. See [hyperion.imageGetPixel()](#hyperion-imagegetpixel) | -| hyperion.imageSave() | Integer | Create a snapshot of the current effect image and returns an ID. To display the snapshot do `hyperion.imageShow(ID)`. Snapshots are the _current_ state of the picture | -| hyperion.setColor() | - | Not recommended, read why! See [hyperion.setColor()](#hyperion-setcolor) | -| hyperion.setImage() | - | hyperion.setImage(width, height, RGB_bytearray) | - - -### hyperion.imageMinSize() -As the `hyperion.imageWidth()` and `hyperion.imageHeight()` scales with the led layout, you could define a minimum size to get more pixels to work with. Keep in mind that the ratio between width/height depends always on user led setup, you can't force it. -::: warning -Should be called before you start painting! -::: -`hyperion.imageMinSize(pixelX,pixelY)` -| Argument | Type | Comment | -| ---------- | -------- | ---------------------------------------------------------------------------------- | -| pixelX | Integer | Minimum Pixels at the x-axis of the image to draw on with `hyperion.image*` functions | -| pixelY | Integer | Minimum Pixels at the y-axis of the image to draw on with `hyperion.image*` functions | - -### hyperion.imageCRotate() -Rotates the coordinate system at the center which is 0 at the x-axis and 0 at the y-axis by the given angle clockwise. Note: If you want to move the center of the coordinate system you could use hyperion.imageCOffset(). **The rotation is kept until the effect ends**. \ -`hyperion.imageCRotate(angle)` -| Argument | Type | Comment | -| ---------- | -------- | ----------------------------------------------------- | -| angle | Integer | Angle of the rotation between `0` and `360`, clockwise | - -### hyperion.imageCOffset() -Add offset to the coordinate system at the x-axis and y-axis. -::: warning -Changes at the coordinate system results in weird behavior of some shorter versions of other hyperion.image* drawing functions -::: -`hyperion.imageCOffset(offsetX, offsetY)` -| Argument | Type | Comment | -| -------- | ---------- | ----------------------------------------------------- | -| offsetX | Integer | Offset which is added to the coordinate system at the x-axis. Positive value moves to the right, negative to the left | -| offsetY | Integer | Offset which is added to the coordinate system at the y-axis. Positive value moves to the right, negative to the left | - -### hyperion.imageCShear() -Shears the coordinate system at the vertical and horizontal. More info to shearing here: [Shear Mapping](https://en.wikipedia.org/wiki/Shear_mapping) -::: warning -Changes at the coordinate system results in weird behavior of some shorter versions of other hyperion.image* drawing functions -::: -`hyperion.imageCShear(sh, sv)` -| Argument | Type | Comment | -| -------- | ---------- | -------------------------- | -| sh | Integer | Horizontal pixels to shear | -| sv | Integer | Vertical pixels to shear. | - -### hyperion.imageConicalGradient() -Draws a conical gradient on the image, all arguments are required. Add the arguments in the order of rows below. Short explanation for conical gradient at the QT docs: [Conical Gradient](http://doc.qt.io/qt-5/qconicalgradient.html#details) \ -`hyperion.imageConicalGradient(startX, startY, width, height, centerX, centerY, angle, bytearray)` -| Argument | Type | Comment | -| -------- | ---------- | ----------------------------------------------------- | -| startX | Integer | Defines the start point at the x-axis of the rectangle that contains the gradient | -| startY | Integer | Defines the start point at the y-axis of the rectangle that contains the gradient | -| width | Integer | Defines the width of the rectangle | -| height | Integer | Defines the height of the rectangle | -| centerX | Integer | Defines the center of the gradient at the x-axis. For the center of the picture use `hyperion.imageWidth()*0.5`, don't forget to surround it with int() or round() | -| centerY | Integer | Defines the center of the gradient at the y-axis. For the center of the picture use `hyperion.imageHeight()*0.5`, don't forget to surround it with int() or round() | -| angle | Integer | Defines the angle from `0` to `360`. Used to rotate the gradient at the center point. | -| bytearray | ByteArray | bytearray of (position,red,green,blue,alpha,position,red,green,blue,alpha,...). Could be repeated as often you need it, all values have ranges from 0 to 255. The position is a point where the red green blue values are assigned.
**Example:** `bytearray([0,255,0,0,255,255,0,255,0,255])` - this is a gradient which starts at 0 with color 255,0,0 and alpha 255 and ends at position 255 with color 0,255,0 and alpha 255. The colors in between are interpolation, so this example is a color shift from red to green from 0° to 360°. | - -::: tip Shorter versions of hyperion.imageConicalGradient() -`hyperion.imageConicalGradient(centerX, centerY, angle, bytearray)` -> startX and startY are 0 and the width/height is max. -> Entire image -::: - -### hyperion.imageRadialGradient() -Draws a radial gradient on the image. Add the arguments in the order of rows below. All arguments are required. -Short description at QT Docs: [Radial Gradient](http://doc.qt.io/qt-5/qradialgradient.html#details) \ -`hyperion.imageRadialGradient(startX, startY, width, height, centerX, centerY, radius, focalX, focalY, focalRadius, bytearray, spread)` -| Argument | Type | Comment | -| --------- | ---------- | ----------------------------------------------------- | -| startX | Integer | start point at the x-axis of the rectangle which contains the gradient. | -| startY | Integer | start point at the y-axis of the rectangle which contains the gradient. | -| width | Integer | width of the rectangle. | -| height | Integer | height of the rectangle. | -| centerX | Integer | Defines the center at the x-axis of the gradient. For the center of the picture use `hyperion.imageWidth()*0.5`, don't forget to surround it with int() or round() | -| centerY | Integer | Defines the center at the y-axis of the gradient. For the center of the picture use `hyperion.imageHeight()*0.5`, don't forget to surround it with int() or round() | -| radius | Integer | Defines the radius of the gradient in pixels | -| focalX | Integer | Defines the focal point at the x-axis | -| focalY | Integer | Defines the focal point at the y-axis | -|focalRadius| Integer | Defines the radius of the focal point | -| bytearray | ByteArray | bytearray of (position,red,green,blue,position,red,green,blue,...). Could be repeated as often you need it, all values have ranges from 0 to 255. The position is a point where the red green blue values are assigned
**Example:** `bytearray([0,255,0,0,255,0,255,0])` - this is a gradient which starts at 0 with color 255,0,0 and ends at position 255 with color 0,255,0. The colors in between are interpolation, so this example is a color shift from red to green. | -| spread | Integer | Defines the spread method outside the gradient. Available spread modes are:
`0` -> The area is filled with the closest stop color
`1` -> The gradient is reflected outside the gradient area
`2` -> The gradient is repeated outside the gradient area
Please note that outside means _inside_ the rectangle but outside of the gradient start and end points, so if these points are the same, you don't see the spread mode. A picture to the spread modes can you find here: [Spread modes](http://doc.qt.io/qt-5/qradialgradient.html#details) | - -::: tip Shorter versions of hyperion.imageRadialGradient() - - `hyperion.imageRadialGradient(startX, startY, width, height, centerX, centerY, radius, bytearray, spread)` -> focalX, focalY, focalRadius get their values from centerX, centerY and radius - - `hyperion.imageRadialGradient(centerX, centerY, radius, focalX, focalY, focalRadius, bytearray, spread)` -> startX and startY are 0 - - `hyperion.imageRadialGradient(centerX, centerY, radius, bytearray, spread)` -> startX and startY are 0 & focalX, focalY, focalRadius get their values from centerX, centerY and radius -::: - -### hyperion.imageLinearGradient() -Draws a linear gradient on the image. Add the arguments in the order of rows below. All arguments are required. -Short description at QT Docs: [Linear Gradient](http://doc.qt.io/qt-5/qlineargradient.html#details) \ -`hyperion.imageLinearGradient(startRX, startRY, width, height, startX, startY, endX, endY, bytearray, spread)` -| Argument | Type | Comment | -| --------- | ---------- | ----------------------------------------------------- | -| startRX | Integer | start point at the x-axis of the rectangle which contains the gradient. | -| startRY | Integer | start point at the y-axis of the rectangle which contains the gradient. | -| width | Integer | width of the rectangle. | -| height | Integer | height of the rectangle. | -| startX | Integer | Defines the start at the x-axis for the gradient. | -| startY | Integer | Defines the start at the y-axis for the gradient. | -| endX | Integer | Defines the end at the x-axis for the gradient. | -| endY | Integer | Defines the end at the y-axis for the gradient. | -| bytearray | ByteArray | bytearray of (position,red,green,blue,alpha,position,red,green,blue,alpha,...). Could be repeated as often you need it, all values have ranges from 0 to 255. The position is a point where the red green blue values are assigned.
**Example:** `bytearray([0,255,0,0,255,255,0,255,0,127])` this is a gradient which starts at 0 with color 255,0,0 and alpha 255 and ends at position 255 with color 0,255,0 and alpha 127. The colors in between are interpolation, so this example is a color shift from red to green. | -| spread | Integer | Defines the spread method outside the gradient. Available spread modes are:
`0` -> The area is filled with the closest stop color
`1` -> The gradient is reflected outside the gradient area
`2` -> The gradient is repeated outside the gradient area
Please note that outside means _inside_ the rectangle but outside of the gradient start and end points, so if these points are the same, you don't see the spread mode. A picture to the spread modes can you find here: [Spread modes](http://doc.qt.io/qt-5/qlineargradient.html#details) | - -::: tip Shorter versions of hyperion.imageLinearGradient() -`hyperion.imageLinearGradient(startX, startY, endX, endY, bytearray, spread)` -> The rectangle which contains the gradient defaults to the full image -::: - -### hyperion.imageDrawLine() -Draws a line at the image. All arguments are required, exception a for alpha. Add the arguments in the order of rows below. \ -`hyperion.imageDrawLine(startX, startY, endX, endY, thick, r, g, b, a)` -| Argument | Type | Comment | -| --------- | ---------- | ----------------------------------------------------- | -| startX | Integer | start point at the x-axis. Relates to `hyperion.imageWidth()` | -| startY | Integer | start point at the y-axis. Relates to `hyperion.imageHeight()` | -| endX | Integer | end point at the x-axis. Relates to `hyperion.imageWidth()` | -| endY | Integer | end point at the y-axis. Relates to `hyperion.imageHeight()` | -| thick | Integer | Thickness of the line, should be calculated based on image height or width. But at least one Pixel. Example: `max(int(0.1*hyperion.imageHeight(),1)` is 10% of the image height. | -| r | Integer | red color from `0` to `255` | -| g | Integer | green color from `0` to `255` | -| b | Integer | blue color from `0` to `255` | -| a | Integer | **Optional** alpha of the color from `0` to `255`, if not provided, it's `255` | - -::: tip Shorter versions of hyperion.imageLinearGradient() -`hyperion.imageLinearGradient(startX, startY, endX, endY, bytearray, spread)` -> The rectangle which contains the gradient defaults to the full image -::: - -### hyperion.imageDrawPoint() -Draws a point/dot at the image. All arguments are required, exception a for alpha. Add the arguments in the order of rows below. \ -`hyperion.imageDrawPoint(x, y, thick, r, g, b, a)` -| Argument | Type | Comment | -| --------- | ---------- | ----------------------------------------------------- | -| x | Integer | point position at the x-axis. Relates to `hyperion.imageWidth()` | -| y | Integer | point position at the y-axis. Relates to `hyperion.imageHeight()` | -| thick | Integer | Thickness of the point in pixel, should be calculated based on image height or width. But at least one Pixel. Example: `max(int(0.1*hyperion.imageHeight(),1)` is 10% of the image height. | -| r | Integer | red color from `0` to `255` | -| g | Integer | green color from `0` to `255` | -| b | Integer | blue color from `0` to `255` | -| a | Integer | **Optional** alpha of the color from `0` to `255`, if not provided, it's `255` | - -::: tip Shorter versions of hyperion.imageDrawPoint() -`hyperion.imageDrawPoint(x, y, thick, r, g, b)` -> alpha defaults to 255 -::: - -### hyperion.imageDrawPolygon() -Draws a polygon at the image and fills it with the specific color. Used for free forming (triangle, hexagon,... whatever you want ). All arguments are required, exception a for alpha. Add the arguments in the order of rows below. \ -`hyperion.imageDrawPolygon(bytearray, r, g, b, a)` -| Argument | Type | Comment | -| --------- | ---------- | ----------------------------------------------------- | -| bytearray | ByteArray | bytearray([point1X,point1Y,point2X,point2Y,point3X,point3Y,...]). Add pairs of X/Y coordinates to specific the corners of the polygon, each point has a X and a Y coordinate, you could add as much points as you need. The last point automatically connects to the first point.| -| r | Integer | red color from `0` to `255` | -| g | Integer | green color from `0` to `255` | -| b | Integer | blue color from `0` to `255` | -| a | Integer | **Optional** alpha of the color from `0` to `255`, if not provided, it's `255` | - -::: tip Shorter versions of hyperion.imageDrawPolygon() -`hyperion.imageDrawPolygon(bytearray, r, g, b)` -> alpha defaults to 255 -::: - -### hyperion.imageDrawPie() -Draws a pie (also known from pie charts) at the image and fills it with the specific color. All arguments are required, exception a for alpha. Add the arguments in the order of rows below. \ -`hyperion.imageDrawPie(centerX, centerY, radius, startAngle, spanAngle, r, g, b, a)` -| Argument | Type | Comment | -| --------- | ---------- | ----------------------------------------------------- | -| centerX | Integer | The center of the Pie at the x-axis | -| centerY | Integer | The center of the Pie at the y-axis | -| radius | Integer | radius of the Pie in Pixels | -| startAngle| Integer | start angle from `0` to `360`. `0` is at 3 o'clock | -| spanAngle | Integer | span (wide) of the pie from `-360` to `360` which starts at the startAngle, positive values are counter-clockwise, negative clockwise | -| r | Integer | red color from `0` to `255` | -| g | Integer | green color from `0` to `255` | -| b | Integer | blue color from `0` to `255` | -| a | Integer | **Optional** alpha of the color from `0` to `255`, if not provided, it's `255` | - -::: tip Shorter versions of hyperion.imageDrawPie() -`hyperion.imageDrawPie(centerX, centerY, radius, startAngle, spanAngle, r, g, b)` -> alpha defaults to 255 -::: - -### hyperion.imageDrawRect() -Draws a rectangle on the image. All arguments are required, exception a for alpha. Add the arguments in the order of rows below. \ -`hyperion.imageDrawRect(startX, startY, width, height, thick, r, g, b, a,)` -| Argument | Type | Comment | -| --------- | ---------- | ----------------------------------------------------- | -| startX | Integer | start point at the x-axis. Relates to `hyperion.imageWidth()` | -| startY | Integer | start point at the y-axis. Relates to `hyperion.imageHeight()` | -| width | Integer | width of the rectangle. Relates to `hyperion.imageWidth()` | -| height | Integer | height of the rectangle. Relates to `hyperion.imageHeight()` | -| thick | Integer | Thickness of the rectangle, a good start value is `1` | -| r | Integer | define red color from `0` to `255` | -| g | Integer | define green color from `0` to `255` | -| b | Integer | define blue color from `0` to `255` | -| a | Integer | **Optional** alpha of the color from `0` to `255`, if not provided, it's `255` | - -### hyperion.imageSolidFill() -Fill a specific part of the image with a solid color (or entire). All arguments are required. Add the arguments in the order of rows below. \ -`hyperion.imageSolidFill(startX, startY, width, height, r, g, b, a)` -| Argument | Type | Comment | -| --------- | ---------- | ----------------------------------------------------- | -| startX | Integer | start point at the x-axis. Relates to `hyperion.imageWidth()` | -| startY | Integer | start point at the y-axis. Relates to `hyperion.imageHeight()` | -| width | Integer | width of the fill area. Relates to `hyperion.imageWidth()` | -| height | Integer | height of the fill area. Relates to `hyperion.imageHeight()` | -| r | Integer | define red color from `0` to `255` | -| g | Integer | define green color from `0` to `255` | -| b | Integer | define blue color from `0` to `255` | -| a | Integer | alpha of the color from `0` to `255` | - -::: tip Shorter versions of hyperion.imageSolidFill() - - `hyperion.imageSolidFill(startX, startY, width, height, r, g, b)` -> no alpha, defaults to 255 - - `hyperion.imageSolidFill(r, g, b, a)` -> startX and startY is 0, width and height is max. -> full image - - `hyperion.imageSolidFill(r, g, b)` -> startX and startY is 0, width and height is max, alpha 255. -> full image -::: - -### hyperion.imageSetPixel() -Assign a color to a specific pixel position. All arguments are required. Add the arguments in the order of rows below. \ -`hyperion.imageSetPixel(X, Y, r, g, b)` -| Argument | Type | Comment | -| --------- | ---------- | ----------------------------------------------------- | -| X | Integer | pixel point at the x-axis. Relates to `hyperion.imageWidth()` | -| Y | Integer | pixel point at the y-axis. Relates to `hyperion.imageHeight()` | -| r | Integer | define red color from `0` to `255` | -| g | Integer | define green color from `0` to `255` | -| b | Integer | define blue color from `0` to `255` | - -### hyperion.imageGetPixel() -Get a color of a specific pixel position. All arguments are required. Add the arguments in the order of rows below. \ -`hyperion.imageGetPixel(X, Y)` -| Argument | Type | Comment | -| --------- | ---------- | ----------------------------------------------------- | -| X | Integer | pixel point at the x-axis. Relates to `hyperion.imageWidth()` | -| Y | Integer | pixel point at the y-axis. Relates to `hyperion.imageHeight()` | -| Return | Tuple | Returns a Python Tuple of RGB values | - - - -### hyperion.setColor() -Set a single color to all leds by adding `hyperion.setColor(255,0,0)`, all leds will be red. But it is also possible to send a bytearray of RGB values. Each RGB value in this bytearray represents one led. - - **Example 1:** `hyperion.setColor(bytearray([255,0,0]))` The first led will be red - - **Example 2:** `hyperion.setColor(bytearray([255,0,0,0,255,0]))` The first led will be red, the second is green - - **Example 3:** `hyperion.setColor(bytearray([255,0,0,0,255,0,255,255,255]))` The first led will be red, the second is green, the third is white - - You usually assign to all leds a color, therefore you need to know how much leds the user currently have. Get it with `hyperion.ledCount` - -::: warning hyperion.setColor() - - hyperion.setColor() function is not recommended to assign led colors, it doesn't work together with **`hyperion.image*`** functions - - You don't know where is top/left/right/bottom and it doesn't work with matrix layouts! - - Please consider to use the **`hyperion.image*`** functions instead to create amazing effects that scales with the user setup -::: \ No newline at end of file diff --git a/docs/docs/en/effects/OurFirstEffect.md b/docs/docs/en/effects/OurFirstEffect.md deleted file mode 100644 index de26b883..00000000 --- a/docs/docs/en/effects/OurFirstEffect.md +++ /dev/null @@ -1,147 +0,0 @@ -# Our first Effect -Let's create together our first effect! \ -Target of this effect is to show the general structure of an effect, make you confident with the API and workflow. - -## Requirements - * An installed and running Hyperion. You need access to the filesystem where Hyperion has been installed. - * Text editor (of your liking, i would recommend [Visual Studio Code](https://code.visualstudio.com/)) - * Navigate to the "custom-effects" folder of your Hyperion installation (Inside .hyperion folder of your home directory) - * **Configure a led matrix layout at "LED Hardware"-section at the web configuration to 10x10 LEDs** - -### Start -First, we start with the python file. Create a new file called `neweffect.py` in your `custom-effects` folder. \ -We need to import some modules, `hyperion` and `time` is always required. The time module comes from Python, if you want to know, what methods such a module has, visit the [Python documentation](https://docs.python.org/3.5/library/). What `hyperion` can do, is already explained at [Effect Engine API](/en/effects/api.md). - -``` python -# Let's import our modules, so we can use them -import hyperion, time - -# Create a loop, this loop runs until the user stops the effect -while not hyperion.abort(): - # Here we are inside the loop, let's do something - # According to the documentation of hyperion.imageDrawPoint() - # The position of this point is 2 at x-axis and 5 at the y-axis with a thickness of 1 pixel and color red - hyperion.imageDrawPoint(2,5,1,255,0,0) - # Now we need to tell Hyperion that we want to send the image we painted - hyperion.imageShow() - # As we are still in our loop let's have a break to slow down the execution. We should never waste CPU power :) - # Sleep a second until the loop starts from the beginning - time.sleep(1) -``` -**Recap:**: First effect finished! We printed a red dot with a size of one pixel on an empty image and sent that to Hyperion. - -### Configuration -Let's test our neweffect.py. Create a new file called `neweffect.json`. And place the following code inside -``` json -{ - "name" : "My first own effect!", - "script" : "neweffect.py", - "args" : { - } -} -``` -Let's talk about what we have done here - - The `neweffect.json` contains the configuration for our effect. - - The `name` property is the effect name which is displayed at the effect list and could be freely defined. - - The `script` property points to the python file it should start. - - The `args` property contains options and their values, for example a color, speed and so on. We leave this empty for the moment. - -**After you added this file to your custom-effects folder, you need to restart Hyperion once** - -Now you should see the "My first own effect!" effect at the remote page effect list. Start the effect, you should see something like this at led visualization. - - -According to the [coordinate system](http://doc.qt.io/qt-5/coordsys.html#rendering), we are at 2 at the x-axis and 5 at the y-axis like written before. Perfect! - -### Add color option -Now we want to make the color of the dot configurable. \ -Let's edit the neweffect.py. - -``` python -import hyperion, time - -# Let's get the value of option custom-color, values will be saved in the color variable -color = hyperion.args.get('custom-color', (0,255,200)) - -while not hyperion.abort(): - # Get the color information from the variable color - hyperion.imageDrawPoint(2,5,1,color[0],color[1],color[2]) - hyperion.imageShow() - time.sleep(1) -``` - * With `hyperion.args.get()` we grab the values from the neweffect.json that starts this python file (from the `args` property of the neweffect.json, which is currently empty.). - * The color array at the end of `hyperion.args.get('custom-color', (0,255,200))` is a fallback value as we don't deliver a `custom-color` property inside the args of the neweffect.json. This ensures always a working effect, choose these default values wisely. - * As you see the `hyperion.imageDrawPoint(...)` got also a modification, as we write the `custom-color` into the variable `color` we access the values with `color[0]` which is 0, `color[1]` which is 255 and `color[2]` which is 200. - -**Save the neweffect.py and restart the effect, a restart of Hyperion is not required** \ -It should now look like this - - -### More dots! -Now we have a single dot, and we prepared the color for the dot to be configurable. Now we want more of them! \ -Again we edit the neweffect.py -``` python -import hyperion, time, random - -color = hyperion.args.get('custom-color', (0,255,200)) -iWidth = hyperion.imageWidth() -iHeight = hyperion.imageHeight() - -while not hyperion.abort(): - hyperion.imageDrawPoint(random.randint(0,iWidth),random.randint(0,iHeight),1,color[0],color[1],color[2]) - hyperion.imageShow() - time.sleep(1) -``` - * We grab now the width (`hyperion.imageWidth()`) and height (`hyperion.imageHeight()`) of the image to make sure that we can fill the entire image with dots. For the required randomness we [import random](https://docs.python.org/3.5/library/random.html) and use `random.randint()` with a minimum value of 0 and a maximum value of our width and height. This creates random integer numbers. - * Keep in mind that the user setup has always a different width, height and even the ratio between them is dynamic based on the led layout. - * **Never use fixed positions, thickness,... calculate them always!** - -So this is the image when we run the effect again. - - -Each second (remember the `sleep.time(1)`) it paints at a random position a new dot, endless. It doesn't check if there is already a dot, it just overwrites the old dot. - -### More color -Let's add an option which force the effect to paint optional a random color for each dot instead always the same. \ -Again we edit the neweffect.py -``` python -import hyperion, time, random -# a helper function to convert HSV to RGB space -def hsv_to_rgb(h, s, v): - if s == 0.0: v*=255; return [v, v, v] - i = int(h*6.) - f = (h*6.)-i; p,q,t = int(255*(v*(1.-s))), int(255*(v*(1.-s*f))), int(255*(v*(1.-s*(1.-f)))); v*=255; i%=6 - if i == 0: return [v, t, p] - if i == 1: return [q, v, p] - if i == 2: return [p, v, t] - if i == 3: return [p, q, v] - if i == 4: return [t, p, v] - if i == 5: return [v, p, q] - -color = hyperion.args.get('custom-color', (0,255,200)) -randomColor = bool(hyperion.args.get('random-color', True)) -iWidth = hyperion.imageWidth() -iHeight = hyperion.imageHeight() - -while not hyperion.abort(): - - if randomColor: - color = hsv_to_rgb(random.uniform(0,1), 1, 1) - - hyperion.imageDrawPoint(random.randint(0,iWidth),random.randint(0,iHeight),1,color[0],color[1],color[2]) - hyperion.imageShow() - time.sleep(1) -``` - * To generate bright colors we write our own function: `def hsv_to_rgb(h, s, v): ...` - * So we add also a new option `randomColor` which is True, we parse True/False values always as `bool(...)` to make sure they are really bool, and not a string. If you don't know what's the difference between a bool, string, int and float is, do a short browse at the [python documentation](https://docs.python.org/3.5/library/stdtypes.html). - * Inside our `while not hyperion.abort():` loop we check with `if randomColor:` if randomColor is true or not, if it is true (enabled) we overwrite our variable `color` with a random color that is generated with `hsv_to_rgb(h,s,v)`. We just randomize h for Hue with our random function `hsv_to_rgb(random.uniform(0,1), 1, 1)`, the h accepts values between 0 and 1. What is hue? Play around with hue at [this](https://www.w3schools.com/colors/colors_hsl.asp) colorpicker. You see why this is a easy way to generate bright colors with a simple random function. - -**Save the file and restart the effect** - - -### Clear the image -Let's add a option to set the image to black on a configurable interval in seconds. This overwrites all dots with black. - -::: tip - I am sorry, more will come soon -::: diff --git a/docs/docs/en/effects/README.md b/docs/docs/en/effects/README.md deleted file mode 100644 index 963e773e..00000000 --- a/docs/docs/en/effects/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# Effect development -Hyperion provides a powerful API to write your own effects, along with possible options and user interface to tune them. - -[[toc]] - -## Effect Files -An effect has 3 different files. -| File | language | Comment | -| :-------------------: | :-----------------------------------: | :-----------------------------------------------------------------------------------: | -| neweffect.py | [Python](https://www.python.org) | The heart of the effect | -| neweffect.json | [JSON](http://www.json.org) | Contains options for the python file, which makes it configurable | -| neweffect.schema.json | [JSON Schema](http://json-schema.org) | Creates the options UI and is used to validate user input. [Read more](/en/api/ui.md) | \ No newline at end of file diff --git a/docs/docs/en/json/Authorization.md b/docs/docs/en/json/Authorization.md deleted file mode 100644 index f7e4bbce..00000000 --- a/docs/docs/en/json/Authorization.md +++ /dev/null @@ -1,164 +0,0 @@ -## Authorization -Hyperion has an authorization system allowing users to login via password, and -applications to login with tokens. The user can configure how strong or weak the Hyperion API -should be protected from the `Configuration` -> `Network Services` panel on the Web UI. - -[[toc]] - -### Token System -Tokens are a simple way to authenticate an App for API access. They can be created in -the UI on the `Configuration` -> `Network Services` panel (the panel appears when `API -Authentication` options is checked). Your application can also [request a -token](#request-a-token) via the API. - -### Authorization Check - -Callers can check whether authorization is required to work with the API, by sending: -```json -{ - "command" : "authorize", - "subcommand" : "tokenRequired" -} -``` -If the property `required` is true, authentication is required. An example response: -```json -{ - "command" : "authorize-tokenRequired", - "info" : { - "required" : true - }, - "success" : true, - "tan" :0 -} -``` - -### Login with Token -Login with a token as follows -- the caller will receive a [Login response](#login-response). -```json -{ - "command" : "authorize", - "subcommand" : "login", - "token" : "YourPrivateTokenHere" -} -``` - -### Login with Token over HTTP/S -Add the HTTP Authorization header to every request. On error, the user will get a failed [Login response](#login-response). -```http - Authorization : token YourPrivateTokenHere -``` - -#### Login response -A successful login response: -```json -{ - "command" : "authorize-login", - "success" : true, - "tan" : 0 -} -``` - -A failed login response: -```json -{ - "command" : "authorize-login", - "error" : "No Authorization", - "success" : false, - "tan" : 0 -} -``` - -### Logout -Users can also logout. Hyperion doesn't verify the login state, this call will always -return a success. - -```json -{ - "command" : "authorize", - "subcommand" : "logout" -} -``` - -Response: -```json -{ - "command" : "authorize-logout", - "success" : true, - "tan" : 0 -} -``` -::: warning -Logging out will stop all streaming data services and subscriptions -::: - -### Request a Token - -Here is the recommended workflow for your application to authenticate: - * Ask Hyperion for a token along with a comment (a short meaningful string that - identifies the caller is the most useful, e.g. includes an application name and - device) and a short randomly created `id` (numbers/letters). - * Wait for the response. The user will need to accept the token request from the Web UI. - * On success: The call will return a UUID token that can be repeatedly used. Note that - access could be revoked by the user at any time, but will continue to last for - currently connected sessions in this case. - * On error: The call won't get a token, which means the user either denied the request or it timed out (180s). - -Request a token using the follow command, being sure to add a comment that is -descriptive enough for the Web UI user to make a decision as to whether to grant or deny -the request. The `id` field has 5 random chars created by the caller, which will appear -in the Web UI as the user considers granting their approval. -```json -{ - "command" : "authorize", - "subcommand" : "requestToken", - "comment" : "OpenHab 2 Binding", - "id" : "T3c91" -} -``` - -After the call, a popup will appear in the Web UI to accept/reject the token request. -The calling application should show the comment and the id so that the user can confirm -the origin properly in the Hyperion UI. After 180 seconds without a user action, the -request is automatically rejected, and the caller will get a failure response (see below). - -#### Success response -If the user accepted the token request the caller will get the following response: -```json -{ - "command" : "authorize-requestToken", - "success" : true, - "info": { - "comment" : "OpenHab2 Binding", - "id" : "T3c91", - "token" : "YourPrivateTokenHere" - } -} -``` - * Save the token somewhere for further use. The token does not expire. - * Be aware that a user can revoke the token. It will continue to function for currently connected sessions. - -#### Failed response -A request will fail when either: - * It times out (i.e. user neither approves nor rejects for 180 seconds after the request - is sent). - * User rejects the request. -```json -{ - "command" : "authorize-requestToken", - "success" : false, - "error" : "Token request timeout or denied" -} -``` - -#### Request abort -You can abort the token request by adding an "accept" property to the original request. -The request will be deleted: -```json -{ - "command" : "authorize", - "subcommand" : "requestToken", - "comment" : "OpenHab 2 Binding", - "id" : "T3c91", - "accept" : false -} -``` diff --git a/docs/docs/en/json/Control.md b/docs/docs/en/json/Control.md deleted file mode 100644 index 84509c16..00000000 --- a/docs/docs/en/json/Control.md +++ /dev/null @@ -1,385 +0,0 @@ -# Control -You can control Hyperion by sending specific JSON messages. - -::: tip -The `tan` property is supported in these calls, but omitted for brevity. -::: - -[[toc]] - -## Sections - -### Set Color -Set a color for all leds or provide a pattern of led colors. - -| Property | Type | Required | Comment | -| :------: | :-----: | :------: | :--------------------------------------------------------------------------------------------------------------: | -| color | Array | true | An array of R G B Integer values e.g. `[R,G,B]` | -| duration | Integer | false | Duration of color in ms. If you don't provide a duration, it's `0` -> indefinite | -| priority | Integer | true | We recommend `50`, following the [Priority Guidelines](/en/api/guidelines#priority_guidelines). Min `2` Max `99` | -| origin | String | true | A short name of your application like `Hyperion of App` . Max length is `20`, min `4`. | - -```json -// Example: Set a blue color with indefinite duration at priority 50 -{ - "command":"color", - "color":[0,0,255], - "priority":50, - "origin":"My Fancy App" -} -// Example: Set a cyan color for 12 seconds at priority 20 -{ - "command":"color", - "color":[0,255,255], - "duration":12000, - "priority":20, - "origin":"My Fancy App" -} - -// Example: Provide a color pattern, which will be repeated until all LEDs have a color -// In this case LED 1: Red, LED 2: Red, LED 3: Blue. -{ - "command":"color", - "color":[255,0,0,255,0,0,0,0,255], // one led has 3 values (Red,Green,Blue) with range of 0-255 - "duration":12000, - "priority":20, - "origin":"My Fancy App" -} -``` - -### Set Effect -Set an effect by name. Available names can be found in the [serverinfo effect list](/en/json/ServerInfo.md#effect-list). - -| Property | Type | Required | Comment | -| :------: | :-----: | :------: | :--------------------------------------------------------------------------------------------------------------: | -| effect | Object | true | Object with additional properties. e.g. `"name":"EffectName"`. | -| duration | Integer | false | Duration of effect in ms. If you don't provide a duration, it's `0` -> indefinite | -| priority | Integer | true | We recommend `50`, following the [Priority Guidelines](/en/api/guidelines#priority_guidelines). Min `2` Max `99` | -| origin | String | true | A short name of your application like `Hyperion of App` . Max length is `20`, min `4`. | - -```json -// Example: Set the 'Warm mood blobs' effect with indefinite duration -{ - "command":"effect", - "effect":{ - "name":"Warm mood blobs" - }, - "priority":50, - "origin":"My Fancy App" -} -// Example: Set 'Rainbow swirl' effect for 5 seconds -{ - "command":"effect", - "effect":{ - "name":"Rainbow swirl" - }, - "duration":5000, - "priority":50, - "origin":"My Fancy App" -} -// Example: Set 'Rainbow swirl' effect for 1 second with overridden agrument -// Each effect has different agruments inside the args property that can be overridden. -// WARNING: We highly recommend using the effects configurator in the UI instead. Sending invalid values may cause the effect to misbehave or crash. -{ - "command":"effect", - "effect":{ - "name":"Rainbow swirl", - "args":{ - "rotation-time":1 - } - }, - "duration":5000, - "priority":50, - "origin":"My Fancy App"} -``` - -### Set Image -Set a single image. Supports all [Qt5](https://doc.qt.io/qt-5/qimagereader.html#supportedImageFormats) image formats, including png/jpg/gif. - -| Property | Type | Required | Comment | -| :-------: | :-----: | :------: | :--------------------------------------------------------------------------------------------------------------: | -| imagedata | String | true | Data of image as [Base64](https://en.wikipedia.org/wiki/Base64) | -| format | String | true | Set to `auto` to let Hyperion parse the image according to type | -| name | String | true | The name of the image | -| duration | Integer | false | Duration of image in ms. If you don't provide a duration, it's `0` -> endless | -| priority | Integer | true | We recommend `50`, following the [Priority Guidelines](/en/api/guidelines#priority_guidelines). Min `2` Max `99` | -| origin | String | true | A short name of your application like `Hyperion of App` . Max length is `20`, min `4`. | - -```json -// Set an image for 5 seconds -{ - "command":"image", - "imagedata":"VGhpcyBpcyBubyBpbWFnZSEgOik=", // as base64! - "name":"Name of Image", - "format":"auto", - "priority":50, - "duration":5000, - "origin": "My Fancy App" -} -``` - -### Clear -Clear a priority, usually used to revert [set color](#set-color), [set -effect](#set-effect) or [set image](#set-image). -```json -// Clear effect/color/image with priority 50 -{ - "command":"clear", - "priority":50, -} -// Clear all effects/colors/images -{ - "command":"clear", - "priority":-1, -} -``` -::: warning -When you clear all, you clear all effects and colors regardless of who set them! -Instead, we recommend users provide a list of possible clear targets based on a -priority list -::: - -### Adjustments -Adjustments reflect the color calibration. You can modify all properties of [serverinfo adjustments](/en/json/serverinfo#adjustments). - -| Property | Type | Required | Comment | -| :--------------------: | :------------: | :------: | :--------------------------------------------------------------------------------------------: | -| red | Array | false | An array of R G B Integer values e.g. `[R,G,B]` | -| green | Array | false | An array of R G B Integer values e.g. `[R,G,B]` | -| blue | Array | false | An array of R G B Integer values e.g. `[R,G,B]` | -| cyan | Array | false | An array of R G B Integer values e.g. `[R,G,B]` | -| magenta | Array | false | An array of R G B Integer values e.g. `[R,G,B]` | -| yellow | Array | false | An array of R G B Integer values e.g. `[R,G,B]` | -| white | Array | false | An array of R G B Integer values e.g. `[R,G,B]` | -| gammaRed | Number (float) | false | minimum:`0.1` maximum `5.0` step of `0.1` | -| gammaGreen | Number (float) | false | minimum:`0.1` maximum `5.0` step of `0.1` | -| gammaBlue | Number (float) | false | minimum:`0.1` maximum `5.0` step of `0.1` | -| brightness | Integer | false | minimum: `0` maximum `100` step of `1` | -| brightnessCompensation | Integer | false | minimum: `0` maximum `100` step of `1` | -| backlightThreshold | Integer | false | minimum: `0` maximum `100`. Step of `1`. (Minimum brightness!) Disabled for effect/color/image | -| backlightColored | Boolean | false | If `true` the backlight is colored, `false` it's white. Disabled for effect/color/image | -| id | String | false | Short identifier | - -```json -// Example: Set gammaRed to 1.5 -{ - "command":"adjustment", - "adjustment":{ - "gammaRed":1.5 - } -} -// Example: Set green to [0,236,0] -{ - "command":"adjustment", - "adjustment":{ - "green":[0,236,0] - } -} -// Example: Set backlightColored to true -{ - "command":"adjustment", - "adjustment":{ - "backlightColored":true - } -} -// Example: Send the 3 examples above at once -{ - "command":"adjustment", - "adjustment":{ - "backlightColored":true, - "gammaRed":1.5, - "green":[0,236,0] - } -} -``` - -### LED mapping -Switch the image to led mapping mode. Possible values are `unicolor_mean` (led color based on whole picture color) and `multicolor_mean` (led colors based on led layout) -```json -// Example: Set mapping mode to multicolor_mean -{ - "command":"processing", - "mappingType":"multicolor_mean" -} -// Example: Set mapping mode to unicolor_mean -{ - "command":"processing", - "mappingType":"unicolor_mean" -} -``` - -### Video Mode -Switch the video mode. Possible values are: `2D`, `3DSBS` and `3DTAB`. - ```json -// Example: Set video mode to 3DTAB -{ - "command":"videomode", - "videoMode":"3DTAB" -} -// Example: Set video mode to 3DSBS -{ - "command":"videomode", - "videoMode":"3DSBS" -} -``` - -### Control Components -Some components can be enabled and disabled at runtime. To get the current state and -available components see [Serverinfo Components](/en/json/serverinfo#components). See -also: [Components/IDs explained](#components-ids-explained) - - ```json -// Example: disable LEDDEVICE component -{ - "command":"componentstate", - "componentstate":{ - "component":"LEDDEVICE", - "state":false - } -} -// Example: enable SMOOTHING component -{ - "command":"componentstate", - "componentstate":{ - "component":"SMOOTHING", - "state":true - } -} -``` -::: warning -Hyperion itself needs to be enabled! Check the status of "ALL" in the components list before you change another component! -::: - -### Components/IDs explained -Each component has a unique id. Not all of them can be enabled/disabled -- some of them, -such as effect and color, are used to determine the source type when examining the -[priority list](/en/json/ServerInfo.html#priorities). -| ComponentID | Component | Enable/Disable | Comment | -| :------------: | :------------------: | :------------: | :---------------------------------------------------------------------------: | -| SMOOTHING | Smoothing | Yes | Smoothing component | -| BLACKBORDER | Blackborder detector | Yes | Black bar detection component | -| FORWARDER | Json/Proto forwarder | Yes | Json/Proto forwarder component | -| BOBLIGHTSERVER | Boblight server | Yes | Boblight server component | -| GRABBER | Platform capture | Yes | Platform Capture component | -| V4L | V4L capture device | Yes | USB capture device component | -| LEDDEVICE | Led device | Yes | Led device component start/stops output of the configured led device | -| ALL | SPECIAL: Hyperion | Yes | Enable or disable Hyperion. Recovers/saves last state of all other components | -| COLOR | Solid color | No | All colors that has been set belongs to this component | -| EFFECT | Effect | No | All effects belongs to this component | -| IMAGE | Solid Image | No | All single/solid images belongs to this. NOT for streaming | -| FLATBUFSERVER | Flatbuffers Server | No | All image stream sources from flatbuffer server | -| PROTOSERVER | Protobuffer Server | No | All image stream sources from Protobuffer server | - - -### Source Selection -Sources are always selected automatically by priority value (lowest value is the highest -priority). You need to know the priority value of the source you want to select -- these -priority values are available in the [serverinfo -Priorities](/en/json/serverinfo#priorities). -```json -// Example: Set priority 50 to visible -{ - "command":"sourceselect", - "priority":50 -} -``` -If you get a success response, the `priorities_autoselect`-status will switch to false (see [serverinfo Autoselection Mode](/en/json/serverinfo##priorities-selection-auto-manual)). You are now in manual mode, to switch back to auto mode send: -```json -{ - "command":"sourceselect", - "auto":true -} -``` -After which, the `priorities_autoselect`-status will return to `true`. - -::: warning -You can only select priorities which are `active:true`! -::: - -### Control Instances -An instance represents an LED hardware instance. It runs within its own scope with it's -own plugin settings, led layout and calibration. Before selecting you can instance, you -should first get information about the available instances from [serverinfo](/en/json/serverinfo#instance). - -```json -// Command to start instance 1 -{ - "command" : "instance", - "subcommand" : "startInstance", - "instance" : 1 -} - -// Command to stop instance 1 -{ - "command" : "instance", - "subcommand" : "stopInstance", - "instance" : 1 -} -``` - -### API Instance handling -On connection to the API you will be connected to instance `0` by default. You can -control only one instance at the same time within a single connection, and -[subscriptions](/en/json/subscribe#instance-updates) are in the context of the selected instance. - -It's possible to switch to another instance with the following command: - -```json -// Switch to instance 1 -{ - "command" : "instance", - "subcommand" : "switchTo", - "instance" : 1 -} -``` -This will return a success response or an error if the instance isn't available. - -::: warning -It's possible that an instance will stop while you are connected to it. In this case -connections on that instance will automatically be reset to instance `0`. Keep watching -the instance data via subscription if you need to handle this case. -See: [Instance updates](/en/json/subscribe#instance-updates). -::: - -### Live Image Stream -You can request a live image stream (if the current source priority supports it, -otherwise here may be no response). -```json -{ - "command":"ledcolors", - "subcommand":"imagestream-start" -} -``` -You will receive "ledcolors-imagestream-update" messages with a base64 encoded image. -Stop the stream by sending: -```json -{ - "command":"ledcolors", - "subcommand":"imagestream-stop" -} -``` -::: danger HTTP/S -This feature is not available for HTTP/S JSON-RPC -::: - - -### Live Led Color Stream -You can request a live led color stream with current color values in RGB for each single -led. The update rate is 125ms. -```json -{ - "command":"ledcolors", - "subcommand":"ledstream-start" -} -``` -You will receive "ledcolors-ledstream-update" messages with an array of all led colors. -Stop the stream by sending: -```json -{ - "command":"ledcolors", - "subcommand":"ledstream-stop" -} -``` -::: danger HTTP/S -This feature is not available for HTTP/S JSON-RPC -::: diff --git a/docs/docs/en/json/README.md b/docs/docs/en/json/README.md deleted file mode 100644 index bf716b7a..00000000 --- a/docs/docs/en/json/README.md +++ /dev/null @@ -1,89 +0,0 @@ -# JSON RPC Introduction -The JSON-RPC interfaces provides many ways to interact with Hyperion. You can retrieve -information about your server, your instances and take actions (such as setting a -priority input). - -[[toc]] - -## What is JSON? -JSON is a standardized message format (see [JSON.org](http://www.json.org/)) and is supported -by most programming languages. It is human readable which makes for easier debugging. - -### Sending JSON -Hyperion requires a specially formatted JSON message. A `command` argument is always -required. A `tan` argument is optional. This is an integer you can freely choose -- it is -part of the response you will receive to allow you to filter the response from other server -messages (this functionality is likely necessary for advanced usecases only). - -```json -{ - "command" : "YourCommand", - "tan" : 1 -} -``` -Depending on the command, there might be an additional subcommand required: -```json -{ - "command" : "YourCommand", - "subcommand" : "YourSubCommand", - "tan" : 1 -} -``` - -### Response -Most messages you send will trigger a response of the following format: -```json -{ - "command" : "YourCommand", - "info":{ ...DATA... }, - "success" : true, - "tan" : 1 -} -``` -- **command**: The command you requested. -- **tan**: The tan you provided (If not, it will default to 0 in the response). -- **success**: true or false. If false, an **error** argument will contain details of the issue. -- **info**: The data you requested (if any). - -## Connect -Hyperion currently supports multiple connection mechanisms: TCP Socket ("Json Server"), WebSocket and HTTP/S. -::: tip -You can automatically discover Hyperion servers! See [Detect Hyperion](/en/api/detect.md) -::: - -### TCP Socket -This is a "raw" connection, you can send and receive line-separated json from the server -(default port: 19444). This is also known as the "Json Server". - -### WebSocket -This is part of the Hyperion webserver (default port: 8090). You send and receive json -commands. WSS is also supported on port 8092. Only TEXT mode is supported. Read more -about websockets at [Websocket](https://en.wikipedia.org/wiki/WebSocket|). - -### HTTP/S Json -HTTP requests can also be sent to the webserver (default port: 8090, for HTTPS: 8092). Send a HTTP/S POST request along with a properly formatted json message in the body to the (example) url: `http://IpOfDevice:WebserverPort/json-rpc` - - -Example picture with a [Firefox](https://addons.mozilla.org/de/firefox/addon/restclient/)/[Chrome](https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo/related) Addon to send HTTP JSON messages - - - -::: tip -If you get a "No Authorization" response, you need to create an [Authorization Token](/en/json/Authorization.md#token-system) -::: - -::: warning HTTP/S Restrictions -Please note that the HTTP JSON-RPC lacks of the following functions due to technical limitations. -- Image streams, led color streams, logging streams, subscriptions -::: - -## API - -### Server Info -A large variety of data is available from the server: [Server Info](/en/json/ServerInfo.md) -### Control -Control your Hyperion server: [Control](/en/json/Control.md) -### Authorization -Authorization mechanisms: [Authorization](/en/json/Authorization.md) -### Subscribe -Data subscriptions: [Subscribe](/en/json/Subscribe.md) diff --git a/docs/docs/en/json/ServerInfo.md b/docs/docs/en/json/ServerInfo.md deleted file mode 100644 index 2e9448f1..00000000 --- a/docs/docs/en/json/ServerInfo.md +++ /dev/null @@ -1,322 +0,0 @@ -# Server Information -This is the primary read mechanism of the Hyperion server. This single command provides data about the live state of Hyperion, broken down into a number -of different parts (described below). - -[[toc]] - -You can request a `serverinfo` response by sending the following command: -```json -{ - "command":"serverinfo", - "tan":1 -} -``` - -## Parts of a serverinfo response - -### Components -List of Hyperion components and their current status "enabled" (on/off). You can enable -or disable them during runtime . The "ALL" component reflect Hyperion as a whole -- if -"ALL" is false (off) you can't enable any other component. [See control -components](/en/json/control#control-components) -::: tip Subscribe -You can subscribe to future data updates. Read more about [Component updates](/en/json/subscribe#component-updates) -::: - -```json -{ - "components":[ - { - "enabled":true, - "name":"ALL" - }, - { - "enabled":true, - "name":"SMOOTHING" - }, - { - "enabled":true, - "name":"BLACKBORDER" - }, - { - "enabled":false, - "name":"FORWARDER" - }, - { - "enabled":false, - "name":"BOBLIGHTSERVER" - }, - { - "enabled":false, - "name":"GRABBER" - }, - { - "enabled":false, - "name":"V4L" - }, - { - "enabled":true, - "name":"LEDDEVICE" - } - ] -} -``` - -### Adjustments -Adjustments reflect the value of the last performed (non-persistent) color adjustment -(e.g. brightness). Read more about [control Adjustments](/en/json/control#adjustments) -::: tip Subscribe -You can subscribe to future data updates. Read more about [Adjustment updates](/en/json/subscribe#adjustment-updates) -::: -```json -{ - "adjustment":[ - { - "backlightColored":true, - "backlightThreshold":0, - "blue":[0,0,255], - "brightness":1, - "cyan":[0,127,127], - "gammaBlue":1.4, - "gammaGreen":1.4, - "gammaRed":1.4, - "green":[0,255,0], - "id":"default", - "magenta":[255,0,255], - "red":[255,0,0], - "white":[255,255,255], - "yellow":[255,255,0] - } - ] -} -``` - -### Effect list -An array of effects where each object is one named effect. You can filter between user -created effects and system provided effects by checking the effect `file` string -- if -it begins with `:` it's a system provided effect, whereas if the path begins with `/`, -it's a user created effect. - -See also [set Effect](/en/json/control#set-effect) -::: tip Subscribe -You can subscribe to future data updates. Read more about [Effect updates](/en/json/subscribe#effects-updates) -::: -```json -{ - "effects":[ - { - "args":{ - "blobs":5, - "color":[ - 0, - 0, - 255 - ], - "hueChange":60, - "reverse":false, - "rotationTime":60 - }, - "file":":/effects//mood-blobs-blue.json", - "name":"Blue mood blobs", - "script":":/effects//mood-blobs.py" - }, - { - "args":{ - "brightness":100, - "candles":"all", - "color":[ - 255, - 138, - 0 - ], - "sleepTime":0.14999999999999999 - }, - "file":":/effects//candle.json", - "name":"Candle", - "script":":/effects//candle.py" - } - .... - ] -} -``` - -### LED mapping -Active mode of the led area mapping. [See control LED mapping](/en/json/control#led-mapping) -::: tip Subscribe -You can subscribe to future data updates. Read more about [LED mapping updates](/en/json/subscribe#led-mapping-updates) -::: -```json - "imageToLedMappingType":"multicolor_mean" -``` - -### Video mode -The current video mode of grabbers. Can be switched to 3DHSBS, 3DVSBS. [See control video mode](/en/json/control#video-mode) -::: tip Subscribe -You can subscribe to future data updates. Read more about [Video mode updates](/en/json/subscribe#videomode-updates) -::: -```json - "videomode" : "2D" -``` - -### Priorities -Overview of the registered/active sources. Each object is a source. - * **active**: If "true" it is selectable for manual source selection. [See also source selection](/en/json/control#source-selection) - * **visible**: If "true" this source is displayed and pushed to the led device. The `visible:true`-source is always the first entry! - * **componentId**: A key belonging to a specific component that indicates the kind of input. [See available components](/en/json/control#components-ids-explained) - * **origin**: A named external setter of this source for reference purposes. If not given it's `System` (from Hyperion). - * **owner**: Contains additional information related to the componentId. If it's an effect, - the effect name is shown here. If it's USB capture, the capture device is shown. If - it's platform capture, you get the name of the platform capture implementation (e.g. dispmanx/x11/amlogic/...). - * **priority**: The priority of this source, an integer between 0 and 255. - * **value**: If the source is a color AND color data is available (if active is false - there's usually no datta),hen this will be the color in RGB and HSL. - * **duration_ms**: Actual duration in ms until this priority is automatically deleted. - This is shown if source is color or effect AND a specific duration higher than - `0` is set (0 means indefinite). - -::: tip Subscribe -You can subscribe to future data updates. Read more about [Priority updates](/en/json/subscribe#priority-updates) -::: -```json - "priorities":[ - { - "active":true, - "componentId":"COLOR", - "origin":"Web Configuration@192.168.0.28", - "owner":"COLOR", - "priority":1, - "value":{ - "HSL":[ - 0, - 1, - 0.50000762939453125 - ], - "RGB":[ - 0, - 0, - 255 - ] - }, - "visible":true - }, - { - "active":true, - "componentId":"EFFECT", - "origin":"System", - "owner":"Warm mood blobs", - "priority":255, - "visible":false - } - ] -``` - -### Priorities selection: Auto/Manual -If `priorities_autoselect` is "true" the visible source is determined by priority. The -lowest number is automatically selected. If a caller requests to set a source manually, -then `priorities_autoselect` switches to `false`. - -If the manually selected source is cleared/stops/completes-duration OR the user requests -the auto selection, `priorities_autoselect` switches back to `true`. This value is -atomically updated with the priority updates (shown above). -[See also source selection](/en/json/control#source-selection). - -### Instance -Information about available instances and their state. Each instance represents a LED -device. Instances can be controlled, see: [Control Instance](/en/json/control#control-instances). -::: tip Subscribe -You can subscribe to future data updates. Read more about [Instance Updates](/en/json/subscribe#instance-updates) -::: -```json - "instance":[ - { - "instance": 0, - "running" : true, - "friendly_name" : "My First LED Hardware instance" - }, - { - "instance": 1, - "running" : false, - "friendly_name" : "PhilipsHue LED Hardware instance" - } - ] -``` - -### LEDs -Information about led layout (image mapping positions) and led count. -::: tip Subscribe -You can subscribe to future data updates. Read more about [LEDs Updates](/en/json/subscribe#leds-updates) -::: -```json -{ - "leds":[ - { - "hmin":0.0, - "hmax":1.0, - "vmin":0.0, - "vmax":1.0 - }, - { - "hmin":0.0, - "hmax":1.0, - "vmin":0.0, - "vmax":1.0 - }, - ... - ] -} -``` - -### System & Hyperion -It's possible to retrieve basic system information about the Hyperion server and the -host it runs on. This information is static and won't change during runtime. -```json -{ - "command" : "sysinfo", - "tan" : 1 -} -``` -You can use the "version" (Hyperion version) string to check application compatibility. We use [Semantic Versioning 2.0.0](https://semver.org/). -If you need a specific id to re-detect known servers you can use the `id` field which -provides a unique id and will not change for a given server. -```json -{ - "hyperion":{ - "build":"webd (brindosch-38f97dc/814977d-1489698970)", - "gitremote": "https://github.com/hyperion-project/hyperion.git", - "time":"Mar 16 2017 21:25:46", - "version":"2.0.0", - "id":"jKsh78D3hd..." - }, - "system":{ - "architecture":"arm", - "hostName":"raspberrypi", - "kernelType":"linux", - "kernelVersion":"4.4.13-v7+", - "prettyName":"Raspbian GNU/Linux 8 (jessie)", - "productType":"raspbian", - "productVersion":"8", - "wordSize":"32" - } -} -``` - -### Sessions - `sessions` shows all Hyperion servers on the current network found via Zeroconf/avahi/bonjour. See also [detect Hyperion](/en/api/detect.md) - ::: tip Subscribe -You can subscribe to future data updates. Read more about [Session updates](/en/json/subscribe#session-updates) -::: - -```json -{ - "sessions":[ - { - "address":"192.168.0.20", - "domain":"local.", - "host":"raspberrypi", - "name":"Awwh yeah!!@raspberrypi:8099", - "port":8090, - "type":"_hyperiond-http._tcp." - } - ] -} -``` diff --git a/docs/docs/en/json/Subscribe.md b/docs/docs/en/json/Subscribe.md deleted file mode 100644 index ed458543..00000000 --- a/docs/docs/en/json/Subscribe.md +++ /dev/null @@ -1,305 +0,0 @@ -# Subscription -During a `serverinfo` request the caller can optionally subscribe to updates -- either -to specific [serverinfo parts](/en/json/ServerInfo.html#parts) or all available data. -These updates will be pushed whenever a server-side data change occurs, without the need -for the caller to poll. - -[[toc]] - -To subscribe to specific updates, you can modify the serverinfo command to: -```json -{ - "command":"serverinfo", - "subscribe":[ - "firstCommand", - "secondCommand", - "thirdCommand" - ], - "tan":1 -} -``` -To subscribe for all available updates modify the severinfo command to -```json -{ - "command":"serverinfo", - "subscribe":["all"], - "tan":1 -} -``` -### Base response layout -All pushed subscription updates will have an `-update` suffix added to the relevant key -from the [serverinfo part in question](/en/json/ServerInfo.html#parts). The new data -will be in the `data` property. There is no `tan` nor `success` argument provided. -```json -{ - "command":"XYZ-update", - "data":{ - ..Data here.. - } -} -``` -### Component updates -The caller can subscribe to component updates. These updates are meant to update the -`components` section of the caller's initial serverinfo. Relevant `serverinfo` -subscription command: - -```json -{ - "command":"serverinfo", - "subscribe":[ - "components-update" - ], - "tan":1 -} -``` -After this, the caller will receive incremental updates. An example: -```json -{ - "command":"components-update", - "data":{ - "enabled":false, - "name":"SMOOTHING" - } -} -``` - -### Session updates -The caller can subscribe to session updates (Hyperion instances found with -Bonjour/Zeroconf/Ahavi). These updates are meant to update the `sessions` section of -the caller's initial serverinfo. Relevant `serverinfo` subscription command: -```json -{ - "command":"serverinfo", - "subscribe":[ - "sessions-update" - ], - "tan":1 -} -``` -These updates aren't incremental -- they contain all found entries on each update. -Example response with 2 HTTP server sessions (`_hyperiond-http._tcp`): -```json -{ - "command":"sessions-update", - "data":[ - { - "address":"192.168.58.169", - "domain":"local.", - "host":"ubuntu-2", - "name":"My Hyperion Config@ubuntu:8090", - "port":8090, - "type":"_hyperiond-http._tcp." - }, - { - "address":"192.168.58.169", - "domain":"local.", - "host":"ubuntu-2", - "name":"My Hyperion Config@ubuntu:8099", - "port":8099, - "type":"_hyperiond-http._tcp." - } - ] -} -``` -### Priority updates -The caller can subscribe to priority updates. These updates are meant to update the -`priorities` and `priorities_autoselect` section of the caller's initial `serverinfo`. -Relevant `serverinfo` subscription command: -```json -{ - "command":"serverinfo", - "subscribe":["priorities-update"], - "tan":1 -} -``` -Caller will get the complete data. Please note that if a color or effect is running with -a timeout > -1, the caller will receive new data each second. An example update: -```json -{ - "command":"priorities-update", - "data":{ - "priorities":[ - { - "active":true, - "componentId":"GRABBER", - "origin":"System", - "owner":"X11", - "priority":250, - "visible":true - }, - { - "active":true, - "componentId":"EFFECT", - "origin":"System", - "owner":"Warm mood blobs", - "priority":254, - "visible":false - }, - { - "active":true, - "componentId":"COLOR", - "origin":"System", - "owner":"System", - "priority":40, - "value":{ - "HSL":[65535,0,0], - "RGB":[0,0,0] - }, - "visible":false - } - ], - "priorities_autoselect":false - } -} -``` -### LED Mapping updates -The caller can subscribe to LED mapping type updates. These updates are meant to update -the `imageToLedMappingType` section of the caller's initial `serverinfo`. -Relevant `serverinfo` subscription command: -```json -{ - "command":"serverinfo", - "subscribe":["imageToLedMapping-update"], - "tan":1} -``` -An example update: -```json -{ - "command":"imageToLedMapping-update", - "data":{ - "imageToLedMappingType":"multicolor_mean" - } -} -``` -### Adjustment updates -The caller can subscribe to adjustment updates. These updates are meant to update the -`adjustment` section of the caller's initial `serverinfo`. Relevant `serverinfo` -subscription command: -```json -{ - "command":"serverinfo", - "subscribe":["adjustment-update"], - "tan":1 -} -``` -An example update: -```json -{ - "command":"adjustment-update", - "data":[{ - "backlightColored":true, - "backlightThreshold":0, - "black":[0,0,0], - "blue":[0,0,255], - "brightness":1, - "cyan":[0,127,127], - "gammaBlue":1.4, - "gammaGreen":1.4, - "gammaRed":1.4, - "green":[0,255,0], - "id":"default", - "magenta":[255,0,255], - "red":[255,0,0], - "white":[255,255,255], - "yellow":[255,255,0] - }] -} -``` -### VideoMode updates -The caller can subscribe to videomode updates. These updates are meant to update the -`videomode` section of the cakker's initial `serverinfo`. Relevant `serverinfo` -subscription command: -```json -{ - "command":"serverinfo", - "subscribe":["videomode-update"], - "tan":1 -} -``` -An example update: -```json -{ - "command":"videomode-update", - "data":{ - "videomode": "2D" - } -} -``` -### Effects updates -The caller can subscribe to effect list updates. These updates are meant to update the -`effects` section of the caller's initial `serverinfo`. Relevant `serverinfo` -subscription command: -```json -{ - "command":"serverinfo", - "subscribe":["effects-update"], - "tan":1 -} -``` -An example update: -```json -{ - "command":"effects-update", - "data":{ - "effects": [ ..All effects here..] - } -} -``` - -### Instance updates -The caller can subscribe to instance updates. These updates are meant to update the -`instance` section of the caller's initial serverinfo. Relevant `serverinfo` -subscription command: -```json -{ - "command":"serverinfo", - "subscribe":["instance-update"], - "tan":1 -} -``` -An example update. This is not incremental -- the caller will get the full set of -instances: -```json -{ - "command":"instance-update", - "data":[ - { - "instance": 0, - "running" : true, - "friendly_name" : "My First LED Hardware instance" - }, - { - "instance": 1, - "running" : false, - "friendly_name" : "PhilipsHue LED Hardware instance" - } - ] -} -``` -### LEDs updates -The caller can subscribe to leds updates. These updates are meant to update the `leds` -section of the caller's initial `serverinfo`. Relevant `serverinfo` subscription command: -```json -{ - "command":"serverinfo", - "subscribe":["leds-update"], - "tan":1 -} -``` -An example update. This is not incremental -- the caller willg et the full set of leds: -```json -{ - "command":"leds-update", - "data": { - "leds" : [ - { - "hmin":0.0, - "hmax":1.0, - "vmin":0.0, - "vmax":1.0 - }, - ... more leds ... - ] - } - } -``` diff --git a/docs/docs/en/user/Configuration.md b/docs/docs/en/user/Configuration.md deleted file mode 100644 index 6a631483..00000000 --- a/docs/docs/en/user/Configuration.md +++ /dev/null @@ -1,43 +0,0 @@ -# Configuration -Hyperion is fully configurable via web browser. The interface is fully responsive and created with touch devices in mind. - -## Web Configuration -Open the web configuration by typing the IP address of your device and the port 8090 in your browser. The installation script will show you the address, if you don't know it. \ -**Example:** `http://192.168.0.20:8090` - -### Dashboard - - -#### Top right navbar - * **Arrows** - Switch between different LED hardware instances (If multiple are available) - * **TV** - Live led visualization - * **Wand/magic stick** - Wizards that guide you through color calibration and more - * **Wrench** - Settings for language selection, settings level, logout, ... - - **Left sidebar** - * **Dashboard** - Yes, here we are. - * **Configuration** - All available settings - * **Remote Control** - Control Hyperion like any other Hyperion remote application - * **Effects Configurator** - Create new effects based on effect templates - * **Support** - Where you get support and how to support us (and why) - * **System** - Inspect your log messages, upload a report for support, credits page, etc - -#### Page - * The **Information** panel shows some important/useful informations. With a small smart access area with important actions. - * The **Component status** shows always the latest state (enabled/disabled) of the components - -::: tip Hashtag navigation -The web configuration supports hashtags for sitenames, so you could directly open a specific page by calling the hashtag. **Example:**`http://192.168.0.20:8090/#remote` - will open the remote control page. -::: - -### Configuration -We added additional information(s) to each option. Some topics require additional attention which are covered here. If you need more help or something lacks of infos, just dive into our Forum. - -#### Language -By default, the web configuration selects the language based on your browser locale or best matching next to. So no configuration is required. In case you want to start learning Hyperion in another language, select from the provided once. \ -Want to contribute a new translation? It's easy! Checkout: [Contribute to Hyperion](https://github.com/hyperion-project/hyperion.ng#contributing). - - -#### Settings level -Settings level prevents a option flooding for new users. While the **Default** level is for beginners and has the lowest amount of options the **Advanced** is for people that want to or need to dive a little deeper. **Expert** is for experts, you shouldn't need it that often. - diff --git a/docs/docs/en/user/HyperBian.md b/docs/docs/en/user/HyperBian.md deleted file mode 100644 index 305de19d..00000000 --- a/docs/docs/en/user/HyperBian.md +++ /dev/null @@ -1,55 +0,0 @@ -# HyperBian -Is a ready to use image for your Raspberry Pi. Based on the original Raspberry Pi Foundation image "Raspbian lite". Hyperion is already pre installed. So simply -1. Download -2. Burn image on SD -3. Power on your Pi -4. Visit with your Browser `http://IpOfYourPi:8090` for configuration - - -## Requirements - * SD card with at least 2GB size - * Raspberry Pi - * Linux/Mac/Windows + SD card read/writer - -## Installation - * Download the image here: [HyperBian Download](https://github.com/Hyperion-Project/HyperBian/releases) - * Extract HyperBian-XXXX.img out of the HyperBian.zip - * Burn the extracted HyperBian-XXXX.img to your SD card. Below 3 instructions for the specific system - * On Windows: [INSTALLING OPERATING SYSTEM IMAGES USING WINDOWS](https://www.raspberrypi.org/documentation/installation/installing-images/windows.md) - * On Mac: [INSTALLING OPERATING SYSTEM IMAGES ON MAC OS](https://www.raspberrypi.org/documentation/installation/installing-images/mac.md) - * On Linux: [INSTALLING OPERATING SYSTEM IMAGES ON LINUX](https://www.raspberrypi.org/documentation/installation/installing-images/linux.md) - * In case your Raspberry Pi has WLAN or you want to use a WLAN stick, you could pre-configure the WLAN SSID and password before you plugin the SD in your Pi. See [HyperBian WLAN](#hyperbian-wlan) - * Optional: Enable SSH [HyperBian SSH](#HyperBian-SSH) - -::: tip -As a image is already outdated the moment you create it. We update it once a week with latest sources from the Raspberry Pi Foundation. Or upon a new Hyperion release. -::: - -### HyperBian WLAN -In case you want to use WLAN with your Raspberry Pi, you can include the WLAN SSID and password after you burned the HyperBian-XXXX.img to your SD card for auto configuration on first boot. -Open the SD card with a file explorer. It's called "boot". - - Create a new text file - - - Rename it to "wpa_supplicant.conf" - - - Add your WLAN credentials, replace **YOUR_SSID** and **YOUR_PASSWORD** with your values -``` -ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev -update_config=1 -country=GB - - network={ - ssid="YOUR_SSID" - psk="YOUR_PASSWORD" - key_mgmt=WPA-PSK - } -``` - - - Save it! You are done, the WLAN will be configured during next boot - -### HyperBian SSH -You should never need it for daily usage, but for completion: To enable SSH access, plugin your sd card with HyperBian already installed into your computer, and open the "boot" partition with a file explorer. Create a empty file named `ssh` in the root directory (without file extension). SSH will be enabled now on next boot. \ -**SSH LOGIN** - - User: pi - - Password: raspberry - diff --git a/docs/docs/en/user/Installation.md b/docs/docs/en/user/Installation.md deleted file mode 100644 index f09a45c0..00000000 --- a/docs/docs/en/user/Installation.md +++ /dev/null @@ -1,49 +0,0 @@ -# Install Hyperion -Hyperion supports various platforms for installation, as package or portable .zip. - -## Requirements - -### Supported Systems - * Raspberry Pi (See also [HyperBian](/en/user/HyperBian)) - * Debian 9 | Ubuntu 16.04 or higher - * Mac OS - -**Please note that some arm devices have limited support in terms of screen capturing** - -### Supported Browsers -Hyperion will be configured and controlled trough a web interface. - * Chrome 47+ - * Firefox 43+ - * Opera 34+ - * Safari 9.1+ - * Microsoft Edge 14+ - -::: warning Internet Explorer -Internet Explorer is not supported -::: - -## Install Hyperion - * Raspberry Pi you can use [HyperBian](/en/user/HyperBian.md) for a fresh start. Or use the install system - * We provide installation packages (.deb) to install Hyperion with a single click on Debian/Ubuntu based systems. - * Mac OSX - currently just a zip file with the binary - -### Debian/Ubuntu -For Debian/Ubuntu we provide a .deb file. A one click installation package that does the job for you. \ -Download the file from the [Release page](https://github.com/hyperion-project/hyperion.ng/releases) \ -Install from commandline by typing. \ -`sudo apt install ./Hyperion-2.0.0-Linux-x86_64.deb` \ -Hyperion can be now started from your start menu. - -### Fedora -For Fedora we provide a .rpm file. A one click installation package that does the job for you. \ -Download the file from the [Release page](https://github.com/hyperion-project/hyperion.ng/releases) \ -Install from commandline by typing. \ -`sudo dnf install ./Hyperion-2.0.0-Linux-x86_64.rpm` \ -Hyperion can be now started from your start menu. - -## Uninstall Hyperion -On Debian/Ubuntu you can remove Hyperion with this command \ -`sudo apt remove hyperion` \ - -### Hyperion user data -Hyperion stores user data inside your home directory (folder `.hyperion`). diff --git a/docs/docs/en/user/LedDevices.md b/docs/docs/en/user/LedDevices.md deleted file mode 100644 index ddeb1139..00000000 --- a/docs/docs/en/user/LedDevices.md +++ /dev/null @@ -1,164 +0,0 @@ ---- -sidebarDepth: 2 ---- - -# LED Hardware -Hyperion supports a lot of different controllers and led chips. Also network communication is possible, therefore we also support Philips Hue, AtmoOrb and more. - -## General Settings -Applicable for all led hardware implementations \ - * RGB byte order: If you want to check this value, use the wizard. - * Refresh time: If no source is active and the led hardware component is enabled, this will update by the given interval time the led hardware with black color. - -## Specific Settings -Each LED hardware has specific settings which are explained here - -### SPI -Are 4 wire leds which can be powered via SPI of a Raspberry Pi or an Arduino (which is USB connected to your computer/HTPC/Pi) - -#### apa102 -APA 102. These LEDs are known for a good color spectrum (converting a data signal to the wanted color). - -#### ws2801 -The color spectrum of these leds is bad. - -#### lpd6803 -#### lpd8806 -#### p9813 -#### sk6812spi -The SK6812 are **3** wire leds, you could also drive them via spi. - -#### sk6822spi -The SK6822 are **3** wire leds, you could also drive them via spi. - -#### sk9822 -The SK9822 are **4** wire leds compatible to APA 102 with addition of global brightness control. - -#### ws2812spi -The WS2812 are **3** wire leds, you could also drive them via spi. - -### USB -Plug and play. The following controllers are supported. - -#### adalight -Most used because it's cheap and easy! An Arduino powered by an adalight sketch. We provide a modified version of it. Checkout TUTORIAL - -#### atmo - -#### dmx -#### file -#### hyperionusbasp -#### lightpack -#### multilightpack -#### paintpack -#### rawhid -#### sedu -#### tpm2 - -### Network -Hue bridges, nodeMCU, AtmoOrbs everything that is reachable over network. - -#### philipshue -The well known [Philips Hue Bridge + Bulbs](https://www.amazon.com/s/ref=nb_sb_noss?url=search-alias%3Daps&field-keywords=philips+hue+starter+set&rh=i%3Aaps%2Ck%3Aphilips+hue+starter+set&tag=hyperionpro05-20) is supported. How to configure them with Hyperion? Checkout: Web configuration - -#### Entertainment API - -::: danger Photosensitive seizure warning -Certain individuals may experience discomfort when exposed to quick flashes/patterns of light. -Please refrain from using entertainment mode immediately if you feel any discomfort or have any known health conditions. Please consult a physician under those circumstances. Make sure your entertainment room is well-lit. - -Hyperion cannot be held liable for any foreseeable, or unforeseeable, negative or harmful impact. - -::: - -##### Requirements - * Before you start, the Entertainment API requires at least one entertainment group/area with minimum one assigned lamp! Checkout: [Entertainment groups / areas](#entertainment-groups--areas) - * A normal Hue group, does NOT work with the Hue Entertainment API! - * Check the "Use Hue Entertainment API" option and use the Philips Hue Entertainment wizard at the web configuration for configuration (available at led hardware section)! - * The Entertainment API requires also a username and a suitable clientkey. Checkout: [Philips Hue Entertainment wizard](#philips-hue-entertainment-wizard) - -##### Philips Hue Entertainment wizard - * In the wizard, your Hue Bridge is automatically discovered via the Philips Hue Cloud when it is registered. If not, try entering the bridge IP address and click the "retry" icon / button next to the IP entry field. - * If only the username is known or you start from scratch, create a new user with the Philips Hue Entertainment wizard and a clientkey will automatically generated. - * If no Entertainment group / area was found on the bridge you are using, the wizard switches back to the classic version and deactivates the use of the Hue Entertainment API! - * Username, clientkey and Entertainment group / area ready? Select your Entertainment group / area, you would like to use and fine-tune your preselected screen positions for each lamp. - * Don't forget to save your changes! ;) - -##### Bridge requirements / limits - * To use the Philips Hue Entertainment API, the bridge must use at least API version 1.22! - * Only one Entertainment group / area can be active at one time on a single Hue Bridge! - -##### Multiple and / or none original Hue bridges - * Automatic detection will only find the first available bridge. - * If your bridge wasn't found or was found, but not the one you want to use, manually enter the desired bridge IP address and click the "retry" icon / button next to the IP entry field. - -##### Entertainment groups / areas - * Entertainment groups / areas can be created using the original Philips Hue app. - * Set also the right z-axis (Ground height, TV height and Ceiling height) for each lamp within the configuration of the Entertainment group / area. Tapping each lamp changes the height and will be recognized it in the Philips Hue Entertainment wizard to also preselect the correct screen position. - * You can connect up to 10 Philips Hue or Friends of Hue color-capable lights per Entertainment group / area. - * When a Entertainment group / area is used with the Entertainment API, you can't control any of the lamps in the Entertainment group / area, until the Entertainment API stops! - -#### Advanced Settings - -##### Signal detection - * The Entertainment API is a permanent stream that continuously sends color information to the bridge. That's why the signal detection came into play. - * With the `Signal detection timeout on black` option, you can control how long all lamps are set to black, before the Entertainment API stops and the previous lamp state will be recovered. - * Set the ms value higher, so longer dark scenes in movies will not stop the Entertainment API. - * The Entertainment API automatically restarts when color information other than black is available to send. - * Some grabbers do not provide real black, but rather dark gray, so black = 0 never occurs. With the option `Signal detection brightness minimum` you can set the minimum brightness which is considered black. The range can be set from 0 = 0% to 1 = 100%, e.g. 0,005 = 0.5%. If 0 doesn't' work for your setup, increase this value in 0,005 steps. It's like the thresholds for USB Capture. - -##### Brightness *Settings may be removed in future releases* - * Set / leave `brightness factor` back to 1 (default) - classic low brightness bug is fixed - * Set / leave `brightness minimum` to 0 (default) - you can set a minimum brightness, so the lamps will never be off - * Set / leave `brightness maximum` to 1 (default) - you can set a maximum brightness, if you don't want the whole room to light up in bright scenes - * Value range for brightness minimum / maximum are: 0 = 0% to 1 = 100%, E.g. 0,05 = 5% / 0,5 = 50% - * The brightness factor is a multiplier for the input brightness, means E.g. 50% input brightness * brightness factor (e.g. 1,5) = new 75% brightness. - * __Be warned__: - If you change the brightness factor / minimum / maximum to a value other than the default value, the color rendering will also change!!! - E.g. Dark / Black will appear as a deep dark blue, if you raise the minimum brightness, because the deepest color inside the hue light system is a deep blue, because black is not a color, it's only off. - __AND__ you can miss the entire Entertainment API experience ;) - -::: warning Fast uncontrolled colors / flickering - * The color information for each lamp, depends on the input signal from your grabber source, the defined screen position to use for the lamp (like any other led configuration) and the used capture framerate! - * Input signals with noise and other image disturbances can cause this effect of rapidly changing colors / flickering. For more information on how to reduce this problem, see the next tip: - -::: - -::: tip Activate smoothing in image processing! - This allows the extremely fast color / flicker to be controlled very well. - These values ​​work well, but decide for yourself: - Time: 80 - 120 ms - Update frequency: 35 - 40 Hz - higher values leads to faster color change / flickering again - Update delay: 0 ms - Continuous output: no - does not have to, since the last color values ​​are stored in the respective lamp - -::: - -##### Configuration Tips & Tricks - * Color calibration is not required, you can keep the default values. - * To enable/disable the active Entertainment group / area from Hyperion, disable Hyperion or just the led hardware component. The previous lamp state will be recovered - other solutions may come in future releases - Hint: [Signal detection](#signal-detection) - -#### Classic Philips Hue usage without the Entertainment API - -##### Configuration Tips & Tricks - * Use the Philips Hue wizard at the web configuration for configuration (available at led hardware section)! - * Color calibration is not required, you can keep the default values. - * If the brightness is to low for you and Hyperion is already at 100% you can higher the brightness factor at the web configuration -> LED hardware - * Brightness compensation influences the brightness across different color (Adjust at the color section) - * To enable/disable the bridge control from Hyperion, disable Hyperion or just the led hardware component. The previous lamp state will be recovered - -#### atmoorb -#### tpm2net -#### udpe131 -#### udph801 -#### udpraw -#### tinkerforge -#### fadecandy - -### Raspberry Pi -Just for the Raspberry Pi! -#### ws281x -Driving all kinds of WS281X stripes. Due to mixed feedback we recommend adalight or Raspberry Pi SPI. -#### piblaster -[PiBlaster on Github](https://github.com/sarfata/pi-blaster) - diff --git a/docs/docs/en/user/README.md b/docs/docs/en/user/README.md deleted file mode 100644 index 14a7ed38..00000000 --- a/docs/docs/en/user/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# User Documentation -All you need to know about Hyperion diff --git a/docs/docs/en/user/advanced/Advanced.md b/docs/docs/en/user/advanced/Advanced.md deleted file mode 100644 index c8ce7119..00000000 --- a/docs/docs/en/user/advanced/Advanced.md +++ /dev/null @@ -1,194 +0,0 @@ -# Advanced -Specific topics with details - -[[TOC]] - -## LED Layout -Hyperion assigns each single led a specific position at the picture. These positions are squares and to create a square you need 4 values (top edge, bottom edge, left edge, right edge). These edges are reflected in `hmin`, `hmax` for horizontal and `vmin`, `vmax` for vertical. They have a value range from `0.0` to `1.0`. - - -Assignment of LED edges - - - -So let's have a closer look. Following a single led definition: -``` json -{ - "hmax": 0.2, - "hmin": 0, - "vmax": 0.2, - "vmin": 0 -} -``` -Let's visualize the example above! - - -A single led definition - - - -So let us add 2 more leds to make it more clear \ -**The order is important! The first entry is the first led, the second the second led, ...** -``` json -{ - "hmax": 0.2, - "hmin": 0, - "vmax": 0.2, - "vmin": 0 -}, -{ - "hmax": 0.5, - "hmin": 0.3, - "vmax": 0.5, - "vmin": 0.3 -}, -{ - "hmax": 1.0, - "hmin": 0.7, - "vmax": 1, - "vmin": 0.7 -} -``` - -Now with three LEDs - - - -### Additional properties -You may connected different led stripe charges with different RGB byte orders. You can overwrite the global RGB byte order by adding a `colorOrder` property to all leds that require a different one. -``` json -{ - "hmax": 0.2, - "hmin": 0, - "vmax": 0.2, - "vmin": 0, - "colorOrder":"gbr" -}, -{ - "hmax": 0.5, - "hmin": 0.3, - "vmax": 0.5, - "vmin": 0.3 -}, -{ - "hmax": 1.0, - "hmin": 0.7, - "vmax": 1, - "vmin": 0.7 -} -``` -In this example the first led will be `gbr`, the other leds will be assigned to the global RGB order that has been defined at the led hardware section. - -### Edit with Web Configuration -While editing these values in a local texteditor is a little bit weird, you could edit them at the web configuration! - - Make sure you raised the [Hyperion Settings level](../Configuration.md#settings-level) to **Advanced**. - - Navigate to Configuration -> LED Hardware and switch to the LED Layout tab. You will notice a new section **Generated/Current LED Configuration**. - - -You could freely edit the values, show a preview on the right side by clicking **Update Preview**. When you are happy with the changes don't forget to save. - -## Blackbar detection -Explain the differences between the available modes for blackbar detection. - - * **Default:** 3 scanlines in each direction (X Y) - fastest detection - * **Classic:** The original implementation - lower cpu time (legacy for RPi 1) just scan the top one third of the picture which leads to a slow detection and trouble with TV channel logo. - * **OSD:** Based on the default mode - not that effective but prevents border switching which may caused of OSD overlays (program infos and volume bar). - * **Letterbox:** Based on the default mode - only considers blackbars at the top and bottom of the picture, ignoring the sides. - - -## Gamma Curve - Gamma values in a graphic. AS you see 1.0 is neutral. Lower than 1.0 increase the color, higher reduce color. - - - -## CLI -All executables shipped with Hyperion have some command line arguments/options - -### hyperiond -The heart of Hyperion -``` sh -# Show the version/build date/commit of Hyperion -hyperiond --version - -# Reset current adminstration password back to 'hyperion' -hyperiond --resetPassword - -# Overwrite the path for user data (which defaults to your home directory) -hyperiond --userdata /temp/anotherDir - -# Overwrite log level temporarily: hyperiond -s for silent -v for verbose and -d for debug -hyperiond -d - -# Export effects to directory -hyperiond --export-effects /tmp - -# Run Hyperion in desktop mode -hyperiond --desktop -``` - -::: tip -If a path name contains spaces, surround it with `“`. -`hyperiond --userdata "/temp/another Dir"` -::: - -### hyperion-remote -hyperion-remote is a command line tool which translates given arguments to JSON commands and sends them to the Hyperion JSON-RPC. Easy to use for scripts. It supports nearly all commands that Hyperion provides. - -``` sh -# Get a list of all available commands -hyperion-remote -h - -# Set a color by using HTML color names -hyperion-remote -c aqua - -# Set color with hex value -hyperion-remote -c FF7F50 - -# Set color with a duration of 5 seconds instead endless -hyperion-remote -c FF7F50 -d 5000 - -# Start an effect -hyperion-remote -e "Rainbow swirl" - -# with a duration of 8 seconds instead endless -hyperion-remote -e "Rainbow swirl" -d 8000 - -# Target a specific instance -# ATTENTION: Hyperion instances will synchronize with the Instance Syncing feature by default -# You can configure the behaviour for each instance -hyperion-remote -I "My cool instance name" -# Or -hyperion-remote --instance "My cool instance name" -# Example set effect for instance -hyperion-remote --instance "My cool instance name" -e "Rainbow swirl" -``` - -::: tip -Hyperion remote will search for a Hyperion server automatically. So you can even use that on another device in your local network without providing a ip/port -::: - -### hyperion-capture - We deliver also stand alone capture apps right in your Hyperion directory. They are called hyperion-dispmanx, hyperion-osx, hyperion-x11, hyperion-amlogic, hyperion-framebuffer, hyperion-qt. Depending on your platform you have more or less. - -All these application can be started independent from Hyperion and all of these have slightly different options. They communicate with the flatbuffer interface of Hyperion. So let's start one of them! In this example i use dispmanx for Raspberry Pi, so let us check the available options. - -``` sh -hyprion-dispmanx -h - -f, --framerate Capture frame rate [default: 10] - --width Width of the captured image [default: 64] - --height Height of the captured image [default: 64] - --screenshot Take a single screenshot, save it to file and quit - -a, --address
Set the address of the hyperion server [default: 127.0.0.1:19445] - -p, --priority Use the provided priority channel (suggested 100-199) [default: 150] - --skip-reply Do not receive and check reply messages from Hyperion - -h, --help Show this help message and exit - --crop-left pixels to remove on left after grabbing - --crop-right pixels to remove on right after grabbing - --crop-top pixels to remove on top after grabbing - --crop-bottom pixels to remove on bottom after grabbing - --3DSBS Interpret the incoming video stream as 3D side-by-side - --3DTAB Interpret the incoming video stream as 3D top-and-bottom - -# Let's start with capture interval of 15, width of 100 and a height of 100 -hyperion-dispmanx -a 192.168.0.20:19445 -f 15 --width 100 --height 100 -``` diff --git a/docs/docs/en/user/advanced/Support.md b/docs/docs/en/user/advanced/Support.md deleted file mode 100644 index c25befe6..00000000 --- a/docs/docs/en/user/advanced/Support.md +++ /dev/null @@ -1,76 +0,0 @@ -# Support Request -In case you need support or you found a bug it's all about informations that you need to deliver. - -## Usual request -For this purpose and to save a lot of time we included a report creation and upload function into the web configuration. -So visit your web configuration and click on System -> Log. Now you click on the button "Upload report for support request". -> Image of report tool - -If everything has gone well, you will notice a Link below the button. Add this link to your support request at our [Hyperion Project Forum](https://forum.hyperion-project.org). - -## Segmentation faults -Debugging segmentation faults requires a bunch of work, if we don't own your hardware (idr one of these plenty ARM systems) or can't reconstruct the segmentation fault we need a backtrace log from you. In order to create one, follow these steps. - - You need a "Debug" version of Hyperion, download and install it over your existing installation. - - Install "GDB", gbd is a tool which is often used for debugging. Get it from the software repository of your distribution (Debian e.g. `sudo apt-get install gdb` - -### Steps of execution - * Open a terminal - * Make sure Hyperion is NOT running, this can be done by typing `sudo service hyperiond stop` into the terminal and press enter - * Type in `gdb` and press enter. You will now see the gdb welcome information and a "(gdb)" in front of your cursor - * Tell gdb where "hyperiond" is located, usually at /usr/share/hyperion/bin/hyperiond. Prepend "file" to the path. So type into terminal something like that and press enter: `file /usr/share/hyperion/bin/hyperiond` - * gdb should tell you now that the binary has been loaded with it's symbols etc - * Now type in `run` and press enter, this will start Hyperion. Now you can use Hyperion as usual, repeat the steps you did to create a segmentation fault. - * A segmentation fault happened, when Hyperion stops responding and you see something like this as last message at the terminal: `Thread 1 "hyperiond" received signal SIGSEGV, Segmentation fault.` - * Now type in `backtrace` and press enter, add the backtrace to your support request thread at our forum. [Hyperion Project Forum](https://forum.hyperion-project.org) - * To quit gdb press enter and type in `quit`, you can start Hyperion again with `sudo service hyperiond start`. It's not recommended to use "Debug" Hyperion builds in production, just install the "Release" version again. - -### Example backtrace log -``` - (gdb) backtrace - #0 0x0000000000000000 in ?? () - #1 0x00000000006173f2 in LinearColorSmoothing::queueColors (this=0xfdfa70, - ledColors=std::vector of length 34, capacity 34 = {...}) - at /home/hyperion/Dokumente/hyperion.ngBeta/libsrc/hyperion/LinearColorSmoothing.cpp:153 - #2 0x0000000000617374 in LinearColorSmoothing::updateLeds (this=0xfdfa70) - at /home/hyperion/Dokumente/hyperion.ngBeta/libsrc/hyperion/LinearColorSmoothing.cpp:143 - #3 0x0000000000609652 in LinearColorSmoothing::qt_static_metacall ( - _o=0xfdfa70, _c=QMetaObject::InvokeMetaMethod, _id=1, _a=0x7fffffffd190) - at /home/hyperion/Dokumente/hyperion.ngBeta/build/libsrc/hyperion/moc_LinearColorSmoothing.cpp:85 - #4 0x00007ffff59abd2a in QMetaObject::activate(QObject*, int, int, void**) () - from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5 - #5 0x00007ffff59b85c8 in QTimer::timerEvent(QTimerEvent*) () - from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5 - #6 0x00007ffff59acbb3 in QObject::event(QEvent*) () - from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5 - #7 0x00007ffff78a505c in QApplicationPrivate::notify_helper(QObject*, QEvent*) - () from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5 - #8 0x00007ffff78aa516 in QApplication::notify(QObject*, QEvent*) () - from /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5 - #9 0x00007ffff597d38b in QCoreApplication::notifyInternal(QObject*, QEvent*) - ---Type to continue, or q to quit--- - () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5 - #10 0x00007ffff59d25ed in QTimerInfoList::activateTimers() () - from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5 - #11 0x00007ffff59d2af1 in ?? () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5 - #12 0x00007ffff4572127 in g_main_context_dispatch () - from /lib/x86_64-linux-gnu/libglib-2.0.so.0 - #13 0x00007ffff4572380 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0 - #14 0x00007ffff457242c in g_main_context_iteration () - from /lib/x86_64-linux-gnu/libglib-2.0.so.0 - #15 0x00007ffff59d37cf in QEventDispatcherGlib::processEvents(QFlags) () from /usr/lib/x86_64-linux- - gnu/libQt5Core.so.5 - #16 0x00007ffff597ab4a in QEventLoop::exec(QFlags) () from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5 - #17 0x00007ffff5982bec in QCoreApplication::exec() () - from /usr/lib/x86_64-linux-gnu/libQt5Core.so.5 - #18 0x00000000005d9279 in main (argc=1, argv=0x7fffffffde08) - at /home/hyperion/Dokumente/hyperion.ngBeta/src/hyperiond/main.cpp:337 -``` - -## Report Privacy Policy -Hyperion gathers the following informations and uploads them to our server. - * System informations (OS, Version, Kernel, Arch) Hyperion runs on. - * Current state (active components, active priorities, webconfig settings) - * Browser and OS - * Configuration file content - * Log (if available) -No additional data is acquired. We use this informations just for support requests. \ No newline at end of file diff --git a/docs/package.json b/docs/package.json deleted file mode 100644 index 6c0fca7e..00000000 --- a/docs/package.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "hyperion-docs", - "version": "1.0.0", - "description": "Hyperion Documentation", - "homepage": "https://www.hyperion-project.org", - "author": "brindosch", - "private": true, - "licence": "MIT", - "scripts": { - "docs:dev": "vuepress dev docs", - "docs:build": "vuepress build docs", - "docs:serve": "vuepress serve docs --build --open" - }, - "dependencies": { - "vuepress": "^1.4.1", - "vuepress-plugin-medium-zoom": "^1.1.8", - "vuepress-plugin-redirect": "^1.2.3" - }, - "devDependencies": { - "@vuepress/plugin-back-to-top": "^1.4.1", - "@vuepress/plugin-pwa": "^1.4.1", - "babel-eslint": "^10.1.0", - "eslint": "^6.8.0", - "eslint-plugin-vue": "^6.2.2", - "vuepress-plugin-serve": "^2.0.2" - }, - "engines": { - "node": ">= 10.16.0", - "npm": ">= 5.6.0", - "yarn": ">= 1.19.0" - } -} diff --git a/docs/yarn.lock b/docs/yarn.lock deleted file mode 100644 index 63d6093b..00000000 --- a/docs/yarn.lock +++ /dev/null @@ -1,8772 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@babel/code-frame@^7.0.0": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" - integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== - dependencies: - "@babel/highlight" "^7.0.0" - -"@babel/code-frame@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e" - integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g== - dependencies: - "@babel/highlight" "^7.8.3" - -"@babel/compat-data@^7.8.6", "@babel/compat-data@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.9.0.tgz#04815556fc90b0c174abd2c0c1bb966faa036a6c" - integrity sha512-zeFQrr+284Ekvd9e7KAX954LkapWiOmQtsfHirhxqfdlX6MEC32iRE+pqUGlYIBchdevaCwvzxWGSy/YBNI85g== - dependencies: - browserslist "^4.9.1" - invariant "^2.2.4" - semver "^5.5.0" - -"@babel/core@^7.8.4", "@babel/core@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.0.tgz#ac977b538b77e132ff706f3b8a4dbad09c03c56e" - integrity sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w== - dependencies: - "@babel/code-frame" "^7.8.3" - "@babel/generator" "^7.9.0" - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helpers" "^7.9.0" - "@babel/parser" "^7.9.0" - "@babel/template" "^7.8.6" - "@babel/traverse" "^7.9.0" - "@babel/types" "^7.9.0" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.1" - json5 "^2.1.2" - lodash "^4.17.13" - resolve "^1.3.2" - semver "^5.4.1" - source-map "^0.5.0" - -"@babel/generator@^7.9.0", "@babel/generator@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.5.tgz#27f0917741acc41e6eaaced6d68f96c3fa9afaf9" - integrity sha512-GbNIxVB3ZJe3tLeDm1HSn2AhuD/mVcyLDpgtLXa5tplmWrJdF/elxB56XNqCuD6szyNkDi6wuoKXln3QeBmCHQ== - dependencies: - "@babel/types" "^7.9.5" - jsesc "^2.5.1" - lodash "^4.17.13" - source-map "^0.5.0" - -"@babel/helper-annotate-as-pure@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz#60bc0bc657f63a0924ff9a4b4a0b24a13cf4deee" - integrity sha512-6o+mJrZBxOoEX77Ezv9zwW7WV8DdluouRKNY/IR5u/YTMuKHgugHOzYWlYvYLpLA9nPsQCAAASpCIbjI9Mv+Uw== - dependencies: - "@babel/types" "^7.8.3" - -"@babel/helper-builder-binary-assignment-operator-visitor@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.8.3.tgz#c84097a427a061ac56a1c30ebf54b7b22d241503" - integrity sha512-5eFOm2SyFPK4Rh3XMMRDjN7lBH0orh3ss0g3rTYZnBQ+r6YPj7lgDyCvPphynHvUrobJmeMignBr6Acw9mAPlw== - dependencies: - "@babel/helper-explode-assignable-expression" "^7.8.3" - "@babel/types" "^7.8.3" - -"@babel/helper-compilation-targets@^7.8.7": - version "7.8.7" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.7.tgz#dac1eea159c0e4bd46e309b5a1b04a66b53c1dde" - integrity sha512-4mWm8DCK2LugIS+p1yArqvG1Pf162upsIsjE7cNBjez+NjliQpVhj20obE520nao0o14DaTnFJv+Fw5a0JpoUw== - dependencies: - "@babel/compat-data" "^7.8.6" - browserslist "^4.9.1" - invariant "^2.2.4" - levenary "^1.1.1" - semver "^5.5.0" - -"@babel/helper-create-class-features-plugin@^7.8.3": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.9.5.tgz#79753d44017806b481017f24b02fd4113c7106ea" - integrity sha512-IipaxGaQmW4TfWoXdqjY0TzoXQ1HRS0kPpEgvjosb3u7Uedcq297xFqDQiCcQtRRwzIMif+N1MLVI8C5a4/PAA== - dependencies: - "@babel/helper-function-name" "^7.9.5" - "@babel/helper-member-expression-to-functions" "^7.8.3" - "@babel/helper-optimise-call-expression" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-replace-supers" "^7.8.6" - "@babel/helper-split-export-declaration" "^7.8.3" - -"@babel/helper-create-regexp-features-plugin@^7.8.3", "@babel/helper-create-regexp-features-plugin@^7.8.8": - version "7.8.8" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.8.tgz#5d84180b588f560b7864efaeea89243e58312087" - integrity sha512-LYVPdwkrQEiX9+1R29Ld/wTrmQu1SSKYnuOk3g0CkcZMA1p0gsNxJFj/3gBdaJ7Cg0Fnek5z0DsMULePP7Lrqg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.8.3" - "@babel/helper-regex" "^7.8.3" - regexpu-core "^4.7.0" - -"@babel/helper-define-map@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.8.3.tgz#a0655cad5451c3760b726eba875f1cd8faa02c15" - integrity sha512-PoeBYtxoZGtct3md6xZOCWPcKuMuk3IHhgxsRRNtnNShebf4C8YonTSblsK4tvDbm+eJAw2HAPOfCr+Q/YRG/g== - dependencies: - "@babel/helper-function-name" "^7.8.3" - "@babel/types" "^7.8.3" - lodash "^4.17.13" - -"@babel/helper-explode-assignable-expression@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.8.3.tgz#a728dc5b4e89e30fc2dfc7d04fa28a930653f982" - integrity sha512-N+8eW86/Kj147bO9G2uclsg5pwfs/fqqY5rwgIL7eTBklgXjcOJ3btzS5iM6AitJcftnY7pm2lGsrJVYLGjzIw== - dependencies: - "@babel/traverse" "^7.8.3" - "@babel/types" "^7.8.3" - -"@babel/helper-function-name@^7.8.3", "@babel/helper-function-name@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz#2b53820d35275120e1874a82e5aabe1376920a5c" - integrity sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw== - dependencies: - "@babel/helper-get-function-arity" "^7.8.3" - "@babel/template" "^7.8.3" - "@babel/types" "^7.9.5" - -"@babel/helper-get-function-arity@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz#b894b947bd004381ce63ea1db9f08547e920abd5" - integrity sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA== - dependencies: - "@babel/types" "^7.8.3" - -"@babel/helper-hoist-variables@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.8.3.tgz#1dbe9b6b55d78c9b4183fc8cdc6e30ceb83b7134" - integrity sha512-ky1JLOjcDUtSc+xkt0xhYff7Z6ILTAHKmZLHPxAhOP0Nd77O+3nCsd6uSVYur6nJnCI029CrNbYlc0LoPfAPQg== - dependencies: - "@babel/types" "^7.8.3" - -"@babel/helper-member-expression-to-functions@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz#659b710498ea6c1d9907e0c73f206eee7dadc24c" - integrity sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA== - dependencies: - "@babel/types" "^7.8.3" - -"@babel/helper-module-imports@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d" - integrity sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A== - dependencies: - "@babel/types" "^7.0.0" - -"@babel/helper-module-imports@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz#7fe39589b39c016331b6b8c3f441e8f0b1419498" - integrity sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg== - dependencies: - "@babel/types" "^7.8.3" - -"@babel/helper-module-transforms@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz#43b34dfe15961918707d247327431388e9fe96e5" - integrity sha512-0FvKyu0gpPfIQ8EkxlrAydOWROdHpBmiCiRwLkUiBGhCUPRRbVD2/tm3sFr/c/GWFrQ/ffutGUAnx7V0FzT2wA== - dependencies: - "@babel/helper-module-imports" "^7.8.3" - "@babel/helper-replace-supers" "^7.8.6" - "@babel/helper-simple-access" "^7.8.3" - "@babel/helper-split-export-declaration" "^7.8.3" - "@babel/template" "^7.8.6" - "@babel/types" "^7.9.0" - lodash "^4.17.13" - -"@babel/helper-optimise-call-expression@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz#7ed071813d09c75298ef4f208956006b6111ecb9" - integrity sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ== - dependencies: - "@babel/types" "^7.8.3" - -"@babel/helper-plugin-utils@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" - integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== - -"@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz#9ea293be19babc0f52ff8ca88b34c3611b208670" - integrity sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ== - -"@babel/helper-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.8.3.tgz#139772607d51b93f23effe72105b319d2a4c6965" - integrity sha512-BWt0QtYv/cg/NecOAZMdcn/waj/5P26DR4mVLXfFtDokSR6fyuG0Pj+e2FqtSME+MqED1khnSMulkmGl8qWiUQ== - dependencies: - lodash "^4.17.13" - -"@babel/helper-remap-async-to-generator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.8.3.tgz#273c600d8b9bf5006142c1e35887d555c12edd86" - integrity sha512-kgwDmw4fCg7AVgS4DukQR/roGp+jP+XluJE5hsRZwxCYGg+Rv9wSGErDWhlI90FODdYfd4xG4AQRiMDjjN0GzA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.8.3" - "@babel/helper-wrap-function" "^7.8.3" - "@babel/template" "^7.8.3" - "@babel/traverse" "^7.8.3" - "@babel/types" "^7.8.3" - -"@babel/helper-replace-supers@^7.8.3", "@babel/helper-replace-supers@^7.8.6": - version "7.8.6" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz#5ada744fd5ad73203bf1d67459a27dcba67effc8" - integrity sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.8.3" - "@babel/helper-optimise-call-expression" "^7.8.3" - "@babel/traverse" "^7.8.6" - "@babel/types" "^7.8.6" - -"@babel/helper-simple-access@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz#7f8109928b4dab4654076986af575231deb639ae" - integrity sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw== - dependencies: - "@babel/template" "^7.8.3" - "@babel/types" "^7.8.3" - -"@babel/helper-split-export-declaration@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz#31a9f30070f91368a7182cf05f831781065fc7a9" - integrity sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA== - dependencies: - "@babel/types" "^7.8.3" - -"@babel/helper-validator-identifier@^7.9.0", "@babel/helper-validator-identifier@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz#90977a8e6fbf6b431a7dc31752eee233bf052d80" - integrity sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g== - -"@babel/helper-wrap-function@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz#9dbdb2bb55ef14aaa01fe8c99b629bd5352d8610" - integrity sha512-LACJrbUET9cQDzb6kG7EeD7+7doC3JNvUgTEQOx2qaO1fKlzE/Bf05qs9w1oXQMmXlPO65lC3Tq9S6gZpTErEQ== - dependencies: - "@babel/helper-function-name" "^7.8.3" - "@babel/template" "^7.8.3" - "@babel/traverse" "^7.8.3" - "@babel/types" "^7.8.3" - -"@babel/helpers@^7.9.0": - version "7.9.2" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.9.2.tgz#b42a81a811f1e7313b88cba8adc66b3d9ae6c09f" - integrity sha512-JwLvzlXVPjO8eU9c/wF9/zOIN7X6h8DYf7mG4CiFRZRvZNKEF5dQ3H3V+ASkHoIB3mWhatgl5ONhyqHRI6MppA== - dependencies: - "@babel/template" "^7.8.3" - "@babel/traverse" "^7.9.0" - "@babel/types" "^7.9.0" - -"@babel/highlight@^7.0.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" - integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ== - dependencies: - chalk "^2.0.0" - esutils "^2.0.2" - js-tokens "^4.0.0" - -"@babel/highlight@^7.8.3": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.9.0.tgz#4e9b45ccb82b79607271b2979ad82c7b68163079" - integrity sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ== - dependencies: - "@babel/helper-validator-identifier" "^7.9.0" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/parser@^7.7.0", "@babel/parser@^7.8.6", "@babel/parser@^7.9.0": - version "7.9.4" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.4.tgz#68a35e6b0319bbc014465be43828300113f2f2e8" - integrity sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA== - -"@babel/plugin-proposal-async-generator-functions@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz#bad329c670b382589721b27540c7d288601c6e6f" - integrity sha512-NZ9zLv848JsV3hs8ryEh7Uaz/0KsmPLqv0+PdkDJL1cJy0K4kOCFa8zc1E3mp+RHPQcpdfb/6GovEsW4VDrOMw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-remap-async-to-generator" "^7.8.3" - "@babel/plugin-syntax-async-generators" "^7.8.0" - -"@babel/plugin-proposal-class-properties@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.8.3.tgz#5e06654af5cd04b608915aada9b2a6788004464e" - integrity sha512-EqFhbo7IosdgPgZggHaNObkmO1kNUe3slaKu54d5OWvy+p9QIKOzK1GAEpAIsZtWVtPXUHSMcT4smvDrCfY4AA== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-proposal-decorators@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.8.3.tgz#2156860ab65c5abf068c3f67042184041066543e" - integrity sha512-e3RvdvS4qPJVTe288DlXjwKflpfy1hr0j5dz5WpIYYeP7vQZg2WfAEIp8k5/Lwis/m5REXEteIz6rrcDtXXG7w== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-decorators" "^7.8.3" - -"@babel/plugin-proposal-dynamic-import@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.8.3.tgz#38c4fe555744826e97e2ae930b0fb4cc07e66054" - integrity sha512-NyaBbyLFXFLT9FP+zk0kYlUlA8XtCUbehs67F0nnEg7KICgMc2mNkIeu9TYhKzyXMkrapZFwAhXLdnt4IYHy1w== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-dynamic-import" "^7.8.0" - -"@babel/plugin-proposal-json-strings@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.8.3.tgz#da5216b238a98b58a1e05d6852104b10f9a70d6b" - integrity sha512-KGhQNZ3TVCQG/MjRbAUwuH+14y9q0tpxs1nWWs3pbSleRdDro9SAMMDyye8HhY1gqZ7/NqIc8SKhya0wRDgP1Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-json-strings" "^7.8.0" - -"@babel/plugin-proposal-nullish-coalescing-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz#e4572253fdeed65cddeecfdab3f928afeb2fd5d2" - integrity sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" - -"@babel/plugin-proposal-numeric-separator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.8.3.tgz#5d6769409699ec9b3b68684cd8116cedff93bad8" - integrity sha512-jWioO1s6R/R+wEHizfaScNsAx+xKgwTLNXSh7tTC4Usj3ItsPEhYkEpU4h+lpnBwq7NBVOJXfO6cRFYcX69JUQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.8.3" - -"@babel/plugin-proposal-object-rest-spread@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.5.tgz#3fd65911306d8746014ec0d0cf78f0e39a149116" - integrity sha512-VP2oXvAf7KCYTthbUHwBlewbl1Iq059f6seJGsxMizaCdgHIeczOr7FBqELhSqfkIl04Fi8okzWzl63UKbQmmg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-transform-parameters" "^7.9.5" - -"@babel/plugin-proposal-optional-catch-binding@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.8.3.tgz#9dee96ab1650eed88646ae9734ca167ac4a9c5c9" - integrity sha512-0gkX7J7E+AtAw9fcwlVQj8peP61qhdg/89D5swOkjYbkboA2CVckn3kiyum1DE0wskGb7KJJxBdyEBApDLLVdw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" - -"@babel/plugin-proposal-optional-chaining@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.9.0.tgz#31db16b154c39d6b8a645292472b98394c292a58" - integrity sha512-NDn5tu3tcv4W30jNhmc2hyD5c56G6cXx4TesJubhxrJeCvuuMpttxr0OnNCqbZGhFjLrg+NIhxxC+BK5F6yS3w== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-optional-chaining" "^7.8.0" - -"@babel/plugin-proposal-unicode-property-regex@^7.4.4", "@babel/plugin-proposal-unicode-property-regex@^7.8.3": - version "7.8.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.8.tgz#ee3a95e90cdc04fe8cd92ec3279fa017d68a0d1d" - integrity sha512-EVhjVsMpbhLw9ZfHWSx2iy13Q8Z/eg8e8ccVWt23sWQK5l1UdkoLJPN5w69UA4uITGBnEZD2JOe4QOHycYKv8A== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.8" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-syntax-async-generators@^7.8.0": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" - integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-decorators@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.8.3.tgz#8d2c15a9f1af624b0025f961682a9d53d3001bda" - integrity sha512-8Hg4dNNT9/LcA1zQlfwuKR8BUc/if7Q7NkTam9sGTcJphLwpf2g4S42uhspQrIrR+dpzE0dtTqBVFoHl8GtnnQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-syntax-dynamic-import@^7.8.0", "@babel/plugin-syntax-dynamic-import@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" - integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-json-strings@^7.8.0": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" - integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-jsx@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.2.0.tgz#0b85a3b4bc7cdf4cc4b8bf236335b907ca22e7c7" - integrity sha512-VyN4QANJkRW6lDBmENzRszvZf3/4AXaj9YR7GwrWeeN9tEBPuXbmDYVU9bYBN0D70zCWVwUy0HWq2553VCb6Hw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-syntax-jsx@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.8.3.tgz#521b06c83c40480f1e58b4fd33b92eceb1d6ea94" - integrity sha512-WxdW9xyLgBdefoo0Ynn3MRSkhe5tFVxxKNVdnZSh318WrG2e2jH+E9wd/++JsqcLJZPfz87njQJ8j2Upjm0M0A== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" - integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-numeric-separator@^7.8.0", "@babel/plugin-syntax-numeric-separator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.8.3.tgz#0e3fb63e09bea1b11e96467271c8308007e7c41f" - integrity sha512-H7dCMAdN83PcCmqmkHB5dtp+Xa9a6LKSvA2hiFBC/5alSHxM5VgWZXFqDi0YFe8XNGT6iCa+z4V4zSt/PdZ7Dw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-syntax-object-rest-spread@^7.8.0": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" - integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-catch-binding@^7.8.0": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" - integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-chaining@^7.8.0": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" - integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-top-level-await@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.8.3.tgz#3acdece695e6b13aaf57fc291d1a800950c71391" - integrity sha512-kwj1j9lL/6Wd0hROD3b/OZZ7MSrZLqqn9RAZ5+cYYsflQ9HZBIKCUkr3+uL1MEJ1NePiUbf98jjiMQSv0NMR9g== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-arrow-functions@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz#82776c2ed0cd9e1a49956daeb896024c9473b8b6" - integrity sha512-0MRF+KC8EqH4dbuITCWwPSzsyO3HIWWlm30v8BbbpOrS1B++isGxPnnuq/IZvOX5J2D/p7DQalQm+/2PnlKGxg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-async-to-generator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.8.3.tgz#4308fad0d9409d71eafb9b1a6ee35f9d64b64086" - integrity sha512-imt9tFLD9ogt56Dd5CI/6XgpukMwd/fLGSrix2httihVe7LOGVPhyhMh1BU5kDM7iHD08i8uUtmV2sWaBFlHVQ== - dependencies: - "@babel/helper-module-imports" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-remap-async-to-generator" "^7.8.3" - -"@babel/plugin-transform-block-scoped-functions@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.8.3.tgz#437eec5b799b5852072084b3ae5ef66e8349e8a3" - integrity sha512-vo4F2OewqjbB1+yaJ7k2EJFHlTP3jR634Z9Cj9itpqNjuLXvhlVxgnjsHsdRgASR8xYDrx6onw4vW5H6We0Jmg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-block-scoping@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.8.3.tgz#97d35dab66857a437c166358b91d09050c868f3a" - integrity sha512-pGnYfm7RNRgYRi7bids5bHluENHqJhrV4bCZRwc5GamaWIIs07N4rZECcmJL6ZClwjDz1GbdMZFtPs27hTB06w== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - lodash "^4.17.13" - -"@babel/plugin-transform-classes@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.9.5.tgz#800597ddb8aefc2c293ed27459c1fcc935a26c2c" - integrity sha512-x2kZoIuLC//O5iA7PEvecB105o7TLzZo8ofBVhP79N+DO3jaX+KYfww9TQcfBEZD0nikNyYcGB1IKtRq36rdmg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.8.3" - "@babel/helper-define-map" "^7.8.3" - "@babel/helper-function-name" "^7.9.5" - "@babel/helper-optimise-call-expression" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-replace-supers" "^7.8.6" - "@babel/helper-split-export-declaration" "^7.8.3" - globals "^11.1.0" - -"@babel/plugin-transform-computed-properties@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.8.3.tgz#96d0d28b7f7ce4eb5b120bb2e0e943343c86f81b" - integrity sha512-O5hiIpSyOGdrQZRQ2ccwtTVkgUDBBiCuK//4RJ6UfePllUTCENOzKxfh6ulckXKc0DixTFLCfb2HVkNA7aDpzA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-destructuring@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.9.5.tgz#72c97cf5f38604aea3abf3b935b0e17b1db76a50" - integrity sha512-j3OEsGel8nHL/iusv/mRd5fYZ3DrOxWC82x0ogmdN/vHfAP4MYw+AFKYanzWlktNwikKvlzUV//afBW5FTp17Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-dotall-regex@^7.4.4", "@babel/plugin-transform-dotall-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.8.3.tgz#c3c6ec5ee6125c6993c5cbca20dc8621a9ea7a6e" - integrity sha512-kLs1j9Nn4MQoBYdRXH6AeaXMbEJFaFu/v1nQkvib6QzTj8MZI5OQzqmD83/2jEM1z0DLilra5aWO5YpyC0ALIw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-duplicate-keys@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.8.3.tgz#8d12df309aa537f272899c565ea1768e286e21f1" - integrity sha512-s8dHiBUbcbSgipS4SMFuWGqCvyge5V2ZeAWzR6INTVC3Ltjig/Vw1G2Gztv0vU/hRG9X8IvKvYdoksnUfgXOEQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-exponentiation-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.8.3.tgz#581a6d7f56970e06bf51560cd64f5e947b70d7b7" - integrity sha512-zwIpuIymb3ACcInbksHaNcR12S++0MDLKkiqXHl3AzpgdKlFNhog+z/K0+TGW+b0w5pgTq4H6IwV/WhxbGYSjQ== - dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-for-of@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.9.0.tgz#0f260e27d3e29cd1bb3128da5e76c761aa6c108e" - integrity sha512-lTAnWOpMwOXpyDx06N+ywmF3jNbafZEqZ96CGYabxHrxNX8l5ny7dt4bK/rGwAh9utyP2b2Hv7PlZh1AAS54FQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-function-name@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.8.3.tgz#279373cb27322aaad67c2683e776dfc47196ed8b" - integrity sha512-rO/OnDS78Eifbjn5Py9v8y0aR+aSYhDhqAwVfsTl0ERuMZyr05L1aFSCJnbv2mmsLkit/4ReeQ9N2BgLnOcPCQ== - dependencies: - "@babel/helper-function-name" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-literals@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.8.3.tgz#aef239823d91994ec7b68e55193525d76dbd5dc1" - integrity sha512-3Tqf8JJ/qB7TeldGl+TT55+uQei9JfYaregDcEAyBZ7akutriFrt6C/wLYIer6OYhleVQvH/ntEhjE/xMmy10A== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-member-expression-literals@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.8.3.tgz#963fed4b620ac7cbf6029c755424029fa3a40410" - integrity sha512-3Wk2EXhnw+rP+IDkK6BdtPKsUE5IeZ6QOGrPYvw52NwBStw9V1ZVzxgK6fSKSxqUvH9eQPR3tm3cOq79HlsKYA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-modules-amd@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.9.0.tgz#19755ee721912cf5bb04c07d50280af3484efef4" - integrity sha512-vZgDDF003B14O8zJy0XXLnPH4sg+9X5hFBBGN1V+B2rgrB+J2xIypSN6Rk9imB2hSTHQi5OHLrFWsZab1GMk+Q== - dependencies: - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helper-plugin-utils" "^7.8.3" - babel-plugin-dynamic-import-node "^2.3.0" - -"@babel/plugin-transform-modules-commonjs@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.0.tgz#e3e72f4cbc9b4a260e30be0ea59bdf5a39748940" - integrity sha512-qzlCrLnKqio4SlgJ6FMMLBe4bySNis8DFn1VkGmOcxG9gqEyPIOzeQrA//u0HAKrWpJlpZbZMPB1n/OPa4+n8g== - dependencies: - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-simple-access" "^7.8.3" - babel-plugin-dynamic-import-node "^2.3.0" - -"@babel/plugin-transform-modules-systemjs@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.9.0.tgz#e9fd46a296fc91e009b64e07ddaa86d6f0edeb90" - integrity sha512-FsiAv/nao/ud2ZWy4wFacoLOm5uxl0ExSQ7ErvP7jpoihLR6Cq90ilOFyX9UXct3rbtKsAiZ9kFt5XGfPe/5SQ== - dependencies: - "@babel/helper-hoist-variables" "^7.8.3" - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helper-plugin-utils" "^7.8.3" - babel-plugin-dynamic-import-node "^2.3.0" - -"@babel/plugin-transform-modules-umd@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.9.0.tgz#e909acae276fec280f9b821a5f38e1f08b480697" - integrity sha512-uTWkXkIVtg/JGRSIABdBoMsoIeoHQHPTL0Y2E7xf5Oj7sLqwVsNXOkNk0VJc7vF0IMBsPeikHxFjGe+qmwPtTQ== - dependencies: - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-named-capturing-groups-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.8.3.tgz#a2a72bffa202ac0e2d0506afd0939c5ecbc48c6c" - integrity sha512-f+tF/8UVPU86TrCb06JoPWIdDpTNSGGcAtaD9mLP0aYGA0OS0j7j7DHJR0GTFrUZPUU6loZhbsVZgTh0N+Qdnw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.3" - -"@babel/plugin-transform-new-target@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.8.3.tgz#60cc2ae66d85c95ab540eb34babb6434d4c70c43" - integrity sha512-QuSGysibQpyxexRyui2vca+Cmbljo8bcRckgzYV4kRIsHpVeyeC3JDO63pY+xFZ6bWOBn7pfKZTqV4o/ix9sFw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-object-super@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.8.3.tgz#ebb6a1e7a86ffa96858bd6ac0102d65944261725" - integrity sha512-57FXk+gItG/GejofIyLIgBKTas4+pEU47IXKDBWFTxdPd7F80H8zybyAY7UoblVfBhBGs2EKM+bJUu2+iUYPDQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-replace-supers" "^7.8.3" - -"@babel/plugin-transform-parameters@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.9.5.tgz#173b265746f5e15b2afe527eeda65b73623a0795" - integrity sha512-0+1FhHnMfj6lIIhVvS4KGQJeuhe1GI//h5uptK4PvLt+BGBxsoUJbd3/IW002yk//6sZPlFgsG1hY6OHLcy6kA== - dependencies: - "@babel/helper-get-function-arity" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-property-literals@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.8.3.tgz#33194300d8539c1ed28c62ad5087ba3807b98263" - integrity sha512-uGiiXAZMqEoQhRWMK17VospMZh5sXWg+dlh2soffpkAl96KAm+WZuJfa6lcELotSRmooLqg0MWdH6UUq85nmmg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-regenerator@^7.8.7": - version "7.8.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.7.tgz#5e46a0dca2bee1ad8285eb0527e6abc9c37672f8" - integrity sha512-TIg+gAl4Z0a3WmD3mbYSk+J9ZUH6n/Yc57rtKRnlA/7rcCvpekHXe0CMZHP1gYp7/KLe9GHTuIba0vXmls6drA== - dependencies: - regenerator-transform "^0.14.2" - -"@babel/plugin-transform-reserved-words@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.8.3.tgz#9a0635ac4e665d29b162837dd3cc50745dfdf1f5" - integrity sha512-mwMxcycN3omKFDjDQUl+8zyMsBfjRFr0Zn/64I41pmjv4NJuqcYlEtezwYtw9TFd9WR1vN5kiM+O0gMZzO6L0A== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-runtime@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.9.0.tgz#45468c0ae74cc13204e1d3b1f4ce6ee83258af0b" - integrity sha512-pUu9VSf3kI1OqbWINQ7MaugnitRss1z533436waNXp+0N3ur3zfut37sXiQMxkuCF4VUjwZucen/quskCh7NHw== - dependencies: - "@babel/helper-module-imports" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - resolve "^1.8.1" - semver "^5.5.1" - -"@babel/plugin-transform-shorthand-properties@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz#28545216e023a832d4d3a1185ed492bcfeac08c8" - integrity sha512-I9DI6Odg0JJwxCHzbzW08ggMdCezoWcuQRz3ptdudgwaHxTjxw5HgdFJmZIkIMlRymL6YiZcped4TTCB0JcC8w== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-spread@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.8.3.tgz#9c8ffe8170fdfb88b114ecb920b82fb6e95fe5e8" - integrity sha512-CkuTU9mbmAoFOI1tklFWYYbzX5qCIZVXPVy0jpXgGwkplCndQAa58s2jr66fTeQnA64bDox0HL4U56CFYoyC7g== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-sticky-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.8.3.tgz#be7a1290f81dae767475452199e1f76d6175b100" - integrity sha512-9Spq0vGCD5Bb4Z/ZXXSK5wbbLFMG085qd2vhL1JYu1WcQ5bXqZBAYRzU1d+p79GcHs2szYv5pVQCX13QgldaWw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-regex" "^7.8.3" - -"@babel/plugin-transform-template-literals@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.8.3.tgz#7bfa4732b455ea6a43130adc0ba767ec0e402a80" - integrity sha512-820QBtykIQOLFT8NZOcTRJ1UNuztIELe4p9DCgvj4NK+PwluSJ49we7s9FB1HIGNIYT7wFUJ0ar2QpCDj0escQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-typeof-symbol@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.4.tgz#ede4062315ce0aaf8a657a920858f1a2f35fc412" - integrity sha512-2QKyfjGdvuNfHsb7qnBBlKclbD4CfshH2KvDabiijLMGXPHJXGxtDzwIF7bQP+T0ysw8fYTtxPafgfs/c1Lrqg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-unicode-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz#0cef36e3ba73e5c57273effb182f46b91a1ecaad" - integrity sha512-+ufgJjYdmWfSQ+6NS9VGUR2ns8cjJjYbrbi11mZBTaWm+Fui/ncTLFF28Ei1okavY+xkojGr1eJxNsWYeA5aZw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/preset-env@^7.9.0": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.9.5.tgz#8ddc76039bc45b774b19e2fc548f6807d8a8919f" - integrity sha512-eWGYeADTlPJH+wq1F0wNfPbVS1w1wtmMJiYk55Td5Yu28AsdR9AsC97sZ0Qq8fHqQuslVSIYSGJMcblr345GfQ== - dependencies: - "@babel/compat-data" "^7.9.0" - "@babel/helper-compilation-targets" "^7.8.7" - "@babel/helper-module-imports" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-proposal-async-generator-functions" "^7.8.3" - "@babel/plugin-proposal-dynamic-import" "^7.8.3" - "@babel/plugin-proposal-json-strings" "^7.8.3" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-proposal-numeric-separator" "^7.8.3" - "@babel/plugin-proposal-object-rest-spread" "^7.9.5" - "@babel/plugin-proposal-optional-catch-binding" "^7.8.3" - "@babel/plugin-proposal-optional-chaining" "^7.9.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.8.3" - "@babel/plugin-syntax-async-generators" "^7.8.0" - "@babel/plugin-syntax-dynamic-import" "^7.8.0" - "@babel/plugin-syntax-json-strings" "^7.8.0" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" - "@babel/plugin-syntax-numeric-separator" "^7.8.0" - "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" - "@babel/plugin-syntax-optional-chaining" "^7.8.0" - "@babel/plugin-syntax-top-level-await" "^7.8.3" - "@babel/plugin-transform-arrow-functions" "^7.8.3" - "@babel/plugin-transform-async-to-generator" "^7.8.3" - "@babel/plugin-transform-block-scoped-functions" "^7.8.3" - "@babel/plugin-transform-block-scoping" "^7.8.3" - "@babel/plugin-transform-classes" "^7.9.5" - "@babel/plugin-transform-computed-properties" "^7.8.3" - "@babel/plugin-transform-destructuring" "^7.9.5" - "@babel/plugin-transform-dotall-regex" "^7.8.3" - "@babel/plugin-transform-duplicate-keys" "^7.8.3" - "@babel/plugin-transform-exponentiation-operator" "^7.8.3" - "@babel/plugin-transform-for-of" "^7.9.0" - "@babel/plugin-transform-function-name" "^7.8.3" - "@babel/plugin-transform-literals" "^7.8.3" - "@babel/plugin-transform-member-expression-literals" "^7.8.3" - "@babel/plugin-transform-modules-amd" "^7.9.0" - "@babel/plugin-transform-modules-commonjs" "^7.9.0" - "@babel/plugin-transform-modules-systemjs" "^7.9.0" - "@babel/plugin-transform-modules-umd" "^7.9.0" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.8.3" - "@babel/plugin-transform-new-target" "^7.8.3" - "@babel/plugin-transform-object-super" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.9.5" - "@babel/plugin-transform-property-literals" "^7.8.3" - "@babel/plugin-transform-regenerator" "^7.8.7" - "@babel/plugin-transform-reserved-words" "^7.8.3" - "@babel/plugin-transform-shorthand-properties" "^7.8.3" - "@babel/plugin-transform-spread" "^7.8.3" - "@babel/plugin-transform-sticky-regex" "^7.8.3" - "@babel/plugin-transform-template-literals" "^7.8.3" - "@babel/plugin-transform-typeof-symbol" "^7.8.4" - "@babel/plugin-transform-unicode-regex" "^7.8.3" - "@babel/preset-modules" "^0.1.3" - "@babel/types" "^7.9.5" - browserslist "^4.9.1" - core-js-compat "^3.6.2" - invariant "^2.2.2" - levenary "^1.1.1" - semver "^5.5.0" - -"@babel/preset-modules@^0.1.3": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.3.tgz#13242b53b5ef8c883c3cf7dddd55b36ce80fbc72" - integrity sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" - "@babel/plugin-transform-dotall-regex" "^7.4.4" - "@babel/types" "^7.4.4" - esutils "^2.0.2" - -"@babel/runtime@^7.3.4", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": - version "7.9.2" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.2.tgz#d90df0583a3a252f09aaa619665367bae518db06" - integrity sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/template@^7.8.3", "@babel/template@^7.8.6": - version "7.8.6" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b" - integrity sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg== - dependencies: - "@babel/code-frame" "^7.8.3" - "@babel/parser" "^7.8.6" - "@babel/types" "^7.8.6" - -"@babel/traverse@^7.7.0", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.6", "@babel/traverse@^7.9.0": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.5.tgz#6e7c56b44e2ac7011a948c21e283ddd9d9db97a2" - integrity sha512-c4gH3jsvSuGUezlP6rzSJ6jf8fYjLj3hsMZRx/nX0h+fmHN0w+ekubRrHPqnMec0meycA2nwCsJ7dC8IPem2FQ== - dependencies: - "@babel/code-frame" "^7.8.3" - "@babel/generator" "^7.9.5" - "@babel/helper-function-name" "^7.9.5" - "@babel/helper-split-export-declaration" "^7.8.3" - "@babel/parser" "^7.9.0" - "@babel/types" "^7.9.5" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.13" - -"@babel/types@^7.0.0", "@babel/types@^7.4.4": - version "7.6.3" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.6.3.tgz#3f07d96f854f98e2fbd45c64b0cb942d11e8ba09" - integrity sha512-CqbcpTxMcpuQTMhjI37ZHVgjBkysg5icREQIEZ0eG1yCNwg3oy+5AaLiOKmjsCj6nqOsa6Hf0ObjRVwokb7srA== - dependencies: - esutils "^2.0.2" - lodash "^4.17.13" - to-fast-properties "^2.0.0" - -"@babel/types@^7.7.0", "@babel/types@^7.8.3", "@babel/types@^7.8.6", "@babel/types@^7.9.0", "@babel/types@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.5.tgz#89231f82915a8a566a703b3b20133f73da6b9444" - integrity sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg== - dependencies: - "@babel/helper-validator-identifier" "^7.9.5" - lodash "^4.17.13" - to-fast-properties "^2.0.0" - -"@hapi/address@2.x.x": - version "2.1.4" - resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.1.4.tgz#5d67ed43f3fd41a69d4b9ff7b56e7c0d1d0a81e5" - integrity sha512-QD1PhQk+s31P1ixsX0H0Suoupp3VMXzIVMSwobR3F3MSUO2YCV0B7xqLcUw/Bh8yuvd3LhpyqLQWTNcRmp6IdQ== - -"@hapi/bourne@1.x.x": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@hapi/bourne/-/bourne-1.3.2.tgz#0a7095adea067243ce3283e1b56b8a8f453b242a" - integrity sha512-1dVNHT76Uu5N3eJNTYcvxee+jzX4Z9lfciqRRHCU27ihbUcYi+iSc2iml5Ke1LXe1SyJCLA0+14Jh4tXJgOppA== - -"@hapi/hoek@8.x.x", "@hapi/hoek@^8.3.0": - version "8.5.1" - resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-8.5.1.tgz#fde96064ca446dec8c55a8c2f130957b070c6e06" - integrity sha512-yN7kbciD87WzLGc5539Tn0sApjyiGHAJgKvG9W8C7O+6c7qmoQMfVs0W4bX17eqz6C78QJqqFrtgdK5EWf6Qow== - -"@hapi/joi@^15.0.0": - version "15.1.1" - resolved "https://registry.yarnpkg.com/@hapi/joi/-/joi-15.1.1.tgz#c675b8a71296f02833f8d6d243b34c57b8ce19d7" - integrity sha512-entf8ZMOK8sc+8YfeOlM8pCfg3b5+WZIKBfUaaJT8UsjAAPjartzxIYm3TIbjvA4u+u++KbcXD38k682nVHDAQ== - dependencies: - "@hapi/address" "2.x.x" - "@hapi/bourne" "1.x.x" - "@hapi/hoek" "8.x.x" - "@hapi/topo" "3.x.x" - -"@hapi/topo@3.x.x": - version "3.1.6" - resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-3.1.6.tgz#68d935fa3eae7fdd5ab0d7f953f3205d8b2bfc29" - integrity sha512-tAag0jEcjwH+P2quUfipd7liWCNX2F8NvYjQp2wtInsZxnMlypdw0FtAOLxtvvkO+GSRRbmNi8m/5y42PQJYCQ== - dependencies: - "@hapi/hoek" "^8.3.0" - -"@mrmlnc/readdir-enhanced@^2.2.1": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" - integrity sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g== - dependencies: - call-me-maybe "^1.0.1" - glob-to-regexp "^0.3.0" - -"@nodelib/fs.stat@^1.1.2": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" - integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== - -"@shigma/stringify-object@^3.3.0": - version "3.3.0" - resolved "https://registry.yarnpkg.com/@shigma/stringify-object/-/stringify-object-3.3.0.tgz#c6611dcdf650024a9f6397580f821accd3021be3" - integrity sha512-tO5pn6RJp8m1ldYtqY3GEQA6+Nqp1cIZVrVx7iFVPx0YfhMqfplwrvyrQPP1cCwuyRoAyDr/BxVZYt+USm8LXQ== - dependencies: - get-own-enumerable-property-symbols "^3.0.0" - is-obj "^1.0.1" - is-regexp "^2.0.0" - -"@sindresorhus/is@^0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" - integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== - -"@szmarczak/http-timer@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" - integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== - dependencies: - defer-to-connect "^1.0.1" - -"@types/color-name@^1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" - integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== - -"@types/events@*": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" - integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g== - -"@types/glob@^7.1.1": - version "7.1.1" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575" - integrity sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w== - dependencies: - "@types/events" "*" - "@types/minimatch" "*" - "@types/node" "*" - -"@types/minimatch@*": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" - integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== - -"@types/node@*": - version "12.11.1" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.1.tgz#1fd7b821f798b7fa29f667a1be8f3442bb8922a3" - integrity sha512-TJtwsqZ39pqcljJpajeoofYRfeZ7/I/OMUQ5pR4q5wOKf2ocrUvBAZUMhWsOvKx3dVc/aaV5GluBivt0sWqA5A== - -"@types/q@^1.5.1": - version "1.5.2" - resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" - integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== - -"@vue/babel-helper-vue-jsx-merge-props@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.0.0.tgz#048fe579958da408fb7a8b2a3ec050b50a661040" - integrity sha512-6tyf5Cqm4m6v7buITuwS+jHzPlIPxbFzEhXR5JGZpbrvOcp1hiQKckd305/3C7C36wFekNTQSxAtgeM0j0yoUw== - -"@vue/babel-plugin-transform-vue-jsx@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@vue/babel-plugin-transform-vue-jsx/-/babel-plugin-transform-vue-jsx-1.1.2.tgz#c0a3e6efc022e75e4247b448a8fc6b86f03e91c0" - integrity sha512-YfdaoSMvD1nj7+DsrwfTvTnhDXI7bsuh+Y5qWwvQXlD24uLgnsoww3qbiZvWf/EoviZMrvqkqN4CBw0W3BWUTQ== - dependencies: - "@babel/helper-module-imports" "^7.0.0" - "@babel/plugin-syntax-jsx" "^7.2.0" - "@vue/babel-helper-vue-jsx-merge-props" "^1.0.0" - html-tags "^2.0.0" - lodash.kebabcase "^4.1.1" - svg-tags "^1.0.0" - -"@vue/babel-preset-app@^4.1.2": - version "4.3.1" - resolved "https://registry.yarnpkg.com/@vue/babel-preset-app/-/babel-preset-app-4.3.1.tgz#bb67aae562983067c5b242c27fb7de17f40cf109" - integrity sha512-iNkySkbRWXGUA+Cvzj+/gEP0Y0uVAwwzfn21S7hkggSeIg9LJyZ+QzdxgKO0wgi01yTdb2mYWgeLQAfHZ65aew== - dependencies: - "@babel/core" "^7.9.0" - "@babel/helper-compilation-targets" "^7.8.7" - "@babel/helper-module-imports" "^7.8.3" - "@babel/plugin-proposal-class-properties" "^7.8.3" - "@babel/plugin-proposal-decorators" "^7.8.3" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - "@babel/plugin-syntax-jsx" "^7.8.3" - "@babel/plugin-transform-runtime" "^7.9.0" - "@babel/preset-env" "^7.9.0" - "@babel/runtime" "^7.9.2" - "@vue/babel-preset-jsx" "^1.1.2" - babel-plugin-dynamic-import-node "^2.3.0" - core-js "^3.6.4" - core-js-compat "^3.6.4" - -"@vue/babel-preset-jsx@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@vue/babel-preset-jsx/-/babel-preset-jsx-1.1.2.tgz#2e169eb4c204ea37ca66c2ea85a880bfc99d4f20" - integrity sha512-zDpVnFpeC9YXmvGIDSsKNdL7qCG2rA3gjywLYHPCKDT10erjxF4U+6ay9X6TW5fl4GsDlJp9bVfAVQAAVzxxvQ== - dependencies: - "@vue/babel-helper-vue-jsx-merge-props" "^1.0.0" - "@vue/babel-plugin-transform-vue-jsx" "^1.1.2" - "@vue/babel-sugar-functional-vue" "^1.1.2" - "@vue/babel-sugar-inject-h" "^1.1.2" - "@vue/babel-sugar-v-model" "^1.1.2" - "@vue/babel-sugar-v-on" "^1.1.2" - -"@vue/babel-sugar-functional-vue@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@vue/babel-sugar-functional-vue/-/babel-sugar-functional-vue-1.1.2.tgz#f7e24fba09e6f1ee70104560a8808057555f1a9a" - integrity sha512-YhmdJQSVEFF5ETJXzrMpj0nkCXEa39TvVxJTuVjzvP2rgKhdMmQzlJuMv/HpadhZaRVMCCF3AEjjJcK5q/cYzQ== - dependencies: - "@babel/plugin-syntax-jsx" "^7.2.0" - -"@vue/babel-sugar-inject-h@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@vue/babel-sugar-inject-h/-/babel-sugar-inject-h-1.1.2.tgz#8a5276b6d8e2ed16ffc8078aad94236274e6edf0" - integrity sha512-VRSENdTvD5htpnVp7i7DNuChR5rVMcORdXjvv5HVvpdKHzDZAYiLSD+GhnhxLm3/dMuk8pSzV+k28ECkiN5m8w== - dependencies: - "@babel/plugin-syntax-jsx" "^7.2.0" - -"@vue/babel-sugar-v-model@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@vue/babel-sugar-v-model/-/babel-sugar-v-model-1.1.2.tgz#1ff6fd1b800223fc9cb1e84dceb5e52d737a8192" - integrity sha512-vLXPvNq8vDtt0u9LqFdpGM9W9IWDmCmCyJXuozlq4F4UYVleXJ2Fa+3JsnTZNJcG+pLjjfnEGHci2339Kj5sGg== - dependencies: - "@babel/plugin-syntax-jsx" "^7.2.0" - "@vue/babel-helper-vue-jsx-merge-props" "^1.0.0" - "@vue/babel-plugin-transform-vue-jsx" "^1.1.2" - camelcase "^5.0.0" - html-tags "^2.0.0" - svg-tags "^1.0.0" - -"@vue/babel-sugar-v-on@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@vue/babel-sugar-v-on/-/babel-sugar-v-on-1.1.2.tgz#b2ef99b8f2fab09fbead25aad70ef42e1cf5b13b" - integrity sha512-T8ZCwC8Jp2uRtcZ88YwZtZXe7eQrJcfRq0uTFy6ShbwYJyz5qWskRFoVsdTi9o0WEhmQXxhQUewodOSCUPVmsQ== - dependencies: - "@babel/plugin-syntax-jsx" "^7.2.0" - "@vue/babel-plugin-transform-vue-jsx" "^1.1.2" - camelcase "^5.0.0" - -"@vue/component-compiler-utils@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-3.0.0.tgz#d16fa26b836c06df5baaeb45f3d80afc47e35634" - integrity sha512-am+04/0UX7ektcmvhYmrf84BDVAD8afFOf4asZjN84q8xzxFclbk5x0MtxuKGfp+zjN5WWPJn3fjFAWtDdIGSw== - dependencies: - consolidate "^0.15.1" - hash-sum "^1.0.2" - lru-cache "^4.1.2" - merge-source-map "^1.1.0" - postcss "^7.0.14" - postcss-selector-parser "^5.0.0" - prettier "1.16.3" - source-map "~0.6.1" - vue-template-es2015-compiler "^1.9.0" - -"@vuepress/core@1.4.1": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@vuepress/core/-/core-1.4.1.tgz#b6f75720d9b7132b90cce46f620bcdda5d07e581" - integrity sha512-R1oJeSiDQPw8sVo70mrP1Zn2H0nCqnAHb6DV9mpJBQ6ur4VT6qQnCpd2onKU+bZRLlEhm4G8IQNDEV+DuE7zZQ== - dependencies: - "@babel/core" "^7.8.4" - "@vue/babel-preset-app" "^4.1.2" - "@vuepress/markdown" "1.4.1" - "@vuepress/markdown-loader" "1.4.1" - "@vuepress/plugin-last-updated" "1.4.1" - "@vuepress/plugin-register-components" "1.4.1" - "@vuepress/shared-utils" "1.4.1" - autoprefixer "^9.5.1" - babel-loader "^8.0.4" - cache-loader "^3.0.0" - chokidar "^2.0.3" - connect-history-api-fallback "^1.5.0" - copy-webpack-plugin "^5.0.2" - core-js "^3.6.4" - cross-spawn "^6.0.5" - css-loader "^2.1.1" - file-loader "^3.0.1" - js-yaml "^3.13.1" - lru-cache "^5.1.1" - mini-css-extract-plugin "0.6.0" - optimize-css-assets-webpack-plugin "^5.0.1" - portfinder "^1.0.13" - postcss-loader "^3.0.0" - postcss-safe-parser "^4.0.1" - toml "^3.0.0" - url-loader "^1.0.1" - vue "^2.6.10" - vue-loader "^15.7.1" - vue-router "^3.1.3" - vue-server-renderer "^2.6.10" - vue-template-compiler "^2.6.10" - vuepress-html-webpack-plugin "^3.2.0" - vuepress-plugin-container "^2.0.2" - webpack "^4.8.1" - webpack-chain "^6.0.0" - webpack-dev-server "^3.5.1" - webpack-merge "^4.1.2" - webpackbar "3.2.0" - -"@vuepress/markdown-loader@1.4.1": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@vuepress/markdown-loader/-/markdown-loader-1.4.1.tgz#7a97772ed5238c68eb1ab2921fc5ced21ff7e18e" - integrity sha512-FGtZ15rRwo9iVMcJ0eX4tf1bxWSKKpC4NGNLJuYzaPlO9ND/U04jsj4Xj454piokr2JzBSmaJlIZTAG1EuiTNw== - dependencies: - "@vuepress/markdown" "1.4.1" - loader-utils "^1.1.0" - lru-cache "^5.1.1" - -"@vuepress/markdown@1.4.1": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@vuepress/markdown/-/markdown-1.4.1.tgz#cc507ce4a3447dfc459082105cb83909db4b54f1" - integrity sha512-5a69ufnu1A3NXqQtzAE5LiR7EbtsQ1qe8UcIr+KizNO4gCg8+E8/uu3hxvDOLs2ElS6b0AihKIuwmeIgZkfeKA== - dependencies: - "@vuepress/shared-utils" "1.4.1" - markdown-it "^8.4.1" - markdown-it-anchor "^5.0.2" - markdown-it-chain "^1.3.0" - markdown-it-emoji "^1.4.0" - markdown-it-table-of-contents "^0.4.0" - prismjs "^1.13.0" - -"@vuepress/plugin-active-header-links@1.4.1": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@vuepress/plugin-active-header-links/-/plugin-active-header-links-1.4.1.tgz#36c6952230f12056d18c63229e0e499c6ef74fe5" - integrity sha512-xv/qDY6S8rHzLGDHtwn3XV7Gi3Fnevp6d3H18PFK3sNwT2KGzKIe2c7lbn1qHDRUWcxY7+EoT7zmdJwIeG6dWQ== - dependencies: - lodash.debounce "^4.0.8" - -"@vuepress/plugin-back-to-top@^1.4.1": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@vuepress/plugin-back-to-top/-/plugin-back-to-top-1.4.1.tgz#80b310be5f8ebc13504904e9bafda1c8f0984d52" - integrity sha512-EOpBordx0xD4E8e6lSywi0JHF0IQL0T3Wxbt03W5ngKa2LDKMAusmIRpLDALZ1vHN9Z2ZqYFEWePxrX4rmC9mQ== - dependencies: - lodash.debounce "^4.0.8" - -"@vuepress/plugin-last-updated@1.4.1": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@vuepress/plugin-last-updated/-/plugin-last-updated-1.4.1.tgz#89a9a4cbc242f9e0c5d380f73edb85ac4a7186c6" - integrity sha512-67ouc9cB3C19zcDqeJwhwqO9CXjy8G67tcXUgPpL/GsuK11oQbnR4rkupILvNa9HoemtCcF2aaxXSGsi/1VEtA== - dependencies: - cross-spawn "^6.0.5" - -"@vuepress/plugin-nprogress@1.4.1": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@vuepress/plugin-nprogress/-/plugin-nprogress-1.4.1.tgz#2a16217091102a2b4fddc1b09f5854ac4f80f992" - integrity sha512-CIhIuIgKtvk/ULENjefkZAJQqUstdZcqiM/Gs8CDyTKJITpwyqoZcgolFZ+1ZofUQuHuqDj1hKKm3AQ1cG3cBA== - dependencies: - nprogress "^0.2.0" - -"@vuepress/plugin-pwa@^1.4.1": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@vuepress/plugin-pwa/-/plugin-pwa-1.4.1.tgz#febe16bcdc3543d5118aab3a90110b54e651ac40" - integrity sha512-oWlBuC9cquuuuCUBGVbZQFJARq3mVUnuFtD4Wkwjm937kTwC+GbxfS7tSVAMgjdDM2JiyB6HSVKwqFmtwHipaA== - dependencies: - "@vuepress/shared-utils" "1.4.1" - register-service-worker "^1.7.0" - workbox-build "^4.3.1" - -"@vuepress/plugin-register-components@1.4.1": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@vuepress/plugin-register-components/-/plugin-register-components-1.4.1.tgz#25d70834006960f54475da97255ebaca66ecc5a6" - integrity sha512-6yI4J/tMhOASSLmlP+5p4ccljlWuNBRsyYSKiD5jWAV181oMmN32LtuoCggXBhSvQUgn2grxyjmYw+tcSV5KGQ== - dependencies: - "@vuepress/shared-utils" "1.4.1" - -"@vuepress/plugin-search@1.4.1": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@vuepress/plugin-search/-/plugin-search-1.4.1.tgz#5842f7ef0214c8f9f3cafa6ca2f4648f8dbc03d2" - integrity sha512-J4JyXD6M1oOU013s4ZLKMkKEGd7qEtSIsAw2nZY2mckZ7ETX49R5Pv2S5uCqLRQfUQSIGR5TEABL22q0B8uCVA== - -"@vuepress/shared-utils@1.4.1": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@vuepress/shared-utils/-/shared-utils-1.4.1.tgz#d09fcd742111f2efeef93b9c9b353bcd8202ae97" - integrity sha512-FBUHFhvR7vk6glQy/qUntBz8bVeWiNYZ2/G16EKaerKKn15xAiD7tUFCQ3L/KjtQJ8TV38GK47UEXh7UTcRwQg== - dependencies: - chalk "^2.3.2" - diacritics "^1.3.0" - escape-html "^1.0.3" - fs-extra "^7.0.1" - globby "^9.2.0" - gray-matter "^4.0.1" - hash-sum "^1.0.2" - semver "^6.0.0" - upath "^1.1.0" - -"@vuepress/shared-utils@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@vuepress/shared-utils/-/shared-utils-1.2.0.tgz#8d9ab40c24f75f027ef32c2ad0169f0f08e949fa" - integrity sha512-wo5Ng2/xzsmIYCzvWxgLFlDBp7FkmJp2shAkbSurLNAh1vixhs0+LyDxsk01+m34ktJSp9rTUUsm6khw/Fvo0w== - dependencies: - chalk "^2.3.2" - diacritics "^1.3.0" - escape-html "^1.0.3" - fs-extra "^7.0.1" - globby "^9.2.0" - gray-matter "^4.0.1" - hash-sum "^1.0.2" - semver "^6.0.0" - upath "^1.1.0" - -"@vuepress/theme-default@1.4.1": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@vuepress/theme-default/-/theme-default-1.4.1.tgz#8a0ddc51bee6f3c3b93fae059cac76fe63c51db3" - integrity sha512-QhU1ORj20xmGr9Gk5szWJyzHm8i+NqxotBTeOF4WsKewB/3SPamJUoipgX4VdChw9jVew1oJQw0TpyDZfiHx+A== - dependencies: - "@vuepress/plugin-active-header-links" "1.4.1" - "@vuepress/plugin-nprogress" "1.4.1" - "@vuepress/plugin-search" "1.4.1" - docsearch.js "^2.5.2" - lodash "^4.17.15" - stylus "^0.54.5" - stylus-loader "^3.0.2" - vuepress-plugin-container "^2.0.2" - vuepress-plugin-smooth-scroll "^0.0.3" - -"@webassemblyjs/ast@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359" - integrity sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ== - dependencies: - "@webassemblyjs/helper-module-context" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/wast-parser" "1.8.5" - -"@webassemblyjs/floating-point-hex-parser@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz#1ba926a2923613edce496fd5b02e8ce8a5f49721" - integrity sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ== - -"@webassemblyjs/helper-api-error@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz#c49dad22f645227c5edb610bdb9697f1aab721f7" - integrity sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA== - -"@webassemblyjs/helper-buffer@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz#fea93e429863dd5e4338555f42292385a653f204" - integrity sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q== - -"@webassemblyjs/helper-code-frame@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz#9a740ff48e3faa3022b1dff54423df9aa293c25e" - integrity sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ== - dependencies: - "@webassemblyjs/wast-printer" "1.8.5" - -"@webassemblyjs/helper-fsm@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz#ba0b7d3b3f7e4733da6059c9332275d860702452" - integrity sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow== - -"@webassemblyjs/helper-module-context@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz#def4b9927b0101dc8cbbd8d1edb5b7b9c82eb245" - integrity sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g== - dependencies: - "@webassemblyjs/ast" "1.8.5" - mamacro "^0.0.3" - -"@webassemblyjs/helper-wasm-bytecode@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz#537a750eddf5c1e932f3744206551c91c1b93e61" - integrity sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ== - -"@webassemblyjs/helper-wasm-section@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz#74ca6a6bcbe19e50a3b6b462847e69503e6bfcbf" - integrity sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-buffer" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/wasm-gen" "1.8.5" - -"@webassemblyjs/ieee754@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz#712329dbef240f36bf57bd2f7b8fb9bf4154421e" - integrity sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g== - dependencies: - "@xtuc/ieee754" "^1.2.0" - -"@webassemblyjs/leb128@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.8.5.tgz#044edeb34ea679f3e04cd4fd9824d5e35767ae10" - integrity sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A== - dependencies: - "@xtuc/long" "4.2.2" - -"@webassemblyjs/utf8@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.8.5.tgz#a8bf3b5d8ffe986c7c1e373ccbdc2a0915f0cedc" - integrity sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw== - -"@webassemblyjs/wasm-edit@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz#962da12aa5acc1c131c81c4232991c82ce56e01a" - integrity sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-buffer" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/helper-wasm-section" "1.8.5" - "@webassemblyjs/wasm-gen" "1.8.5" - "@webassemblyjs/wasm-opt" "1.8.5" - "@webassemblyjs/wasm-parser" "1.8.5" - "@webassemblyjs/wast-printer" "1.8.5" - -"@webassemblyjs/wasm-gen@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz#54840766c2c1002eb64ed1abe720aded714f98bc" - integrity sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/ieee754" "1.8.5" - "@webassemblyjs/leb128" "1.8.5" - "@webassemblyjs/utf8" "1.8.5" - -"@webassemblyjs/wasm-opt@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz#b24d9f6ba50394af1349f510afa8ffcb8a63d264" - integrity sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-buffer" "1.8.5" - "@webassemblyjs/wasm-gen" "1.8.5" - "@webassemblyjs/wasm-parser" "1.8.5" - -"@webassemblyjs/wasm-parser@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz#21576f0ec88b91427357b8536383668ef7c66b8d" - integrity sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-api-error" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/ieee754" "1.8.5" - "@webassemblyjs/leb128" "1.8.5" - "@webassemblyjs/utf8" "1.8.5" - -"@webassemblyjs/wast-parser@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz#e10eecd542d0e7bd394f6827c49f3df6d4eefb8c" - integrity sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/floating-point-hex-parser" "1.8.5" - "@webassemblyjs/helper-api-error" "1.8.5" - "@webassemblyjs/helper-code-frame" "1.8.5" - "@webassemblyjs/helper-fsm" "1.8.5" - "@xtuc/long" "4.2.2" - -"@webassemblyjs/wast-printer@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz#114bbc481fd10ca0e23b3560fa812748b0bae5bc" - integrity sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/wast-parser" "1.8.5" - "@xtuc/long" "4.2.2" - -"@xtuc/ieee754@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" - integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== - -"@xtuc/long@4.2.2": - version "4.2.2" - resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" - integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== - -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== - -accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== - dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" - -acorn-jsx@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.2.0.tgz#4c66069173d6fdd68ed85239fc256226182b2ebe" - integrity sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ== - -acorn@^6.2.1: - version "6.3.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.3.0.tgz#0087509119ffa4fc0a0041d1e93a417e68cb856e" - integrity sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA== - -acorn@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.1.tgz#e35668de0b402f359de515c5482a1ab9f89a69bf" - integrity sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg== - -agentkeepalive@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-2.2.0.tgz#c5d1bd4b129008f1163f236f86e5faea2026e2ef" - integrity sha1-xdG9SxKQCPEWPyNvhuX66iAm4u8= - -ajv-errors@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" - integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== - -ajv-keywords@^3.1.0, ajv-keywords@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da" - integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ== - -ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.5: - version "6.10.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" - integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw== - dependencies: - fast-deep-equal "^2.0.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -algoliasearch@^3.24.5: - version "3.35.1" - resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-3.35.1.tgz#297d15f534a3507cab2f5dfb996019cac7568f0c" - integrity sha512-K4yKVhaHkXfJ/xcUnil04xiSrB8B8yHZoFEhWNpXg23eiCnqvTZw1tn/SqvdsANlYHLJlKl0qi3I/Q2Sqo7LwQ== - dependencies: - agentkeepalive "^2.2.0" - debug "^2.6.9" - envify "^4.0.0" - es6-promise "^4.1.0" - events "^1.1.0" - foreach "^2.0.5" - global "^4.3.2" - inherits "^2.0.1" - isarray "^2.0.1" - load-script "^1.0.0" - object-keys "^1.0.11" - querystring-es3 "^0.2.1" - reduce "^1.0.1" - semver "^5.1.0" - tunnel-agent "^0.6.0" - -alphanum-sort@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" - integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= - -ansi-align@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.0.tgz#b536b371cf687caaef236c18d3e21fe3797467cb" - integrity sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw== - dependencies: - string-width "^3.0.0" - -ansi-colors@^3.0.0: - version "3.2.4" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" - integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA== - -ansi-escapes@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.2.1.tgz#4dccdb846c3eee10f6d64dea66273eab90c37228" - integrity sha512-Cg3ymMAdN10wOk/VYfLV7KCQyv7EDirJ64500sU7n9UlmioEtDuU5Gd+hj73hXSU/ex7tHJSssmyftDdkMLO8Q== - dependencies: - type-fest "^0.5.2" - -ansi-escapes@^4.2.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.1.tgz#a5c47cc43181f1f38ffd7076837700d395522a61" - integrity sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA== - dependencies: - type-fest "^0.11.0" - -ansi-html@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e" - integrity sha1-gTWEAhliqenm/QOflA0S9WynhZ4= - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= - -ansi-regex@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" - integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== - -ansi-regex@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" - integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== - -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= - -ansi-styles@^3.2.0, ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" - integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== - dependencies: - "@types/color-name" "^1.1.1" - color-convert "^2.0.1" - -anymatch@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" - integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== - dependencies: - micromatch "^3.1.4" - normalize-path "^2.1.1" - -aproba@^1.0.3, aproba@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== - -are-we-there-yet@~1.1.2: - version "1.1.5" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -arr-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= - -arr-flatten@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== - -arr-union@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= - -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= - -array-flatten@^2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" - integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== - -array-union@^1.0.1, array-union@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= - dependencies: - array-uniq "^1.0.1" - -array-uniq@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= - -array-unique@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= - -asn1.js@^4.0.0: - version "4.10.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" - integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== - dependencies: - bn.js "^4.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - -asn1@~0.2.3: - version "0.2.4" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" - integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== - dependencies: - safer-buffer "~2.1.0" - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= - -assert@^1.1.1: - version "1.5.0" - resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" - integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== - dependencies: - object-assign "^4.1.1" - util "0.10.3" - -assign-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= - -astral-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" - integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== - -async-each@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" - integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== - -async-limiter@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" - integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== - -async@^2.6.2: - version "2.6.3" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" - integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== - dependencies: - lodash "^4.17.14" - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= - -atob@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" - integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== - -autocomplete.js@0.36.0: - version "0.36.0" - resolved "https://registry.yarnpkg.com/autocomplete.js/-/autocomplete.js-0.36.0.tgz#94fe775fe64b6cd42e622d076dc7fd26bedd837b" - integrity sha512-jEwUXnVMeCHHutUt10i/8ZiRaCb0Wo+ZyKxeGsYwBDtw6EJHqEeDrq4UwZRD8YBSvp3g6klP678il2eeiVXN2Q== - dependencies: - immediate "^3.2.3" - -autoprefixer@^9.5.1: - version "9.6.5" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.6.5.tgz#98f4afe7e93cccf323287515d426019619775e5e" - integrity sha512-rGd50YV8LgwFQ2WQp4XzOTG69u1qQsXn0amww7tjqV5jJuNazgFKYEVItEBngyyvVITKOg20zr2V+9VsrXJQ2g== - dependencies: - browserslist "^4.7.0" - caniuse-lite "^1.0.30000999" - chalk "^2.4.2" - normalize-range "^0.1.2" - num2fraction "^1.2.2" - postcss "^7.0.18" - postcss-value-parser "^4.0.2" - -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= - -aws4@^1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" - integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== - -babel-eslint@^10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" - integrity sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.7.0" - "@babel/traverse" "^7.7.0" - "@babel/types" "^7.7.0" - eslint-visitor-keys "^1.0.0" - resolve "^1.12.0" - -babel-extract-comments@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/babel-extract-comments/-/babel-extract-comments-1.0.0.tgz#0a2aedf81417ed391b85e18b4614e693a0351a21" - integrity sha512-qWWzi4TlddohA91bFwgt6zO/J0X+io7Qp184Fw0m2JYRSTZnJbFR8+07KmzudHCZgOiKRCrjhylwv9Xd8gfhVQ== - dependencies: - babylon "^6.18.0" - -babel-loader@^8.0.4: - version "8.0.6" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.0.6.tgz#e33bdb6f362b03f4bb141a0c21ab87c501b70dfb" - integrity sha512-4BmWKtBOBm13uoUwd08UwjZlaw3O9GWf456R9j+5YykFZ6LUIjIKLc0zEZf+hauxPOJs96C8k6FvYD09vWzhYw== - dependencies: - find-cache-dir "^2.0.0" - loader-utils "^1.0.2" - mkdirp "^0.5.1" - pify "^4.0.1" - -babel-plugin-dynamic-import-node@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f" - integrity sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ== - dependencies: - object.assign "^4.1.0" - -babel-plugin-syntax-object-rest-spread@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" - integrity sha1-/WU28rzhODb/o6VFjEkDpZe7O/U= - -babel-plugin-transform-object-rest-spread@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06" - integrity sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY= - dependencies: - babel-plugin-syntax-object-rest-spread "^6.8.0" - babel-runtime "^6.26.0" - -babel-runtime@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.11.0" - -babylon@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" - integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= - -base64-js@^1.0.2: - version "1.3.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" - integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== - -base@^0.11.1: - version "0.11.2" - resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== - dependencies: - cache-base "^1.0.1" - class-utils "^0.3.5" - component-emitter "^1.2.1" - define-property "^1.0.0" - isobject "^3.0.1" - mixin-deep "^1.2.0" - pascalcase "^0.1.1" - -batch@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" - integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY= - -bcrypt-pbkdf@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= - dependencies: - tweetnacl "^0.14.3" - -big.js@^3.1.3: - version "3.2.0" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" - integrity sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q== - -big.js@^5.2.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" - integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== - -binary-extensions@^1.0.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" - integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== - -bluebird@^3.1.1, bluebird@^3.5.5: - version "3.7.1" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.1.tgz#df70e302b471d7473489acf26a93d63b53f874de" - integrity sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg== - -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: - version "4.11.9" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828" - integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw== - -body-parser@1.19.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" - integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== - dependencies: - bytes "3.1.0" - content-type "~1.0.4" - debug "2.6.9" - depd "~1.1.2" - http-errors "1.7.2" - iconv-lite "0.4.24" - on-finished "~2.3.0" - qs "6.7.0" - raw-body "2.4.0" - type-is "~1.6.17" - -bonjour@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5" - integrity sha1-jokKGD2O6aI5OzhExpGkK897yfU= - dependencies: - array-flatten "^2.1.0" - deep-equal "^1.0.1" - dns-equal "^1.0.0" - dns-txt "^2.0.2" - multicast-dns "^6.0.1" - multicast-dns-service-types "^1.1.0" - -boolbase@^1.0.0, boolbase@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" - integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= - -boxen@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/boxen/-/boxen-4.2.0.tgz#e411b62357d6d6d36587c8ac3d5d974daa070e64" - integrity sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ== - dependencies: - ansi-align "^3.0.0" - camelcase "^5.3.1" - chalk "^3.0.0" - cli-boxes "^2.2.0" - string-width "^4.1.0" - term-size "^2.1.0" - type-fest "^0.8.1" - widest-line "^3.1.0" - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^2.3.1, braces@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== - dependencies: - arr-flatten "^1.1.0" - array-unique "^0.3.2" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.1" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^3.0.2" - to-regex "^3.0.1" - -brorand@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= - -browserify-aes@^1.0.0, browserify-aes@^1.0.4: - version "1.2.0" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" - integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== - dependencies: - buffer-xor "^1.0.3" - cipher-base "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.3" - inherits "^2.0.1" - safe-buffer "^5.0.1" - -browserify-cipher@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" - integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== - dependencies: - browserify-aes "^1.0.4" - browserify-des "^1.0.0" - evp_bytestokey "^1.0.0" - -browserify-des@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" - integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== - dependencies: - cipher-base "^1.0.1" - des.js "^1.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -browserify-rsa@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" - integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= - dependencies: - bn.js "^4.1.0" - randombytes "^2.0.1" - -browserify-sign@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" - integrity sha1-qk62jl17ZYuqa/alfmMMvXqT0pg= - dependencies: - bn.js "^4.1.1" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.2" - elliptic "^6.0.0" - inherits "^2.0.1" - parse-asn1 "^5.0.0" - -browserify-zlib@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" - integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== - dependencies: - pako "~1.0.5" - -browserslist@^4.0.0, browserslist@^4.7.0: - version "4.7.1" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.7.1.tgz#bd400d1aea56538580e8c4d5f1c54ac11b5ab468" - integrity sha512-QtULFqKIAtiyNx7NhZ/p4rB8m3xDozVo/pi5VgTlADLF2tNigz/QH+v0m5qhn7XfHT7u+607NcCNOnC0HZAlMg== - dependencies: - caniuse-lite "^1.0.30000999" - electron-to-chromium "^1.3.284" - node-releases "^1.1.36" - -browserslist@^4.8.5, browserslist@^4.9.1: - version "4.12.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.12.0.tgz#06c6d5715a1ede6c51fc39ff67fd647f740b656d" - integrity sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg== - dependencies: - caniuse-lite "^1.0.30001043" - electron-to-chromium "^1.3.413" - node-releases "^1.1.53" - pkg-up "^2.0.0" - -buffer-from@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" - integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== - -buffer-indexof@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" - integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g== - -buffer-json@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/buffer-json/-/buffer-json-2.0.0.tgz#f73e13b1e42f196fe2fd67d001c7d7107edd7c23" - integrity sha512-+jjPFVqyfF1esi9fvfUs3NqM0pH1ziZ36VP4hmA/y/Ssfo/5w5xHKfTw9BwQjoJ1w/oVtpLomqwUHKdefGyuHw== - -buffer-xor@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= - -buffer@^4.3.0: - version "4.9.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" - integrity sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg= - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - isarray "^1.0.0" - -builtin-status-codes@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" - integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= - -bytes@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" - integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= - -bytes@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" - integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== - -cac@^6.5.6: - version "6.5.8" - resolved "https://registry.yarnpkg.com/cac/-/cac-6.5.8.tgz#b15d183ee478226f846888be74612ac080533667" - integrity sha512-jLv2+ps4T2HRVR1k4UlQZoAFvliAhf5LVR0yjPjIaIr/Cw99p/I7CXIEkXtw5q+AkYk4NCFJcF5ErmELSyrZnw== - -cacache@^11.3.3: - version "11.3.3" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.3.3.tgz#8bd29df8c6a718a6ebd2d010da4d7972ae3bbadc" - integrity sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA== - dependencies: - bluebird "^3.5.5" - chownr "^1.1.1" - figgy-pudding "^3.5.1" - glob "^7.1.4" - graceful-fs "^4.1.15" - lru-cache "^5.1.1" - mississippi "^3.0.0" - mkdirp "^0.5.1" - move-concurrently "^1.0.1" - promise-inflight "^1.0.1" - rimraf "^2.6.3" - ssri "^6.0.1" - unique-filename "^1.1.1" - y18n "^4.0.0" - -cacache@^12.0.2: - version "12.0.3" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.3.tgz#be99abba4e1bf5df461cd5a2c1071fc432573390" - integrity sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw== - dependencies: - bluebird "^3.5.5" - chownr "^1.1.1" - figgy-pudding "^3.5.1" - glob "^7.1.4" - graceful-fs "^4.1.15" - infer-owner "^1.0.3" - lru-cache "^5.1.1" - mississippi "^3.0.0" - mkdirp "^0.5.1" - move-concurrently "^1.0.1" - promise-inflight "^1.0.1" - rimraf "^2.6.3" - ssri "^6.0.1" - unique-filename "^1.1.1" - y18n "^4.0.0" - -cache-base@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== - dependencies: - collection-visit "^1.0.0" - component-emitter "^1.2.1" - get-value "^2.0.6" - has-value "^1.0.0" - isobject "^3.0.1" - set-value "^2.0.0" - to-object-path "^0.3.0" - union-value "^1.0.0" - unset-value "^1.0.0" - -cache-loader@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/cache-loader/-/cache-loader-3.0.1.tgz#cee6cf4b3cdc7c610905b26bad6c2fc439c821af" - integrity sha512-HzJIvGiGqYsFUrMjAJNDbVZoG7qQA+vy9AIoKs7s9DscNfki0I589mf2w6/tW+kkFH3zyiknoWV5Jdynu6b/zw== - dependencies: - buffer-json "^2.0.0" - find-cache-dir "^2.1.0" - loader-utils "^1.2.3" - mkdirp "^0.5.1" - neo-async "^2.6.1" - schema-utils "^1.0.0" - -cacheable-request@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" - integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== - dependencies: - clone-response "^1.0.2" - get-stream "^5.1.0" - http-cache-semantics "^4.0.0" - keyv "^3.0.0" - lowercase-keys "^2.0.0" - normalize-url "^4.1.0" - responselike "^1.0.2" - -call-me-maybe@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" - integrity sha1-JtII6onje1y95gJQoV8DHBak1ms= - -caller-callsite@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" - integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= - dependencies: - callsites "^2.0.0" - -caller-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" - integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= - dependencies: - caller-callsite "^2.0.0" - -callsites@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" - integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -camel-case@3.0.x: - version "3.0.0" - resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73" - integrity sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M= - dependencies: - no-case "^2.2.0" - upper-case "^1.1.1" - -camelcase@^5.0.0, camelcase@^5.2.0, camelcase@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -caniuse-api@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" - integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== - dependencies: - browserslist "^4.0.0" - caniuse-lite "^1.0.0" - lodash.memoize "^4.1.2" - lodash.uniq "^4.5.0" - -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000999: - version "1.0.30001001" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001001.tgz#19dff5b917890786537d684776099d81f019c2fc" - integrity sha512-MsWRX5x8GsZJcvIh1zkTERAcX9cRlT+If1f4xk3B5EAJftiwjab2oBKPbned9IuBiKae5u9PMp7T2xJBDo+9Sw== - -caniuse-lite@^1.0.30001043: - version "1.0.30001048" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001048.tgz#4bb4f1bc2eb304e5e1154da80b93dee3f1cf447e" - integrity sha512-g1iSHKVxornw0K8LG9LLdf+Fxnv7T1Z+mMsf0/YYLclQX4Cd522Ap0Lrw6NFqHgezit78dtyWxzlV2Xfc7vgRg== - -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= - -chalk@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" - integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -chardet@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== - -chokidar@^2.0.2, chokidar@^2.0.3, chokidar@^2.1.8: - version "2.1.8" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" - integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== - dependencies: - anymatch "^2.0.0" - async-each "^1.0.1" - braces "^2.3.2" - glob-parent "^3.1.0" - inherits "^2.0.3" - is-binary-path "^1.0.0" - is-glob "^4.0.0" - normalize-path "^3.0.0" - path-is-absolute "^1.0.0" - readdirp "^2.2.1" - upath "^1.1.1" - optionalDependencies: - fsevents "^1.2.7" - -chownr@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142" - integrity sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw== - -chrome-trace-event@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4" - integrity sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ== - dependencies: - tslib "^1.9.0" - -ci-info@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" - integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A== - -ci-info@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" - integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== - -cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -class-utils@^0.3.5: - version "0.3.6" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== - dependencies: - arr-union "^3.1.0" - define-property "^0.2.5" - isobject "^3.0.0" - static-extend "^0.1.1" - -clean-css@4.2.x: - version "4.2.1" - resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.1.tgz#2d411ef76b8569b6d0c84068dabe85b0aa5e5c17" - integrity sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g== - dependencies: - source-map "~0.6.0" - -cli-boxes@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.0.tgz#538ecae8f9c6ca508e3c3c95b453fe93cb4c168d" - integrity sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w== - -cli-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" - integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== - dependencies: - restore-cursor "^3.1.0" - -cli-width@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" - integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= - -clipboard@^2.0.0: - version "2.0.6" - resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.6.tgz#52921296eec0fdf77ead1749421b21c968647376" - integrity sha512-g5zbiixBRk/wyKakSwCKd7vQXDjFnAMGHoEyBogG/bw9kTD9GvdAvaoRR1ALcEzt3pVKxZR0pViekPMIS0QyGg== - dependencies: - good-listener "^1.2.2" - select "^1.1.2" - tiny-emitter "^2.0.0" - -cliui@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" - integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ== - dependencies: - string-width "^2.1.1" - strip-ansi "^4.0.0" - wrap-ansi "^2.0.0" - -clone-response@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" - integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= - dependencies: - mimic-response "^1.0.0" - -coa@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" - integrity sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA== - dependencies: - "@types/q" "^1.5.1" - chalk "^2.4.1" - q "^1.1.2" - -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= - -collection-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= - dependencies: - map-visit "^1.0.0" - object-visit "^1.0.0" - -color-convert@^1.9.0, color-convert@^1.9.1: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= - -color-name@^1.0.0, color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -color-string@^1.5.2: - version "1.5.3" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc" - integrity sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw== - dependencies: - color-name "^1.0.0" - simple-swizzle "^0.2.2" - -color@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/color/-/color-3.1.2.tgz#68148e7f85d41ad7649c5fa8c8106f098d229e10" - integrity sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg== - dependencies: - color-convert "^1.9.1" - color-string "^1.5.2" - -combined-stream@^1.0.6, combined-stream@~1.0.6: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - -commander@2.17.x: - version "2.17.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" - integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== - -commander@^2.20.0: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - -commander@~2.19.0: - version "2.19.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" - integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== - -common-tags@^1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937" - integrity sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw== - -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= - -component-emitter@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" - integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== - -compressible@~2.0.16: - version "2.0.17" - resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.17.tgz#6e8c108a16ad58384a977f3a482ca20bff2f38c1" - integrity sha512-BGHeLCK1GV7j1bSmQQAi26X+GgWcTjLr/0tzSvMCl3LH1w1IJ4PFSPoV5316b30cneTziC+B1a+3OjoSUcQYmw== - dependencies: - mime-db ">= 1.40.0 < 2" - -compression@^1.7.4: - version "1.7.4" - resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" - integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== - dependencies: - accepts "~1.3.5" - bytes "3.0.0" - compressible "~2.0.16" - debug "2.6.9" - on-headers "~1.0.2" - safe-buffer "5.1.2" - vary "~1.1.2" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -concat-stream@^1.5.0: - version "1.6.2" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== - dependencies: - buffer-from "^1.0.0" - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" - -configstore@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96" - integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA== - dependencies: - dot-prop "^5.2.0" - graceful-fs "^4.1.2" - make-dir "^3.0.0" - unique-string "^2.0.0" - write-file-atomic "^3.0.0" - xdg-basedir "^4.0.0" - -connect-history-api-fallback@^1.5.0, connect-history-api-fallback@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" - integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== - -consola@^2.6.0: - version "2.10.1" - resolved "https://registry.yarnpkg.com/consola/-/consola-2.10.1.tgz#4693edba714677c878d520e4c7e4f69306b4b927" - integrity sha512-4sxpH6SGFYLADfUip4vuY65f/gEogrzJoniVhNUYkJHtng0l8ZjnDCqxxrSVRHOHwKxsy8Vm5ONZh1wOR3/l/w== - -console-browserify@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" - integrity sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA= - dependencies: - date-now "^0.1.4" - -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= - -consolidate@^0.15.1: - version "0.15.1" - resolved "https://registry.yarnpkg.com/consolidate/-/consolidate-0.15.1.tgz#21ab043235c71a07d45d9aad98593b0dba56bab7" - integrity sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw== - dependencies: - bluebird "^3.1.1" - -constants-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" - integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= - -content-disposition@0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" - integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== - dependencies: - safe-buffer "5.1.2" - -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== - -convert-source-map@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" - integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== - dependencies: - safe-buffer "~5.1.1" - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= - -cookie@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" - integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== - -copy-concurrently@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" - integrity sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A== - dependencies: - aproba "^1.1.1" - fs-write-stream-atomic "^1.0.8" - iferr "^0.1.5" - mkdirp "^0.5.1" - rimraf "^2.5.4" - run-queue "^1.0.0" - -copy-descriptor@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= - -copy-webpack-plugin@^5.0.2: - version "5.0.4" - resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-5.0.4.tgz#c78126f604e24f194c6ec2f43a64e232b5d43655" - integrity sha512-YBuYGpSzoCHSSDGyHy6VJ7SHojKp6WHT4D7ItcQFNAYx2hrwkMe56e97xfVR0/ovDuMTrMffXUiltvQljtAGeg== - dependencies: - cacache "^11.3.3" - find-cache-dir "^2.1.0" - glob-parent "^3.1.0" - globby "^7.1.1" - is-glob "^4.0.1" - loader-utils "^1.2.3" - minimatch "^3.0.4" - normalize-path "^3.0.0" - p-limit "^2.2.0" - schema-utils "^1.0.0" - serialize-javascript "^1.7.0" - webpack-log "^2.0.0" - -core-js-compat@^3.6.2, core-js-compat@^3.6.4: - version "3.6.5" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.5.tgz#2a51d9a4e25dfd6e690251aa81f99e3c05481f1c" - integrity sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng== - dependencies: - browserslist "^4.8.5" - semver "7.0.0" - -core-js@^2.4.0: - version "2.6.10" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.10.tgz#8a5b8391f8cc7013da703411ce5b585706300d7f" - integrity sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA== - -core-js@^3.6.4: - version "3.6.5" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a" - integrity sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA== - -core-util-is@1.0.2, core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= - -cosmiconfig@^5.0.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" - integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== - dependencies: - import-fresh "^2.0.0" - is-directory "^0.3.1" - js-yaml "^3.13.1" - parse-json "^4.0.0" - -create-ecdh@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" - integrity sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw== - dependencies: - bn.js "^4.1.0" - elliptic "^6.0.0" - -create-hash@^1.1.0, create-hash@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" - integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== - dependencies: - cipher-base "^1.0.1" - inherits "^2.0.1" - md5.js "^1.3.4" - ripemd160 "^2.0.1" - sha.js "^2.4.0" - -create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: - version "1.1.7" - resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" - integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== - dependencies: - cipher-base "^1.0.3" - create-hash "^1.1.0" - inherits "^2.0.1" - ripemd160 "^2.0.0" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -cross-spawn@^6.0.0, cross-spawn@^6.0.5: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== - dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" - -crypto-browserify@^3.11.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" - integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== - dependencies: - browserify-cipher "^1.0.0" - browserify-sign "^4.0.0" - create-ecdh "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.0" - diffie-hellman "^5.0.0" - inherits "^2.0.1" - pbkdf2 "^3.0.3" - public-encrypt "^4.0.0" - randombytes "^2.0.0" - randomfill "^1.0.3" - -crypto-random-string@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" - integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== - -css-color-names@0.0.4, css-color-names@^0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" - integrity sha1-gIrcLnnPhHOAabZGyyDsJ762KeA= - -css-declaration-sorter@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz#c198940f63a76d7e36c1e71018b001721054cb22" - integrity sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA== - dependencies: - postcss "^7.0.1" - timsort "^0.3.0" - -css-loader@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-2.1.1.tgz#d8254f72e412bb2238bb44dd674ffbef497333ea" - integrity sha512-OcKJU/lt232vl1P9EEDamhoO9iKY3tIjY5GU+XDLblAykTdgs6Ux9P1hTHve8nFKy5KPpOXOsVI/hIwi3841+w== - dependencies: - camelcase "^5.2.0" - icss-utils "^4.1.0" - loader-utils "^1.2.3" - normalize-path "^3.0.0" - postcss "^7.0.14" - postcss-modules-extract-imports "^2.0.0" - postcss-modules-local-by-default "^2.0.6" - postcss-modules-scope "^2.1.0" - postcss-modules-values "^2.0.0" - postcss-value-parser "^3.3.0" - schema-utils "^1.0.0" - -css-parse@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/css-parse/-/css-parse-2.0.0.tgz#a468ee667c16d81ccf05c58c38d2a97c780dbfd4" - integrity sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q= - dependencies: - css "^2.0.0" - -css-select-base-adapter@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" - integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w== - -css-select@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" - integrity sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg= - dependencies: - boolbase "~1.0.0" - css-what "2.1" - domutils "1.5.1" - nth-check "~1.0.1" - -css-select@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.0.2.tgz#ab4386cec9e1f668855564b17c3733b43b2a5ede" - integrity sha512-dSpYaDVoWaELjvZ3mS6IKZM/y2PMPa/XYoEfYNZePL4U/XgyxZNroHEHReDx/d+VgXh9VbCTtFqLkFbmeqeaRQ== - dependencies: - boolbase "^1.0.0" - css-what "^2.1.2" - domutils "^1.7.0" - nth-check "^1.0.2" - -css-tree@1.0.0-alpha.29: - version "1.0.0-alpha.29" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.29.tgz#3fa9d4ef3142cbd1c301e7664c1f352bd82f5a39" - integrity sha512-sRNb1XydwkW9IOci6iB2xmy8IGCj6r/fr+JWitvJ2JxQRPzN3T4AGGVWCMlVmVwM1gtgALJRmGIlWv5ppnGGkg== - dependencies: - mdn-data "~1.1.0" - source-map "^0.5.3" - -css-tree@1.0.0-alpha.33: - version "1.0.0-alpha.33" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.33.tgz#970e20e5a91f7a378ddd0fc58d0b6c8d4f3be93e" - integrity sha512-SPt57bh5nQnpsTBsx/IXbO14sRc9xXu5MtMAVuo0BaQQmyf0NupNPPSoMaqiAF5tDFafYsTkfeH4Q/HCKXkg4w== - dependencies: - mdn-data "2.0.4" - source-map "^0.5.3" - -css-unit-converter@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.1.tgz#d9b9281adcfd8ced935bdbaba83786897f64e996" - integrity sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY= - -css-what@2.1, css-what@^2.1.2: - version "2.1.3" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" - integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== - -css@^2.0.0: - version "2.2.4" - resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929" - integrity sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw== - dependencies: - inherits "^2.0.3" - source-map "^0.6.1" - source-map-resolve "^0.5.2" - urix "^0.1.0" - -cssesc@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703" - integrity sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg== - -cssesc@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" - integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== - -cssnano-preset-default@^4.0.7: - version "4.0.7" - resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz#51ec662ccfca0f88b396dcd9679cdb931be17f76" - integrity sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA== - dependencies: - css-declaration-sorter "^4.0.1" - cssnano-util-raw-cache "^4.0.1" - postcss "^7.0.0" - postcss-calc "^7.0.1" - postcss-colormin "^4.0.3" - postcss-convert-values "^4.0.1" - postcss-discard-comments "^4.0.2" - postcss-discard-duplicates "^4.0.2" - postcss-discard-empty "^4.0.1" - postcss-discard-overridden "^4.0.1" - postcss-merge-longhand "^4.0.11" - postcss-merge-rules "^4.0.3" - postcss-minify-font-values "^4.0.2" - postcss-minify-gradients "^4.0.2" - postcss-minify-params "^4.0.2" - postcss-minify-selectors "^4.0.2" - postcss-normalize-charset "^4.0.1" - postcss-normalize-display-values "^4.0.2" - postcss-normalize-positions "^4.0.2" - postcss-normalize-repeat-style "^4.0.2" - postcss-normalize-string "^4.0.2" - postcss-normalize-timing-functions "^4.0.2" - postcss-normalize-unicode "^4.0.1" - postcss-normalize-url "^4.0.1" - postcss-normalize-whitespace "^4.0.2" - postcss-ordered-values "^4.1.2" - postcss-reduce-initial "^4.0.3" - postcss-reduce-transforms "^4.0.2" - postcss-svgo "^4.0.2" - postcss-unique-selectors "^4.0.1" - -cssnano-util-get-arguments@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz#ed3a08299f21d75741b20f3b81f194ed49cc150f" - integrity sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8= - -cssnano-util-get-match@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz#c0e4ca07f5386bb17ec5e52250b4f5961365156d" - integrity sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0= - -cssnano-util-raw-cache@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz#b26d5fd5f72a11dfe7a7846fb4c67260f96bf282" - integrity sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA== - dependencies: - postcss "^7.0.0" - -cssnano-util-same-parent@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz#574082fb2859d2db433855835d9a8456ea18bbf3" - integrity sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q== - -cssnano@^4.1.10: - version "4.1.10" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-4.1.10.tgz#0ac41f0b13d13d465487e111b778d42da631b8b2" - integrity sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ== - dependencies: - cosmiconfig "^5.0.0" - cssnano-preset-default "^4.0.7" - is-resolvable "^1.0.0" - postcss "^7.0.0" - -csso@^3.5.1: - version "3.5.1" - resolved "https://registry.yarnpkg.com/csso/-/csso-3.5.1.tgz#7b9eb8be61628973c1b261e169d2f024008e758b" - integrity sha512-vrqULLffYU1Q2tLdJvaCYbONStnfkfimRxXNaGjxMldI0C7JPBC4rB1RyjhfdZ4m1frm8pM9uRPKH3d2knZ8gg== - dependencies: - css-tree "1.0.0-alpha.29" - -cyclist@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" - integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= - -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= - dependencies: - assert-plus "^1.0.0" - -date-now@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" - integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs= - -de-indent@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" - integrity sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0= - -debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@^3.1.1, debug@^3.2.5, debug@^3.2.6: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== - dependencies: - ms "^2.1.1" - -debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== - dependencies: - ms "^2.1.1" - -debug@~3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== - dependencies: - ms "2.0.0" - -decamelize@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= - -decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= - -decompress-response@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= - dependencies: - mimic-response "^1.0.0" - -deep-equal@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.0.tgz#3103cdf8ab6d32cf4a8df7865458f2b8d33f3745" - integrity sha512-ZbfWJq/wN1Z273o7mUSjILYqehAktR2NVoSrOukDkU9kg2v/Uv89yU4Cvz8seJeAmtN5oqiefKq8FPuXOboqLw== - dependencies: - is-arguments "^1.0.4" - is-date-object "^1.0.1" - is-regex "^1.0.4" - object-is "^1.0.1" - object-keys "^1.1.1" - regexp.prototype.flags "^1.2.0" - -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - -deep-is@~0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" - integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= - -deepmerge@^1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-1.5.2.tgz#10499d868844cdad4fee0842df8c7f6f0c95a753" - integrity sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ== - -default-gateway@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b" - integrity sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA== - dependencies: - execa "^1.0.0" - ip-regex "^2.1.0" - -defer-to-connect@^1.0.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" - integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== - -define-properties@^1.1.2, define-properties@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== - dependencies: - object-keys "^1.0.12" - -define-property@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= - dependencies: - is-descriptor "^0.1.0" - -define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= - dependencies: - is-descriptor "^1.0.0" - -define-property@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== - dependencies: - is-descriptor "^1.0.2" - isobject "^3.0.1" - -del@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4" - integrity sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ== - dependencies: - "@types/glob" "^7.1.1" - globby "^6.1.0" - is-path-cwd "^2.0.0" - is-path-in-cwd "^2.0.0" - p-map "^2.0.0" - pify "^4.0.1" - rimraf "^2.6.3" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= - -delegate@^3.1.2: - version "3.2.0" - resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166" - integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw== - -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= - -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= - -des.js@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" - integrity sha1-wHTS4qpqipoH29YfmhXCzYPsjsw= - dependencies: - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= - -detect-libc@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= - -detect-node@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c" - integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw== - -diacritics@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/diacritics/-/diacritics-1.3.0.tgz#3efa87323ebb863e6696cebb0082d48ff3d6f7a1" - integrity sha1-PvqHMj67hj5mls67AILUj/PW96E= - -diffie-hellman@^5.0.0: - version "5.0.3" - resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" - integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== - dependencies: - bn.js "^4.1.0" - miller-rabin "^4.0.0" - randombytes "^2.0.0" - -dir-glob@^2.0.0, dir-glob@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4" - integrity sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw== - dependencies: - path-type "^3.0.0" - -dns-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" - integrity sha1-s55/HabrCnW6nBcySzR1PEfgZU0= - -dns-packet@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.1.tgz#12aa426981075be500b910eedcd0b47dd7deda5a" - integrity sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg== - dependencies: - ip "^1.1.0" - safe-buffer "^5.0.1" - -dns-txt@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/dns-txt/-/dns-txt-2.0.2.tgz#b91d806f5d27188e4ab3e7d107d881a1cc4642b6" - integrity sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY= - dependencies: - buffer-indexof "^1.0.0" - -docsearch.js@^2.5.2: - version "2.6.3" - resolved "https://registry.yarnpkg.com/docsearch.js/-/docsearch.js-2.6.3.tgz#57cb4600d3b6553c677e7cbbe6a734593e38625d" - integrity sha512-GN+MBozuyz664ycpZY0ecdQE0ND/LSgJKhTLA0/v3arIS3S1Rpf2OJz6A35ReMsm91V5apcmzr5/kM84cvUg+A== - dependencies: - algoliasearch "^3.24.5" - autocomplete.js "0.36.0" - hogan.js "^3.0.2" - request "^2.87.0" - stack-utils "^1.0.1" - to-factory "^1.0.0" - zepto "^1.2.0" - -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - -dom-converter@^0.2: - version "0.2.0" - resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" - integrity sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA== - dependencies: - utila "~0.4" - -dom-serializer@0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.1.tgz#13650c850daffea35d8b626a4cfc4d3a17643fdb" - integrity sha512-sK3ujri04WyjwQXVoK4PU3y8ula1stq10GJZpqHIUgoGZdsGzAGu65BnU3d08aTVSvO7mGPZUc0wTEDL+qGE0Q== - dependencies: - domelementtype "^2.0.1" - entities "^2.0.0" - -dom-walk@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" - integrity sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg= - -domain-browser@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" - integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== - -domelementtype@1, domelementtype@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" - integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== - -domelementtype@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" - integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ== - -domhandler@^2.3.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" - integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== - dependencies: - domelementtype "1" - -domutils@1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" - integrity sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8= - dependencies: - dom-serializer "0" - domelementtype "1" - -domutils@^1.5.1, domutils@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" - integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== - dependencies: - dom-serializer "0" - domelementtype "1" - -dot-prop@^4.1.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" - integrity sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ== - dependencies: - is-obj "^1.0.0" - -dot-prop@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.2.0.tgz#c34ecc29556dc45f1f4c22697b6f4904e0cc4fcb" - integrity sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A== - dependencies: - is-obj "^2.0.0" - -duplexer3@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" - integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= - -duplexify@^3.4.2, duplexify@^3.6.0: - version "3.7.1" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" - integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== - dependencies: - end-of-stream "^1.0.0" - inherits "^2.0.1" - readable-stream "^2.0.0" - stream-shift "^1.0.0" - -ecc-jsbn@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= - dependencies: - jsbn "~0.1.0" - safer-buffer "^2.1.0" - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= - -electron-to-chromium@^1.3.284: - version "1.3.289" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.289.tgz#1f85add5d7086ce95d9361348c26aa9de5779906" - integrity sha512-39GEOWgTxtMDk/WjIQLg4W/l1s4FZdiMCqUBLjd92tAXsBPDFLwuwCba5OGhuTdVYm6E128TZIqSnMpeocUlCQ== - -electron-to-chromium@^1.3.413: - version "1.3.418" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.418.tgz#840021191f466b803a873e154113620c9f53cec6" - integrity sha512-i2QrQtHes5fK/F9QGG5XacM5WKEuR322fxTYF9e8O9Gu0mc0WmjjwGpV8c7Htso6Zf2Di18lc3SIPxmMeRFBug== - -elliptic@^6.0.0: - version "6.5.3" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.3.tgz#cb59eb2efdaf73a0bd78ccd7015a62ad6e0f93d6" - integrity sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw== - dependencies: - bn.js "^4.4.0" - brorand "^1.0.1" - hash.js "^1.0.0" - hmac-drbg "^1.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.0" - -emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -emojis-list@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" - integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= - -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= - -end-of-stream@^1.0.0, end-of-stream@^1.1.0: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - -enhanced-resolve@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz#2937e2b8066cd0fe7ce0990a98f0d71a35189f66" - integrity sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA== - dependencies: - graceful-fs "^4.1.2" - memory-fs "^0.5.0" - tapable "^1.0.0" - -entities@^1.1.1, entities@~1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" - integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== - -entities@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" - integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== - -envify@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/envify/-/envify-4.1.0.tgz#f39ad3db9d6801b4e6b478b61028d3f0b6819f7e" - integrity sha512-IKRVVoAYr4pIx4yIWNsz9mOsboxlNXiu7TNBnem/K/uTHdkyzXWDzHCK7UTolqBbgaBz0tQHsD3YNls0uIIjiw== - dependencies: - esprima "^4.0.0" - through "~2.3.4" - -envinfo@^7.2.0: - version "7.4.0" - resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.4.0.tgz#bef4ece9e717423aaf0c3584651430b735ad6630" - integrity sha512-FdDfnWnCVjxTTpWE3d6Jgh5JDIA3Cw7LCgpM/pI7kK1ORkjaqI2r6NqQ+ln2j0dfpgxY00AWieSvtkiZQKIItA== - -errno@^0.1.3, errno@~0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" - integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== - dependencies: - prr "~1.0.1" - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -es-abstract@^1.12.0, es-abstract@^1.5.1: - version "1.16.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.0.tgz#d3a26dc9c3283ac9750dca569586e976d9dcc06d" - integrity sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg== - dependencies: - es-to-primitive "^1.2.0" - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.0" - is-callable "^1.1.4" - is-regex "^1.0.4" - object-inspect "^1.6.0" - object-keys "^1.1.1" - string.prototype.trimleft "^2.1.0" - string.prototype.trimright "^2.1.0" - -es-to-primitive@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" - integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -es6-promise@^4.1.0: - version "4.2.8" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" - integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== - -escape-goat@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675" - integrity sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q== - -escape-html@^1.0.3, escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= - -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -eslint-plugin-vue@^6.2.2: - version "6.2.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-6.2.2.tgz#27fecd9a3a24789b0f111ecdd540a9e56198e0fe" - integrity sha512-Nhc+oVAHm0uz/PkJAWscwIT4ijTrK5fqNqz9QB1D35SbbuMG1uB6Yr5AJpvPSWg+WOw7nYNswerYh0kOk64gqQ== - dependencies: - natural-compare "^1.4.0" - semver "^5.6.0" - vue-eslint-parser "^7.0.0" - -eslint-scope@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" - integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== - dependencies: - esrecurse "^4.1.0" - estraverse "^4.1.1" - -eslint-scope@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9" - integrity sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw== - dependencies: - esrecurse "^4.1.0" - estraverse "^4.1.1" - -eslint-utils@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" - integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== - dependencies: - eslint-visitor-keys "^1.1.0" - -eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" - integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== - -eslint@^6.8.0: - version "6.8.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb" - integrity sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig== - dependencies: - "@babel/code-frame" "^7.0.0" - ajv "^6.10.0" - chalk "^2.1.0" - cross-spawn "^6.0.5" - debug "^4.0.1" - doctrine "^3.0.0" - eslint-scope "^5.0.0" - eslint-utils "^1.4.3" - eslint-visitor-keys "^1.1.0" - espree "^6.1.2" - esquery "^1.0.1" - esutils "^2.0.2" - file-entry-cache "^5.0.1" - functional-red-black-tree "^1.0.1" - glob-parent "^5.0.0" - globals "^12.1.0" - ignore "^4.0.6" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - inquirer "^7.0.0" - is-glob "^4.0.0" - js-yaml "^3.13.1" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.3.0" - lodash "^4.17.14" - minimatch "^3.0.4" - mkdirp "^0.5.1" - natural-compare "^1.4.0" - optionator "^0.8.3" - progress "^2.0.0" - regexpp "^2.0.1" - semver "^6.1.2" - strip-ansi "^5.2.0" - strip-json-comments "^3.0.1" - table "^5.2.3" - text-table "^0.2.0" - v8-compile-cache "^2.0.3" - -espree@^6.1.2: - version "6.2.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-6.2.1.tgz#77fc72e1fd744a2052c20f38a5b575832e82734a" - integrity sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw== - dependencies: - acorn "^7.1.1" - acorn-jsx "^5.2.0" - eslint-visitor-keys "^1.1.0" - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -esquery@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" - integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== - dependencies: - estraverse "^4.0.0" - -esrecurse@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" - integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== - dependencies: - estraverse "^4.1.0" - -estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= - -eventemitter3@^4.0.0: - version "4.0.7" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" - integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== - -events@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" - integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ= - -events@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88" - integrity sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA== - -eventsource@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-1.0.7.tgz#8fbc72c93fcd34088090bc0a4e64f4b5cee6d8d0" - integrity sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ== - dependencies: - original "^1.0.0" - -evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== - dependencies: - md5.js "^1.3.4" - safe-buffer "^5.1.1" - -execa@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" - integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== - dependencies: - cross-spawn "^6.0.0" - get-stream "^4.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - -expand-brackets@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= - dependencies: - debug "^2.3.3" - define-property "^0.2.5" - extend-shallow "^2.0.1" - posix-character-classes "^0.1.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -express@^4.16.4, express@^4.17.1: - version "4.17.1" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" - integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== - dependencies: - accepts "~1.3.7" - array-flatten "1.1.1" - body-parser "1.19.0" - content-disposition "0.5.3" - content-type "~1.0.4" - cookie "0.4.0" - cookie-signature "1.0.6" - debug "2.6.9" - depd "~1.1.2" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "~1.1.2" - fresh "0.5.2" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "~2.3.0" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.5" - qs "6.7.0" - range-parser "~1.2.1" - safe-buffer "5.1.2" - send "0.17.1" - serve-static "1.14.1" - setprototypeof "1.1.1" - statuses "~1.5.0" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= - dependencies: - is-extendable "^0.1.0" - -extend-shallow@^3.0.0, extend-shallow@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= - dependencies: - assign-symbols "^1.0.0" - is-extendable "^1.0.1" - -extend@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -external-editor@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" - integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== - dependencies: - chardet "^0.7.0" - iconv-lite "^0.4.24" - tmp "^0.0.33" - -extglob@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== - dependencies: - array-unique "^0.3.2" - define-property "^1.0.0" - expand-brackets "^2.1.4" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= - -extsprintf@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= - -fast-deep-equal@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" - integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= - -fast-glob@^2.2.6: - version "2.2.7" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d" - integrity sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw== - dependencies: - "@mrmlnc/readdir-enhanced" "^2.2.1" - "@nodelib/fs.stat" "^1.1.2" - glob-parent "^3.1.0" - is-glob "^4.0.0" - merge2 "^1.2.3" - micromatch "^3.1.10" - -fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= - -fast-levenshtein@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= - -faye-websocket@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4" - integrity sha1-TkkvjQTftviQA1B/btvy1QHnxvQ= - dependencies: - websocket-driver ">=0.5.1" - -faye-websocket@~0.11.1: - version "0.11.3" - resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.3.tgz#5c0e9a8968e8912c286639fde977a8b209f2508e" - integrity sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA== - dependencies: - websocket-driver ">=0.5.1" - -figgy-pudding@^3.5.1: - version "3.5.1" - resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" - integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w== - -figures@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-3.0.0.tgz#756275c964646163cc6f9197c7a0295dbfd04de9" - integrity sha512-HKri+WoWoUgr83pehn/SIgLOMZ9nAWC6dcGj26RY2R4F50u4+RTUz0RCrUlOV3nKRAICW1UGzyb+kcX2qK1S/g== - dependencies: - escape-string-regexp "^1.0.5" - -file-entry-cache@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" - integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== - dependencies: - flat-cache "^2.0.1" - -file-loader@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-3.0.1.tgz#f8e0ba0b599918b51adfe45d66d1e771ad560faa" - integrity sha512-4sNIOXgtH/9WZq4NvlfU3Opn5ynUsqBwSLyM+I7UOwdGigTBYfVVQEwe/msZNX/j4pCJTIM14Fsw66Svo1oVrw== - dependencies: - loader-utils "^1.0.2" - schema-utils "^1.0.0" - -fill-range@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= - dependencies: - extend-shallow "^2.0.1" - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range "^2.1.0" - -finalhandler@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.3" - statuses "~1.5.0" - unpipe "~1.0.0" - -find-cache-dir@^2.0.0, find-cache-dir@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" - integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== - dependencies: - commondir "^1.0.1" - make-dir "^2.0.0" - pkg-dir "^3.0.0" - -find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= - dependencies: - locate-path "^2.0.0" - -find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - -flat-cache@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" - integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== - dependencies: - flatted "^2.0.0" - rimraf "2.6.3" - write "1.0.3" - -flatted@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08" - integrity sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg== - -flush-write-stream@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" - integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w== - dependencies: - inherits "^2.0.3" - readable-stream "^2.3.6" - -follow-redirects@^1.0.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db" - integrity sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA== - -for-in@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= - -foreach@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" - integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= - -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= - -form-data@~2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" - integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - -forwarded@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" - integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= - -fragment-cache@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= - dependencies: - map-cache "^0.2.2" - -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= - -from2@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" - integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= - dependencies: - inherits "^2.0.1" - readable-stream "^2.0.0" - -fs-extra@^4.0.2: - version "4.0.3" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" - integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - -fs-extra@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" - integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - -fs-minipass@^1.2.5: - version "1.2.7" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" - integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== - dependencies: - minipass "^2.6.0" - -fs-write-stream-atomic@^1.0.8: - version "1.0.10" - resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" - integrity sha1-tH31NJPvkR33VzHnCp3tAYnbQMk= - dependencies: - graceful-fs "^4.1.2" - iferr "^0.1.5" - imurmurhash "^0.1.4" - readable-stream "1 || 2" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -fsevents@^1.2.7: - version "1.2.9" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.9.tgz#3f5ed66583ccd6f400b5a00db6f7e861363e388f" - integrity sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw== - dependencies: - nan "^2.12.1" - node-pre-gyp "^0.12.0" - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -functional-red-black-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= - -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - -gensync@^1.0.0-beta.1: - version "1.0.0-beta.1" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" - integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== - -get-caller-file@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" - integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== - -get-own-enumerable-property-symbols@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.1.tgz#6f7764f88ea11e0b514bd9bd860a132259992ca4" - integrity sha512-09/VS4iek66Dh2bctjRkowueRJbY1JDGR1L/zRxO1Qk8Uxs6PnqaNSqalpizPT+CDjre3hnEsuzvhgomz9qYrA== - -get-stream@^4.0.0, get-stream@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" - integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== - dependencies: - pump "^3.0.0" - -get-stream@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9" - integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw== - dependencies: - pump "^3.0.0" - -get-value@^2.0.3, get-value@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= - -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= - dependencies: - assert-plus "^1.0.0" - -glob-parent@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - -glob-parent@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" - integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw== - dependencies: - is-glob "^4.0.1" - -glob-to-regexp@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" - integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= - -glob@^7.0.3, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: - version "7.1.4" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" - integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -global-dirs@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-2.0.1.tgz#acdf3bb6685bcd55cb35e8a052266569e9469201" - integrity sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A== - dependencies: - ini "^1.3.5" - -global@^4.3.2: - version "4.4.0" - resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406" - integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w== - dependencies: - min-document "^2.19.0" - process "^0.11.10" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globals@^12.1.0: - version "12.4.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8" - integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg== - dependencies: - type-fest "^0.8.1" - -globby@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" - integrity sha1-9abXDoOV4hyFj7BInWTfAkJNUGw= - dependencies: - array-union "^1.0.1" - glob "^7.0.3" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -globby@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/globby/-/globby-7.1.1.tgz#fb2ccff9401f8600945dfada97440cca972b8680" - integrity sha1-+yzP+UAfhgCUXfral0QMypcrhoA= - dependencies: - array-union "^1.0.1" - dir-glob "^2.0.0" - glob "^7.1.2" - ignore "^3.3.5" - pify "^3.0.0" - slash "^1.0.0" - -globby@^9.2.0: - version "9.2.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-9.2.0.tgz#fd029a706c703d29bdd170f4b6db3a3f7a7cb63d" - integrity sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg== - dependencies: - "@types/glob" "^7.1.1" - array-union "^1.0.2" - dir-glob "^2.2.2" - fast-glob "^2.2.6" - glob "^7.1.3" - ignore "^4.0.3" - pify "^4.0.1" - slash "^2.0.0" - -good-listener@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50" - integrity sha1-1TswzfkxPf+33JoNR3CWqm0UXFA= - dependencies: - delegate "^3.1.2" - -got@^9.6.0: - version "9.6.0" - resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" - integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== - dependencies: - "@sindresorhus/is" "^0.14.0" - "@szmarczak/http-timer" "^1.1.2" - cacheable-request "^6.0.0" - decompress-response "^3.3.0" - duplexer3 "^0.1.4" - get-stream "^4.1.0" - lowercase-keys "^1.0.1" - mimic-response "^1.0.1" - p-cancelable "^1.0.0" - to-readable-stream "^1.0.0" - url-parse-lax "^3.0.0" - -graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6: - version "4.2.2" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02" - integrity sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q== - -gray-matter@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-4.0.2.tgz#9aa379e3acaf421193fce7d2a28cebd4518ac454" - integrity sha512-7hB/+LxrOjq/dd8APlK0r24uL/67w7SkYnfwhNFwg/VDIGWGmduTDYf3WNstLW2fbbmRwrDGCVSJ2isuf2+4Hw== - dependencies: - js-yaml "^3.11.0" - kind-of "^6.0.2" - section-matter "^1.0.0" - strip-bom-string "^1.0.0" - -handle-thing@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.0.tgz#0e039695ff50c93fc288557d696f3c1dc6776754" - integrity sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ== - -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= - -har-validator@~5.1.0: - version "5.1.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" - integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== - dependencies: - ajv "^6.5.5" - har-schema "^2.0.0" - -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= - dependencies: - ansi-regex "^2.0.0" - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" - integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= - -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= - -has-value@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= - dependencies: - get-value "^2.0.3" - has-values "^0.1.4" - isobject "^2.0.0" - -has-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= - dependencies: - get-value "^2.0.6" - has-values "^1.0.0" - isobject "^3.0.0" - -has-values@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= - -has-values@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - -has-yarn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" - integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== - -has@^1.0.0, has@^1.0.1, has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -hash-base@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" - integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg= - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -hash-sum@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/hash-sum/-/hash-sum-1.0.2.tgz#33b40777754c6432573c120cc3808bbd10d47f04" - integrity sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ= - -hash.js@^1.0.0, hash.js@^1.0.3: - version "1.1.7" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" - integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.1" - -he@1.2.x, he@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" - integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== - -hex-color-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" - integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== - -hmac-drbg@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= - dependencies: - hash.js "^1.0.3" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.1" - -hogan.js@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/hogan.js/-/hogan.js-3.0.2.tgz#4cd9e1abd4294146e7679e41d7898732b02c7bfd" - integrity sha1-TNnhq9QpQUbnZ55B14mHMrAse/0= - dependencies: - mkdirp "0.3.0" - nopt "1.0.10" - -hpack.js@^2.1.6: - version "2.1.6" - resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" - integrity sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI= - dependencies: - inherits "^2.0.1" - obuf "^1.0.0" - readable-stream "^2.0.1" - wbuf "^1.1.0" - -hsl-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/hsl-regex/-/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e" - integrity sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4= - -hsla-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38" - integrity sha1-wc56MWjIxmFAM6S194d/OyJfnDg= - -html-comment-regex@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.2.tgz#97d4688aeb5c81886a364faa0cad1dda14d433a7" - integrity sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ== - -html-entities@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f" - integrity sha1-DfKTUfByEWNRXfueVUPl9u7VFi8= - -html-minifier@^3.2.3: - version "3.5.21" - resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-3.5.21.tgz#d0040e054730e354db008463593194015212d20c" - integrity sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA== - dependencies: - camel-case "3.0.x" - clean-css "4.2.x" - commander "2.17.x" - he "1.2.x" - param-case "2.1.x" - relateurl "0.2.x" - uglify-js "3.4.x" - -html-tags@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-2.0.0.tgz#10b30a386085f43cede353cc8fa7cb0deeea668b" - integrity sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos= - -htmlparser2@^3.3.0: - version "3.10.1" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" - integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== - dependencies: - domelementtype "^1.3.1" - domhandler "^2.3.0" - domutils "^1.5.1" - entities "^1.1.1" - inherits "^2.0.1" - readable-stream "^3.1.1" - -http-cache-semantics@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" - integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== - -http-deceiver@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" - integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc= - -http-errors@1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" - integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - -http-errors@~1.6.2: - version "1.6.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" - integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.0" - statuses ">= 1.4.0 < 2" - -http-errors@~1.7.2: - version "1.7.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" - integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== - dependencies: - depd "~1.1.2" - inherits "2.0.4" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - -"http-parser-js@>=0.4.0 <0.4.11": - version "0.4.10" - resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.10.tgz#92c9c1374c35085f75db359ec56cc257cbb93fa4" - integrity sha1-ksnBN0w1CF912zWexWzCV8u5P6Q= - -http-proxy-middleware@0.19.1: - version "0.19.1" - resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz#183c7dc4aa1479150306498c210cdaf96080a43a" - integrity sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q== - dependencies: - http-proxy "^1.17.0" - is-glob "^4.0.0" - lodash "^4.17.11" - micromatch "^3.1.10" - -http-proxy@^1.17.0: - version "1.18.1" - resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" - integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== - dependencies: - eventemitter3 "^4.0.0" - follow-redirects "^1.0.0" - requires-port "^1.0.0" - -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -https-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" - integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= - -iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -icss-replace-symbols@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded" - integrity sha1-Bupvg2ead0njhs/h/oEq5dsiPe0= - -icss-utils@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467" - integrity sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA== - dependencies: - postcss "^7.0.14" - -ieee754@^1.1.4: - version "1.1.13" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" - integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== - -iferr@^0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" - integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= - -ignore-walk@^3.0.1: - version "3.0.3" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37" - integrity sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw== - dependencies: - minimatch "^3.0.4" - -ignore@^3.3.5: - version "3.3.10" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" - integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== - -ignore@^4.0.3, ignore@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" - integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== - -immediate@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c" - integrity sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw= - -import-cwd@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9" - integrity sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk= - dependencies: - import-from "^2.1.0" - -import-fresh@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" - integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= - dependencies: - caller-path "^2.0.0" - resolve-from "^3.0.0" - -import-fresh@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.1.0.tgz#6d33fa1dcef6df930fae003446f33415af905118" - integrity sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -import-from@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/import-from/-/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1" - integrity sha1-M1238qev/VOqpHHUuAId7ja387E= - dependencies: - resolve-from "^3.0.0" - -import-lazy@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" - integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= - -import-local@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" - integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ== - dependencies: - pkg-dir "^3.0.0" - resolve-cwd "^2.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= - -indexes-of@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" - integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= - -infer-owner@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" - integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -inherits@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" - integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= - -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - -ini@^1.3.5, ini@~1.3.0: - version "1.3.8" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" - integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== - -inquirer@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.1.0.tgz#1298a01859883e17c7264b82870ae1034f92dd29" - integrity sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg== - dependencies: - ansi-escapes "^4.2.1" - chalk "^3.0.0" - cli-cursor "^3.1.0" - cli-width "^2.0.0" - external-editor "^3.0.3" - figures "^3.0.0" - lodash "^4.17.15" - mute-stream "0.0.8" - run-async "^2.4.0" - rxjs "^6.5.3" - string-width "^4.1.0" - strip-ansi "^6.0.0" - through "^2.3.6" - -internal-ip@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907" - integrity sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg== - dependencies: - default-gateway "^4.2.0" - ipaddr.js "^1.9.0" - -invariant@^2.2.2, invariant@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== - dependencies: - loose-envify "^1.0.0" - -invert-kv@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" - integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== - -ip-regex@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" - integrity sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk= - -ip@^1.1.0, ip@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" - integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= - -ipaddr.js@1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.0.tgz#37df74e430a0e47550fe54a2defe30d8acd95f65" - integrity sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA== - -ipaddr.js@^1.9.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" - integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== - -is-absolute-url@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" - integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY= - -is-absolute-url@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698" - integrity sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q== - -is-accessor-descriptor@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= - dependencies: - kind-of "^3.0.2" - -is-accessor-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== - dependencies: - kind-of "^6.0.0" - -is-arguments@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.0.4.tgz#3faf966c7cba0ff437fb31f6250082fcf0448cf3" - integrity sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA== - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= - -is-arrayish@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" - integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== - -is-binary-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= - dependencies: - binary-extensions "^1.0.0" - -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - -is-callable@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" - integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== - -is-ci@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" - integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== - dependencies: - ci-info "^2.0.0" - -is-color-stop@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345" - integrity sha1-z/9HGu5N1cnhWFmPvhKWe1za00U= - dependencies: - css-color-names "^0.0.4" - hex-color-regex "^1.1.0" - hsl-regex "^1.0.0" - hsla-regex "^1.0.0" - rgb-regex "^1.0.1" - rgba-regex "^1.0.0" - -is-data-descriptor@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= - dependencies: - kind-of "^3.0.2" - -is-data-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== - dependencies: - kind-of "^6.0.0" - -is-date-object@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" - integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= - -is-descriptor@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== - dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" - -is-descriptor@^1.0.0, is-descriptor@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== - dependencies: - is-accessor-descriptor "^1.0.0" - is-data-descriptor "^1.0.0" - kind-of "^6.0.2" - -is-directory@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" - integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= - -is-extendable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== - dependencies: - is-plain-object "^2.0.4" - -is-extglob@^2.1.0, is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= - dependencies: - is-extglob "^2.1.0" - -is-glob@^4.0.0, is-glob@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" - integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== - dependencies: - is-extglob "^2.1.1" - -is-installed-globally@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.3.2.tgz#fd3efa79ee670d1187233182d5b0a1dd00313141" - integrity sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g== - dependencies: - global-dirs "^2.0.1" - is-path-inside "^3.0.1" - -is-npm@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-4.0.0.tgz#c90dd8380696df87a7a6d823c20d0b12bbe3c84d" - integrity sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig== - -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= - dependencies: - kind-of "^3.0.2" - -is-obj@^1.0.0, is-obj@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= - -is-obj@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" - integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== - -is-path-cwd@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" - integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== - -is-path-in-cwd@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz#bfe2dca26c69f397265a4009963602935a053acb" - integrity sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ== - dependencies: - is-path-inside "^2.1.0" - -is-path-inside@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-2.1.0.tgz#7c9810587d659a40d27bcdb4d5616eab059494b2" - integrity sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg== - dependencies: - path-is-inside "^1.0.2" - -is-path-inside@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.2.tgz#f5220fc82a3e233757291dddc9c5877f2a1f3017" - integrity sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg== - -is-plain-obj@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= - -is-plain-object@^2.0.3, is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - -is-promise@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" - integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= - -is-regex@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" - integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= - dependencies: - has "^1.0.1" - -is-regexp@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" - integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= - -is-regexp@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-2.1.0.tgz#cd734a56864e23b956bf4e7c66c396a4c0b22c2d" - integrity sha512-OZ4IlER3zmRIoB9AqNhEggVxqIH4ofDns5nRrPS6yQxXE1TPCUpFznBfRQmQa8uC+pXqjMnukiJBxCisIxiLGA== - -is-resolvable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" - integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== - -is-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= - -is-svg@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75" - integrity sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ== - dependencies: - html-comment-regex "^1.1.0" - -is-symbol@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" - integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== - dependencies: - has-symbols "^1.0.0" - -is-typedarray@^1.0.0, is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= - -is-windows@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== - -is-wsl@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" - integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= - -is-yarn-global@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" - integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw== - -isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -isarray@^2.0.1: - version "2.0.5" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" - integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= - -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= - dependencies: - isarray "1.0.0" - -isobject@^3.0.0, isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= - -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= - -javascript-stringify@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/javascript-stringify/-/javascript-stringify-1.6.0.tgz#142d111f3a6e3dae8f4a9afd77d45855b5a9cce3" - integrity sha1-FC0RHzpuPa6PSpr9d9RYVbWpzOM= - -javascript-stringify@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/javascript-stringify/-/javascript-stringify-2.0.1.tgz#6ef358035310e35d667c675ed63d3eb7c1aa19e5" - integrity sha512-yV+gqbd5vaOYjqlbk16EG89xB5udgjqQF3C5FAORDg4f/IS1Yc5ERCv5e/57yBcfJYw05V5JyIXabhwb75Xxow== - -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^3.11.0, js-yaml@^3.13.1: - version "3.13.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" - integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= - -json-buffer@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" - integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= - -json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= - -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= - -json3@^3.3.2: - version "3.3.3" - resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81" - integrity sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA== - -json5@^0.5.0: - version "0.5.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" - integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= - -json5@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== - dependencies: - minimist "^1.2.0" - -json5@^2.1.2: - version "2.1.3" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" - integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== - dependencies: - minimist "^1.2.5" - -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= - optionalDependencies: - graceful-fs "^4.1.6" - -jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.2.3" - verror "1.10.0" - -keyv@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" - integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== - dependencies: - json-buffer "3.0.0" - -killable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" - integrity sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg== - -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= - dependencies: - is-buffer "^1.1.5" - -kind-of@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== - -kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" - integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== - -last-call-webpack-plugin@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz#9742df0e10e3cf46e5c0381c2de90d3a7a2d7555" - integrity sha512-7KI2l2GIZa9p2spzPIVZBYyNKkN+e/SQPpnjlTiPhdbDW3F86tdKKELxKpzJ5sgU19wQWsACULZmpTPYHeWO5w== - dependencies: - lodash "^4.17.5" - webpack-sources "^1.1.0" - -latest-version@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" - integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA== - dependencies: - package-json "^6.3.0" - -lcid@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" - integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA== - dependencies: - invert-kv "^2.0.0" - -leven@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" - integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== - -levenary@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/levenary/-/levenary-1.1.1.tgz#842a9ee98d2075aa7faeedbe32679e9205f46f77" - integrity sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ== - dependencies: - leven "^3.1.0" - -levn@^0.3.0, levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - -linkify-it@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.2.0.tgz#e3b54697e78bf915c70a38acd78fd09e0058b1cf" - integrity sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw== - dependencies: - uc.micro "^1.0.1" - -load-script@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/load-script/-/load-script-1.0.0.tgz#0491939e0bee5643ee494a7e3da3d2bac70c6ca4" - integrity sha1-BJGTngvuVkPuSUp+PaPSuscMbKQ= - -loader-runner@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" - integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== - -loader-utils@^0.2.16: - version "0.2.17" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348" - integrity sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g= - dependencies: - big.js "^3.1.3" - emojis-list "^2.0.0" - json5 "^0.5.0" - object-assign "^4.0.1" - -loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" - integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA== - dependencies: - big.js "^5.2.2" - emojis-list "^2.0.0" - json5 "^1.0.1" - -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - -locate-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" - integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== - dependencies: - p-locate "^3.0.0" - path-exists "^3.0.0" - -lodash._reinterpolate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" - integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= - -lodash.clonedeep@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" - integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= - -lodash.debounce@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= - -lodash.kebabcase@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36" - integrity sha1-hImxyw0p/4gZXM7KRI/21swpXDY= - -lodash.memoize@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= - -lodash.template@^4.4.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" - integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A== - dependencies: - lodash._reinterpolate "^3.0.0" - lodash.templatesettings "^4.0.0" - -lodash.templatesettings@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33" - integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ== - dependencies: - lodash._reinterpolate "^3.0.0" - -lodash.uniq@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" - integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= - -lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.3, lodash@^4.17.5: - version "4.17.19" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" - integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== - -loglevel@^1.6.4: - version "1.6.4" - resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.4.tgz#f408f4f006db8354d0577dcf6d33485b3cb90d56" - integrity sha512-p0b6mOGKcGa+7nnmKbpzR6qloPbrgLcnio++E+14Vo/XffOGwZtRpUhr8dTH/x2oCMmEoIU0Zwm3ZauhvYD17g== - -loose-envify@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -lower-case@^1.1.1: - version "1.1.4" - resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" - integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw= - -lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== - -lowercase-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" - integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== - -lru-cache@^4.1.2: - version "4.1.5" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" - integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== - dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" - -lru-cache@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== - dependencies: - yallist "^3.0.2" - -make-dir@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" - integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== - dependencies: - pify "^4.0.1" - semver "^5.6.0" - -make-dir@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" - integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== - dependencies: - semver "^6.0.0" - -mamacro@^0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/mamacro/-/mamacro-0.0.3.tgz#ad2c9576197c9f1abf308d0787865bd975a3f3e4" - integrity sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA== - -map-age-cleaner@^0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" - integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== - dependencies: - p-defer "^1.0.0" - -map-cache@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= - -map-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= - dependencies: - object-visit "^1.0.0" - -markdown-it-anchor@^5.0.2: - version "5.2.5" - resolved "https://registry.yarnpkg.com/markdown-it-anchor/-/markdown-it-anchor-5.2.5.tgz#dbf13cfcdbffd16a510984f1263e1d479a47d27a" - integrity sha512-xLIjLQmtym3QpoY9llBgApknl7pxAcN3WDRc2d3rwpl+/YvDZHPmKscGs+L6E05xf2KrCXPBvosWt7MZukwSpQ== - -markdown-it-chain@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/markdown-it-chain/-/markdown-it-chain-1.3.0.tgz#ccf6fe86c10266bafb4e547380dfd7f277cc17bc" - integrity sha512-XClV8I1TKy8L2qsT9iX3qiV+50ZtcInGXI80CA+DP62sMs7hXlyV/RM3hfwy5O3Ad0sJm9xIwQELgANfESo8mQ== - dependencies: - webpack-chain "^4.9.0" - -markdown-it-container@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/markdown-it-container/-/markdown-it-container-2.0.0.tgz#0019b43fd02eefece2f1960a2895fba81a404695" - integrity sha1-ABm0P9Au7+zi8ZYKKJX7qBpARpU= - -markdown-it-emoji@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/markdown-it-emoji/-/markdown-it-emoji-1.4.0.tgz#9bee0e9a990a963ba96df6980c4fddb05dfb4dcc" - integrity sha1-m+4OmpkKljupbfaYDE/dsF37Tcw= - -markdown-it-table-of-contents@^0.4.0: - version "0.4.4" - resolved "https://registry.yarnpkg.com/markdown-it-table-of-contents/-/markdown-it-table-of-contents-0.4.4.tgz#3dc7ce8b8fc17e5981c77cc398d1782319f37fbc" - integrity sha512-TAIHTHPwa9+ltKvKPWulm/beozQU41Ab+FIefRaQV1NRnpzwcV9QOe6wXQS5WLivm5Q/nlo0rl6laGkMDZE7Gw== - -markdown-it@^8.4.1: - version "8.4.2" - resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.4.2.tgz#386f98998dc15a37722aa7722084f4020bdd9b54" - integrity sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ== - dependencies: - argparse "^1.0.7" - entities "~1.1.1" - linkify-it "^2.0.0" - mdurl "^1.0.1" - uc.micro "^1.0.5" - -md5.js@^1.3.4: - version "1.3.5" - resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" - integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -mdn-data@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" - integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA== - -mdn-data@~1.1.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-1.1.4.tgz#50b5d4ffc4575276573c4eedb8780812a8419f01" - integrity sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA== - -mdurl@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" - integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= - -medium-zoom@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/medium-zoom/-/medium-zoom-1.0.4.tgz#b1063093f81151a19989489589edf28e6090630c" - integrity sha512-BjE+00gQku3XQfgHDcqyYwQaBtFddzh6Lnj1RZOliqJ9HS0mh/P2IaqVJ25/j9EbnjAUf27mLeLZBRxnd00bfA== - -mem@^4.0.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178" - integrity sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w== - dependencies: - map-age-cleaner "^0.1.1" - mimic-fn "^2.0.0" - p-is-promise "^2.0.0" - -memory-fs@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" - integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= - dependencies: - errno "^0.1.3" - readable-stream "^2.0.1" - -memory-fs@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c" - integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA== - dependencies: - errno "^0.1.3" - readable-stream "^2.0.1" - -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= - -merge-source-map@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646" - integrity sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw== - dependencies: - source-map "^0.6.1" - -merge2@^1.2.3: - version "1.3.0" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" - integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw== - -methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= - -micromatch@^3.1.10, micromatch@^3.1.4: - version "3.1.10" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.1" - define-property "^2.0.2" - extend-shallow "^3.0.2" - extglob "^2.0.4" - fragment-cache "^0.2.1" - kind-of "^6.0.2" - nanomatch "^1.2.9" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.2" - -miller-rabin@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" - integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== - dependencies: - bn.js "^4.0.0" - brorand "^1.0.1" - -mime-db@1.40.0: - version "1.40.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32" - integrity sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA== - -"mime-db@>= 1.40.0 < 2": - version "1.42.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.42.0.tgz#3e252907b4c7adb906597b4b65636272cf9e7bac" - integrity sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ== - -mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: - version "2.1.24" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.24.tgz#b6f8d0b3e951efb77dedeca194cff6d16f676f81" - integrity sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ== - dependencies: - mime-db "1.40.0" - -mime@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== - -mime@^2.0.3, mime@^2.4.4: - version "2.4.4" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5" - integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA== - -mimic-fn@^2.0.0, mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -mimic-response@^1.0.0, mimic-response@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" - integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== - -min-document@^2.19.0: - version "2.19.0" - resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" - integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU= - dependencies: - dom-walk "^0.1.0" - -mini-css-extract-plugin@0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.6.0.tgz#a3f13372d6fcde912f3ee4cd039665704801e3b9" - integrity sha512-79q5P7YGI6rdnVyIAV4NXpBQJFWdkzJxCim3Kog4078fM0piAaFlwocqbejdWtLW1cEzCexPrh6EdyFsPgVdAw== - dependencies: - loader-utils "^1.1.0" - normalize-url "^2.0.1" - schema-utils "^1.0.0" - webpack-sources "^1.1.0" - -minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== - -minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= - -minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= - -minimist@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= - -minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== - -minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" - integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== - dependencies: - safe-buffer "^5.1.2" - yallist "^3.0.0" - -minizlib@^1.2.1: - version "1.3.3" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" - integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== - dependencies: - minipass "^2.9.0" - -mississippi@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" - integrity sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA== - dependencies: - concat-stream "^1.5.0" - duplexify "^3.4.2" - end-of-stream "^1.1.0" - flush-write-stream "^1.0.0" - from2 "^2.1.0" - parallel-transform "^1.1.0" - pump "^3.0.0" - pumpify "^1.3.3" - stream-each "^1.1.0" - through2 "^2.0.0" - -mixin-deep@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" - integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== - dependencies: - for-in "^1.0.2" - is-extendable "^1.0.1" - -mkdirp@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" - integrity sha1-G79asbqCevI1dRQ0kEJkVfSB/h4= - -mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1, mkdirp@~0.5.x: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= - dependencies: - minimist "0.0.8" - -move-concurrently@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" - integrity sha1-viwAX9oy4LKa8fBdfEszIUxwH5I= - dependencies: - aproba "^1.1.1" - copy-concurrently "^1.0.0" - fs-write-stream-atomic "^1.0.8" - mkdirp "^0.5.1" - rimraf "^2.5.4" - run-queue "^1.0.3" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== - -ms@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -multicast-dns-service-types@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901" - integrity sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE= - -multicast-dns@^6.0.1: - version "6.2.3" - resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-6.2.3.tgz#a0ec7bd9055c4282f790c3c82f4e28db3b31b229" - integrity sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g== - dependencies: - dns-packet "^1.3.1" - thunky "^1.0.2" - -mute-stream@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" - integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== - -nan@^2.12.1: - version "2.14.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" - integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== - -nanomatch@^1.2.9: - version "1.2.13" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" - integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^2.0.2" - extend-shallow "^3.0.2" - fragment-cache "^0.2.1" - is-windows "^1.0.2" - kind-of "^6.0.2" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= - -needle@^2.2.1: - version "2.4.0" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.0.tgz#6833e74975c444642590e15a750288c5f939b57c" - integrity sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg== - dependencies: - debug "^3.2.6" - iconv-lite "^0.4.4" - sax "^1.2.4" - -negotiator@0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== - -neo-async@^2.5.0, neo-async@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" - integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== - -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== - -no-case@^2.2.0: - version "2.3.2" - resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac" - integrity sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ== - dependencies: - lower-case "^1.1.1" - -node-forge@0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579" - integrity sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ== - -node-libs-browser@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" - integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== - dependencies: - assert "^1.1.1" - browserify-zlib "^0.2.0" - buffer "^4.3.0" - console-browserify "^1.1.0" - constants-browserify "^1.0.0" - crypto-browserify "^3.11.0" - domain-browser "^1.1.1" - events "^3.0.0" - https-browserify "^1.0.0" - os-browserify "^0.3.0" - path-browserify "0.0.1" - process "^0.11.10" - punycode "^1.2.4" - querystring-es3 "^0.2.0" - readable-stream "^2.3.3" - stream-browserify "^2.0.1" - stream-http "^2.7.2" - string_decoder "^1.0.0" - timers-browserify "^2.0.4" - tty-browserify "0.0.0" - url "^0.11.0" - util "^0.11.0" - vm-browserify "^1.0.1" - -node-pre-gyp@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149" - integrity sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A== - dependencies: - detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" - nopt "^4.0.1" - npm-packlist "^1.1.6" - npmlog "^4.0.2" - rc "^1.2.7" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^4" - -node-releases@^1.1.36: - version "1.1.36" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.36.tgz#44b7cb8254138e87bdbfa47761d0f825e20900b4" - integrity sha512-ggXhX6QGyJSjj3r+6ml2LqqC28XOWmKtpb+a15/Zpr9V3yoNazxJNlcQDS9bYaid5FReEWHEgToH1mwoUceWwg== - dependencies: - semver "^6.3.0" - -node-releases@^1.1.53: - version "1.1.53" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.53.tgz#2d821bfa499ed7c5dffc5e2f28c88e78a08ee3f4" - integrity sha512-wp8zyQVwef2hpZ/dJH7SfSrIPD6YoJz6BDQDpGEkcA0s3LpAQoxBIYmfIq6QAhC1DhwsyCgTaTTcONwX8qzCuQ== - -nopt@1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" - integrity sha1-bd0hvSoxQXuScn3Vhfim83YI6+4= - dependencies: - abbrev "1" - -nopt@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= - dependencies: - abbrev "1" - osenv "^0.1.4" - -normalize-path@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= - dependencies: - remove-trailing-separator "^1.0.1" - -normalize-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -normalize-range@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" - integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= - -normalize-url@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-2.0.1.tgz#835a9da1551fa26f70e92329069a23aa6574d7e6" - integrity sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw== - dependencies: - prepend-http "^2.0.0" - query-string "^5.0.1" - sort-keys "^2.0.0" - -normalize-url@^3.0.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" - integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== - -normalize-url@^4.1.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129" - integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ== - -npm-bundled@^1.0.1: - version "1.0.6" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd" - integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== - -npm-packlist@^1.1.6: - version "1.4.6" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.6.tgz#53ba3ed11f8523079f1457376dd379ee4ea42ff4" - integrity sha512-u65uQdb+qwtGvEJh/DgQgW1Xg7sqeNbmxYyrvlNznaVTjV3E5P6F/EFjM+BVHXl7JJlsdG8A64M0XI8FI/IOlg== - dependencies: - ignore-walk "^3.0.1" - npm-bundled "^1.0.1" - -npm-run-path@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= - dependencies: - path-key "^2.0.0" - -npmlog@^4.0.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - -nprogress@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/nprogress/-/nprogress-0.2.0.tgz#cb8f34c53213d895723fcbab907e9422adbcafb1" - integrity sha1-y480xTIT2JVyP8urkH6UIq28r7E= - -nth-check@^1.0.2, nth-check@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" - integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== - dependencies: - boolbase "~1.0.0" - -num2fraction@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" - integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4= - -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= - -oauth-sign@~0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" - integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== - -object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -object-copy@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= - dependencies: - copy-descriptor "^0.1.0" - define-property "^0.2.5" - kind-of "^3.0.3" - -object-inspect@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" - integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== - -object-is@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.1.tgz#0aa60ec9989a0b3ed795cf4d06f62cf1ad6539b6" - integrity sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY= - -object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.0, object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object-visit@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= - dependencies: - isobject "^3.0.0" - -object.assign@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" - integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== - dependencies: - define-properties "^1.1.2" - function-bind "^1.1.1" - has-symbols "^1.0.0" - object-keys "^1.0.11" - -object.getownpropertydescriptors@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" - integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= - dependencies: - define-properties "^1.1.2" - es-abstract "^1.5.1" - -object.pick@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= - dependencies: - isobject "^3.0.1" - -object.values@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.0.tgz#bf6810ef5da3e5325790eaaa2be213ea84624da9" - integrity sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.12.0" - function-bind "^1.1.1" - has "^1.0.3" - -obuf@^1.0.0, obuf@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" - integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== - -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= - dependencies: - ee-first "1.1.1" - -on-headers@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" - integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== - -once@^1.3.0, once@^1.3.1, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - -onetime@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" - integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== - dependencies: - mimic-fn "^2.1.0" - -opencollective-postinstall@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.2.tgz#5657f1bede69b6e33a45939b061eb53d3c6c3a89" - integrity sha512-pVOEP16TrAO2/fjej1IdOyupJY8KDUM1CvsaScRbw6oddvpQoOfGk4ywha0HKKVAD6RkW4x6Q+tNBwhf3Bgpuw== - -opn@^5.4.0, opn@^5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc" - integrity sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA== - dependencies: - is-wsl "^1.1.0" - -optimize-css-assets-webpack-plugin@^5.0.1: - version "5.0.3" - resolved "https://registry.yarnpkg.com/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.3.tgz#e2f1d4d94ad8c0af8967ebd7cf138dcb1ef14572" - integrity sha512-q9fbvCRS6EYtUKKSwI87qm2IxlyJK5b4dygW1rKUBT6mMDhdG5e5bZT63v6tnJR9F9FB/H5a0HTmtw+laUBxKA== - dependencies: - cssnano "^4.1.10" - last-call-webpack-plugin "^3.0.0" - -optionator@^0.8.3: - version "0.8.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" - integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.6" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - word-wrap "~1.2.3" - -original@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/original/-/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f" - integrity sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg== - dependencies: - url-parse "^1.4.3" - -os-browserify@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" - integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= - -os-homedir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= - -os-locale@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" - integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q== - dependencies: - execa "^1.0.0" - lcid "^2.0.0" - mem "^4.0.0" - -os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= - -osenv@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.0" - -p-cancelable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" - integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== - -p-defer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" - integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww= - -p-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= - -p-is-promise@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e" - integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg== - -p-limit@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== - dependencies: - p-try "^1.0.0" - -p-limit@^2.0.0, p-limit@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" - integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== - dependencies: - p-try "^2.0.0" - -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= - dependencies: - p-limit "^1.1.0" - -p-locate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" - integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== - dependencies: - p-limit "^2.0.0" - -p-map@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" - integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== - -p-retry@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-3.0.1.tgz#316b4c8893e2c8dc1cfa891f406c4b422bebf328" - integrity sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w== - dependencies: - retry "^0.12.0" - -p-try@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -package-json@^6.3.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0" - integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ== - dependencies: - got "^9.6.0" - registry-auth-token "^4.0.0" - registry-url "^5.0.0" - semver "^6.2.0" - -pako@~1.0.5: - version "1.0.10" - resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732" - integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw== - -parallel-transform@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.2.0.tgz#9049ca37d6cb2182c3b1d2c720be94d14a5814fc" - integrity sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg== - dependencies: - cyclist "^1.0.1" - inherits "^2.0.3" - readable-stream "^2.1.5" - -param-case@2.1.x: - version "2.1.1" - resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247" - integrity sha1-35T9jPZTHs915r75oIWPvHK+Ikc= - dependencies: - no-case "^2.2.0" - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -parse-asn1@^5.0.0: - version "5.1.5" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.5.tgz#003271343da58dc94cace494faef3d2147ecea0e" - integrity sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ== - dependencies: - asn1.js "^4.0.0" - browserify-aes "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.0" - pbkdf2 "^3.0.3" - safe-buffer "^5.1.1" - -parse-json@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= - dependencies: - error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" - -parseurl@~1.3.2, parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - -pascalcase@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= - -path-browserify@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" - integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== - -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -path-is-inside@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= - -path-key@^2.0.0, path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= - -path-parse@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" - integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== - -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= - -path-type@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" - integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== - dependencies: - pify "^3.0.0" - -pbkdf2@^3.0.3: - version "3.0.17" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" - integrity sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA== - dependencies: - create-hash "^1.1.2" - create-hmac "^1.1.4" - ripemd160 "^2.0.1" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= - -pify@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= - -pify@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" - integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= - -pify@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" - integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= - -pkg-dir@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" - integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== - dependencies: - find-up "^3.0.0" - -pkg-up@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f" - integrity sha1-yBmscoBZpGHKscOImivjxJoATX8= - dependencies: - find-up "^2.1.0" - -portfinder@^1.0.13, portfinder@^1.0.24: - version "1.0.25" - resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.25.tgz#254fd337ffba869f4b9d37edc298059cb4d35eca" - integrity sha512-6ElJnHBbxVA1XSLgBp7G1FiCkQdlqGzuF7DswL5tcea+E8UpuvPU7beVAjjRwCioTS9ZluNbu+ZyRvgTsmqEBg== - dependencies: - async "^2.6.2" - debug "^3.1.1" - mkdirp "^0.5.1" - -posix-character-classes@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= - -postcss-calc@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.1.tgz#36d77bab023b0ecbb9789d84dcb23c4941145436" - integrity sha512-oXqx0m6tb4N3JGdmeMSc/i91KppbYsFZKdH0xMOqK8V1rJlzrKlTdokz8ozUXLVejydRN6u2IddxpcijRj2FqQ== - dependencies: - css-unit-converter "^1.1.1" - postcss "^7.0.5" - postcss-selector-parser "^5.0.0-rc.4" - postcss-value-parser "^3.3.1" - -postcss-colormin@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-4.0.3.tgz#ae060bce93ed794ac71264f08132d550956bd381" - integrity sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw== - dependencies: - browserslist "^4.0.0" - color "^3.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-convert-values@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz#ca3813ed4da0f812f9d43703584e449ebe189a7f" - integrity sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ== - dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-discard-comments@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz#1fbabd2c246bff6aaad7997b2b0918f4d7af4033" - integrity sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg== - dependencies: - postcss "^7.0.0" - -postcss-discard-duplicates@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz#3fe133cd3c82282e550fc9b239176a9207b784eb" - integrity sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ== - dependencies: - postcss "^7.0.0" - -postcss-discard-empty@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz#c8c951e9f73ed9428019458444a02ad90bb9f765" - integrity sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w== - dependencies: - postcss "^7.0.0" - -postcss-discard-overridden@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz#652aef8a96726f029f5e3e00146ee7a4e755ff57" - integrity sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg== - dependencies: - postcss "^7.0.0" - -postcss-load-config@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.1.0.tgz#c84d692b7bb7b41ddced94ee62e8ab31b417b003" - integrity sha512-4pV3JJVPLd5+RueiVVB+gFOAa7GWc25XQcMp86Zexzke69mKf6Nx9LRcQywdz7yZI9n1udOxmLuAwTBypypF8Q== - dependencies: - cosmiconfig "^5.0.0" - import-cwd "^2.0.0" - -postcss-loader@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-3.0.0.tgz#6b97943e47c72d845fa9e03f273773d4e8dd6c2d" - integrity sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA== - dependencies: - loader-utils "^1.1.0" - postcss "^7.0.0" - postcss-load-config "^2.0.0" - schema-utils "^1.0.0" - -postcss-merge-longhand@^4.0.11: - version "4.0.11" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz#62f49a13e4a0ee04e7b98f42bb16062ca2549e24" - integrity sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw== - dependencies: - css-color-names "0.0.4" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - stylehacks "^4.0.0" - -postcss-merge-rules@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz#362bea4ff5a1f98e4075a713c6cb25aefef9a650" - integrity sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ== - dependencies: - browserslist "^4.0.0" - caniuse-api "^3.0.0" - cssnano-util-same-parent "^4.0.0" - postcss "^7.0.0" - postcss-selector-parser "^3.0.0" - vendors "^1.0.0" - -postcss-minify-font-values@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz#cd4c344cce474343fac5d82206ab2cbcb8afd5a6" - integrity sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg== - dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-minify-gradients@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz#93b29c2ff5099c535eecda56c4aa6e665a663471" - integrity sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q== - dependencies: - cssnano-util-get-arguments "^4.0.0" - is-color-stop "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-minify-params@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz#6b9cef030c11e35261f95f618c90036d680db874" - integrity sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg== - dependencies: - alphanum-sort "^1.0.0" - browserslist "^4.0.0" - cssnano-util-get-arguments "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - uniqs "^2.0.0" - -postcss-minify-selectors@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz#e2e5eb40bfee500d0cd9243500f5f8ea4262fbd8" - integrity sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g== - dependencies: - alphanum-sort "^1.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-selector-parser "^3.0.0" - -postcss-modules-extract-imports@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e" - integrity sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ== - dependencies: - postcss "^7.0.5" - -postcss-modules-local-by-default@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-2.0.6.tgz#dd9953f6dd476b5fd1ef2d8830c8929760b56e63" - integrity sha512-oLUV5YNkeIBa0yQl7EYnxMgy4N6noxmiwZStaEJUSe2xPMcdNc8WmBQuQCx18H5psYbVxz8zoHk0RAAYZXP9gA== - dependencies: - postcss "^7.0.6" - postcss-selector-parser "^6.0.0" - postcss-value-parser "^3.3.1" - -postcss-modules-scope@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.1.0.tgz#ad3f5bf7856114f6fcab901b0502e2a2bc39d4eb" - integrity sha512-91Rjps0JnmtUB0cujlc8KIKCsJXWjzuxGeT/+Q2i2HXKZ7nBUeF9YQTZZTNvHVoNYj1AthsjnGLtqDUE0Op79A== - dependencies: - postcss "^7.0.6" - postcss-selector-parser "^6.0.0" - -postcss-modules-values@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-2.0.0.tgz#479b46dc0c5ca3dc7fa5270851836b9ec7152f64" - integrity sha512-Ki7JZa7ff1N3EIMlPnGTZfUMe69FFwiQPnVSXC9mnn3jozCRBYIxiZd44yJOV2AmabOo4qFf8s0dC/+lweG7+w== - dependencies: - icss-replace-symbols "^1.1.0" - postcss "^7.0.6" - -postcss-normalize-charset@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz#8b35add3aee83a136b0471e0d59be58a50285dd4" - integrity sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g== - dependencies: - postcss "^7.0.0" - -postcss-normalize-display-values@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz#0dbe04a4ce9063d4667ed2be476bb830c825935a" - integrity sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ== - dependencies: - cssnano-util-get-match "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-positions@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz#05f757f84f260437378368a91f8932d4b102917f" - integrity sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA== - dependencies: - cssnano-util-get-arguments "^4.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-repeat-style@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz#c4ebbc289f3991a028d44751cbdd11918b17910c" - integrity sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q== - dependencies: - cssnano-util-get-arguments "^4.0.0" - cssnano-util-get-match "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-string@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz#cd44c40ab07a0c7a36dc5e99aace1eca4ec2690c" - integrity sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA== - dependencies: - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-timing-functions@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz#8e009ca2a3949cdaf8ad23e6b6ab99cb5e7d28d9" - integrity sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A== - dependencies: - cssnano-util-get-match "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-unicode@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz#841bd48fdcf3019ad4baa7493a3d363b52ae1cfb" - integrity sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg== - dependencies: - browserslist "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-url@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz#10e437f86bc7c7e58f7b9652ed878daaa95faae1" - integrity sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA== - dependencies: - is-absolute-url "^2.0.0" - normalize-url "^3.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-normalize-whitespace@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz#bf1d4070fe4fcea87d1348e825d8cc0c5faa7d82" - integrity sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA== - dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-ordered-values@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz#0cf75c820ec7d5c4d280189559e0b571ebac0eee" - integrity sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw== - dependencies: - cssnano-util-get-arguments "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-reduce-initial@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz#7fd42ebea5e9c814609639e2c2e84ae270ba48df" - integrity sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA== - dependencies: - browserslist "^4.0.0" - caniuse-api "^3.0.0" - has "^1.0.0" - postcss "^7.0.0" - -postcss-reduce-transforms@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz#17efa405eacc6e07be3414a5ca2d1074681d4e29" - integrity sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg== - dependencies: - cssnano-util-get-match "^4.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-safe-parser@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-safe-parser/-/postcss-safe-parser-4.0.1.tgz#8756d9e4c36fdce2c72b091bbc8ca176ab1fcdea" - integrity sha512-xZsFA3uX8MO3yAda03QrG3/Eg1LN3EPfjjf07vke/46HERLZyHrTsQ9E1r1w1W//fWEhtYNndo2hQplN2cVpCQ== - dependencies: - postcss "^7.0.0" - -postcss-selector-parser@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz#4f875f4afb0c96573d5cf4d74011aee250a7e865" - integrity sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU= - dependencies: - dot-prop "^4.1.1" - indexes-of "^1.0.1" - uniq "^1.0.1" - -postcss-selector-parser@^5.0.0, postcss-selector-parser@^5.0.0-rc.4: - version "5.0.0" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz#249044356697b33b64f1a8f7c80922dddee7195c" - integrity sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ== - dependencies: - cssesc "^2.0.0" - indexes-of "^1.0.1" - uniq "^1.0.1" - -postcss-selector-parser@^6.0.0: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz#934cf799d016c83411859e09dcecade01286ec5c" - integrity sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg== - dependencies: - cssesc "^3.0.0" - indexes-of "^1.0.1" - uniq "^1.0.1" - -postcss-svgo@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-4.0.2.tgz#17b997bc711b333bab143aaed3b8d3d6e3d38258" - integrity sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw== - dependencies: - is-svg "^3.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - svgo "^1.0.0" - -postcss-unique-selectors@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz#9446911f3289bfd64c6d680f073c03b1f9ee4bac" - integrity sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg== - dependencies: - alphanum-sort "^1.0.0" - postcss "^7.0.0" - uniqs "^2.0.0" - -postcss-value-parser@^3.0.0, postcss-value-parser@^3.3.0, postcss-value-parser@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" - integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== - -postcss-value-parser@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.2.tgz#482282c09a42706d1fc9a069b73f44ec08391dc9" - integrity sha512-LmeoohTpp/K4UiyQCwuGWlONxXamGzCMtFxLq4W1nZVGIQLYvMCJx3yAF9qyyuFpflABI9yVdtJAqbihOsCsJQ== - -postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.18, postcss@^7.0.5, postcss@^7.0.6: - version "7.0.18" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.18.tgz#4b9cda95ae6c069c67a4d933029eddd4838ac233" - integrity sha512-/7g1QXXgegpF+9GJj4iN7ChGF40sYuGYJ8WZu8DZWnmhQ/G36hfdk3q9LBJmoK+lZ+yzZ5KYpOoxq7LF1BxE8g== - dependencies: - chalk "^2.4.2" - source-map "^0.6.1" - supports-color "^6.1.0" - -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= - -prepend-http@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" - integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= - -prettier@1.16.3: - version "1.16.3" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.16.3.tgz#8c62168453badef702f34b45b6ee899574a6a65d" - integrity sha512-kn/GU6SMRYPxUakNXhpP0EedT/KmaPzr0H5lIsDogrykbaxOpOfAFfk5XA7DZrJyMAv1wlMV3CPcZruGXVVUZw== - -pretty-bytes@^5.1.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.3.0.tgz#f2849e27db79fb4d6cfe24764fc4134f165989f2" - integrity sha512-hjGrh+P926p4R4WbaB6OckyRtO0F0/lQBiT+0gnxjV+5kjPBrfVBFCsCLbMqVQeydvIoouYTCmmEURiH3R1Bdg== - -pretty-error@^2.0.2: - version "2.1.1" - resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-2.1.1.tgz#5f4f87c8f91e5ae3f3ba87ab4cf5e03b1a17f1a3" - integrity sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM= - dependencies: - renderkid "^2.0.1" - utila "~0.4" - -pretty-time@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pretty-time/-/pretty-time-1.1.0.tgz#ffb7429afabb8535c346a34e41873adf3d74dd0e" - integrity sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA== - -prismjs@^1.13.0: - version "1.21.0" - resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.21.0.tgz#36c086ec36b45319ec4218ee164c110f9fc015a3" - integrity sha512-uGdSIu1nk3kej2iZsLyDoJ7e9bnPzIgY0naW/HdknGj61zScaprVEVGHrPoXqI+M9sP0NDnTK2jpkvmldpuqDw== - optionalDependencies: - clipboard "^2.0.0" - -private@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" - integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -process@^0.11.10: - version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= - -progress@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" - integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== - -promise-inflight@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" - integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= - -proxy-addr@~2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.5.tgz#34cbd64a2d81f4b1fd21e76f9f06c8a45299ee34" - integrity sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ== - dependencies: - forwarded "~0.1.2" - ipaddr.js "1.9.0" - -prr@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" - integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= - -pseudomap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= - -psl@^1.1.24: - version "1.4.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.4.0.tgz#5dd26156cdb69fa1fdb8ab1991667d3f80ced7c2" - integrity sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw== - -public-encrypt@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" - integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== - dependencies: - bn.js "^4.1.0" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - parse-asn1 "^5.0.0" - randombytes "^2.0.1" - safe-buffer "^5.1.2" - -pump@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" - integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -pumpify@^1.3.3: - version "1.5.1" - resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" - integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== - dependencies: - duplexify "^3.6.0" - inherits "^2.0.3" - pump "^2.0.0" - -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= - -punycode@^1.2.4, punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= - -punycode@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -pupa@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.0.1.tgz#dbdc9ff48ffbea4a26a069b6f9f7abb051008726" - integrity sha512-hEJH0s8PXLY/cdXh66tNEQGndDrIKNqNC5xmrysZy3i5C3oEoLna7YAOad+7u125+zH1HNXUmGEkrhb3c2VriA== - dependencies: - escape-goat "^2.0.0" - -q@^1.1.2: - version "1.5.1" - resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" - integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= - -qs@6.7.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" - integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== - -qs@~6.5.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== - -query-string@^5.0.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" - integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== - dependencies: - decode-uri-component "^0.2.0" - object-assign "^4.1.0" - strict-uri-encode "^1.0.0" - -querystring-es3@^0.2.0, querystring-es3@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" - integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= - -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= - -querystringify@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e" - integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA== - -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -randomfill@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" - integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== - dependencies: - randombytes "^2.0.5" - safe-buffer "^5.1.0" - -range-parser@^1.2.1, range-parser@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -raw-body@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" - integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== - dependencies: - bytes "3.1.0" - http-errors "1.7.2" - iconv-lite "0.4.24" - unpipe "1.0.0" - -rc@^1.2.7, rc@^1.2.8: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: - version "2.3.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@^3.0.6, readable-stream@^3.1.1: - version "3.4.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc" - integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readdirp@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" - integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== - dependencies: - graceful-fs "^4.1.11" - micromatch "^3.1.10" - readable-stream "^2.0.2" - -reduce@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/reduce/-/reduce-1.0.2.tgz#0cd680ad3ffe0b060e57a5c68bdfce37168d361b" - integrity sha512-xX7Fxke/oHO5IfZSk77lvPa/7bjMh9BuCk4OOoX5XTXrM7s0Z+MkPfSDfz0q7r91BhhGSs8gii/VEN/7zhCPpQ== - dependencies: - object-keys "^1.1.0" - -regenerate-unicode-properties@^8.2.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" - integrity sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA== - dependencies: - regenerate "^1.4.0" - -regenerate@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" - integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== - -regenerator-runtime@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" - integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== - -regenerator-runtime@^0.13.4: - version "0.13.5" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" - integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA== - -regenerator-transform@^0.14.2: - version "0.14.4" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.4.tgz#5266857896518d1616a78a0479337a30ea974cc7" - integrity sha512-EaJaKPBI9GvKpvUz2mz4fhx7WPgvwRLY9v3hlNHWmAuJHI13T4nwKnNvm5RWJzEdnI5g5UwtOww+S8IdoUC2bw== - dependencies: - "@babel/runtime" "^7.8.4" - private "^0.1.8" - -regex-not@^1.0.0, regex-not@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== - dependencies: - extend-shallow "^3.0.2" - safe-regex "^1.1.0" - -regexp.prototype.flags@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz#6b30724e306a27833eeb171b66ac8890ba37e41c" - integrity sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA== - dependencies: - define-properties "^1.1.2" - -regexpp@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" - integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== - -regexpu-core@^4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.0.tgz#fcbf458c50431b0bb7b45d6967b8192d91f3d938" - integrity sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ== - dependencies: - regenerate "^1.4.0" - regenerate-unicode-properties "^8.2.0" - regjsgen "^0.5.1" - regjsparser "^0.6.4" - unicode-match-property-ecmascript "^1.0.4" - unicode-match-property-value-ecmascript "^1.2.0" - -register-service-worker@^1.7.0: - version "1.7.1" - resolved "https://registry.yarnpkg.com/register-service-worker/-/register-service-worker-1.7.1.tgz#6308347ac6c0af0f6c0b22ea5d59d25e836bc932" - integrity sha512-IdTfUZ4u8iJL8o1w8es8l6UMGPmkwHolUdT+UmM1UypC80IB4KbpuIlvwWVj8UDS7eJwkEYRcKRgfRX+oTmJsw== - -registry-auth-token@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.1.1.tgz#40a33be1e82539460f94328b0f7f0f84c16d9479" - integrity sha512-9bKS7nTl9+/A1s7tnPeGrUpRcVY+LUh7bfFgzpndALdPfXQBfQV77rQVtqgUV3ti4vc/Ik81Ex8UJDWDQ12zQA== - dependencies: - rc "^1.2.8" - -registry-url@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009" - integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw== - dependencies: - rc "^1.2.8" - -regjsgen@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.1.tgz#48f0bf1a5ea205196929c0d9798b42d1ed98443c" - integrity sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg== - -regjsparser@^0.6.4: - version "0.6.4" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.4.tgz#a769f8684308401a66e9b529d2436ff4d0666272" - integrity sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw== - dependencies: - jsesc "~0.5.0" - -relateurl@0.2.x: - version "0.2.7" - resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" - integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk= - -remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= - -renderkid@^2.0.1: - version "2.0.3" - resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-2.0.3.tgz#380179c2ff5ae1365c522bf2fcfcff01c5b74149" - integrity sha512-z8CLQp7EZBPCwCnncgf9C4XAi3WR0dv+uWu/PjIyhhAb5d6IJ/QZqlHFprHeKT+59//V6BNUsLbvN8+2LarxGA== - dependencies: - css-select "^1.1.0" - dom-converter "^0.2" - htmlparser2 "^3.3.0" - strip-ansi "^3.0.0" - utila "^0.4.0" - -repeat-element@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" - integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== - -repeat-string@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= - -request@^2.87.0: - version "2.88.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" - integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.8.0" - caseless "~0.12.0" - combined-stream "~1.0.6" - extend "~3.0.2" - forever-agent "~0.6.1" - form-data "~2.3.2" - har-validator "~5.1.0" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.19" - oauth-sign "~0.9.0" - performance-now "^2.1.0" - qs "~6.5.2" - safe-buffer "^5.1.2" - tough-cookie "~2.4.3" - tunnel-agent "^0.6.0" - uuid "^3.3.2" - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= - -require-main-filename@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" - integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= - -requires-port@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= - -resolve-cwd@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" - integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo= - dependencies: - resolve-from "^3.0.0" - -resolve-from@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - integrity sha1-six699nWiBvItuZTM17rywoYh0g= - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve-url@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= - -resolve@^1.12.0, resolve@^1.2.0, resolve@^1.3.2, resolve@^1.8.1: - version "1.12.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" - integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== - dependencies: - path-parse "^1.0.6" - -responselike@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" - integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= - dependencies: - lowercase-keys "^1.0.0" - -restore-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" - integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== - dependencies: - onetime "^5.1.0" - signal-exit "^3.0.2" - -ret@~0.1.10: - version "0.1.15" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== - -retry@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" - integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= - -rgb-regex@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1" - integrity sha1-wODWiC3w4jviVKR16O3UGRX+rrE= - -rgba-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" - integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= - -rimraf@2.6.3: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== - dependencies: - glob "^7.1.3" - -rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - -ripemd160@^2.0.0, ripemd160@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" - integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - -run-async@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.0.tgz#e59054a5b86876cfae07f431d18cbaddc594f1e8" - integrity sha512-xJTbh/d7Lm7SBhc1tNvTpeCHaEzoyxPrqNlvSdMfBTYwaY++UJFyXUOxAtsRUXjlqOfj8luNaR9vjCh4KeV+pg== - dependencies: - is-promise "^2.1.0" - -run-queue@^1.0.0, run-queue@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" - integrity sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec= - dependencies: - aproba "^1.1.1" - -rxjs@^6.5.3: - version "6.5.5" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.5.tgz#c5c884e3094c8cfee31bf27eb87e54ccfc87f9ec" - integrity sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ== - dependencies: - tslib "^1.9.0" - -safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" - integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== - -safe-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= - dependencies: - ret "~0.1.10" - -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@^2.1.2, safer-buffer@~2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -sax@^1.2.4, sax@~1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== - -schema-utils@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" - integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== - dependencies: - ajv "^6.1.0" - ajv-errors "^1.0.0" - ajv-keywords "^3.1.0" - -section-matter@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/section-matter/-/section-matter-1.0.0.tgz#e9041953506780ec01d59f292a19c7b850b84167" - integrity sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA== - dependencies: - extend-shallow "^2.0.1" - kind-of "^6.0.0" - -select-hose@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" - integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo= - -select@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d" - integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0= - -selfsigned@^1.10.7: - version "1.10.7" - resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.7.tgz#da5819fd049d5574f28e88a9bcc6dbc6e6f3906b" - integrity sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA== - dependencies: - node-forge "0.9.0" - -semver-diff@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-3.1.1.tgz#05f77ce59f325e00e2706afd67bb506ddb1ca32b" - integrity sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg== - dependencies: - semver "^6.3.0" - -semver@7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" - integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== - -semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@^6.0.0, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -send@0.17.1: - version "0.17.1" - resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" - integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== - dependencies: - debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "~1.7.2" - mime "1.6.0" - ms "2.1.1" - on-finished "~2.3.0" - range-parser "~1.2.1" - statuses "~1.5.0" - -serialize-javascript@^1.3.0, serialize-javascript@^1.7.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.9.1.tgz#cfc200aef77b600c47da9bb8149c943e798c2fdb" - integrity sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A== - -serve-index@^1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" - integrity sha1-03aNabHn2C5c4FD/9bRTvqEqkjk= - dependencies: - accepts "~1.3.4" - batch "0.6.1" - debug "2.6.9" - escape-html "~1.0.3" - http-errors "~1.6.2" - mime-types "~2.1.17" - parseurl "~1.3.2" - -serve-static@1.14.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" - integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.17.1" - -set-blocking@^2.0.0, set-blocking@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= - -set-value@^2.0.0, set-value@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" - integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.3" - split-string "^3.0.1" - -setimmediate@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= - -setprototypeof@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" - integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== - -setprototypeof@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" - integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== - -sha.js@^2.4.0, sha.js@^2.4.8: - version "2.4.11" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= - dependencies: - shebang-regex "^1.0.0" - -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= - -signal-exit@^3.0.0, signal-exit@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= - -simple-swizzle@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" - integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= - dependencies: - is-arrayish "^0.3.1" - -slash@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" - integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= - -slash@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" - integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== - -slice-ansi@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" - integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== - dependencies: - ansi-styles "^3.2.0" - astral-regex "^1.0.0" - is-fullwidth-code-point "^2.0.0" - -smoothscroll-polyfill@^0.4.3: - version "0.4.4" - resolved "https://registry.yarnpkg.com/smoothscroll-polyfill/-/smoothscroll-polyfill-0.4.4.tgz#3a259131dc6930e6ca80003e1cb03b603b69abf8" - integrity sha512-TK5ZA9U5RqCwMpfoMq/l1mrH0JAR7y7KRvOBx0n2869aLxch+gT9GhN3yUfjiw+d/DiF1mKo14+hd62JyMmoBg== - -snapdragon-node@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== - dependencies: - define-property "^1.0.0" - isobject "^3.0.0" - snapdragon-util "^3.0.1" - -snapdragon-util@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== - dependencies: - kind-of "^3.2.0" - -snapdragon@^0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== - dependencies: - base "^0.11.1" - debug "^2.2.0" - define-property "^0.2.5" - extend-shallow "^2.0.1" - map-cache "^0.2.2" - source-map "^0.5.6" - source-map-resolve "^0.5.0" - use "^3.1.0" - -sockjs-client@1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.4.0.tgz#c9f2568e19c8fd8173b4997ea3420e0bb306c7d5" - integrity sha512-5zaLyO8/nri5cua0VtOrFXBPK1jbL4+1cebT/mmKA1E1ZXOvJrII75bPu0l0k843G/+iAbhEqzyKr0w/eCCj7g== - dependencies: - debug "^3.2.5" - eventsource "^1.0.7" - faye-websocket "~0.11.1" - inherits "^2.0.3" - json3 "^3.3.2" - url-parse "^1.4.3" - -sockjs@0.3.19: - version "0.3.19" - resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.19.tgz#d976bbe800af7bd20ae08598d582393508993c0d" - integrity sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw== - dependencies: - faye-websocket "^0.10.0" - uuid "^3.0.1" - -sort-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128" - integrity sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg= - dependencies: - is-plain-obj "^1.0.0" - -source-list-map@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" - integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== - -source-map-resolve@^0.5.0, source-map-resolve@^0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" - integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== - dependencies: - atob "^2.1.1" - decode-uri-component "^0.2.0" - resolve-url "^0.2.1" - source-map-url "^0.4.0" - urix "^0.1.0" - -source-map-support@~0.5.12: - version "0.5.13" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" - integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map-url@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" - integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= - -source-map@0.5.6: - version "0.5.6" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" - integrity sha1-dc449SvwczxafwwRjYEzSiu19BI= - -source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -source-map@^0.7.3: - version "0.7.3" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" - integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== - -spdy-transport@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" - integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw== - dependencies: - debug "^4.1.0" - detect-node "^2.0.4" - hpack.js "^2.1.6" - obuf "^1.1.2" - readable-stream "^3.0.6" - wbuf "^1.7.3" - -spdy@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.1.tgz#6f12ed1c5db7ea4f24ebb8b89ba58c87c08257f2" - integrity sha512-HeZS3PBdMA+sZSu0qwpCxl3DeALD5ASx8pAX0jZdKXSpPWbQ6SYGnlg3BBmYLx5LtiZrmkAZfErCm2oECBcioA== - dependencies: - debug "^4.1.0" - handle-thing "^2.0.0" - http-deceiver "^1.2.7" - select-hose "^2.0.0" - spdy-transport "^3.0.0" - -split-string@^3.0.1, split-string@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== - dependencies: - extend-shallow "^3.0.0" - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= - -sshpk@^1.7.0: - version "1.16.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" - integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - bcrypt-pbkdf "^1.0.0" - dashdash "^1.12.0" - ecc-jsbn "~0.1.1" - getpass "^0.1.1" - jsbn "~0.1.0" - safer-buffer "^2.0.2" - tweetnacl "~0.14.0" - -ssri@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8" - integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA== - dependencies: - figgy-pudding "^3.5.1" - -stable@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" - integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== - -stack-utils@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8" - integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA== - -static-extend@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= - dependencies: - define-property "^0.2.5" - object-copy "^0.1.0" - -"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= - -std-env@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/std-env/-/std-env-2.2.1.tgz#2ffa0fdc9e2263e0004c1211966e960948a40f6b" - integrity sha512-IjYQUinA3lg5re/YMlwlfhqNRTzMZMqE+pezevdcTaHceqx8ngEi1alX9nNCk9Sc81fy1fLDeQoaCzeiW1yBOQ== - dependencies: - ci-info "^1.6.0" - -stream-browserify@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" - integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== - dependencies: - inherits "~2.0.1" - readable-stream "^2.0.2" - -stream-each@^1.1.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" - integrity sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw== - dependencies: - end-of-stream "^1.1.0" - stream-shift "^1.0.0" - -stream-http@^2.7.2: - version "2.8.3" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" - integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== - dependencies: - builtin-status-codes "^3.0.0" - inherits "^2.0.1" - readable-stream "^2.3.6" - to-arraybuffer "^1.0.0" - xtend "^4.0.0" - -stream-shift@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" - integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI= - -strict-uri-encode@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" - integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= - -string-width@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string-width@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.1.0" - -string-width@^4.0.0, string-width@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" - integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.0" - -string.prototype.trimleft@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" - integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw== - dependencies: - define-properties "^1.1.3" - function-bind "^1.1.1" - -string.prototype.trimright@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" - integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg== - dependencies: - define-properties "^1.1.3" - function-bind "^1.1.1" - -string_decoder@^1.0.0, string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -stringify-object@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629" - integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw== - dependencies: - get-own-enumerable-property-symbols "^3.0.0" - is-obj "^1.0.1" - is-regexp "^1.0.0" - -strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= - dependencies: - ansi-regex "^3.0.0" - -strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - -strip-ansi@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" - integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== - dependencies: - ansi-regex "^5.0.0" - -strip-bom-string@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz#e5211e9224369fbb81d633a2f00044dc8cedad92" - integrity sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI= - -strip-comments@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/strip-comments/-/strip-comments-1.0.2.tgz#82b9c45e7f05873bee53f37168af930aa368679d" - integrity sha512-kL97alc47hoyIQSV165tTt9rG5dn4w1dNnBhOQ3bOU1Nc1hel09jnXANaHJ7vzHLd4Ju8kseDGzlev96pghLFw== - dependencies: - babel-extract-comments "^1.0.0" - babel-plugin-transform-object-rest-spread "^6.26.0" - -strip-eof@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= - -strip-json-comments@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" - integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw== - -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - -stylehacks@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5" - integrity sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g== - dependencies: - browserslist "^4.0.0" - postcss "^7.0.0" - postcss-selector-parser "^3.0.0" - -stylus-loader@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/stylus-loader/-/stylus-loader-3.0.2.tgz#27a706420b05a38e038e7cacb153578d450513c6" - integrity sha512-+VomPdZ6a0razP+zinir61yZgpw2NfljeSsdUF5kJuEzlo3khXhY19Fn6l8QQz1GRJGtMCo8nG5C04ePyV7SUA== - dependencies: - loader-utils "^1.0.2" - lodash.clonedeep "^4.5.0" - when "~3.6.x" - -stylus@^0.54.5: - version "0.54.7" - resolved "https://registry.yarnpkg.com/stylus/-/stylus-0.54.7.tgz#c6ce4793965ee538bcebe50f31537bfc04d88cd2" - integrity sha512-Yw3WMTzVwevT6ZTrLCYNHAFmanMxdylelL3hkWNgPMeTCpMwpV3nXjpOHuBXtFv7aiO2xRuQS6OoAdgkNcSNug== - dependencies: - css-parse "~2.0.0" - debug "~3.1.0" - glob "^7.1.3" - mkdirp "~0.5.x" - safer-buffer "^2.1.2" - sax "~1.2.4" - semver "^6.0.0" - source-map "^0.7.3" - -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" - integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" - integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== - dependencies: - has-flag "^4.0.0" - -svg-tags@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764" - integrity sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q= - -svgo@^1.0.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.0.tgz#bae51ba95ded9a33a36b7c46ce9c359ae9154313" - integrity sha512-MLfUA6O+qauLDbym+mMZgtXCGRfIxyQoeH6IKVcFslyODEe/ElJNwr0FohQ3xG4C6HK6bk3KYPPXwHVJk3V5NQ== - dependencies: - chalk "^2.4.1" - coa "^2.0.2" - css-select "^2.0.0" - css-select-base-adapter "^0.1.1" - css-tree "1.0.0-alpha.33" - csso "^3.5.1" - js-yaml "^3.13.1" - mkdirp "~0.5.1" - object.values "^1.1.0" - sax "~1.2.4" - stable "^0.1.8" - unquote "~1.1.1" - util.promisify "~1.0.0" - -table@^5.2.3: - version "5.4.6" - resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" - integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== - dependencies: - ajv "^6.10.2" - lodash "^4.17.14" - slice-ansi "^2.1.0" - string-width "^3.0.0" - -tapable@^1.0.0, tapable@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" - integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== - -tar@^4: - version "4.4.13" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" - integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== - dependencies: - chownr "^1.1.1" - fs-minipass "^1.2.5" - minipass "^2.8.6" - minizlib "^1.2.1" - mkdirp "^0.5.0" - safe-buffer "^5.1.2" - yallist "^3.0.3" - -term-size@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.0.tgz#1f16adedfe9bdc18800e1776821734086fcc6753" - integrity sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw== - -terser-webpack-plugin@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.1.tgz#61b18e40eaee5be97e771cdbb10ed1280888c2b4" - integrity sha512-ZXmmfiwtCLfz8WKZyYUuuHf3dMYEjg8NrjHMb0JqHVHVOSkzp3cW2/XG1fP3tRhqEqSzMwzzRQGtAPbs4Cncxg== - dependencies: - cacache "^12.0.2" - find-cache-dir "^2.1.0" - is-wsl "^1.1.0" - schema-utils "^1.0.0" - serialize-javascript "^1.7.0" - source-map "^0.6.1" - terser "^4.1.2" - webpack-sources "^1.4.0" - worker-farm "^1.7.0" - -terser@^4.1.2: - version "4.3.9" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.3.9.tgz#e4be37f80553d02645668727777687dad26bbca8" - integrity sha512-NFGMpHjlzmyOtPL+fDw3G7+6Ueh/sz4mkaUYa4lJCxOPTNzd0Uj0aZJOmsDYoSQyfuVoWDMSWTPU3huyOm2zdA== - dependencies: - commander "^2.20.0" - source-map "~0.6.1" - source-map-support "~0.5.12" - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= - -through2@^2.0.0: - version "2.0.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" - integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== - dependencies: - readable-stream "~2.3.6" - xtend "~4.0.1" - -through@^2.3.6, through@~2.3.4: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= - -thunky@^1.0.2: - version "1.1.0" - resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" - integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== - -timers-browserify@^2.0.4: - version "2.0.11" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.11.tgz#800b1f3eee272e5bc53ee465a04d0e804c31211f" - integrity sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ== - dependencies: - setimmediate "^1.0.4" - -timsort@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" - integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= - -tiny-emitter@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423" - integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q== - -tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - -to-arraybuffer@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" - integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= - -to-factory@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/to-factory/-/to-factory-1.0.0.tgz#8738af8bd97120ad1d4047972ada5563bf9479b1" - integrity sha1-hzivi9lxIK0dQEeXKtpVY7+UebE= - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= - -to-object-path@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= - dependencies: - kind-of "^3.0.2" - -to-readable-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" - integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== - -to-regex-range@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= - dependencies: - is-number "^3.0.0" - repeat-string "^1.6.1" - -to-regex@^3.0.1, to-regex@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== - dependencies: - define-property "^2.0.2" - extend-shallow "^3.0.2" - regex-not "^1.0.2" - safe-regex "^1.1.0" - -toidentifier@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" - integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== - -toml@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/toml/-/toml-3.0.0.tgz#342160f1af1904ec9d204d03a5d61222d762c5ee" - integrity sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w== - -toposort@^1.0.0: - version "1.0.7" - resolved "https://registry.yarnpkg.com/toposort/-/toposort-1.0.7.tgz#2e68442d9f64ec720b8cc89e6443ac6caa950029" - integrity sha1-LmhELZ9k7HILjMieZEOsbKqVACk= - -tough-cookie@~2.4.3: - version "2.4.3" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" - integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== - dependencies: - psl "^1.1.24" - punycode "^1.4.1" - -tslib@^1.9.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" - integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== - -tty-browserify@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" - integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= - -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= - dependencies: - safe-buffer "^5.0.1" - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= - -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= - dependencies: - prelude-ls "~1.1.2" - -type-fest@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1" - integrity sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ== - -type-fest@^0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.5.2.tgz#d6ef42a0356c6cd45f49485c3b6281fc148e48a2" - integrity sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw== - -type-fest@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" - integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== - -type-is@~1.6.17, type-is@~1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" - -typedarray-to-buffer@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== - dependencies: - is-typedarray "^1.0.0" - -typedarray@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= - -uc.micro@^1.0.1, uc.micro@^1.0.5: - version "1.0.6" - resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" - integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== - -uglify-js@3.4.x: - version "3.4.10" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.10.tgz#9ad9563d8eb3acdfb8d38597d2af1d815f6a755f" - integrity sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw== - dependencies: - commander "~2.19.0" - source-map "~0.6.1" - -unicode-canonical-property-names-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" - integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== - -unicode-match-property-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" - integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== - dependencies: - unicode-canonical-property-names-ecmascript "^1.0.4" - unicode-property-aliases-ecmascript "^1.0.4" - -unicode-match-property-value-ecmascript@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz#0d91f600eeeb3096aa962b1d6fc88876e64ea531" - integrity sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ== - -unicode-property-aliases-ecmascript@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz#a9cc6cc7ce63a0a3023fc99e341b94431d405a57" - integrity sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw== - -union-value@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" - integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== - dependencies: - arr-union "^3.1.0" - get-value "^2.0.6" - is-extendable "^0.1.1" - set-value "^2.0.1" - -uniq@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" - integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= - -uniqs@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" - integrity sha1-/+3ks2slKQaW5uFl1KWe25mOawI= - -unique-filename@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" - integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== - dependencies: - unique-slug "^2.0.0" - -unique-slug@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" - integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== - dependencies: - imurmurhash "^0.1.4" - -unique-string@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" - integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg== - dependencies: - crypto-random-string "^2.0.0" - -universalify@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== - -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= - -unquote@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" - integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= - -unset-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= - dependencies: - has-value "^0.3.1" - isobject "^3.0.0" - -upath@^1.1.0, upath@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" - integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== - -update-notifier@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-4.1.0.tgz#4866b98c3bc5b5473c020b1250583628f9a328f3" - integrity sha512-w3doE1qtI0/ZmgeoDoARmI5fjDoT93IfKgEGqm26dGUOh8oNpaSTsGNdYRN/SjOuo10jcJGwkEL3mroKzktkew== - dependencies: - boxen "^4.2.0" - chalk "^3.0.0" - configstore "^5.0.1" - has-yarn "^2.1.0" - import-lazy "^2.1.0" - is-ci "^2.0.0" - is-installed-globally "^0.3.1" - is-npm "^4.0.0" - is-yarn-global "^0.3.0" - latest-version "^5.0.0" - pupa "^2.0.1" - semver-diff "^3.1.1" - xdg-basedir "^4.0.0" - -upper-case@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" - integrity sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg= - -uri-js@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" - integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== - dependencies: - punycode "^2.1.0" - -urix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= - -url-loader@^1.0.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-1.1.2.tgz#b971d191b83af693c5e3fea4064be9e1f2d7f8d8" - integrity sha512-dXHkKmw8FhPqu8asTc1puBfe3TehOCo2+RmOOev5suNCIYBcT626kxiWg1NBVkwc4rO8BGa7gP70W7VXuqHrjg== - dependencies: - loader-utils "^1.1.0" - mime "^2.0.3" - schema-utils "^1.0.0" - -url-parse-lax@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" - integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= - dependencies: - prepend-http "^2.0.0" - -url-parse@^1.4.3: - version "1.4.7" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278" - integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg== - dependencies: - querystringify "^2.1.1" - requires-port "^1.0.0" - -url@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= - dependencies: - punycode "1.3.2" - querystring "0.2.0" - -use@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" - integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== - -util-deprecate@^1.0.1, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -util.promisify@1.0.0, util.promisify@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" - integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA== - dependencies: - define-properties "^1.1.2" - object.getownpropertydescriptors "^2.0.3" - -util@0.10.3: - version "0.10.3" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" - integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= - dependencies: - inherits "2.0.1" - -util@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" - integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== - dependencies: - inherits "2.0.3" - -utila@^0.4.0, utila@~0.4: - version "0.4.0" - resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" - integrity sha1-ihagXURWV6Oupe7MWxKk+lN5dyw= - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= - -uuid@^3.0.1, uuid@^3.3.2: - version "3.3.3" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866" - integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ== - -v8-compile-cache@^2.0.3: - version "2.1.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" - integrity sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g== - -vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= - -vendors@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.3.tgz#a6467781abd366217c050f8202e7e50cc9eef8c0" - integrity sha512-fOi47nsJP5Wqefa43kyWSg80qF+Q3XA6MUkgi7Hp1HQaKDQW4cQrK2D0P7mmbFtsV1N89am55Yru/nyEwRubcw== - -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - -vm-browserify@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.0.tgz#bd76d6a23323e2ca8ffa12028dc04559c75f9019" - integrity sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw== - -vue-eslint-parser@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-7.0.0.tgz#a4ed2669f87179dedd06afdd8736acbb3a3864d6" - integrity sha512-yR0dLxsTT7JfD2YQo9BhnQ6bUTLsZouuzt9SKRP7XNaZJV459gvlsJo4vT2nhZ/2dH9j3c53bIx9dnqU2prM9g== - dependencies: - debug "^4.1.1" - eslint-scope "^5.0.0" - eslint-visitor-keys "^1.1.0" - espree "^6.1.2" - esquery "^1.0.1" - lodash "^4.17.15" - -vue-hot-reload-api@^2.3.0: - version "2.3.4" - resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz#532955cc1eb208a3d990b3a9f9a70574657e08f2" - integrity sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog== - -vue-loader@^15.7.1: - version "15.7.1" - resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.7.1.tgz#6ccacd4122aa80f69baaac08ff295a62e3aefcfd" - integrity sha512-fwIKtA23Pl/rqfYP5TSGK7gkEuLhoTvRYW+TU7ER3q9GpNLt/PjG5NLv3XHRDiTg7OPM1JcckBgds+VnAc+HbA== - dependencies: - "@vue/component-compiler-utils" "^3.0.0" - hash-sum "^1.0.2" - loader-utils "^1.1.0" - vue-hot-reload-api "^2.3.0" - vue-style-loader "^4.1.0" - -vue-router@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.1.3.tgz#e6b14fabc0c0ee9fda0e2cbbda74b350e28e412b" - integrity sha512-8iSa4mGNXBjyuSZFCCO4fiKfvzqk+mhL0lnKuGcQtO1eoj8nq3CmbEG8FwK5QqoqwDgsjsf1GDuisDX4cdb/aQ== - -vue-server-renderer@^2.6.10: - version "2.6.10" - resolved "https://registry.yarnpkg.com/vue-server-renderer/-/vue-server-renderer-2.6.10.tgz#cb2558842ead360ae2ec1f3719b75564a805b375" - integrity sha512-UYoCEutBpKzL2fKCwx8zlRtRtwxbPZXKTqbl2iIF4yRZUNO/ovrHyDAJDljft0kd+K0tZhN53XRHkgvCZoIhug== - dependencies: - chalk "^1.1.3" - hash-sum "^1.0.2" - he "^1.1.0" - lodash.template "^4.4.0" - lodash.uniq "^4.5.0" - resolve "^1.2.0" - serialize-javascript "^1.3.0" - source-map "0.5.6" - -vue-style-loader@^4.1.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/vue-style-loader/-/vue-style-loader-4.1.2.tgz#dedf349806f25ceb4e64f3ad7c0a44fba735fcf8" - integrity sha512-0ip8ge6Gzz/Bk0iHovU9XAUQaFt/G2B61bnWa2tCcqqdgfHs1lF9xXorFbE55Gmy92okFT+8bfmySuUOu13vxQ== - dependencies: - hash-sum "^1.0.2" - loader-utils "^1.0.2" - -vue-template-compiler@^2.6.10: - version "2.6.10" - resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.6.10.tgz#323b4f3495f04faa3503337a82f5d6507799c9cc" - integrity sha512-jVZkw4/I/HT5ZMvRnhv78okGusqe0+qH2A0Em0Cp8aq78+NK9TII263CDVz2QXZsIT+yyV/gZc/j/vlwa+Epyg== - dependencies: - de-indent "^1.0.2" - he "^1.1.0" - -vue-template-es2015-compiler@^1.9.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825" - integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw== - -vue@^2.6.10: - version "2.6.10" - resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.10.tgz#a72b1a42a4d82a721ea438d1b6bf55e66195c637" - integrity sha512-ImThpeNU9HbdZL3utgMCq0oiMzAkt1mcgy3/E6zWC/G6AaQoeuFdsl9nDhTDU3X1R6FK7nsIUuRACVcjI+A2GQ== - -vuepress-html-webpack-plugin@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/vuepress-html-webpack-plugin/-/vuepress-html-webpack-plugin-3.2.0.tgz#219be272ad510faa8750d2d4e70fd028bfd1c16e" - integrity sha512-BebAEl1BmWlro3+VyDhIOCY6Gef2MCBllEVAP3NUAtMguiyOwo/dClbwJ167WYmcxHJKLl7b0Chr9H7fpn1d0A== - dependencies: - html-minifier "^3.2.3" - loader-utils "^0.2.16" - lodash "^4.17.3" - pretty-error "^2.0.2" - tapable "^1.0.0" - toposort "^1.0.0" - util.promisify "1.0.0" - -vuepress-plugin-container@^2.0.2: - version "2.1.0" - resolved "https://registry.yarnpkg.com/vuepress-plugin-container/-/vuepress-plugin-container-2.1.0.tgz#eb2ba3e01cdac419bd678d40e05c934caffe6db0" - integrity sha512-i4p7S1cqYUrg/3pt+xSghZtKSHVI3VXMQNept8ILxA+lMK1XJkdRkjNovZzwpXlrErQssvrUOTWBV0hdBv7eXQ== - dependencies: - markdown-it-container "^2.0.0" - -vuepress-plugin-dehydrate@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/vuepress-plugin-dehydrate/-/vuepress-plugin-dehydrate-1.1.3.tgz#191460ed3776605b945ae74d26394338c12d5cd7" - integrity sha512-alSW3BXgwmm1U9F6UmeFvP58t0xluNkzxQ9OfsWTq+UG8UyUsdqV6ltaii6wWA0cmlfqOswdQXwgcifJ6jAIfw== - dependencies: - "@vuepress/shared-utils" "^1.2.0" - -vuepress-plugin-medium-zoom@^1.1.8: - version "1.1.8" - resolved "https://registry.yarnpkg.com/vuepress-plugin-medium-zoom/-/vuepress-plugin-medium-zoom-1.1.8.tgz#bb1ea5cdd50efd218b385b5f5fe46c3e1d2d4ec1" - integrity sha512-G6s/kDw7obUqaTNhg94+wbuMYPLmPRS4jZ8voJPO/SHyKq/myzDdTL9OzYq3EMVz/P1pROYhN+jNCT7KpdaAZg== - dependencies: - medium-zoom "^1.0.4" - -vuepress-plugin-redirect@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/vuepress-plugin-redirect/-/vuepress-plugin-redirect-1.2.3.tgz#f0454c7c609f16fa63bb268a0b8e561ee42b2381" - integrity sha512-XIG2Ijty/2WFf5smJylFHArlOmFxZyJI6hrrdIHsDIwGDSJFSl0Q97c9ZgnvkeegsxEHbxjtKOBBI/MMf8qtbg== - dependencies: - "@shigma/stringify-object" "^3.3.0" - vuepress-plugin-dehydrate "1.1.3" - -vuepress-plugin-serve@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/vuepress-plugin-serve/-/vuepress-plugin-serve-2.0.2.tgz#bcadee237348976a3c4087c37578e2c7abeb4726" - integrity sha512-4nFUA3hKVacneAt4i1+eXTT7sQNQyq3Cdiyq6xaI/KTUWbCxU0hGTTdPItci67G3qG7ows+uZx4FxPZhruyxcQ== - dependencies: - chalk "^2.4.2" - express "^4.16.4" - opn "^5.4.0" - -vuepress-plugin-smooth-scroll@^0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/vuepress-plugin-smooth-scroll/-/vuepress-plugin-smooth-scroll-0.0.3.tgz#6eff2d4c186cca917cc9f7df2b0af7de7c8c6438" - integrity sha512-qsQkDftLVFLe8BiviIHaLV0Ea38YLZKKonDGsNQy1IE0wllFpFIEldWD8frWZtDFdx6b/O3KDMgVQ0qp5NjJCg== - dependencies: - smoothscroll-polyfill "^0.4.3" - -vuepress@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/vuepress/-/vuepress-1.4.1.tgz#726885da5c569755b40fd795ef3aed3fae13f83c" - integrity sha512-vFePZLEx9FRJf5buDqSSBHHbTrPzBsL1u3Z4LX0HI9iQmHjkP+cGA8MMS0zVYy/xyYf28xWLWo3L/gj0rdMy7w== - dependencies: - "@vuepress/core" "1.4.1" - "@vuepress/theme-default" "1.4.1" - cac "^6.5.6" - envinfo "^7.2.0" - opencollective-postinstall "^2.0.2" - update-notifier "^4.0.0" - -watchpack@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" - integrity sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA== - dependencies: - chokidar "^2.0.2" - graceful-fs "^4.1.2" - neo-async "^2.5.0" - -wbuf@^1.1.0, wbuf@^1.7.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" - integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA== - dependencies: - minimalistic-assert "^1.0.0" - -webpack-chain@^4.9.0: - version "4.12.1" - resolved "https://registry.yarnpkg.com/webpack-chain/-/webpack-chain-4.12.1.tgz#6c8439bbb2ab550952d60e1ea9319141906c02a6" - integrity sha512-BCfKo2YkDe2ByqkEWe1Rw+zko4LsyS75LVr29C6xIrxAg9JHJ4pl8kaIZ396SUSNp6b4815dRZPSTAS8LlURRQ== - dependencies: - deepmerge "^1.5.2" - javascript-stringify "^1.6.0" - -webpack-chain@^6.0.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/webpack-chain/-/webpack-chain-6.4.0.tgz#22f0b27b6a9bc9ee3cba4f9e6513cf66394034e2" - integrity sha512-f97PYqxU+9/u0IUqp/ekAHRhBD1IQwhBv3wlJo2nvyELpr2vNnUqO3XQEk+qneg0uWGP54iciotszpjfnEExFA== - dependencies: - deepmerge "^1.5.2" - javascript-stringify "^2.0.1" - -webpack-dev-middleware@^3.7.2: - version "3.7.2" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz#0019c3db716e3fa5cecbf64f2ab88a74bab331f3" - integrity sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw== - dependencies: - memory-fs "^0.4.1" - mime "^2.4.4" - mkdirp "^0.5.1" - range-parser "^1.2.1" - webpack-log "^2.0.0" - -webpack-dev-server@^3.5.1: - version "3.8.2" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.8.2.tgz#3292427bf6510da9a3ac2d500b924a4197667ff9" - integrity sha512-0xxogS7n5jHDQWy0WST0q6Ykp7UGj4YvWh+HVN71JoE7BwPxMZrwgraBvmdEMbDVMBzF0u+mEzn8TQzBm5NYJQ== - dependencies: - ansi-html "0.0.7" - bonjour "^3.5.0" - chokidar "^2.1.8" - compression "^1.7.4" - connect-history-api-fallback "^1.6.0" - debug "^4.1.1" - del "^4.1.1" - express "^4.17.1" - html-entities "^1.2.1" - http-proxy-middleware "0.19.1" - import-local "^2.0.0" - internal-ip "^4.3.0" - ip "^1.1.5" - is-absolute-url "^3.0.3" - killable "^1.0.1" - loglevel "^1.6.4" - opn "^5.5.0" - p-retry "^3.0.1" - portfinder "^1.0.24" - schema-utils "^1.0.0" - selfsigned "^1.10.7" - semver "^6.3.0" - serve-index "^1.9.1" - sockjs "0.3.19" - sockjs-client "1.4.0" - spdy "^4.0.1" - strip-ansi "^3.0.1" - supports-color "^6.1.0" - url "^0.11.0" - webpack-dev-middleware "^3.7.2" - webpack-log "^2.0.0" - ws "^6.2.1" - yargs "12.0.5" - -webpack-log@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-2.0.0.tgz#5b7928e0637593f119d32f6227c1e0ac31e1b47f" - integrity sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg== - dependencies: - ansi-colors "^3.0.0" - uuid "^3.3.2" - -webpack-merge@^4.1.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.2.2.tgz#a27c52ea783d1398afd2087f547d7b9d2f43634d" - integrity sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g== - dependencies: - lodash "^4.17.15" - -webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1: - version "1.4.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" - integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== - dependencies: - source-list-map "^2.0.0" - source-map "~0.6.1" - -webpack@^4.8.1: - version "4.41.2" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.41.2.tgz#c34ec76daa3a8468c9b61a50336d8e3303dce74e" - integrity sha512-Zhw69edTGfbz9/8JJoyRQ/pq8FYUoY0diOXqW0T6yhgdhCv6wr0hra5DwwWexNRns2Z2+gsnrNcbe9hbGBgk/A== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-module-context" "1.8.5" - "@webassemblyjs/wasm-edit" "1.8.5" - "@webassemblyjs/wasm-parser" "1.8.5" - acorn "^6.2.1" - ajv "^6.10.2" - ajv-keywords "^3.4.1" - chrome-trace-event "^1.0.2" - enhanced-resolve "^4.1.0" - eslint-scope "^4.0.3" - json-parse-better-errors "^1.0.2" - loader-runner "^2.4.0" - loader-utils "^1.2.3" - memory-fs "^0.4.1" - micromatch "^3.1.10" - mkdirp "^0.5.1" - neo-async "^2.6.1" - node-libs-browser "^2.2.1" - schema-utils "^1.0.0" - tapable "^1.1.3" - terser-webpack-plugin "^1.4.1" - watchpack "^1.6.0" - webpack-sources "^1.4.1" - -webpackbar@3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/webpackbar/-/webpackbar-3.2.0.tgz#bdaad103fad11a4e612500e72aaae98b08ba493f" - integrity sha512-PC4o+1c8gWWileUfwabe0gqptlXUDJd5E0zbpr2xHP1VSOVlZVPBZ8j6NCR8zM5zbKdxPhctHXahgpNK1qFDPw== - dependencies: - ansi-escapes "^4.1.0" - chalk "^2.4.1" - consola "^2.6.0" - figures "^3.0.0" - pretty-time "^1.1.0" - std-env "^2.2.1" - text-table "^0.2.0" - wrap-ansi "^5.1.0" - -websocket-driver@>=0.5.1: - version "0.7.3" - resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.3.tgz#a2d4e0d4f4f116f1e6297eba58b05d430100e9f9" - integrity sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg== - dependencies: - http-parser-js ">=0.4.0 <0.4.11" - safe-buffer ">=5.1.0" - websocket-extensions ">=0.1.1" - -websocket-extensions@>=0.1.1: - version "0.1.4" - resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" - integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== - -when@~3.6.x: - version "3.6.4" - resolved "https://registry.yarnpkg.com/when/-/when-3.6.4.tgz#473b517ec159e2b85005497a13983f095412e34e" - integrity sha1-RztRfsFZ4rhQBUl6E5g/CVQS404= - -which-module@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= - -which@^1.2.9: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - -wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== - dependencies: - string-width "^1.0.2 || 2" - -widest-line@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" - integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== - dependencies: - string-width "^4.0.0" - -word-wrap@~1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== - -workbox-background-sync@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/workbox-background-sync/-/workbox-background-sync-4.3.1.tgz#26821b9bf16e9e37fd1d640289edddc08afd1950" - integrity sha512-1uFkvU8JXi7L7fCHVBEEnc3asPpiAL33kO495UMcD5+arew9IbKW2rV5lpzhoWcm/qhGB89YfO4PmB/0hQwPRg== - dependencies: - workbox-core "^4.3.1" - -workbox-broadcast-update@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/workbox-broadcast-update/-/workbox-broadcast-update-4.3.1.tgz#e2c0280b149e3a504983b757606ad041f332c35b" - integrity sha512-MTSfgzIljpKLTBPROo4IpKjESD86pPFlZwlvVG32Kb70hW+aob4Jxpblud8EhNb1/L5m43DUM4q7C+W6eQMMbA== - dependencies: - workbox-core "^4.3.1" - -workbox-build@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/workbox-build/-/workbox-build-4.3.1.tgz#414f70fb4d6de47f6538608b80ec52412d233e64" - integrity sha512-UHdwrN3FrDvicM3AqJS/J07X0KXj67R8Cg0waq1MKEOqzo89ap6zh6LmaLnRAjpB+bDIz+7OlPye9iii9KBnxw== - dependencies: - "@babel/runtime" "^7.3.4" - "@hapi/joi" "^15.0.0" - common-tags "^1.8.0" - fs-extra "^4.0.2" - glob "^7.1.3" - lodash.template "^4.4.0" - pretty-bytes "^5.1.0" - stringify-object "^3.3.0" - strip-comments "^1.0.2" - workbox-background-sync "^4.3.1" - workbox-broadcast-update "^4.3.1" - workbox-cacheable-response "^4.3.1" - workbox-core "^4.3.1" - workbox-expiration "^4.3.1" - workbox-google-analytics "^4.3.1" - workbox-navigation-preload "^4.3.1" - workbox-precaching "^4.3.1" - workbox-range-requests "^4.3.1" - workbox-routing "^4.3.1" - workbox-strategies "^4.3.1" - workbox-streams "^4.3.1" - workbox-sw "^4.3.1" - workbox-window "^4.3.1" - -workbox-cacheable-response@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/workbox-cacheable-response/-/workbox-cacheable-response-4.3.1.tgz#f53e079179c095a3f19e5313b284975c91428c91" - integrity sha512-Rp5qlzm6z8IOvnQNkCdO9qrDgDpoPNguovs0H8C+wswLuPgSzSp9p2afb5maUt9R1uTIwOXrVQMmPfPypv+npw== - dependencies: - workbox-core "^4.3.1" - -workbox-core@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/workbox-core/-/workbox-core-4.3.1.tgz#005d2c6a06a171437afd6ca2904a5727ecd73be6" - integrity sha512-I3C9jlLmMKPxAC1t0ExCq+QoAMd0vAAHULEgRZ7kieCdUd919n53WC0AfvokHNwqRhGn+tIIj7vcb5duCjs2Kg== - -workbox-expiration@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/workbox-expiration/-/workbox-expiration-4.3.1.tgz#d790433562029e56837f341d7f553c4a78ebe921" - integrity sha512-vsJLhgQsQouv9m0rpbXubT5jw0jMQdjpkum0uT+d9tTwhXcEZks7qLfQ9dGSaufTD2eimxbUOJfWLbNQpIDMPw== - dependencies: - workbox-core "^4.3.1" - -workbox-google-analytics@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/workbox-google-analytics/-/workbox-google-analytics-4.3.1.tgz#9eda0183b103890b5c256e6f4ea15a1f1548519a" - integrity sha512-xzCjAoKuOb55CBSwQrbyWBKqp35yg1vw9ohIlU2wTy06ZrYfJ8rKochb1MSGlnoBfXGWss3UPzxR5QL5guIFdg== - dependencies: - workbox-background-sync "^4.3.1" - workbox-core "^4.3.1" - workbox-routing "^4.3.1" - workbox-strategies "^4.3.1" - -workbox-navigation-preload@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/workbox-navigation-preload/-/workbox-navigation-preload-4.3.1.tgz#29c8e4db5843803b34cd96dc155f9ebd9afa453d" - integrity sha512-K076n3oFHYp16/C+F8CwrRqD25GitA6Rkd6+qAmLmMv1QHPI2jfDwYqrytOfKfYq42bYtW8Pr21ejZX7GvALOw== - dependencies: - workbox-core "^4.3.1" - -workbox-precaching@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/workbox-precaching/-/workbox-precaching-4.3.1.tgz#9fc45ed122d94bbe1f0ea9584ff5940960771cba" - integrity sha512-piSg/2csPoIi/vPpp48t1q5JLYjMkmg5gsXBQkh/QYapCdVwwmKlU9mHdmy52KsDGIjVaqEUMFvEzn2LRaigqQ== - dependencies: - workbox-core "^4.3.1" - -workbox-range-requests@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/workbox-range-requests/-/workbox-range-requests-4.3.1.tgz#f8a470188922145cbf0c09a9a2d5e35645244e74" - integrity sha512-S+HhL9+iTFypJZ/yQSl/x2Bf5pWnbXdd3j57xnb0V60FW1LVn9LRZkPtneODklzYuFZv7qK6riZ5BNyc0R0jZA== - dependencies: - workbox-core "^4.3.1" - -workbox-routing@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/workbox-routing/-/workbox-routing-4.3.1.tgz#a675841af623e0bb0c67ce4ed8e724ac0bed0cda" - integrity sha512-FkbtrODA4Imsi0p7TW9u9MXuQ5P4pVs1sWHK4dJMMChVROsbEltuE79fBoIk/BCztvOJ7yUpErMKa4z3uQLX+g== - dependencies: - workbox-core "^4.3.1" - -workbox-strategies@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/workbox-strategies/-/workbox-strategies-4.3.1.tgz#d2be03c4ef214c115e1ab29c9c759c9fe3e9e646" - integrity sha512-F/+E57BmVG8dX6dCCopBlkDvvhg/zj6VDs0PigYwSN23L8hseSRwljrceU2WzTvk/+BSYICsWmRq5qHS2UYzhw== - dependencies: - workbox-core "^4.3.1" - -workbox-streams@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/workbox-streams/-/workbox-streams-4.3.1.tgz#0b57da70e982572de09c8742dd0cb40a6b7c2cc3" - integrity sha512-4Kisis1f/y0ihf4l3u/+ndMkJkIT4/6UOacU3A4BwZSAC9pQ9vSvJpIi/WFGQRH/uPXvuVjF5c2RfIPQFSS2uA== - dependencies: - workbox-core "^4.3.1" - -workbox-sw@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/workbox-sw/-/workbox-sw-4.3.1.tgz#df69e395c479ef4d14499372bcd84c0f5e246164" - integrity sha512-0jXdusCL2uC5gM3yYFT6QMBzKfBr2XTk0g5TPAV4y8IZDyVNDyj1a8uSXy3/XrvkVTmQvLN4O5k3JawGReXr9w== - -workbox-window@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/workbox-window/-/workbox-window-4.3.1.tgz#ee6051bf10f06afa5483c9b8dfa0531994ede0f3" - integrity sha512-C5gWKh6I58w3GeSc0wp2Ne+rqVw8qwcmZnQGpjiek8A2wpbxSJb1FdCoQVO+jDJs35bFgo/WETgl1fqgsxN0Hg== - dependencies: - workbox-core "^4.3.1" - -worker-farm@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8" - integrity sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw== - dependencies: - errno "~0.1.7" - -wrap-ansi@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" - integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - -wrap-ansi@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" - integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== - dependencies: - ansi-styles "^3.2.0" - string-width "^3.0.0" - strip-ansi "^5.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -write-file-atomic@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" - integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== - dependencies: - imurmurhash "^0.1.4" - is-typedarray "^1.0.0" - signal-exit "^3.0.2" - typedarray-to-buffer "^3.1.5" - -write@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" - integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== - dependencies: - mkdirp "^0.5.1" - -ws@^6.2.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" - integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== - dependencies: - async-limiter "~1.0.0" - -xdg-basedir@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" - integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== - -xtend@^4.0.0, xtend@~4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -"y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" - integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== - -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= - -yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== - -yargs-parser@^11.1.1: - version "11.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4" - integrity sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - -yargs@12.0.5: - version "12.0.5" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13" - integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw== - dependencies: - cliui "^4.0.0" - decamelize "^1.2.0" - find-up "^3.0.0" - get-caller-file "^1.0.1" - os-locale "^3.0.0" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^2.0.0" - which-module "^2.0.0" - y18n "^3.2.1 || ^4.0.0" - yargs-parser "^11.1.1" - -zepto@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/zepto/-/zepto-1.2.0.tgz#e127bd9e66fd846be5eab48c1394882f7c0e4f98" - integrity sha1-4Se9nmb9hGvl6rSME5SIL3wOT5g= diff --git a/include/effectengine/Effect.h b/include/effectengine/Effect.h index a1ecc990..248d458f 100644 --- a/include/effectengine/Effect.h +++ b/include/effectengine/Effect.h @@ -21,6 +21,9 @@ class Effect : public QThread Q_OBJECT public: + + static const int ENDLESS; + friend class EffectModule; Effect(Hyperion *hyperion @@ -44,10 +47,21 @@ public: void requestInterruption() { _interupt = true; } /// - /// @brief Check if the interruption flag has been set + /// @brief Check an interruption was requested. + /// This can come from requestInterruption() + /// or the effect's timeout expiring. + /// /// @return The flag state /// - bool isInterruptionRequested() { return _interupt; } + bool isInterruptionRequested(); + + /// + /// @brief Get the remaining timeout, or indication it is endless + /// + /// @return The flag state + /// + int getRemaining() const; + QString getScript() const { return _script; } QString getName() const { return _name; } @@ -76,7 +90,7 @@ private: const QJsonObject _args; const QString _imageData; - int64_t _endTime; + qint64 _endTime; /// Buffer for colorData QVector _colors; diff --git a/include/effectengine/EffectEngine.h b/include/effectengine/EffectEngine.h index 0288a1ac..455b3f18 100644 --- a/include/effectengine/EffectEngine.h +++ b/include/effectengine/EffectEngine.h @@ -13,6 +13,7 @@ // Effect engine includes #include +#include #include #include #include @@ -69,13 +70,13 @@ signals: public slots: /// Run the specified effect on the given priority channel and optionally specify a timeout - int runEffect(const QString &effectName, int priority, int timeout = -1, const QString &origin="System"); + int runEffect(const QString &effectName, int priority, int timeout = Effect::ENDLESS, const QString &origin="System"); /// Run the specified effect on the given priority channel and optionally specify a timeout int runEffect(const QString &effectName , const QJsonObject &args , int priority - , int timeout = -1 + , int timeout = Effect::ENDLESS , const QString &pythonScript = "" , const QString &origin = "System" , unsigned smoothCfg=0 @@ -102,7 +103,7 @@ private: ,const QString &name , const QJsonObject &args , int priority - , int timeout = -1 + , int timeout = Effect::ENDLESS , const QString &origin="System" , unsigned smoothCfg=0 , const QString &imageData = "" diff --git a/include/effectengine/EffectFileHandler.h b/include/effectengine/EffectFileHandler.h index ea998e29..103a3504 100644 --- a/include/effectengine/EffectFileHandler.h +++ b/include/effectengine/EffectFileHandler.h @@ -64,12 +64,12 @@ private: /// /// @brief Load the effect definition, called by updateEffects() /// - bool loadEffectDefinition(const QString & path, const QString & effectConfigFile, EffectDefinition &effectDefinition); + bool loadEffectDefinition(const QString& path, const QString& effectConfigFile, EffectDefinition& effectDefinition); /// /// @brief load effect schemas, called by updateEffects() /// - bool loadEffectSchema(const QString & path, const QString & effectSchemaFile, EffectSchema &effectSchema); + bool loadEffectSchema(const QString& path, const QString& effectSchemaFile, EffectSchema& effectSchema); private: QJsonObject _effectConfig; diff --git a/include/grabber/DirectXGrabber.h b/include/grabber/DirectXGrabber.h index 39f56d49..b5cca9e5 100644 --- a/include/grabber/DirectXGrabber.h +++ b/include/grabber/DirectXGrabber.h @@ -54,6 +54,11 @@ public: /// virtual void setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom); + /// + /// @brief Apply display index + /// + void setDisplayIndex(int index) override; + private: /// /// @brief Setup a new capture display, will free the previous one @@ -68,6 +73,7 @@ private: private: int _pixelDecimation; + unsigned _display; unsigned _displayWidth; unsigned _displayHeight; RECT* _srcRect; diff --git a/include/grabber/MFGrabber.h b/include/grabber/MFGrabber.h index ab8c670f..ebdedafc 100644 --- a/include/grabber/MFGrabber.h +++ b/include/grabber/MFGrabber.h @@ -11,6 +11,9 @@ #include #include #include +#include +#include +#include // utils includes #include @@ -38,7 +41,6 @@ class MFGrabber : public Grabber { Q_OBJECT friend class SourceReaderCB; - public: struct DeviceProperties { @@ -52,79 +54,72 @@ public: GUID guid = GUID_NULL; }; - MFGrabber(const QString & device, const unsigned width, const unsigned height, const unsigned fps, int pixelDecimation, QString flipMode); + MFGrabber(); ~MFGrabber() override; void receive_image(const void *frameImageBuffer, int size); - QRectF getSignalDetectionOffset() const { return QRectF(_x_frac_min, _y_frac_min, _x_frac_max, _y_frac_max); } - bool getSignalDetectionEnabled() const { return _signalDetectionEnabled; } - bool getCecDetectionEnabled() const { return _cecDetectionEnabled; } - QStringList getDevices() const override; - QString getDeviceName(const QString& devicePath) const override { return devicePath; } - QMultiMap getDeviceInputs(const QString& devicePath) const override { return { {devicePath, 0} }; } - QStringList getAvailableEncodingFormats(const QString& devicePath, const int& /*deviceInput*/) const override; - QMultiMap getAvailableDeviceResolutions(const QString& devicePath, const int& /*deviceInput*/, const PixelFormat& encFormat) const override; - QIntList getAvailableDeviceFramerates(const QString& devicePath, const int& /*deviceInput*/, const PixelFormat& encFormat, const unsigned width, const unsigned height) const override; - void setSignalThreshold(double redSignalThreshold, double greenSignalThreshold, double blueSignalThreshold, int noSignalCounterThreshold) override; - void setSignalDetectionOffset( double verticalMin, double horizontalMin, double verticalMax, double horizontalMax) override; - void setSignalDetectionEnable(bool enable) override; - void setPixelDecimation(int pixelDecimation) override; - void setCecDetectionEnable(bool enable) override; - bool setDevice(QString device) override; + void setDevice(const QString& device); + bool setInput(int input) override; bool setWidthHeight(int width, int height) override; - bool setFramerate(int fps) override; - void setFpsSoftwareDecimation(int decimation); - bool setEncoding(QString enc); - void setFlipMode(QString flipMode); - bool setBrightnessContrastSaturationHue(int brightness, int contrast, int saturation, int hue); + void setEncoding(QString enc); + void setBrightnessContrastSaturationHue(int brightness, int contrast, int saturation, int hue); + void setSignalThreshold(double redSignalThreshold, double greenSignalThreshold, double blueSignalThreshold, int noSignalCounterThreshold); + void setSignalDetectionOffset( double verticalMin, double horizontalMin, double verticalMax, double horizontalMax); + void setSignalDetectionEnable(bool enable); + bool reload(bool force = false); - void reloadGrabber(); + /// + /// @brief Discover available Media Foundation USB devices (for configuration). + /// @param[in] params Parameters used to overwrite discovery default behaviour + /// @return A JSON structure holding a list of USB devices found + /// + QJsonArray discover(const QJsonObject& params); public slots: + bool prepare(); bool start(); void stop(); - void newThreadFrame(unsigned int _workerIndex, const Image& image,unsigned int sourceCount); + void newThreadFrame(Image image); signals: void newFrame(const Image & image); + void readError(const char* err); private: bool init(); void uninit(); HRESULT init_device(QString device, DeviceProperties props); - void uninit_device(); void enumVideoCaptureDevices(); void start_capturing(); void process_image(const void *frameImageBuffer, int size); - void checkSignalDetectionEnabled(Image image); - QString _currentDeviceName, _newDeviceName; + QString _currentDeviceName, + _newDeviceName; QMap> _deviceProperties; HRESULT _hr; + IMFSourceReader* _sourceReader; SourceReaderCB* _sourceReaderCB; - PixelFormat _pixelFormat, _pixelFormatConfig; - int _pixelDecimation, - _lineLength, + MFThreadManager* _threadManager; + PixelFormat _pixelFormat, + _pixelFormatConfig; + int _lineLength, _frameByteSize, _noSignalCounterThreshold, _noSignalCounter, - _fpsSoftwareDecimation, _brightness, _contrast, _saturation, _hue; - volatile unsigned int _currentFrame; + QAtomicInt _currentFrame; ColorRgb _noSignalThresholdColor; bool _signalDetectionEnabled, - _cecDetectionEnabled, _noSignalDetected, - _initialized; + _initialized, + _reload; double _x_frac_min, _y_frac_min, _x_frac_max, _y_frac_max; - MFThreadManager _threadManager; - IMFSourceReader* _sourceReader; #ifdef HAVE_TURBO_JPEG int _subsamp; diff --git a/include/grabber/MFThread.h b/include/grabber/MFThread.h index 567870d1..108d328c 100644 --- a/include/grabber/MFThread.h +++ b/include/grabber/MFThread.h @@ -2,7 +2,6 @@ // Qt includes #include -#include // util includes #include @@ -15,31 +14,27 @@ #include #endif -// Forward class declaration -class MFThreadManager; - /// Encoder thread for USB devices -class MFThread : public QThread +class MFThread : public QObject { Q_OBJECT - friend class MFThreadManager; - public: - MFThread(); + explicit MFThread(); ~MFThread(); void setup( - unsigned int threadIndex, PixelFormat pixelFormat, uint8_t* sharedData, + PixelFormat pixelFormat, uint8_t* sharedData, int size, int width, int height, int lineLength, int subsamp, unsigned cropLeft, unsigned cropTop, unsigned cropBottom, unsigned cropRight, - VideoMode videoMode, FlipMode flipMode, int currentFrame, int pixelDecimation); - void run(); + VideoMode videoMode, FlipMode flipMode, int pixelDecimation); - bool isBusy(); - void noBusy(); + void process(); + + bool isBusy() { return _busy; } + QAtomicInt _busy = false; signals: - void newFrame(unsigned int threadIndex, const Image& data, unsigned int sourceCount); + void newFrame(const Image& data); private: void processImageMjpeg(); @@ -51,73 +46,132 @@ private: tjtransform* _xform; #endif - static volatile bool _isActive; - volatile bool _isBusy; - QSemaphore _semaphore; - unsigned int _threadIndex; - PixelFormat _pixelFormat; - uint8_t* _localData, *_flipBuffer; - int _scalingFactorsCount, _width, _height, _lineLength, _subsamp, _currentFrame, _pixelDecimation; - unsigned long _size; - unsigned _cropLeft, _cropTop, _cropBottom, _cropRight; - FlipMode _flipMode; - ImageResampler _imageResampler; + PixelFormat _pixelFormat; + uint8_t* _localData, + *_flipBuffer; + int _scalingFactorsCount, + _width, + _height, + _lineLength, + _subsamp, + _currentFrame, + _pixelDecimation; + unsigned long _size; + unsigned _cropLeft, + _cropTop, + _cropBottom, + _cropRight; + FlipMode _flipMode; + ImageResampler _imageResampler; +}; + +template class Thread : public QThread +{ +public: + TThread *_thread; + explicit Thread(TThread *thread, QObject *parent = nullptr) + : QThread(parent) + , _thread(thread) + { + _thread->moveToThread(this); + start(); + } + + ~Thread() + { + quit(); + wait(); + } + + MFThread* thread() const { return qobject_cast(_thread); } + + void setup( + PixelFormat pixelFormat, uint8_t* sharedData, + int size, int width, int height, int lineLength, + int subsamp, unsigned cropLeft, unsigned cropTop, unsigned cropBottom, unsigned cropRight, + VideoMode videoMode, FlipMode flipMode, int pixelDecimation) + { + auto mfthread = qobject_cast(_thread); + if (mfthread != nullptr) + mfthread->setup(pixelFormat, sharedData, + size, width, height, lineLength, + subsamp, cropLeft, cropTop, cropBottom, cropRight, + videoMode, flipMode, pixelDecimation); + } + + bool isBusy() + { + auto mfthread = qobject_cast(_thread); + if (mfthread != nullptr) + return mfthread->isBusy(); + + return true; + } + + void process() + { + auto mfthread = qobject_cast(_thread); + if (mfthread != nullptr) + mfthread->process(); + } + +protected: + void run() override + { + QThread::run(); + delete _thread; + } }; class MFThreadManager : public QObject { - Q_OBJECT - + Q_OBJECT public: - MFThreadManager() : _threads(nullptr) + explicit MFThreadManager(QObject *parent = nullptr) + : QObject(parent) + , _threadCount(qMax(QThread::idealThreadCount(), 1)) + , _threads(nullptr) { - _maxThreads = qBound(1, (QThread::idealThreadCount() > 4 ? (QThread::idealThreadCount() - 1) : QThread::idealThreadCount()), 8); + _threads = new Thread*[_threadCount]; + for (int i = 0; i < _threadCount; i++) + { + _threads[i] = new Thread(new MFThread, this); + _threads[i]->setObjectName("MFThread " + i); + } } ~MFThreadManager() { if (_threads != nullptr) { - for(unsigned i=0; i < _maxThreads; i++) - if (_threads[i] != nullptr) - { - _threads[i]->deleteLater(); - _threads[i] = nullptr; - } + for(int i = 0; i < _threadCount; i++) + { + _threads[i]->deleteLater(); + _threads[i] = nullptr; + } delete[] _threads; _threads = nullptr; } } - void initThreads() + void start() { - if (_maxThreads >= 1) - { - _threads = new MFThread*[_maxThreads]; - for (unsigned i=0; i < _maxThreads; i++) - _threads[i] = new MFThread(); - } + if (_threads != nullptr) + for (int i = 0; i < _threadCount; i++) + connect(_threads[i]->thread(), &MFThread::newFrame, this, &MFThreadManager::newFrame); } - void start() { MFThread::_isActive = true; } - bool isActive() { return MFThread::_isActive; } - void stop() { - MFThread::_isActive = false; - if (_threads != nullptr) - { - for(unsigned i = 0; i < _maxThreads; i++) - if (_threads[i] != nullptr) - { - _threads[i]->quit(); - _threads[i]->wait(); - } - } + for(int i = 0; i < _threadCount; i++) + disconnect(_threads[i]->thread(), nullptr, nullptr, nullptr); } - unsigned int _maxThreads; - MFThread** _threads; + int _threadCount; + Thread** _threads; + +signals: + void newFrame(const Image& data); }; diff --git a/include/grabber/MFWrapper.h b/include/grabber/MFWrapper.h deleted file mode 100644 index 9b1d53dc..00000000 --- a/include/grabber/MFWrapper.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include -#include - -class MFWrapper : public GrabberWrapper -{ - Q_OBJECT - -public: - MFWrapper(const QString & device, const unsigned grabWidth, const unsigned grabHeight, const unsigned fps, int pixelDecimation, QString flipMode); - ~MFWrapper() override; - - bool getSignalDetectionEnable() const; - bool getCecDetectionEnable() const; - -public slots: - bool start() override; - void stop() override; - - void setSignalThreshold(double redSignalThreshold, double greenSignalThreshold, double blueSignalThreshold, int noSignalCounterThreshold); - void setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom) override; - void setSignalDetectionOffset(double verticalMin, double horizontalMin, double verticalMax, double horizontalMax); - void setSignalDetectionEnable(bool enable); - void setCecDetectionEnable(bool enable); - bool setDevice(const QString& device); - void setFpsSoftwareDecimation(int decimation); - bool setEncoding(QString enc); - bool setBrightnessContrastSaturationHue(int brightness, int contrast, int saturation, int hue); - void handleSettingsUpdate(settings::type type, const QJsonDocument& config) override; - -private slots: - void newFrame(const Image & image); - - void action() override; - -private: - /// The Media Foundation grabber - MFGrabber _grabber; -}; diff --git a/include/grabber/QtGrabber.h b/include/grabber/QtGrabber.h index 94db630c..63bfda4b 100644 --- a/include/grabber/QtGrabber.h +++ b/include/grabber/QtGrabber.h @@ -15,7 +15,7 @@ class QtGrabber : public Grabber { public: - QtGrabber(int cropLeft, int cropRight, int cropTop, int cropBottom, int pixelDecimation, int display); + QtGrabber(int cropLeft=0, int cropRight=0, int cropTop=0, int cropBottom=0, int pixelDecimation=8, int display=0); ~QtGrabber() override; @@ -39,11 +39,6 @@ public: /// bool setWidthHeight(int width, int height) override { return true; } - /// - /// @brief Apply new pixelDecimation - /// - void setPixelDecimation(int pixelDecimation) override; - /// /// Set the crop values /// @param cropLeft Left pixel crop @@ -58,6 +53,28 @@ public: /// void setDisplayIndex(int index) override; + /// + /// @brief Discover QT screens available (for configuration). + /// + /// @param[in] params Parameters used to overwrite discovery default behaviour + /// + /// @return A JSON structure holding a list of devices found + /// + QJsonObject discover(const QJsonObject& params); + + /// + /// @brief Setup a new capture display, will free the previous one + /// @return True on success, false if no display is found + /// + bool setupDisplay(); + + /// + /// @brief Opens the input device. + /// + /// @return Zero, on success (i.e. device is ready), else negative + /// + bool open(); + private slots: /// /// @brief is called whenever the current _screen changes it's geometry @@ -66,11 +83,7 @@ private slots: void geometryChanged(const QRect &geo); private: - /// - /// @brief Setup a new capture display, will free the previous one - /// @return True on success, false if no display is found - /// - bool setupDisplay(); + /// /// @brief Is called whenever we need new screen dimension calculations based on window geometry @@ -84,13 +97,20 @@ private: private: - unsigned _display; + int _display; + int _numberOfSDisplays; + int _pixelDecimation; - unsigned _calculatedWidth; - unsigned _calculatedHeight; - unsigned _src_x; - unsigned _src_y; - unsigned _src_x_max; - unsigned _src_y_max; + int _calculatedWidth; + int _calculatedHeight; + int _src_x; + int _src_y; + int _src_x_max; + int _src_y_max; + bool _isWayland; + QScreen* _screen; + bool _isVirtual; + + Logger * _logger; }; diff --git a/include/grabber/QtWrapper.h b/include/grabber/QtWrapper.h index 4d32625c..04e2e09b 100644 --- a/include/grabber/QtWrapper.h +++ b/include/grabber/QtWrapper.h @@ -21,6 +21,11 @@ public: /// QtWrapper(int cropLeft, int cropRight, int cropTop, int cropBottom, int pixelDecimation, int display, unsigned updateRate_Hz); + /// + /// Starts the grabber which produces led values with the specified update rate + /// + bool open() override; + public slots: /// /// Performs a single frame grab and computes the led-colors diff --git a/include/grabber/V4L2Grabber.h b/include/grabber/V4L2Grabber.h index e51fa090..56d310b8 100644 --- a/include/grabber/V4L2Grabber.h +++ b/include/grabber/V4L2Grabber.h @@ -16,7 +16,12 @@ #include #include #include -#include + +#include // Required to determine the cmake options + +#if defined(ENABLE_CEC) + #include +#endif // general JPEG decoder includes #ifdef HAVE_JPEG_DECODER @@ -53,8 +58,8 @@ public: QList standards = QList(); struct EncodingProperties { - unsigned int width = 0; - unsigned int height = 0; + int width = 0; + int height = 0; QList framerates = QList(); }; QMultiMap encodingFormats = QMultiMap(); @@ -62,115 +67,40 @@ public: QMap inputs = QMap(); }; - V4L2Grabber(const QString & device, const unsigned width, const unsigned height, const unsigned fps, const unsigned input, VideoStandard videoStandard, PixelFormat pixelFormat, int pixelDecimation); + V4L2Grabber(); ~V4L2Grabber() override; - QRectF getSignalDetectionOffset() const - { - return QRectF(_x_frac_min, _y_frac_min, _x_frac_max, _y_frac_max); - } - - bool getSignalDetectionEnabled() const { return _signalDetectionEnabled; } - bool getCecDetectionEnabled() const { return _cecDetectionEnabled; } - int grabFrame(Image &); - - /// - /// @brief set new PixelDecimation value to ImageResampler - /// @param pixelDecimation The new pixelDecimation value - /// - void setPixelDecimation(int pixelDecimation) override; - - /// - /// @brief overwrite Grabber.h implementation - /// - void setSignalThreshold( - double redSignalThreshold, - double greenSignalThreshold, - double blueSignalThreshold, - int noSignalCounterThreshold = 50) override; - - /// - /// @brief overwrite Grabber.h implementation - /// - void setSignalDetectionOffset( - double verticalMin, - double horizontalMin, - double verticalMax, - double horizontalMax) override; - /// - /// @brief overwrite Grabber.h implementation - /// - void setSignalDetectionEnable(bool enable) override; - - /// - /// @brief overwrite Grabber.h implementation - /// - void setCecDetectionEnable(bool enable) override; - - /// - /// @brief overwrite Grabber.h implementation - /// - void setDeviceVideoStandard(QString device, VideoStandard videoStandard) override; - - /// - /// @brief overwrite Grabber.h implementation - /// + void setDevice(const QString& device); bool setInput(int input) override; - - /// - /// @brief overwrite Grabber.h implementation - /// bool setWidthHeight(int width, int height) override; + void setEncoding(QString enc); + void setBrightnessContrastSaturationHue(int brightness, int contrast, int saturation, int hue); + void setSignalThreshold(double redSignalThreshold, double greenSignalThreshold, double blueSignalThreshold, int noSignalCounterThreshold = 50); + void setSignalDetectionOffset( double verticalMin, double horizontalMin, double verticalMax, double horizontalMax); + void setSignalDetectionEnable(bool enable); + void setCecDetectionEnable(bool enable); + bool reload(bool force = false); + + QRectF getSignalDetectionOffset() const { return QRectF(_x_frac_min, _y_frac_min, _x_frac_max, _y_frac_max); } //used from hyperion-v4l2 + + /// - /// @brief overwrite Grabber.h implementation + /// @brief Discover available V4L2 USB devices (for configuration). + /// @param[in] params Parameters used to overwrite discovery default behaviour + /// @return A JSON structure holding a list of USB devices found /// - bool setFramerate(int fps) override; - - /// - /// @brief overwrite Grabber.h implementation - /// - QStringList getDevices() const override; - - /// - /// @brief overwrite Grabber.h implementation - /// - QString getDeviceName(const QString& devicePath) const override; - - /// - /// @brief overwrite Grabber.h implementation - /// - QMultiMap getDeviceInputs(const QString& devicePath) const override; - - /// - /// @brief overwrite Grabber.h implementation - /// - QList getAvailableDeviceStandards(const QString& devicePath, const int& deviceInput) const override; - - /// - /// @brief overwrite Grabber.h implementation - /// - QStringList getAvailableEncodingFormats(const QString& devicePath, const int& deviceInput) const override; - - /// - /// @brief overwrite Grabber.h implementation - /// - QMultiMap getAvailableDeviceResolutions(const QString& devicePath, const int& deviceInput, const PixelFormat& encFormat) const override; - - /// - /// @brief overwrite Grabber.h implementation - /// - QIntList getAvailableDeviceFramerates(const QString& devicePath, const int& deviceInput, const PixelFormat& encFormat, const unsigned width, const unsigned height) const override; - + QJsonArray discover(const QJsonObject& params); public slots: - + bool prepare() { return true; } bool start(); - void stop(); +#if defined(ENABLE_CEC) void handleCecEvent(CECEvent event); +#endif signals: void newFrame(const Image & image); @@ -180,36 +110,21 @@ private slots: int read_frame(); private: - void getV4Ldevices(); - + void enumVideoCaptureDevices(); bool init(); - void uninit(); - bool open_device(); - void close_device(); - void init_read(unsigned int buffer_size); - void init_mmap(); - void init_userp(unsigned int buffer_size); - void init_device(VideoStandard videoStandard); - void uninit_device(); - void start_capturing(); - void stop_capturing(); - bool process_image(const void *p, int size); - void process_image(const uint8_t *p, int size); - int xioctl(int request, void *arg); - int xioctl(int fileDescriptor, int request, void *arg); void throw_exception(const QString & error) @@ -264,16 +179,14 @@ private: #endif private: - QString _deviceName; - std::map _v4lDevices; + QString _currentDeviceName, _newDeviceName; QMap _deviceProperties; - VideoStandard _videoStandard; io_method _ioMethod; int _fileDescriptor; std::vector _buffers; - PixelFormat _pixelFormat; + PixelFormat _pixelFormat, _pixelFormatConfig; int _pixelDecimation; int _lineLength; int _frameByteSize; @@ -281,10 +194,7 @@ private: // signal detection int _noSignalCounterThreshold; ColorRgb _noSignalThresholdColor; - bool _signalDetectionEnabled; - bool _cecDetectionEnabled; - bool _cecStandbyActivated; - bool _noSignalDetected; + bool _cecDetectionEnabled, _cecStandbyActivated, _signalDetectionEnabled, _noSignalDetected; int _noSignalCounter; double _x_frac_min; double _y_frac_min; @@ -293,8 +203,7 @@ private: QSocketNotifier *_streamNotifier; - bool _initialized; - bool _deviceAutoDiscoverEnabled; + bool _initialized, _reload; protected: void enumFrameIntervals(QList &framerates, int fileDescriptor, int pixelformat, int width, int height); diff --git a/include/grabber/V4L2Wrapper.h b/include/grabber/V4L2Wrapper.h deleted file mode 100644 index b6d6dd7a..00000000 --- a/include/grabber/V4L2Wrapper.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#include -#include - -class V4L2Wrapper : public GrabberWrapper -{ - Q_OBJECT - -public: - V4L2Wrapper(const QString & device, - const unsigned grabWidth, - const unsigned grabHeight, - const unsigned fps, - const unsigned input, - VideoStandard videoStandard, - PixelFormat pixelFormat, - int pixelDecimation); - ~V4L2Wrapper() override; - - bool getSignalDetectionEnable() const; - bool getCecDetectionEnable() const; - -public slots: - bool start() override; - void stop() override; - - void setSignalThreshold(double redSignalThreshold, double greenSignalThreshold, double blueSignalThreshold); - void setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom) override; - void setSignalDetectionOffset(double verticalMin, double horizontalMin, double verticalMax, double horizontalMax); - void setSignalDetectionEnable(bool enable); - void setCecDetectionEnable(bool enable); - void setDeviceVideoStandard(const QString& device, VideoStandard videoStandard); - void handleCecEvent(CECEvent event); - void handleSettingsUpdate(settings::type type, const QJsonDocument& config) override; - -private slots: - void newFrame(const Image & image); - void readError(const char* err); - - void action() override; - -private: - /// The V4L2 grabber - V4L2Grabber _grabber; -}; diff --git a/include/grabber/VideoWrapper.h b/include/grabber/VideoWrapper.h new file mode 100644 index 00000000..932ff1ab --- /dev/null +++ b/include/grabber/VideoWrapper.h @@ -0,0 +1,47 @@ +#pragma once + +#include // Required to determine the cmake options +#include + +#if defined(ENABLE_MF) + #include +#elif defined(ENABLE_V4L2) + #include +#endif + +#if defined(ENABLE_CEC) + #include +#endif + +class VideoWrapper : public GrabberWrapper +{ + Q_OBJECT + +public: + VideoWrapper(); + ~VideoWrapper() override; + +public slots: + bool start() override; + void stop() override; + +#if defined(ENABLE_CEC) + void handleCecEvent(CECEvent event); +#endif + + void handleSettingsUpdate(settings::type type, const QJsonDocument& config) override; + +private slots: + void newFrame(const Image & image); + void readError(const char* err); + + void action() override; + +private: + /// The Media Foundation or V4L2 grabber +#if defined(ENABLE_MF) + MFGrabber _grabber; +#elif defined(ENABLE_V4L2) + V4L2Grabber _grabber; +#endif +}; diff --git a/include/grabber/X11Grabber.h b/include/grabber/X11Grabber.h index 2e5e4358..2a193f4f 100644 --- a/include/grabber/X11Grabber.h +++ b/include/grabber/X11Grabber.h @@ -2,7 +2,13 @@ #include #include #include + +// QT includes #include +#include +#include +#include + // Hyperion-utils includes #include @@ -20,11 +26,13 @@ class X11Grabber : public Grabber , public QAbstractNativeEventFilter { public: - X11Grabber(int cropLeft, int cropRight, int cropTop, int cropBottom, int pixelDecimation); + X11Grabber(int cropLeft=0, int cropRight=0, int cropTop=0, int cropBottom=0, int pixelDecimation=8); ~X11Grabber() override; - bool Setup(); + bool open(); + + bool setupDisplay(); /// /// Captures a single snapshot of the display and writes the data to the given image. The @@ -50,7 +58,7 @@ public: /// /// @brief Apply new pixelDecimation /// - void setPixelDecimation(int pixelDecimation) override; + bool setPixelDecimation(int pixelDecimation) override; /// /// Set the crop values @@ -61,20 +69,31 @@ public: /// void setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom) override; + /// + /// @brief Discover X11 screens available (for configuration). + /// + /// @param[in] params Parameters used to overwrite discovery default behaviour + /// + /// @return A JSON structure holding a list of devices found + /// + QJsonObject discover(const QJsonObject& params); + protected: bool nativeEventFilter(const QByteArray & eventType, void * message, long int * result) override; private: - bool _XShmAvailable, _XShmPixmapAvailable, _XRenderAvailable, _XRandRAvailable; - XImage* _xImage; - XShmSegmentInfo _shminfo; + void freeResources(); + void setupResources(); /// Reference to the X11 display (nullptr if not opened) Display* _x11Display; Window _window; XWindowAttributes _windowAttr; + XImage* _xImage; + XShmSegmentInfo _shminfo; + Pixmap _pixmap; XRenderPictFormat* _srcFormat; XRenderPictFormat* _dstFormat; @@ -92,8 +111,13 @@ private: unsigned _src_x; unsigned _src_y; - Image _image; + bool _XShmAvailable; + bool _XShmPixmapAvailable; + bool _XRenderAvailable; + bool _XRandRAvailable; + bool _isWayland; - void freeResources(); - void setupResources(); + Logger * _logger; + + Image _image; }; diff --git a/include/grabber/XcbGrabber.h b/include/grabber/XcbGrabber.h index a4a573f1..249927d7 100644 --- a/include/grabber/XcbGrabber.h +++ b/include/grabber/XcbGrabber.h @@ -1,7 +1,11 @@ #pragma once #include +// QT includes #include +#include +#include +#include #include #include @@ -21,17 +25,29 @@ class XcbGrabber : public Grabber, public QAbstractNativeEventFilter Q_OBJECT public: - XcbGrabber(int cropLeft, int cropRight, int cropTop, int cropBottom, int pixelDecimation); + XcbGrabber(int cropLeft=0, int cropRight=0, int cropTop=0, int cropBottom=0, int pixelDecimation=8); + ~XcbGrabber() override; - bool Setup(); + bool open(); + bool setupDisplay(); + int grabFrame(Image & image, bool forceUpdate = false); int updateScreenDimensions(bool force = false); void setVideoMode(VideoMode mode) override; bool setWidthHeight(int width, int height) override { return true; } - void setPixelDecimation(int pixelDecimation) override; + bool setPixelDecimation(int pixelDecimation) override; void setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom) override; + /// + /// @brief Discover XCB screens available (for configuration). + /// + /// @param[in] params Parameters used to overwrite discovery default behaviour + /// + /// @return A JSON structure holding a list of devices found + /// + QJsonObject discover(const QJsonObject& params); + private: bool nativeEventFilter(const QByteArray & eventType, void * message, long int * result) override; void freeResources(); @@ -54,6 +70,7 @@ private: int _pixelDecimation; + int _screen_num; unsigned _screenWidth; unsigned _screenHeight; unsigned _src_x; @@ -63,6 +80,8 @@ private: bool _XcbRandRAvailable; bool _XcbShmAvailable; bool _XcbShmPixmapAvailable; + bool _isWayland; + Logger * _logger; uint8_t * _shmData; diff --git a/include/hyperion/BGEffectHandler.h b/include/hyperion/BGEffectHandler.h index 08b67320..9c0dfcbd 100644 --- a/include/hyperion/BGEffectHandler.h +++ b/include/hyperion/BGEffectHandler.h @@ -3,6 +3,7 @@ #include #include #include +#include /// /// @brief Handle the background Effect settings, reacts on runtime to settings changes @@ -37,7 +38,7 @@ private slots: #define BGCONFIG_ARRAY bgColorConfig.toArray() // clear background priority - _hyperion->clear(254); + _hyperion->clear(PriorityMuxer::BG_PRIORITY); // initial background effect/color if (BGEffectConfig["enable"].toBool(true)) { @@ -53,12 +54,12 @@ private slots: static_cast(BGCONFIG_ARRAY.at(2).toInt(0)) } }; - _hyperion->setColor(254, bg_color); + _hyperion->setColor(PriorityMuxer::BG_PRIORITY, bg_color); Info(Logger::getInstance("HYPERION"),"Initial background color set (%d %d %d)",bg_color.at(0).red, bg_color.at(0).green, bg_color.at(0).blue); } else { - int result = _hyperion->setEffect(bgEffectConfig, 254); + int result = _hyperion->setEffect(bgEffectConfig, PriorityMuxer::BG_PRIORITY, Effect::ENDLESS); Info(Logger::getInstance("HYPERION"),"Initial background effect '%s' %s", QSTRING_CSTR(bgEffectConfig), ((result == 0) ? "started" : "failed")); } } diff --git a/include/hyperion/Grabber.h b/include/hyperion/Grabber.h index 6c50d063..c1036b29 100644 --- a/include/hyperion/Grabber.h +++ b/include/hyperion/Grabber.h @@ -41,7 +41,7 @@ public: virtual void setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom); /// - /// @brief Apply new video input (used from v4l) + /// @brief Apply new video input (used from v4l2/MediaFoundation) /// @param input device input /// virtual bool setInput(int input); @@ -53,52 +53,26 @@ public: virtual bool setWidthHeight(int width, int height); /// - /// @brief Apply new framerate (used from v4l) + /// @brief Apply new framerate (used from v4l2/MediaFoundation) /// @param fps framesPerSecond /// virtual bool setFramerate(int fps); /// - /// @brief Apply new pixelDecimation (used from x11, xcb and qt) + /// @brief Apply new framerate software decimation (used from v4l2/MediaFoundation) + /// @param decimation how many frames per second to omit /// - virtual void setPixelDecimation(int pixelDecimation) {} + virtual void setFpsSoftwareDecimation(int decimation); /// - /// @brief Apply new signalThreshold (used from v4l) + /// @brief Apply videoStandard (used from v4l2) /// - virtual void setSignalThreshold( - double redSignalThreshold, - double greenSignalThreshold, - double blueSignalThreshold, - int noSignalCounterThreshold = 50) {} - /// - /// @brief Apply new SignalDetectionOffset (used from v4l) - /// - virtual void setSignalDetectionOffset( - double verticalMin, - double horizontalMin, - double verticalMax, - double horizontalMax) {} + virtual void setVideoStandard(VideoStandard videoStandard); /// - /// @brief Apply SignalDetectionEnable (used from v4l) + /// @brief Apply new pixelDecimation (used from v4l2, MediaFoundation, x11, xcb and qt) /// - virtual void setSignalDetectionEnable(bool enable) {} - - /// - /// @brief Apply CecDetectionEnable (used from v4l) - /// - virtual void setCecDetectionEnable(bool enable) {} - - /// - /// @brief Apply device and videoStandard (used from v4l) - /// - virtual void setDeviceVideoStandard(QString device, VideoStandard videoStandard) {} - - /// - /// @brief Apply device (used from MediaFoundation) - /// - virtual bool setDevice(QString device) { return false; } + virtual bool setPixelDecimation(int pixelDecimation); /// /// @brief Apply display index (used from qt) @@ -125,71 +99,26 @@ public: /// void setEnabled(bool enable); - /// - /// @brief Get a list of all available devices - /// @return List of all available devices on success else empty List - /// - virtual QStringList getDevices() const { return QStringList(); } - - /// - /// @brief Get the device name by path - /// @param devicePath The device path - /// @return The name of the device on success else empty String - /// - virtual QString getDeviceName(const QString& /*devicePath*/) const { return QString(); } - - /// - /// @brief Get a name/index pair of supported device inputs - /// @param devicePath The device path - /// @return multi pair of name/index on success else empty pair - /// - virtual QMultiMap getDeviceInputs(const QString& /*devicePath*/) const { return QMultiMap(); } - - /// - /// @brief Get a list of available device video standards depends on device input - /// @param devicePath The device path - /// @param inputIndex The device input index - /// @return List of video standards on success else empty List - /// - virtual QList getAvailableDeviceStandards(const QString& /*devicePath*/, const int& /*deviceInput*/) const { return QList(); } - - /// - /// @brief Get a list of all available device encoding formats depends on device input - /// @param devicePath The device path - /// @param inputIndex The device input index - /// @return List of device encoding formats on success else empty List - /// - virtual QStringList getAvailableEncodingFormats(const QString& /*devicePath*/, const int& /*deviceInput*/) const { return QStringList(); } - - /// - /// @brief Get a map of available device resolutions (width/heigth) depends on device input and encoding format - /// @param devicePath The device path - /// @param inputIndex The device input index - /// @param encFormat The device encoding format - /// @return Map of resolutions (width/heigth) on success else empty List - /// - virtual QMultiMap getAvailableDeviceResolutions(const QString& /*devicePath*/, const int& /*deviceInput*/, const PixelFormat& /*encFormat*/) const { return QMultiMap(); } - - /// - /// @brief Get a list of available device framerates depends on device input, encoding format and resolution - /// @param devicePath The device path - /// @param inputIndex The device input index - /// @param encFormat The device encoding format - /// @param width The device width - /// @param heigth The device heigth - /// @return List of framerates on success else empty List - /// - virtual QIntList getAvailableDeviceFramerates(const QString& /*devicePath*/, const int& /*deviceInput*/, const PixelFormat& /*encFormat*/, const unsigned /*width*/, const unsigned /*height*/) const { return QIntList(); } + QString getGrabberName() const { return _grabberName; } protected: + + QString _grabberName; + ImageResampler _imageResampler; bool _useImageResampler; - /// The selected VideoMode + /// the selected VideoMode VideoMode _videoMode; - /// The used Flip Mode + /// the used video standard + VideoStandard _videoStandard; + + /// Image size decimation + int _pixelDecimation; + + /// the used Flip Mode FlipMode _flipMode; /// With of the captured snapshot [pixels] @@ -201,6 +130,9 @@ protected: /// frame per second int _fps; + /// fps software decimation + int _fpsSoftwareDecimation; + /// device input int _input; diff --git a/include/hyperion/GrabberWrapper.h b/include/hyperion/GrabberWrapper.h index f121d770..2091c110 100644 --- a/include/hyperion/GrabberWrapper.h +++ b/include/hyperion/GrabberWrapper.h @@ -58,62 +58,6 @@ public: /// virtual bool isActive() const; - /// - /// @brief Get a list of all available devices - /// @return List of all available devices on success else empty List - /// - virtual QStringList getDevices() const; - - /// - /// @brief Get the device name by path - /// @param devicePath The device path - /// @return The name of the device on success else empty String - /// - virtual QString getDeviceName(const QString& devicePath) const; - - /// - /// @brief Get a map of name/index pair of supported device inputs - /// @param devicePath The device path - /// @return multi pair of name/index on success else empty pair - /// - virtual QMultiMap getDeviceInputs(const QString& devicePath) const; - - /// - /// @brief Get a list of available device video standards depends on device input - /// @param devicePath The device path - /// @param inputIndex The device input index - /// @return List of video standards on success else empty List - /// - virtual QList getAvailableDeviceStandards(const QString& devicePath, const int& deviceInput) const; - - /// - /// @brief Get a list of all available device encoding formats depends on device input - /// @param devicePath The device path - /// @param inputIndex The device input index - /// @return List of device encoding formats on success else empty List - /// - virtual QStringList getAvailableEncodingFormats(const QString& devicePath, const int& deviceInput) const; - - /// - /// @brief Get a map of available device resolutions (width/heigth) depends on device input and encoding format - /// @param devicePath The device path - /// @param inputIndex The device input index - /// @param encFormat The device encoding format - /// @return Map of resolutions (width/heigth) on success else empty List - /// - virtual QMultiMap getAvailableDeviceResolutions(const QString& devicePath, const int& deviceInput, const PixelFormat& encFormat) const; - - /// - /// @brief Get a list of available device framerates depends on device input, encoding format and resolution - /// @param devicePath The device path - /// @param inputIndex The device input index - /// @param encFormat The device encoding format - /// @param width The device width - /// @param heigth The device heigth - /// @return List of framerates on success else empty List - /// - virtual QIntList getAvailableDeviceFramerates(const QString& devicePath, const int& deviceInput, const PixelFormat& encFormat, const unsigned width, const unsigned height) const; - /// /// @brief Get active grabber name /// @param hyperionInd The instance index @@ -155,6 +99,12 @@ public slots: /// virtual void setVideoMode(VideoMode videoMode); + /// + /// Set the Flip mode + /// @param flipMode The new flip mode + /// + virtual void setFlipMode(QString flipMode); + /// /// Set the crop values /// @param cropLeft Left pixel crop @@ -166,7 +116,7 @@ public slots: /// /// @brief Handle settings update from HyperionDaemon Settingsmanager emit - /// @param type settingyType from enum + /// @param type settingsType from enum /// @param config configuration object /// virtual void handleSettingsUpdate(settings::type type, const QJsonDocument& config); @@ -189,6 +139,22 @@ private slots: void updateTimer(int interval); protected: + + /// +/// @brief Opens the input device. +/// +/// @return True, on success (i.e. device is ready) +/// + virtual bool open() { return true; } + + /// + /// @brief Closes the input device. + /// + /// @return True on success (i.e. device is closed) + /// + virtual bool close() { return true; } + + QString _grabberName; /// The timer for generating events with the specified update rate diff --git a/include/hyperion/Hyperion.h b/include/hyperion/Hyperion.h index 67a2cb9a..e71a7034 100644 --- a/include/hyperion/Hyperion.h +++ b/include/hyperion/Hyperion.h @@ -26,6 +26,7 @@ // Effect engine includes #include +#include #include #include @@ -217,7 +218,7 @@ public slots: /// @param effectName Name of the effec to run /// @param priority The priority channel of the effect /// @param timeout The timeout of the effect (after the timout, the effect will be cleared) - int setEffect(const QString & effectName, int priority, int timeout = -1, const QString & origin="System"); + int setEffect(const QString & effectName, int priority, int timeout = Effect::ENDLESS, const QString & origin="System"); /// Run the specified effect on the given priority channel and optionally specify a timeout /// @param effectName Name of the effec to run @@ -227,7 +228,7 @@ public slots: int setEffect(const QString &effectName , const QJsonObject &args , int priority - , int timeout = -1 + , int timeout = Effect::ENDLESS , const QString &pythonScript = "" , const QString &origin="System" , const QString &imageData = "" diff --git a/include/hyperion/PriorityMuxer.h b/include/hyperion/PriorityMuxer.h index 7567ff60..278e33fe 100644 --- a/include/hyperion/PriorityMuxer.h +++ b/include/hyperion/PriorityMuxer.h @@ -54,6 +54,9 @@ public: QString owner; }; + //Foreground and Background priorities + const static int FG_PRIORITY; + const static int BG_PRIORITY; /// The lowest possible priority, which is used when no priority channels are active const static int LOWEST_PRIORITY; diff --git a/include/utils/WaitTime.h b/include/utils/WaitTime.h new file mode 100644 index 00000000..0521ed5b --- /dev/null +++ b/include/utils/WaitTime.h @@ -0,0 +1,27 @@ +#ifndef WAITTIME_H +#define WAITTIME_H + +#include +#include + +#include + +inline void wait(std::chrono::milliseconds millisecondsWait) +{ + QEventLoop loop; + QTimer t; + t.connect(&t, &QTimer::timeout, &loop, &QEventLoop::quit); + t.start(millisecondsWait.count()); + loop.exec(); +} + +inline void wait(int millisecondsWait) +{ + QEventLoop loop; + QTimer t; + t.connect(&t, &QTimer::timeout, &loop, &QEventLoop::quit); + t.start(millisecondsWait); + loop.exec(); +} + +#endif // WAITTIME_H diff --git a/include/utils/hyperion.h b/include/utils/hyperion.h index 294c91b2..5bb44ded 100644 --- a/include/utils/hyperion.h +++ b/include/utils/hyperion.h @@ -7,6 +7,7 @@ #include // fg effect #include +#include /// /// @brief Provide utility methods for Hyperion class @@ -16,7 +17,6 @@ namespace hyperion { void handleInitialEffect(Hyperion* hyperion, const QJsonObject& FGEffectConfig) { #define FGCONFIG_ARRAY fgColorConfig.toArray() - const int FG_PRIORITY = 0; const int DURATION_INFINITY = 0; // initial foreground effect/color @@ -41,12 +41,12 @@ namespace hyperion { static_cast(FGCONFIG_ARRAY.at(2).toInt(0)) } }; - hyperion->setColor(FG_PRIORITY, fg_color, fg_duration_ms); + hyperion->setColor(PriorityMuxer::FG_PRIORITY, fg_color, fg_duration_ms); Info(Logger::getInstance("HYPERION"),"Initial foreground color set (%d %d %d)",fg_color.at(0).red,fg_color.at(0).green,fg_color.at(0).blue); } else { - int result = hyperion->setEffect(fgEffectConfig, FG_PRIORITY, fg_duration_ms); + int result = hyperion->setEffect(fgEffectConfig, PriorityMuxer::FG_PRIORITY, fg_duration_ms); Info(Logger::getInstance("HYPERION"),"Initial foreground effect '%s' %s", QSTRING_CSTR(fgEffectConfig), ((result == 0) ? "started" : "failed")); } } diff --git a/libsrc/api/JsonAPI.cpp b/libsrc/api/JsonAPI.cpp index aca267f2..6f90b362 100644 --- a/libsrc/api/JsonAPI.cpp +++ b/libsrc/api/JsonAPI.cpp @@ -16,7 +16,24 @@ #include #include +#include // Required to determine the cmake options + #include +#include + +#if defined(ENABLE_MF) + #include +#elif defined(ENABLE_V4L2) + #include +#endif + +#if defined(ENABLE_X11) + #include +#endif +#if defined(ENABLE_XCB) + #include +#endif + #include #include #include @@ -41,6 +58,9 @@ using namespace hyperion; +// Constants +namespace { const bool verbose = false; } + JsonAPI::JsonAPI(QString peerAddress, Logger *log, bool localConnection, QObject *parent, bool noListener) : API(log, localConnection, parent) { @@ -964,13 +984,13 @@ void JsonAPI::handleLedColorsCommand(const QJsonObject &message, const QString & _ledStreamConnection = connect(_ledStreamTimer, &QTimer::timeout, this, [=]() { emit streamLedcolorsUpdate(_currentLedValues); }, - Qt::UniqueConnection); + Qt::UniqueConnection); // start the timer if (!_ledStreamTimer->isActive() || _ledStreamTimer->interval() != streaming_interval) _ledStreamTimer->start(streaming_interval); }, - Qt::UniqueConnection); + Qt::UniqueConnection); // push once _hyperion->update(); } @@ -1420,7 +1440,7 @@ void JsonAPI::handleLedDeviceCommand(const QJsonObject &message, const QString & void JsonAPI::handleInputSourceCommand(const QJsonObject& message, const QString& command, int tan) { - Debug(_log, "message: [%s]", QString(QJsonDocument(message).toJson(QJsonDocument::Compact)).toUtf8().constData()); + DebugIf(verbose, _log, "message: [%s]", QString(QJsonDocument(message).toJson(QJsonDocument::Compact)).toUtf8().constData()); const QString& subc = message["subcommand"].toString().trimmed(); const QString& sourceType = message["sourceType"].toString().trimmed(); @@ -1438,86 +1458,66 @@ void JsonAPI::handleInputSourceCommand(const QJsonObject& message, const QString { QJsonObject inputSourcesDiscovered; inputSourcesDiscovered.insert("sourceType", sourceType); - QJsonArray videoInputs; #if defined(ENABLE_V4L2) || defined(ENABLE_MF) if (sourceType == "video" ) { - //for (const auto& instance : GrabberWrapper::getInstance()->getDevices()) - //{ +#if defined(ENABLE_MF) + MFGrabber* grabber = new MFGrabber(); +#elif defined(ENABLE_V4L2) + V4L2Grabber* grabber = new V4L2Grabber(); +#endif + QJsonObject params; + videoInputs = grabber->discover(params); + delete grabber; + } + else +#endif + { + DebugIf(verbose, _log, "sourceType: [%s]", QSTRING_CSTR(sourceType)); - for (const auto& devicePath : GrabberWrapper::getInstance()->getDevices()) + if (sourceType == "screen") { + QJsonObject params; QJsonObject device; - device["device"] = devicePath; - device["device_name"] = GrabberWrapper::getInstance()->getDeviceName(devicePath); - device["type"] = "v4l2"; - - QJsonArray video_inputs; - - QMultiMap inputs = GrabberWrapper::getInstance()->getDeviceInputs(devicePath); - for (auto input = inputs.begin(); input != inputs.end(); input++) + #ifdef ENABLE_QT + QtGrabber* qtgrabber = new QtGrabber(); + device = qtgrabber->discover(params); + if (!device.isEmpty() ) { - QJsonObject in; - in["name"] = input.key(); - in["inputIdx"] = input.value(); - - QJsonArray standards; - QList videoStandards = GrabberWrapper::getInstance()->getAvailableDeviceStandards(devicePath, input.value()); - for (auto standard : videoStandards) - { - standards.append(VideoStandard2String(standard)); - } - if (!standards.isEmpty()) - { - in["standards"] = standards; - } - - QJsonArray formats; - QStringList encodingFormats = GrabberWrapper::getInstance()->getAvailableEncodingFormats(devicePath, input.value()); - for (auto encodingFormat : encodingFormats) - { - QJsonObject format; - format["format"] = encodingFormat; - - QJsonArray resolutionArray; - QMultiMap deviceResolutions = GrabberWrapper::getInstance()->getAvailableDeviceResolutions(devicePath, input.value(), parsePixelFormat(encodingFormat)); - for (auto width_height = deviceResolutions.begin(); width_height != deviceResolutions.end(); width_height++) - { - QJsonObject resolution; - resolution["width"] = width_height.key(); - resolution["height"] = width_height.value(); - - QJsonArray fps; - QIntList framerates = GrabberWrapper::getInstance()->getAvailableDeviceFramerates(devicePath, input.value(), parsePixelFormat(encodingFormat), width_height.key(), width_height.value()); - for (auto framerate : framerates) - { - fps.append(framerate); - } - - resolution["fps"] = fps; - resolutionArray.append(resolution); - } - - format["resolutions"] = resolutionArray; - formats.append(format); - } - in["formats"] = formats; - video_inputs.append(in); - + videoInputs.append(device); } + delete qtgrabber; + #endif - device["video_inputs"] = video_inputs; - videoInputs.append(device); + #ifdef ENABLE_X11 + X11Grabber* x11Grabber = new X11Grabber(); + device = x11Grabber->discover(params); + if (!device.isEmpty() ) + { + videoInputs.append(device); + } + delete x11Grabber; + #endif + + #ifdef ENABLE_XCB + XcbGrabber* xcbGrabber = new XcbGrabber(); + device = xcbGrabber->discover(params); + if (!device.isEmpty() ) + { + videoInputs.append(device); + } + delete xcbGrabber; + #endif } + } -#endif inputSourcesDiscovered["video_sources"] = videoInputs; - Debug(_log, "response: [%s]", QString(QJsonDocument(inputSourcesDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData()); + DebugIf(verbose, _log, "response: [%s]", QString(QJsonDocument(inputSourcesDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData()); sendSuccessDataReply(QJsonDocument(inputSourcesDiscovered), full_command, tan); } @@ -1528,7 +1528,6 @@ void JsonAPI::handleInputSourceCommand(const QJsonObject& message, const QString } } - void JsonAPI::handleNotImplemented(const QString &command, int tan) { sendErrorReply("Command not implemented", command, tan); diff --git a/libsrc/effectengine/Effect.cpp b/libsrc/effectengine/Effect.cpp index 3f241f2f..d1d97518 100644 --- a/libsrc/effectengine/Effect.cpp +++ b/libsrc/effectengine/Effect.cpp @@ -12,6 +12,8 @@ // python utils #include +const int Effect::ENDLESS = -1; + Effect::Effect(Hyperion *hyperion, int priority, int timeout, const QString &script, const QString &name, const QJsonObject &args, const QString &imageData) : QThread() , _hyperion(hyperion) @@ -22,7 +24,7 @@ Effect::Effect(Hyperion *hyperion, int priority, int timeout, const QString &scr , _args(args) , _imageData(imageData) , _endTime(-1) - , _colors() + , _interupt(false) , _imageSize(hyperion->getLedGridSize()) , _image(_imageSize,QImage::Format_ARGB32_Premultiplied) { @@ -47,6 +49,24 @@ Effect::~Effect() _imageStack.clear(); } +bool Effect::isInterruptionRequested() +{ + return _interupt || getRemaining() < ENDLESS; +} + +int Effect::getRemaining() const +{ + // determine the timeout + int timeout = _timeout; + + if (timeout > 0) + { + timeout = static_cast( _endTime - QDateTime::currentMSecsSinceEpoch()); + return timeout; + } + return ENDLESS; +} + void Effect::setModuleParameters() { // import the buildtin Hyperion module diff --git a/libsrc/effectengine/EffectEngine.cpp b/libsrc/effectengine/EffectEngine.cpp index 14169890..42386512 100644 --- a/libsrc/effectengine/EffectEngine.cpp +++ b/libsrc/effectengine/EffectEngine.cpp @@ -19,8 +19,6 @@ EffectEngine::EffectEngine(Hyperion * hyperion) : _hyperion(hyperion) - , _availableEffects() - , _activeEffects() , _log(Logger::getInstance("EFFECTENGINE")) , _effectFileHandler(EffectFileHandler::getInstance()) { @@ -202,7 +200,7 @@ void EffectEngine::allChannelsCleared() { for (Effect * effect : _activeEffects) { - if (effect->getPriority() != 254 && !effect->isInterruptionRequested()) + if (effect->getPriority() != PriorityMuxer::BG_PRIORITY && !effect->isInterruptionRequested()) { effect->requestInterruption(); } diff --git a/libsrc/effectengine/EffectFileHandler.cpp b/libsrc/effectengine/EffectFileHandler.cpp index d3d07dd5..6e4dc1df 100644 --- a/libsrc/effectengine/EffectFileHandler.cpp +++ b/libsrc/effectengine/EffectFileHandler.cpp @@ -11,10 +11,10 @@ #include // createEffect helper -struct find_schema: std::unary_function +struct find_schema : std::unary_function { QString pyFile; - find_schema(QString pyFile):pyFile(pyFile) { } + find_schema(QString pyFile) :pyFile(std::move(pyFile)) { } bool operator()(EffectSchema const& schema) const { return schema.pyFile == pyFile; @@ -22,10 +22,10 @@ struct find_schema: std::unary_function }; // deleteEffect helper -struct find_effect: std::unary_function +struct find_effect : std::unary_function { QString effectName; - find_effect(QString effectName) :effectName(effectName) { } + find_effect(QString effectName) :effectName(std::move(effectName)) { } bool operator()(EffectDefinition const& effectDefinition) const { return effectDefinition.name == effectName; @@ -36,7 +36,6 @@ EffectFileHandler* EffectFileHandler::efhInstance; EffectFileHandler::EffectFileHandler(const QString& rootPath, const QJsonDocument& effectConfig, QObject* parent) : QObject(parent) - , _effectConfig() , _log(Logger::getInstance("EFFECTFILES")) , _rootPath(rootPath) { @@ -50,7 +49,7 @@ EffectFileHandler::EffectFileHandler(const QString& rootPath, const QJsonDocumen void EffectFileHandler::handleSettingsUpdate(settings::type type, const QJsonDocument& config) { - if(type == settings::EFFECTS) + if (type == settings::EFFECTS) { _effectConfig = config.object(); // update effects and schemas @@ -67,15 +66,17 @@ QString EffectFileHandler::deleteEffect(const QString& effectName) if (it != effectsDefinition.end()) { QFileInfo effectConfigurationFile(it->file); - if (effectConfigurationFile.absoluteFilePath().mid(0, 1) != ":" ) + if (!effectConfigurationFile.absoluteFilePath().startsWith(':')) { if (effectConfigurationFile.exists()) { - if ( (it->script == ":/effects/gif.py") && !it->args.value("image").toString("").isEmpty()) + if ((it->script == ":/effects/gif.py") && !it->args.value("image").toString("").isEmpty()) { - QFileInfo effectImageFile(effectConfigurationFile.absolutePath() + "/" + it->args.value("image").toString()); - if (effectImageFile.exists()) - QFile::remove(effectImageFile.absoluteFilePath()); + QFileInfo effectImageFile(it->args.value("image").toString()); + if (effectImageFile.exists()) + { + QFile::remove(effectImageFile.absoluteFilePath()); + } } bool result = QFile::remove(effectConfigurationFile.absoluteFilePath()); @@ -83,15 +84,27 @@ QString EffectFileHandler::deleteEffect(const QString& effectName) if (result) { updateEffects(); - return ""; - } else + resultMsg = ""; + } + else + { resultMsg = "Can't delete effect configuration file: " + effectConfigurationFile.absoluteFilePath() + ". Please check permissions"; - } else + } + } + else + { resultMsg = "Can't find effect configuration file: " + effectConfigurationFile.absoluteFilePath(); - } else + } + } + else + { resultMsg = "Can't delete internal effect: " + effectName; - } else + } + } + else + { resultMsg = "Effect " + effectName + " not found"; + } return resultMsg; } @@ -101,17 +114,14 @@ QString EffectFileHandler::saveEffect(const QJsonObject& message) QString resultMsg; if (!message["args"].toObject().isEmpty()) { - QString scriptName; - (message["script"].toString().mid(0, 1) == ":" ) - ? scriptName = ":/effects//" + message["script"].toString().mid(1) - : scriptName = message["script"].toString(); + QString scriptName = message["script"].toString(); std::list effectsSchemas = getEffectSchemas(); std::list::iterator it = std::find_if(effectsSchemas.begin(), effectsSchemas.end(), find_schema(scriptName)); if (it != effectsSchemas.end()) { - if(!JsonUtils::validate("EffectFileHandler", message["args"].toObject(), it->schemaFile, _log)) + if (!JsonUtils::validate("EffectFileHandler", message["args"].toObject(), it->schemaFile, _log)) { return "Error during arg validation against schema, please consult the Hyperion Log"; } @@ -120,9 +130,9 @@ QString EffectFileHandler::saveEffect(const QJsonObject& message) QJsonArray effectArray; effectArray = _effectConfig["paths"].toArray(); - if (effectArray.size() > 0) + if (!effectArray.empty()) { - if (message["name"].toString().trimmed().isEmpty() || message["name"].toString().trimmed().startsWith(".")) + if (message["name"].toString().trimmed().isEmpty() || message["name"].toString().trimmed().startsWith(":")) { return "Can't save new effect. Effect name is empty or begins with a dot."; } @@ -138,41 +148,56 @@ QString EffectFileHandler::saveEffect(const QJsonObject& message) if (iter != availableEffects.end()) { newFileName.setFile(iter->file); - if (newFileName.absoluteFilePath().mid(0, 1) == ":") + if (newFileName.absoluteFilePath().startsWith(':')) { - return "The effect name '" + message["name"].toString() + "' is assigned to an internal effect. Please rename your effekt."; + return "The effect name '" + message["name"].toString() + "' is assigned to an internal effect. Please rename your effect."; } - } else + } + else { - // TODO global special keyword handling - QString f = effectArray[0].toString().replace("$ROOT",_rootPath) + "/" + message["name"].toString().replace(QString(" "), QString("")) + QString(".json"); + QString f = effectArray[0].toString().replace("$ROOT", _rootPath) + '/' + message["name"].toString().replace(QString(" "), QString("")) + QString(".json"); newFileName.setFile(f); } - //TODO check if filename exist if (!message["imageData"].toString("").isEmpty() && !message["args"].toObject().value("image").toString("").isEmpty()) { - QFileInfo imageFileName(effectArray[0].toString().replace("$ROOT",_rootPath) + "/" + message["args"].toObject().value("image").toString()); - if(!FileUtils::writeFile(imageFileName.absoluteFilePath(), QByteArray::fromBase64(message["imageData"].toString("").toUtf8()), _log)) + QJsonObject args = message["args"].toObject(); + QString imageFilePath = effectArray[0].toString().replace("$ROOT", _rootPath) + '/' + args.value("image").toString(); + + QFileInfo imageFileName(imageFilePath); + if (!FileUtils::writeFile(imageFileName.absoluteFilePath(), QByteArray::fromBase64(message["imageData"].toString("").toUtf8()), _log)) { return "Error while saving image file '" + message["args"].toObject().value("image").toString() + ", please check the Hyperion Log"; } + + //Update json with image file location + args["image"] = imageFilePath; + effectJson["args"] = args; } - if(!JsonUtils::write(newFileName.absoluteFilePath(), effectJson, _log)) + if (!JsonUtils::write(newFileName.absoluteFilePath(), effectJson, _log)) { return "Error while saving effect, please check the Hyperion Log"; } Info(_log, "Reload effect list"); updateEffects(); - return ""; - } else + resultMsg = ""; + } + else + { resultMsg = "Can't save new effect. Effect path empty"; - } else + } + } + else + { resultMsg = "Missing schema file for Python script " + message["script"].toString(); - } else + } + } + else + { resultMsg = "Missing or empty Object 'args'"; + } return resultMsg; } @@ -184,50 +209,56 @@ void EffectFileHandler::updateEffects() _effectSchemas.clear(); // read all effects - const QJsonArray & paths = _effectConfig["paths"].toArray(); - const QJsonArray & disabledEfx = _effectConfig["disable"].toArray(); + const QJsonArray& paths = _effectConfig["paths"].toArray(); + const QJsonArray& disabledEfx = _effectConfig["disable"].toArray(); QStringList efxPathList; efxPathList << ":/effects/"; QStringList disableList; - for(auto p : paths) + for (const auto& p : paths) { - efxPathList << p.toString().replace("$ROOT",_rootPath); + QString effectPath = p.toString(); + if (!effectPath.endsWith('/')) + { + effectPath.append('/'); + } + efxPathList << effectPath.replace("$ROOT", _rootPath); } - for(auto efx : disabledEfx) + + for (const auto& efx : disabledEfx) { disableList << efx.toString(); } QMap availableEffects; - for (const QString & path : efxPathList ) + for (const QString& path : qAsConst(efxPathList)) { QDir directory(path); if (!directory.exists()) { - if(directory.mkpath(path)) + if (directory.mkpath(path)) { - Info(_log, "New Effect path \"%s\" created successfully", QSTRING_CSTR(path) ); + Info(_log, "New Effect path \"%s\" created successfully", QSTRING_CSTR(path)); } else { - Warning(_log, "Failed to create Effect path \"%s\", please check permissions", QSTRING_CSTR(path) ); + Warning(_log, "Failed to create Effect path \"%s\", please check permissions", QSTRING_CSTR(path)); } } else { int efxCount = 0; QStringList filenames = directory.entryList(QStringList() << "*.json", QDir::Files, QDir::Name | QDir::IgnoreCase); - for (const QString & filename : filenames) + for (const QString& filename : qAsConst(filenames)) { EffectDefinition def; if (loadEffectDefinition(path, filename, def)) { InfoIf(availableEffects.find(def.name) != availableEffects.end(), _log, - "effect overload effect '%s' is now taken from '%s'", QSTRING_CSTR(def.name), QSTRING_CSTR(path) ); + "effect overload effect '%s' is now taken from '%s'", QSTRING_CSTR(def.name), QSTRING_CSTR(path)); - if ( disableList.contains(def.name) ) + if (disableList.contains(def.name)) { Info(_log, "effect '%s' not loaded, because it is disabled in hyperion config", QSTRING_CSTR(def.name)); } @@ -242,64 +273,65 @@ void EffectFileHandler::updateEffects() // collect effect schemas efxCount = 0; - directory.setPath(path.endsWith("/") ? (path + "schema/") : (path + "/schema/")); - QStringList pynames = directory.entryList(QStringList() << "*.json", QDir::Files, QDir::Name | QDir::IgnoreCase); - for (const QString & pyname : pynames) + + 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)) { EffectSchema pyEffect; - if (loadEffectSchema(path, pyname, pyEffect)) + if (loadEffectSchema(path, directory.filePath(schemaFileName), pyEffect)) { _effectSchemas.push_back(pyEffect); efxCount++; } } - InfoIf(efxCount > 0, _log, "%d effect schemas loaded from directory %s", efxCount, QSTRING_CSTR((path + "schema/"))); + InfoIf(efxCount > 0, _log, "%d effect schemas loaded from directory %s", efxCount, QSTRING_CSTR(schemaPath)); } } - for(auto item : availableEffects) + for (const auto& item : qAsConst(availableEffects)) { _availableEffects.push_back(item); } - ErrorIf(_availableEffects.size()==0, _log, "no effects found, check your effect directories"); + ErrorIf(_availableEffects.empty(), _log, "no effects found, check your effect directories"); emit effectListChanged(); } -bool EffectFileHandler::loadEffectDefinition(const QString &path, const QString &effectConfigFile, EffectDefinition & effectDefinition) +bool EffectFileHandler::loadEffectDefinition(const QString& path, const QString& effectConfigFile, EffectDefinition& effectDefinition) { - QString fileName = path + QDir::separator() + effectConfigFile; + QString fileName = path + effectConfigFile; // Read and parse the effect json config file QJsonObject configEffect; - if(!JsonUtils::readFile(fileName, configEffect, _log)) + if (!JsonUtils::readFile(fileName, configEffect, _log)) { return false; + } // validate effect config with effect schema(path) - if(!JsonUtils::validate(fileName, configEffect, ":effect-schema", _log)) + if (!JsonUtils::validate(fileName, configEffect, ":effect-schema", _log)) { return false; + } // setup the definition effectDefinition.file = fileName; QJsonObject config = configEffect; QString scriptName = config["script"].toString(); effectDefinition.name = config["name"].toString(); - if (scriptName.isEmpty()) + if (scriptName.isEmpty()) { return false; + } QFile fileInfo(scriptName); - - if (scriptName.mid(0, 1) == ":" ) + if (!fileInfo.exists()) { - (!fileInfo.exists()) - ? effectDefinition.script = ":/effects/"+scriptName.mid(1) - : effectDefinition.script = scriptName; - } else + effectDefinition.script = path + scriptName; + } + else { - (!fileInfo.exists()) - ? effectDefinition.script = path + QDir::separator() + scriptName - : effectDefinition.script = scriptName; + effectDefinition.script = scriptName; } effectDefinition.args = config["args"].toObject(); @@ -307,31 +339,31 @@ bool EffectFileHandler::loadEffectDefinition(const QString &path, const QString return true; } -bool EffectFileHandler::loadEffectSchema(const QString &path, const QString &effectSchemaFile, EffectSchema & effectSchema) +bool EffectFileHandler::loadEffectSchema(const QString& path, const QString& schemaFilePath, EffectSchema& effectSchema) { - QString fileName = path + "schema/" + QDir::separator() + effectSchemaFile; - // Read and parse the effect schema file QJsonObject schemaEffect; - if(!JsonUtils::readFile(fileName, schemaEffect, _log)) - return false; - - // setup the definition - QString scriptName = schemaEffect["script"].toString(); - effectSchema.schemaFile = fileName; - fileName = path + QDir::separator() + scriptName; - QFile pyFile(fileName); - - if (scriptName.isEmpty() || !pyFile.open(QIODevice::ReadOnly)) + if (!JsonUtils::readFile(schemaFilePath, schemaEffect, _log)) { - fileName = path + "schema/" + QDir::separator() + effectSchemaFile; - Error( _log, "Python script '%s' in effect schema '%s' could not be loaded", QSTRING_CSTR(scriptName), QSTRING_CSTR(fileName)); return false; } - pyFile.close(); + // setup the definition + QString scriptName = schemaEffect["script"].toString(); + effectSchema.schemaFile = schemaFilePath; - effectSchema.pyFile = (scriptName.mid(0, 1) == ":" ) ? ":/effects/"+scriptName.mid(1) : path + QDir::separator() + scriptName; + QString scriptFilePath = path + scriptName; + QFile pyScriptFile(scriptFilePath); + + if (scriptName.isEmpty() || !pyScriptFile.open(QIODevice::ReadOnly)) + { + Error(_log, "Python script '%s' in effect schema '%s' could not be loaded", QSTRING_CSTR(scriptName), QSTRING_CSTR(schemaFilePath)); + return false; + } + + pyScriptFile.close(); + + effectSchema.pyFile = scriptFilePath; effectSchema.pySchema = schemaEffect; return true; diff --git a/libsrc/effectengine/EffectModule.cpp b/libsrc/effectengine/EffectModule.cpp index 78d6be5d..a5e1f439 100644 --- a/libsrc/effectengine/EffectModule.cpp +++ b/libsrc/effectengine/EffectModule.cpp @@ -121,19 +121,6 @@ PyMethodDef EffectModule::effectMethods[] = { PyObject* EffectModule::wrapSetColor(PyObject *self, PyObject *args) { - // check if we have aborted already - if (getEffect()->isInterruptionRequested()) Py_RETURN_NONE; - - // determine the timeout - int timeout = getEffect()->_timeout; - if (timeout > 0) - { - timeout = getEffect()->_endTime - QDateTime::currentMSecsSinceEpoch(); - - // we are done if the time has passed - if (timeout <= 0) Py_RETURN_NONE; - } - // check the number of arguments int argCount = PyTuple_Size(args); if (argCount == 3) @@ -144,7 +131,7 @@ PyObject* EffectModule::wrapSetColor(PyObject *self, PyObject *args) { getEffect()->_colors.fill(color); QVector _cQV = getEffect()->_colors; - emit getEffect()->setInput(getEffect()->_priority, std::vector( _cQV.begin(), _cQV.end() ), timeout, false); + emit getEffect()->setInput(getEffect()->_priority, std::vector( _cQV.begin(), _cQV.end() ), getEffect()->getRemaining(), false); Py_RETURN_NONE; } return nullptr; @@ -163,7 +150,7 @@ PyObject* EffectModule::wrapSetColor(PyObject *self, PyObject *args) char * data = PyByteArray_AS_STRING(bytearray); memcpy(getEffect()->_colors.data(), data, length); QVector _cQV = getEffect()->_colors; - emit getEffect()->setInput(getEffect()->_priority, std::vector( _cQV.begin(), _cQV.end() ), timeout, false); + emit getEffect()->setInput(getEffect()->_priority, std::vector( _cQV.begin(), _cQV.end() ), getEffect()->getRemaining(), false); Py_RETURN_NONE; } else @@ -192,19 +179,6 @@ PyObject* EffectModule::wrapSetColor(PyObject *self, PyObject *args) PyObject* EffectModule::wrapSetImage(PyObject *self, PyObject *args) { - // check if we have aborted already - if (getEffect()->isInterruptionRequested()) Py_RETURN_NONE; - - // determine the timeout - int timeout = getEffect()->_timeout; - if (timeout > 0) - { - timeout = getEffect()->_endTime - QDateTime::currentMSecsSinceEpoch(); - - // we are done if the time has passed - if (timeout <= 0) Py_RETURN_NONE; - } - // bytearray of values int width, height; PyObject * bytearray = nullptr; @@ -218,7 +192,7 @@ PyObject* EffectModule::wrapSetImage(PyObject *self, PyObject *args) Image image(width, height); char * data = PyByteArray_AS_STRING(bytearray); memcpy(image.memptr(), data, length); - emit getEffect()->setInputImage(getEffect()->_priority, image, timeout, false); + emit getEffect()->setInputImage(getEffect()->_priority, image, getEffect()->getRemaining(), false); Py_RETURN_NONE; } else @@ -245,9 +219,6 @@ PyObject* EffectModule::wrapSetImage(PyObject *self, PyObject *args) PyObject* EffectModule::wrapGetImage(PyObject *self, PyObject *args) { - // check if we have aborted already - if (getEffect()->isInterruptionRequested()) Py_RETURN_NONE; - QString file; QBuffer buffer; QImageReader reader; @@ -329,19 +300,6 @@ PyObject* EffectModule::wrapAbort(PyObject *self, PyObject *) PyObject* EffectModule::wrapImageShow(PyObject *self, PyObject *args) { - // check if we have aborted already - if (getEffect()->isInterruptionRequested()) Py_RETURN_NONE; - - // determine the timeout - int timeout = getEffect()->_timeout; - if (timeout > 0) - { - timeout = getEffect()->_endTime - QDateTime::currentMSecsSinceEpoch(); - - // we are done if the time has passed - if (timeout <= 0) Py_RETURN_NONE; - } - int argCount = PyTuple_Size(args); int imgId = -1; bool argsOk = (argCount == 0); @@ -375,16 +333,13 @@ PyObject* EffectModule::wrapImageShow(PyObject *self, PyObject *args) } memcpy(image.memptr(), binaryImage.data(), binaryImage.size()); - emit getEffect()->setInputImage(getEffect()->_priority, image, timeout, false); + emit getEffect()->setInputImage(getEffect()->_priority, image, getEffect()->getRemaining(), false); return Py_BuildValue(""); } PyObject* EffectModule::wrapImageLinearGradient(PyObject *self, PyObject *args) { - // check if we have aborted already - if (getEffect()->isInterruptionRequested()) Py_RETURN_NONE; - int argCount = PyTuple_Size(args); PyObject * bytearray = nullptr; int startRX = 0; @@ -452,9 +407,6 @@ PyObject* EffectModule::wrapImageLinearGradient(PyObject *self, PyObject *args) PyObject* EffectModule::wrapImageConicalGradient(PyObject *self, PyObject *args) { - // check if we have aborted already - if (getEffect()->isInterruptionRequested()) Py_RETURN_NONE; - int argCount = PyTuple_Size(args); PyObject * bytearray = nullptr; int centerX, centerY, angle; @@ -521,9 +473,6 @@ PyObject* EffectModule::wrapImageConicalGradient(PyObject *self, PyObject *args) PyObject* EffectModule::wrapImageRadialGradient(PyObject *self, PyObject *args) { - // check if we have aborted already - if (getEffect()->isInterruptionRequested()) Py_RETURN_NONE; - int argCount = PyTuple_Size(args); PyObject * bytearray = nullptr; int centerX, centerY, radius, focalX, focalY, focalRadius, spread; @@ -602,9 +551,6 @@ PyObject* EffectModule::wrapImageRadialGradient(PyObject *self, PyObject *args) PyObject* EffectModule::wrapImageDrawPolygon(PyObject *self, PyObject *args) { - // check if we have aborted already - if (getEffect()->isInterruptionRequested()) Py_RETURN_NONE; - PyObject * bytearray = nullptr; int argCount = PyTuple_Size(args); @@ -663,9 +609,6 @@ PyObject* EffectModule::wrapImageDrawPolygon(PyObject *self, PyObject *args) PyObject* EffectModule::wrapImageDrawPie(PyObject *self, PyObject *args) { - // check if we have aborted already - if (getEffect()->isInterruptionRequested()) Py_RETURN_NONE; - PyObject * bytearray = nullptr; QString brush; @@ -760,9 +703,6 @@ PyObject* EffectModule::wrapImageDrawPie(PyObject *self, PyObject *args) PyObject* EffectModule::wrapImageSolidFill(PyObject *self, PyObject *args) { - // check if we have aborted already - if (getEffect()->isInterruptionRequested()) Py_RETURN_NONE; - int argCount = PyTuple_Size(args); int r, g, b; int a = 255; @@ -802,9 +742,6 @@ PyObject* EffectModule::wrapImageSolidFill(PyObject *self, PyObject *args) PyObject* EffectModule::wrapImageDrawLine(PyObject *self, PyObject *args) { - // check if we have aborted already - if (getEffect()->isInterruptionRequested()) Py_RETURN_NONE; - int argCount = PyTuple_Size(args); int r, g, b; int a = 255; @@ -843,9 +780,6 @@ PyObject* EffectModule::wrapImageDrawLine(PyObject *self, PyObject *args) PyObject* EffectModule::wrapImageDrawPoint(PyObject *self, PyObject *args) { - // check if we have aborted already - if (getEffect()->isInterruptionRequested()) Py_RETURN_NONE; - int argCount = PyTuple_Size(args); int r, g, b, x, y; int a = 255; @@ -879,9 +813,6 @@ PyObject* EffectModule::wrapImageDrawPoint(PyObject *self, PyObject *args) PyObject* EffectModule::wrapImageDrawRect(PyObject *self, PyObject *args) { - // check if we have aborted already - if (getEffect()->isInterruptionRequested()) Py_RETURN_NONE; - int argCount = PyTuple_Size(args); int r, g, b; int a = 255; @@ -921,9 +852,6 @@ PyObject* EffectModule::wrapImageDrawRect(PyObject *self, PyObject *args) PyObject* EffectModule::wrapImageSetPixel(PyObject *self, PyObject *args) { - // check if we have aborted already - if (getEffect()->isInterruptionRequested()) Py_RETURN_NONE; - int argCount = PyTuple_Size(args); int r, g, b, x, y; @@ -939,9 +867,6 @@ PyObject* EffectModule::wrapImageSetPixel(PyObject *self, PyObject *args) PyObject* EffectModule::wrapImageGetPixel(PyObject *self, PyObject *args) { - // check if we have aborted already - if (getEffect()->isInterruptionRequested()) Py_RETURN_NONE; - int argCount = PyTuple_Size(args); int x, y; @@ -955,9 +880,6 @@ PyObject* EffectModule::wrapImageGetPixel(PyObject *self, PyObject *args) PyObject* EffectModule::wrapImageSave(PyObject *self, PyObject *args) { - // check if we have aborted already - if (getEffect()->isInterruptionRequested()) Py_RETURN_NONE; - QImage img(getEffect()->_image.copy()); getEffect()->_imageStack.append(img); @@ -966,9 +888,6 @@ PyObject* EffectModule::wrapImageSave(PyObject *self, PyObject *args) PyObject* EffectModule::wrapImageMinSize(PyObject *self, PyObject *args) { - // check if we have aborted already - if (getEffect()->isInterruptionRequested()) Py_RETURN_NONE; - int argCount = PyTuple_Size(args); int w, h; int width = getEffect()->_imageSize.width(); @@ -991,25 +910,16 @@ PyObject* EffectModule::wrapImageMinSize(PyObject *self, PyObject *args) PyObject* EffectModule::wrapImageWidth(PyObject *self, PyObject *args) { - // check if we have aborted already - if (getEffect()->isInterruptionRequested()) Py_RETURN_NONE; - return Py_BuildValue("i", getEffect()->_imageSize.width()); } PyObject* EffectModule::wrapImageHeight(PyObject *self, PyObject *args) { - // check if we have aborted already - if (getEffect()->isInterruptionRequested()) Py_RETURN_NONE; - return Py_BuildValue("i", getEffect()->_imageSize.height()); } PyObject* EffectModule::wrapImageCRotate(PyObject *self, PyObject *args) { - // check if we have aborted already - if (getEffect()->isInterruptionRequested()) Py_RETURN_NONE; - int argCount = PyTuple_Size(args); int angle; @@ -1024,9 +934,6 @@ PyObject* EffectModule::wrapImageCRotate(PyObject *self, PyObject *args) PyObject* EffectModule::wrapImageCOffset(PyObject *self, PyObject *args) { - // check if we have aborted already - if (getEffect()->isInterruptionRequested()) Py_RETURN_NONE; - int offsetX = 0; int offsetY = 0; int argCount = PyTuple_Size(args); @@ -1042,9 +949,6 @@ PyObject* EffectModule::wrapImageCOffset(PyObject *self, PyObject *args) PyObject* EffectModule::wrapImageCShear(PyObject *self, PyObject *args) { - // check if we have aborted already - if (getEffect()->isInterruptionRequested()) Py_RETURN_NONE; - int sh,sv; int argCount = PyTuple_Size(args); @@ -1058,9 +962,6 @@ PyObject* EffectModule::wrapImageCShear(PyObject *self, PyObject *args) PyObject* EffectModule::wrapImageResetT(PyObject *self, PyObject *args) { - // check if we have aborted already - if (getEffect()->isInterruptionRequested()) Py_RETURN_NONE; - getEffect()->_painter->resetTransform(); Py_RETURN_NONE; } diff --git a/libsrc/grabber/CMakeLists.txt b/libsrc/grabber/CMakeLists.txt index 6e5f42c1..68c93b2a 100644 --- a/libsrc/grabber/CMakeLists.txt +++ b/libsrc/grabber/CMakeLists.txt @@ -14,13 +14,13 @@ if (ENABLE_OSX) add_subdirectory(osx) endif(ENABLE_OSX) -if (ENABLE_V4L2) - add_subdirectory(v4l2) -endif (ENABLE_V4L2) +# if (ENABLE_V4L2) +# add_subdirectory(v4l2) +# endif (ENABLE_V4L2) -if (ENABLE_MF) - add_subdirectory(mediafoundation) -endif (ENABLE_MF) +if (ENABLE_V4L2 OR ENABLE_MF) + add_subdirectory(video) +endif () if (ENABLE_X11) add_subdirectory(x11) diff --git a/libsrc/grabber/directx/DirectXGrabber.cpp b/libsrc/grabber/directx/DirectXGrabber.cpp index f8cd3f23..6edadb74 100644 --- a/libsrc/grabber/directx/DirectXGrabber.cpp +++ b/libsrc/grabber/directx/DirectXGrabber.cpp @@ -1,12 +1,13 @@ #include #include -#include + #pragma comment(lib, "d3d9.lib") #pragma comment(lib,"d3dx9.lib") DirectXGrabber::DirectXGrabber(int cropLeft, int cropRight, int cropTop, int cropBottom, int pixelDecimation, int display) : Grabber("DXGRABBER", 0, 0, cropLeft, cropRight, cropTop, cropBottom) , _pixelDecimation(pixelDecimation) + , _display(unsigned(display)) , _displayWidth(0) , _displayHeight(0) , _srcRect(0) @@ -43,6 +44,8 @@ bool DirectXGrabber::setupDisplay() D3DDISPLAYMODE ddm; D3DPRESENT_PARAMETERS d3dpp; + HMONITOR hMonitor = nullptr; + MONITORINFO monitorInfo = { 0 }; if ((_d3d9 = Direct3DCreate9(D3D_SDK_VERSION)) == nullptr) { @@ -50,7 +53,17 @@ bool DirectXGrabber::setupDisplay() return false; } - if (FAILED(_d3d9->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &ddm))) + SecureZeroMemory(&monitorInfo, sizeof(monitorInfo)); + monitorInfo.cbSize = sizeof(MONITORINFO); + + hMonitor = _d3d9->GetAdapterMonitor(_display); + if (hMonitor == nullptr || GetMonitorInfo(hMonitor, &monitorInfo) == FALSE) + { + Info(_log, "Specified display %d is not available. Primary display %d is used", _display, D3DADAPTER_DEFAULT); + _display = D3DADAPTER_DEFAULT; + } + + if (FAILED(_d3d9->GetAdapterDisplayMode(_display, &ddm))) { Error(_log, "Failed to get current display mode"); return false; @@ -69,7 +82,7 @@ bool DirectXGrabber::setupDisplay() d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; - if (FAILED(_d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, nullptr, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &_device))) + if (FAILED(_d3d9->CreateDevice(_display, D3DDEVTYPE_HAL, nullptr, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &_device))) { Error(_log, "CreateDevice failed"); return false; @@ -147,12 +160,11 @@ int DirectXGrabber::grabFrame(Image & image) return 0; } - memcpy(image.memptr(), lockedRect.pBits, _width * _height * 3); + for(int i=0 ; i < _height ; i++) + memcpy((unsigned char*)image.memptr() + i * _width * 3, (unsigned char*)lockedRect.pBits + i * lockedRect.Pitch, _width * 3); + for (int idx = 0; idx < _width * _height; idx++) - { - const ColorRgb & color = image.memptr()[idx]; - image.memptr()[idx] = ColorRgb{color.blue, color.green, color.red}; - } + image.memptr()[idx] = ColorRgb{image.memptr()[idx].blue, image.memptr()[idx].green, image.memptr()[idx].red}; if (FAILED(_surfaceDest->UnlockRect())) { @@ -179,3 +191,12 @@ void DirectXGrabber::setCropping(unsigned cropLeft, unsigned cropRight, unsigned Grabber::setCropping(cropLeft, cropRight, cropTop, cropBottom); setupDisplay(); } + +void DirectXGrabber::setDisplayIndex(int index) +{ + if(_display != unsigned(index)) + { + _display = unsigned(index); + setupDisplay(); + } +} diff --git a/libsrc/grabber/mediafoundation/CMakeLists.txt b/libsrc/grabber/mediafoundation/CMakeLists.txt deleted file mode 100644 index 0a019e72..00000000 --- a/libsrc/grabber/mediafoundation/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -# Define the current source locations -SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber) -SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/mediafoundation) - -FILE ( GLOB MF_SOURCES "${CURRENT_HEADER_DIR}/MF*.h" "${CURRENT_SOURCE_DIR}/*.h" "${CURRENT_SOURCE_DIR}/*.cpp" ) - -add_library(mf-grabber ${MF_SOURCES} ) - -target_link_libraries(mf-grabber - hyperion - ${QT_LIBRARIES} -) - -if(TURBOJPEG_FOUND) - target_link_libraries(mf-grabber ${TurboJPEG_LIBRARY}) -endif(TURBOJPEG_FOUND) diff --git a/libsrc/grabber/mediafoundation/MFWrapper.cpp b/libsrc/grabber/mediafoundation/MFWrapper.cpp deleted file mode 100644 index c70aa0cd..00000000 --- a/libsrc/grabber/mediafoundation/MFWrapper.cpp +++ /dev/null @@ -1,170 +0,0 @@ -#include - -#include - -// qt -#include - -MFWrapper::MFWrapper(const QString &device, unsigned grabWidth, unsigned grabHeight, unsigned fps, int pixelDecimation, QString flipMode) - : GrabberWrapper("V4L2:MEDIA_FOUNDATION", &_grabber, grabWidth, grabHeight, 10) - , _grabber(device, grabWidth, grabHeight, fps, pixelDecimation, flipMode) -{ - _ggrabber = &_grabber; - - // register the image type - qRegisterMetaType>("Image"); - - // Handle the image in the captured thread using a direct connection - connect(&_grabber, &MFGrabber::newFrame, this, &MFWrapper::newFrame, Qt::DirectConnection); -} - -MFWrapper::~MFWrapper() -{ - stop(); -} - -bool MFWrapper::start() -{ - return ( _grabber.start() && GrabberWrapper::start()); -} - -void MFWrapper::stop() -{ - _grabber.stop(); - GrabberWrapper::stop(); -} - -void MFWrapper::setSignalThreshold(double redSignalThreshold, double greenSignalThreshold, double blueSignalThreshold, int noSignalCounterThreshold) -{ - _grabber.setSignalThreshold( redSignalThreshold, greenSignalThreshold, blueSignalThreshold, noSignalCounterThreshold); -} - -void MFWrapper::setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom) -{ - _grabber.setCropping(cropLeft, cropRight, cropTop, cropBottom); -} - -void MFWrapper::setSignalDetectionOffset(double verticalMin, double horizontalMin, double verticalMax, double horizontalMax) -{ - _grabber.setSignalDetectionOffset(verticalMin, horizontalMin, verticalMax, horizontalMax); -} - -void MFWrapper::newFrame(const Image &image) -{ - emit systemImage(_grabberName, image); -} - -void MFWrapper::action() -{ - // dummy -} - -void MFWrapper::setSignalDetectionEnable(bool enable) -{ - _grabber.setSignalDetectionEnable(enable); -} - -bool MFWrapper::getSignalDetectionEnable() const -{ - return _grabber.getSignalDetectionEnabled(); -} - -void MFWrapper::setCecDetectionEnable(bool enable) -{ - _grabber.setCecDetectionEnable(enable); -} - -bool MFWrapper::getCecDetectionEnable() const -{ - return _grabber.getCecDetectionEnabled(); -} - -bool MFWrapper::setDevice(const QString& device) -{ - return _grabber.setDevice(device); -} - -void MFWrapper::setFpsSoftwareDecimation(int decimation) -{ - _grabber.setFpsSoftwareDecimation(decimation); -} - -bool MFWrapper::setEncoding(QString enc) -{ - return _grabber.setEncoding(enc); -} - -bool MFWrapper::setBrightnessContrastSaturationHue(int brightness, int contrast, int saturation, int hue) -{ - return _grabber.setBrightnessContrastSaturationHue(brightness, contrast, saturation, hue); -} - -void MFWrapper::handleSettingsUpdate(settings::type type, const QJsonDocument& config) -{ - if(type == settings::V4L2 && _grabberName.startsWith("V4L2")) - { - // extract settings - const QJsonObject& obj = config.object(); - // reload state - bool reload = false; - - // device name, video standard - if (_grabber.setDevice(obj["device"].toString("auto"))) - reload = true; - - // device input - _grabber.setInput(obj["input"].toInt(-1)); - - // device resolution - if (_grabber.setWidthHeight(obj["width"].toInt(0), obj["height"].toInt(0))) - reload = true; - - // device framerate - if (_grabber.setFramerate(obj["fps"].toInt(15))) - reload = true; - - // image size decimation - _grabber.setPixelDecimation(obj["sizeDecimation"].toInt(8)); - - // flip mode - _grabber.setFlipMode(obj["flip"].toString("NO_CHANGE")); - - // image cropping - _grabber.setCropping( - obj["cropLeft"].toInt(0), - obj["cropRight"].toInt(0), - obj["cropTop"].toInt(0), - obj["cropBottom"].toInt(0)); - - // Brightness, Contrast, Saturation, Hue - if (_grabber.setBrightnessContrastSaturationHue(obj["hardware_brightness"].toInt(0), obj["hardware_contrast"].toInt(0), obj["hardware_saturation"].toInt(0), obj["hardware_hue"].toInt(0))) - reload = true; - - // CEC Standby - _grabber.setCecDetectionEnable(obj["cecDetection"].toBool(true)); - - // software frame skipping - _grabber.setFpsSoftwareDecimation(obj["fpsSoftwareDecimation"].toInt(1)); - - // Signal detection - _grabber.setSignalDetectionEnable(obj["signalDetection"].toBool(true)); - _grabber.setSignalDetectionOffset( - obj["sDHOffsetMin"].toDouble(0.25), - obj["sDVOffsetMin"].toDouble(0.25), - obj["sDHOffsetMax"].toDouble(0.75), - obj["sDVOffsetMax"].toDouble(0.75)); - _grabber.setSignalThreshold( - obj["redSignalThreshold"].toDouble(0.0)/100.0, - obj["greenSignalThreshold"].toDouble(0.0)/100.0, - obj["blueSignalThreshold"].toDouble(0.0)/100.0, - obj["noSignalCounterThreshold"].toInt(50) ); - - // Hardware encoding format - if (_grabber.setEncoding(obj["encoding"].toString("NO_CHANGE"))) - reload = true; - - // Reload the Grabber if any settings have been changed that require it - if (reload) - _grabber.reloadGrabber(); - } -} diff --git a/libsrc/grabber/qt/QtGrabber.cpp b/libsrc/grabber/qt/QtGrabber.cpp index 58cebb68..e4e5efaf 100644 --- a/libsrc/grabber/qt/QtGrabber.cpp +++ b/libsrc/grabber/qt/QtGrabber.cpp @@ -7,10 +7,18 @@ #include #include #include +#include +#include +#include + +// Constants +namespace { + const bool verbose = false; +} //End of constants QtGrabber::QtGrabber(int cropLeft, int cropRight, int cropTop, int cropBottom, int pixelDecimation, int display) : Grabber("QTGRABBER", 0, 0, cropLeft, cropRight, cropTop, cropBottom) - , _display(unsigned(display)) + , _display(display) , _pixelDecimation(pixelDecimation) , _calculatedWidth(0) , _calculatedHeight(0) @@ -18,12 +26,12 @@ QtGrabber::QtGrabber(int cropLeft, int cropRight, int cropTop, int cropBottom, i , _src_y(0) , _src_x_max(0) , _src_y_max(0) + , _isWayland(false) , _screen(nullptr) + , _isVirtual(false) { + _logger = Logger::getInstance("Qt"); _useImageResampler = false; - - // init - setupDisplay(); } QtGrabber::~QtGrabber() @@ -36,51 +44,97 @@ void QtGrabber::freeResources() // Qt seems to hold the ownership of the QScreen pointers } +bool QtGrabber::open() +{ + bool rc = false; + + if (getenv("WAYLAND_DISPLAY") != nullptr) + { + _isWayland = true; + } + else + { + rc = true; + } + return rc; +} + bool QtGrabber::setupDisplay() { - // cleanup last screen - freeResources(); - - QScreen* primary = QGuiApplication::primaryScreen(); - QList screens = QGuiApplication::screens(); - // inject main screen at 0, if not nullptr - if(primary != nullptr) + bool result = false; + if ( ! open() ) { - screens.prepend(primary); - // remove last main screen if twice in list - if(screens.lastIndexOf(primary) > 0) - screens.removeAt(screens.lastIndexOf(primary)); + if ( _isWayland ) + { + Error(_log, "Grabber does not work under Wayland!"); + } } - - if(screens.isEmpty()) + else { - Error(_log, "No displays found to capture from!"); - return false; + // cleanup last screen + freeResources(); + _numberOfSDisplays = 0; + + QScreen* primary = QGuiApplication::primaryScreen(); + QList screens = QGuiApplication::screens(); + // inject main screen at 0, if not nullptr + if(primary != nullptr) + { + screens.prepend(primary); + // remove last main screen if twice in list + if(screens.lastIndexOf(primary) > 0) + { + screens.removeAt(screens.lastIndexOf(primary)); + } + } + + if(screens.isEmpty()) + { + Error(_log, "No displays found to capture from!"); + result = false; + } + else + { + _numberOfSDisplays = screens.size(); + + Info(_log,"Available Displays:"); + int index = 0; + for(auto * screen : qAsConst(screens)) + { + const QRect geo = screen->geometry(); + Info(_log,"Display %d: Name:%s Geometry: (L,T,R,B) %d,%d,%d,%d Depth:%dbit", index, QSTRING_CSTR(screen->name()), geo.left(), geo.top() ,geo.right(), geo.bottom(), screen->depth()); + ++index; + } + + _isVirtual = false; + // be sure the index is available + if (_display > _numberOfSDisplays - 1 ) + { + + if (screens.at(0)->size() != screens.at(0)->virtualSize()) + { + Info(_log, "Using virtual display across all screens"); + _isVirtual = true; + _display = 0; + + } + else + { + Info(_log, "The requested display index '%d' is not available, falling back to display 0", _display); + _display = 0; + } + } + + // init the requested display + _screen = screens.at(_display); + connect(_screen, &QScreen::geometryChanged, this, &QtGrabber::geometryChanged); + updateScreenDimensions(true); + + Info(_log,"Initialized display %d", _display); + result = true; + } } - - Info(_log,"Available Displays:"); - int index = 0; - for(auto screen : screens) - { - const QRect geo = screen->geometry(); - Info(_log,"Display %d: Name:%s Geometry: (L,T,R,B) %d,%d,%d,%d Depth:%dbit", index, QSTRING_CSTR(screen->name()), geo.left(), geo.top() ,geo.right(), geo.bottom(), screen->depth()); - index++; - } - - // be sure the index is available - if(_display > unsigned(screens.size()-1)) - { - Info(_log, "The requested display index '%d' is not available, falling back to display 0", _display); - _display = 0; - } - - // init the requested display - _screen = screens.at(_display); - connect(_screen, &QScreen::geometryChanged, this, &QtGrabber::geometryChanged); - updateScreenDimensions(true); - - Info(_log,"Initialized display %d", _display); - return true; + return result; } void QtGrabber::geometryChanged(const QRect &geo) @@ -91,30 +145,48 @@ void QtGrabber::geometryChanged(const QRect &geo) int QtGrabber::grabFrame(Image & image) { - if (!_enabled) return 0; + if (!_enabled) + { + return 0; + } + if(_screen == nullptr) { // reinit, this will disable capture on failure - setEnabled(setupDisplay()); + bool result = setupDisplay(); + setEnabled(result); return -1; } QPixmap originalPixmap = _screen->grabWindow(0, _src_x, _src_y, _src_x_max, _src_y_max); QImage imageFrame = originalPixmap.toImage().scaled(_calculatedWidth, _calculatedHeight).convertToFormat( QImage::Format_RGB888); - image.resize(_calculatedWidth, _calculatedHeight); + image.resize(static_cast(_calculatedWidth), static_cast(_calculatedHeight)); for (int y = 0; y < imageFrame.height(); y++) - memcpy((unsigned char*)image.memptr() + y * image.width() * 3, (unsigned char*)imageFrame.scanLine(y), imageFrame.width() * 3); + { + memcpy((unsigned char*)image.memptr() + y * image.width() * 3, static_cast(imageFrame.scanLine(y)), imageFrame.width() * 3); + } return 0; } int QtGrabber::updateScreenDimensions(bool force) { - if(!_screen) + if(_screen == nullptr) + { return -1; + } - const QRect& geo = _screen->geometry(); + QRect geo; + + if (_isVirtual) + { + geo = _screen->virtualGeometry(); + } + else + { + geo = _screen->geometry(); + } if (!force && _width == geo.width() && _height == geo.height()) { // No update required @@ -125,7 +197,8 @@ int QtGrabber::updateScreenDimensions(bool force) _width = geo.width(); _height = geo.height(); - int width=0, height=0; + int width=0; + int height=0; // Image scaling is performed by Qt width = (_width > (_cropLeft + _cropRight)) @@ -177,11 +250,6 @@ void QtGrabber::setVideoMode(VideoMode mode) updateScreenDimensions(true); } -void QtGrabber::setPixelDecimation(int pixelDecimation) -{ - _pixelDecimation = pixelDecimation; -} - void QtGrabber::setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom) { Grabber::setCropping(cropLeft, cropRight, cropTop, cropBottom); @@ -190,9 +258,108 @@ void QtGrabber::setCropping(unsigned cropLeft, unsigned cropRight, unsigned crop void QtGrabber::setDisplayIndex(int index) { - if(_display != unsigned(index)) + if (_display != index) { - _display = unsigned(index); + if (index <= _numberOfSDisplays) + { + _display = index; + } + else { + _display = 0; + } setupDisplay(); } } + +QJsonObject QtGrabber::discover(const QJsonObject& params) +{ + DebugIf(verbose, _log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData()); + + QJsonObject inputsDiscovered; + if ( open() ) + { + QList screens = QGuiApplication::screens(); + + inputsDiscovered["device"] = "qt"; + inputsDiscovered["device_name"] = "QT"; + inputsDiscovered["type"] = "screen"; + + QJsonArray video_inputs; + + if (!screens.isEmpty()) + { + QJsonArray fps = { 1, 5, 10, 15, 20, 25, 30, 40, 50, 60 }; + + for (int i = 0; i < screens.size(); ++i) + { + QJsonObject in; + + QString name = screens.at(i)->name(); + + int pos = name.lastIndexOf('\\'); + if (pos != -1) + { + name = name.right(name.length()-pos-1); + } + + in["name"] = name; + in["inputIdx"] = i; + + QJsonArray formats; + QJsonObject format; + + QJsonArray resolutionArray; + + QJsonObject resolution; + + resolution["width"] = screens.at(i)->size().width(); + resolution["height"] = screens.at(i)->size().height(); + resolution["fps"] = fps; + + resolutionArray.append(resolution); + + format["resolutions"] = resolutionArray; + formats.append(format); + + in["formats"] = formats; + video_inputs.append(in); + } + + if (screens.at(0)->size() != screens.at(0)->virtualSize()) + { + QJsonObject in; + in["name"] = "All Displays"; + in["inputIdx"] = screens.size(); + in["virtual"] = true; + + QJsonArray formats; + QJsonObject format; + + QJsonArray resolutionArray; + + QJsonObject resolution; + + resolution["width"] = screens.at(0)->virtualSize().width(); + resolution["height"] = screens.at(0)->virtualSize().height(); + resolution["fps"] = fps; + + resolutionArray.append(resolution); + + format["resolutions"] = resolutionArray; + formats.append(format); + + in["formats"] = formats; + video_inputs.append(in); + } + inputsDiscovered["video_inputs"] = video_inputs; + } + else + { + DebugIf(verbose, _log, "No displays found to capture from!"); + } + } + DebugIf(verbose, _log, "device: [%s]", QString(QJsonDocument(inputsDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData()); + + return inputsDiscovered; + +} diff --git a/libsrc/grabber/qt/QtWrapper.cpp b/libsrc/grabber/qt/QtWrapper.cpp index 2d525198..11d534ab 100644 --- a/libsrc/grabber/qt/QtWrapper.cpp +++ b/libsrc/grabber/qt/QtWrapper.cpp @@ -5,6 +5,11 @@ QtWrapper::QtWrapper(int cropLeft, int cropRight, int cropTop, int cropBottom, i , _grabber(cropLeft, cropRight, cropTop, cropBottom, pixelDecimation, display) {} +bool QtWrapper::open() +{ + return _grabber.open(); +} + void QtWrapper::action() { transferFrame(_grabber); diff --git a/libsrc/grabber/v4l2/CMakeLists.txt b/libsrc/grabber/v4l2/CMakeLists.txt deleted file mode 100644 index 9a41bbe5..00000000 --- a/libsrc/grabber/v4l2/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -# Define the current source locations -SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber) -SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/v4l2) - -FILE ( GLOB V4L2_SOURCES "${CURRENT_HEADER_DIR}/V4L2*.h" "${CURRENT_SOURCE_DIR}/*.h" "${CURRENT_SOURCE_DIR}/*.cpp" ) - -add_library(v4l2-grabber ${V4L2_SOURCES} ) - -target_link_libraries(v4l2-grabber - hyperion - ${QT_LIBRARIES} -) - -if(TURBOJPEG_FOUND) - target_link_libraries(v4l2-grabber ${TurboJPEG_LIBRARY}) -elseif (JPEG_FOUND) - target_link_libraries(v4l2-grabber ${JPEG_LIBRARY}) -endif(TURBOJPEG_FOUND) diff --git a/libsrc/grabber/v4l2/V4L2Wrapper.cpp b/libsrc/grabber/v4l2/V4L2Wrapper.cpp deleted file mode 100644 index 2782f17f..00000000 --- a/libsrc/grabber/v4l2/V4L2Wrapper.cpp +++ /dev/null @@ -1,156 +0,0 @@ -#include - -#include - -// qt -#include - -V4L2Wrapper::V4L2Wrapper(const QString &device, - unsigned grabWidth, - unsigned grabHeight, - unsigned fps, - unsigned input, - VideoStandard videoStandard, - PixelFormat pixelFormat, - int pixelDecimation) - : GrabberWrapper("V4L2:"+device, &_grabber, grabWidth, grabHeight, 10) - , _grabber(device, - grabWidth, - grabHeight, - fps, - input, - videoStandard, - pixelFormat, - pixelDecimation) -{ - _ggrabber = &_grabber; - - // register the image type - qRegisterMetaType>("Image"); - - // Handle the image in the captured thread using a direct connection - connect(&_grabber, &V4L2Grabber::newFrame, this, &V4L2Wrapper::newFrame, Qt::DirectConnection); - connect(&_grabber, &V4L2Grabber::readError, this, &V4L2Wrapper::readError, Qt::DirectConnection); -} - -V4L2Wrapper::~V4L2Wrapper() -{ - stop(); -} - -bool V4L2Wrapper::start() -{ - return ( _grabber.start() && GrabberWrapper::start()); -} - -void V4L2Wrapper::stop() -{ - _grabber.stop(); - GrabberWrapper::stop(); -} - -void V4L2Wrapper::setSignalThreshold(double redSignalThreshold, double greenSignalThreshold, double blueSignalThreshold) -{ - _grabber.setSignalThreshold( redSignalThreshold, greenSignalThreshold, blueSignalThreshold, 50); -} - -void V4L2Wrapper::setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom) -{ - _grabber.setCropping(cropLeft, cropRight, cropTop, cropBottom); -} - -void V4L2Wrapper::setSignalDetectionOffset(double verticalMin, double horizontalMin, double verticalMax, double horizontalMax) -{ - _grabber.setSignalDetectionOffset(verticalMin, horizontalMin, verticalMax, horizontalMax); -} - -void V4L2Wrapper::newFrame(const Image &image) -{ - emit systemImage(_grabberName, image); -} - -void V4L2Wrapper::readError(const char* err) -{ - Error(_log, "stop grabber, because reading device failed. (%s)", err); - stop(); -} - -void V4L2Wrapper::action() -{ - // dummy as v4l get notifications from stream -} - -void V4L2Wrapper::setSignalDetectionEnable(bool enable) -{ - _grabber.setSignalDetectionEnable(enable); -} - -bool V4L2Wrapper::getSignalDetectionEnable() const -{ - return _grabber.getSignalDetectionEnabled(); -} - -void V4L2Wrapper::setCecDetectionEnable(bool enable) -{ - _grabber.setCecDetectionEnable(enable); -} - -bool V4L2Wrapper::getCecDetectionEnable() const -{ - return _grabber.getCecDetectionEnabled(); -} - -void V4L2Wrapper::setDeviceVideoStandard(const QString& device, VideoStandard videoStandard) -{ - _grabber.setDeviceVideoStandard(device, videoStandard); -} - -void V4L2Wrapper::handleCecEvent(CECEvent event) -{ - _grabber.handleCecEvent(event); -} - -void V4L2Wrapper::handleSettingsUpdate(settings::type type, const QJsonDocument& config) -{ - if(type == settings::V4L2 && _grabberName.startsWith("V4L")) - { - // extract settings - const QJsonObject& obj = config.object(); - - // pixel decimation for v4l - _grabber.setPixelDecimation(obj["sizeDecimation"].toInt(8)); - - // crop for v4l - _grabber.setCropping( - obj["cropLeft"].toInt(0), - obj["cropRight"].toInt(0), - obj["cropTop"].toInt(0), - obj["cropBottom"].toInt(0)); - - // device input - _grabber.setInput(obj["input"].toInt(0)); - - // device resolution - _grabber.setWidthHeight(obj["width"].toInt(0), obj["height"].toInt(0)); - - // device framerate - _grabber.setFramerate(obj["fps"].toInt(15)); - - // CEC Standby - _grabber.setCecDetectionEnable(obj["cecDetection"].toBool(true)); - - _grabber.setSignalDetectionEnable(obj["signalDetection"].toBool(true)); - _grabber.setSignalDetectionOffset( - obj["sDHOffsetMin"].toDouble(0.25), - obj["sDVOffsetMin"].toDouble(0.25), - obj["sDHOffsetMax"].toDouble(0.75), - obj["sDVOffsetMax"].toDouble(0.75)); - _grabber.setSignalThreshold( - obj["redSignalThreshold"].toDouble(0.0)/100.0, - obj["greenSignalThreshold"].toDouble(0.0)/100.0, - obj["blueSignalThreshold"].toDouble(0.0)/100.0); - _grabber.setDeviceVideoStandard( - obj["device"].toString("auto"), - parseVideoStandard(obj["standard"].toString("NO_CHANGE"))); - } -} diff --git a/libsrc/grabber/video/CMakeLists.txt b/libsrc/grabber/video/CMakeLists.txt new file mode 100644 index 00000000..0343584e --- /dev/null +++ b/libsrc/grabber/video/CMakeLists.txt @@ -0,0 +1,23 @@ +# Common cmake definition for external video grabber + +# Define the wrapper/header/source locations and collect them +SET(WRAPPER_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/video) +SET(HEADER_DIR ${CMAKE_SOURCE_DIR}/include/grabber) +if (ENABLE_MF) + project(mf-grabber) + SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/video/mediafoundation) + FILE (GLOB SOURCES "${WRAPPER_DIR}/*.cpp" "${HEADER_DIR}/Video*.h" "${HEADER_DIR}/MF*.h" "${CURRENT_SOURCE_DIR}/*.h" "${CURRENT_SOURCE_DIR}/*.cpp") +elseif(ENABLE_V4L2) + project(v4l2-grabber) + SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/grabber/video/v4l2) + FILE (GLOB SOURCES "${WRAPPER_DIR}/*.cpp" "${HEADER_DIR}/Video*.h" "${HEADER_DIR}/V4L2*.h" "${CURRENT_SOURCE_DIR}/*.h" "${CURRENT_SOURCE_DIR}/*.cpp") +endif() + +add_library(${PROJECT_NAME} ${SOURCES}) +target_link_libraries(${PROJECT_NAME} hyperion ${QT_LIBRARIES}) + +if(TURBOJPEG_FOUND) + target_link_libraries(${PROJECT_NAME} ${TurboJPEG_LIBRARY}) +elseif (JPEG_FOUND) + target_link_libraries(${PROJECT_NAME} ${JPEG_LIBRARY}) +endif() diff --git a/libsrc/grabber/video/VideoWrapper.cpp b/libsrc/grabber/video/VideoWrapper.cpp new file mode 100644 index 00000000..6f4c9d55 --- /dev/null +++ b/libsrc/grabber/video/VideoWrapper.cpp @@ -0,0 +1,134 @@ +#include + +#include + +// qt +#include + +VideoWrapper::VideoWrapper() +#if defined(ENABLE_V4L2) + : GrabberWrapper("V4L2", &_grabber, 0, 0, 10) +#elif defined(ENABLE_MF) + : GrabberWrapper("V4L2:MEDIA_FOUNDATION", &_grabber, 0, 0, 10) +#endif + , _grabber() +{ + // register the image type + qRegisterMetaType>("Image"); + + // Handle the image in the captured thread (Media Foundation/V4L2) using a direct connection + connect(&_grabber, SIGNAL(newFrame(const Image&)), this, SLOT(newFrame(const Image&)), Qt::DirectConnection); + connect(&_grabber, SIGNAL(readError(const char*)), this, SLOT(readError(const char*)), Qt::DirectConnection); +} + +VideoWrapper::~VideoWrapper() +{ + stop(); +} + +bool VideoWrapper::start() +{ + return (_grabber.prepare() && _grabber.start() && GrabberWrapper::start()); +} + +void VideoWrapper::stop() +{ + _grabber.stop(); + GrabberWrapper::stop(); +} + +#if defined(ENABLE_CEC) && !defined(ENABLE_MF) + +void VideoWrapper::handleCecEvent(CECEvent event) +{ + _grabber.handleCecEvent(event); +} + +#endif + +void VideoWrapper::handleSettingsUpdate(settings::type type, const QJsonDocument& config) +{ + if(type == settings::V4L2 && _grabberName.startsWith("V4L2")) + { + // extract settings + const QJsonObject& obj = config.object(); + + // Device + _grabber.setDevice(obj["device"].toString("auto")); + + // Device input + _grabber.setInput(obj["input"].toInt(0)); + + // Device resolution + _grabber.setWidthHeight(obj["width"].toInt(0), obj["height"].toInt(0)); + + // Device framerate + _grabber.setFramerate(obj["fps"].toInt(15)); + + // Device encoding format + _grabber.setEncoding(obj["encoding"].toString("NO_CHANGE")); + + // Video standard + _grabber.setVideoStandard(parseVideoStandard(obj["standard"].toString("NO_CHANGE"))); + + // Image size decimation + _grabber.setPixelDecimation(obj["sizeDecimation"].toInt(8)); + + // Flip mode + _grabber.setFlipMode(parseFlipMode(obj["flip"].toString("NO_CHANGE"))); + + // Image cropping + _grabber.setCropping( + obj["cropLeft"].toInt(0), + obj["cropRight"].toInt(0), + obj["cropTop"].toInt(0), + obj["cropBottom"].toInt(0)); + + // Brightness, Contrast, Saturation, Hue + _grabber.setBrightnessContrastSaturationHue( + obj["hardware_brightness"].toInt(0), + obj["hardware_contrast"].toInt(0), + obj["hardware_saturation"].toInt(0), + obj["hardware_hue"].toInt(0)); + +#if defined(ENABLE_CEC) && defined(ENABLE_V4L2) + // CEC Standby + _grabber.setCecDetectionEnable(obj["cecDetection"].toBool(true)); +#endif + + // Software frame skipping + _grabber.setFpsSoftwareDecimation(obj["fpsSoftwareDecimation"].toInt(1)); + + // Signal detection + _grabber.setSignalDetectionEnable(obj["signalDetection"].toBool(true)); + _grabber.setSignalDetectionOffset( + obj["sDHOffsetMin"].toDouble(0.25), + obj["sDVOffsetMin"].toDouble(0.25), + obj["sDHOffsetMax"].toDouble(0.75), + obj["sDVOffsetMax"].toDouble(0.75)); + _grabber.setSignalThreshold( + obj["redSignalThreshold"].toDouble(0.0)/100.0, + obj["greenSignalThreshold"].toDouble(0.0)/100.0, + obj["blueSignalThreshold"].toDouble(0.0)/100.0, + obj["noSignalCounterThreshold"].toInt(50)); + + // Reload the Grabber if any settings have been changed that require it + _grabber.reload(); + } +} + +void VideoWrapper::newFrame(const Image &image) +{ + emit systemImage(_grabberName, image); +} + +void VideoWrapper::readError(const char* err) +{ + Error(_log, "Stop grabber, because reading device failed. (%s)", err); + stop(); +} + +void VideoWrapper::action() +{ + // dummy as v4l get notifications from stream +} diff --git a/libsrc/grabber/mediafoundation/MFGrabber.cpp b/libsrc/grabber/video/mediafoundation/MFGrabber.cpp similarity index 52% rename from libsrc/grabber/mediafoundation/MFGrabber.cpp rename to libsrc/grabber/video/mediafoundation/MFGrabber.cpp index 4252558f..b0e710ff 100644 --- a/libsrc/grabber/mediafoundation/MFGrabber.cpp +++ b/libsrc/grabber/video/mediafoundation/MFGrabber.cpp @@ -4,18 +4,20 @@ // Constants namespace { const bool verbose = false; } -MFGrabber::MFGrabber(const QString & device, unsigned width, unsigned height, unsigned fps, int pixelDecimation, QString flipMode) +MFGrabber::MFGrabber() : Grabber("V4L2:MEDIA_FOUNDATION") - , _currentDeviceName(device) - , _newDeviceName(device) + , _currentDeviceName("none") + , _newDeviceName("none") , _hr(S_FALSE) , _sourceReader(nullptr) - , _pixelDecimation(pixelDecimation) + , _sourceReaderCB(nullptr) + , _threadManager(nullptr) + , _pixelFormat(PixelFormat::NO_CHANGE) + , _pixelFormatConfig(PixelFormat::NO_CHANGE) , _lineLength(-1) , _frameByteSize(-1) , _noSignalCounterThreshold(40) , _noSignalCounter(0) - , _fpsSoftwareDecimation(0) , _brightness(0) , _contrast(0) , _saturation(0) @@ -23,24 +25,18 @@ MFGrabber::MFGrabber(const QString & device, unsigned width, unsigned height, un , _currentFrame(0) , _noSignalThresholdColor(ColorRgb{0,0,0}) , _signalDetectionEnabled(true) - , _cecDetectionEnabled(true) , _noSignalDetected(false) , _initialized(false) + , _reload(false) , _x_frac_min(0.25) , _y_frac_min(0.25) , _x_frac_max(0.75) , _y_frac_max(0.75) { - setWidthHeight(width, height); - setFramerate(fps); - setFlipMode(flipMode); - CoInitializeEx(0, COINIT_MULTITHREADED); _hr = MFStartup(MF_VERSION, MFSTARTUP_NOSOCKET); - if(FAILED(_hr)) + if (FAILED(_hr)) CoUninitialize(); - else - _sourceReaderCB = new SourceReaderCB(this); } MFGrabber::~MFGrabber() @@ -50,105 +46,110 @@ MFGrabber::~MFGrabber() SAFE_RELEASE(_sourceReader); SAFE_RELEASE(_sourceReaderCB); - if(SUCCEEDED(_hr) && SUCCEEDED(MFShutdown())) + if (_threadManager) + delete _threadManager; + _threadManager = nullptr; + + if (SUCCEEDED(_hr) && SUCCEEDED(MFShutdown())) CoUninitialize(); } +bool MFGrabber::prepare() +{ + if (SUCCEEDED(_hr)) + { + if (!_sourceReaderCB) + _sourceReaderCB = new SourceReaderCB(this); + + if (!_threadManager) + _threadManager = new MFThreadManager(this); + + return (_sourceReaderCB != nullptr && _threadManager != nullptr); + } + + return false; +} + +bool MFGrabber::start() +{ + if (!_initialized) + { + if (init()) + { + connect(_threadManager, &MFThreadManager::newFrame, this, &MFGrabber::newThreadFrame); + _threadManager->start(); + DebugIf(verbose, _log, "Decoding threads: %d", _threadManager->_threadCount); + + start_capturing(); + Info(_log, "Started"); + return true; + } + else + { + Error(_log, "The Media Foundation Grabber could not be started"); + return false; + } + } + else + return true; +} + +void MFGrabber::stop() +{ + if (_initialized) + { + _initialized = false; + _threadManager->stop(); + disconnect(_threadManager, nullptr, nullptr, nullptr); + _sourceReader->Flush(MF_SOURCE_READER_FIRST_VIDEO_STREAM); + while (_sourceReaderCB->isBusy()) {} + SAFE_RELEASE(_sourceReader); + _deviceProperties.clear(); + Info(_log, "Stopped"); + } +} + bool MFGrabber::init() { - if(!_initialized && SUCCEEDED(_hr)) + // enumerate the video capture devices on the user's system + enumVideoCaptureDevices(); + + if (!_initialized && SUCCEEDED(_hr)) { - QString foundDevice = ""; - int foundIndex = -1, bestGuess = -1, bestGuessMinX = INT_MAX, bestGuessMinFPS = INT_MAX; - bool autoDiscovery = (QString::compare(_currentDeviceName, "auto", Qt::CaseInsensitive) == 0 ); + int deviceIndex = -1; + bool noDeviceName = _currentDeviceName.compare("none", Qt::CaseInsensitive) == 0 || _currentDeviceName.compare("auto", Qt::CaseInsensitive) == 0; - // enumerate the video capture devices on the user's system - enumVideoCaptureDevices(); + if (noDeviceName) + return false; - // - if(!autoDiscovery && !_deviceProperties.contains(_currentDeviceName)) + if (!_deviceProperties.contains(_currentDeviceName)) { - Debug(_log, "Device '%s' is not available. Changing to auto.", QSTRING_CSTR(_currentDeviceName)); - autoDiscovery = true; - } - - if(autoDiscovery) - { - Debug(_log, "Forcing auto discovery device"); - if(_deviceProperties.count()>0) - { - foundDevice = _deviceProperties.firstKey(); - _currentDeviceName = foundDevice; - Debug(_log, "Auto discovery set to %s", QSTRING_CSTR(_currentDeviceName)); - } - } - else - foundDevice = _currentDeviceName; - - if(foundDevice.isNull() || foundDevice.isEmpty() || !_deviceProperties.contains(foundDevice)) - { - Error(_log, "Could not find any capture device"); + Debug(_log, "Configured device '%s' is not available.", QSTRING_CSTR(_currentDeviceName)); return false; } - QList dev = _deviceProperties[foundDevice]; + Debug(_log, "Searching for %s %d x %d @ %d fps (%s)", QSTRING_CSTR(_currentDeviceName), _width, _height,_fps, QSTRING_CSTR(pixelFormatToString(_pixelFormat))); - Debug(_log, "Searching for %s %d x %d @ %d fps (%s)", QSTRING_CSTR(foundDevice), _width, _height,_fps, QSTRING_CSTR(pixelFormatToString(_pixelFormat))); - - for( int i = 0; i < dev.count() && foundIndex < 0; ++i ) + QList dev = _deviceProperties[_currentDeviceName]; + for ( int i = 0; i < dev.count() && deviceIndex < 0; ++i ) { - bool strict = false; - const auto& val = dev[i]; - - if(bestGuess == -1 || (val.width <= bestGuessMinX && val.width >= 640 && val.fps <= bestGuessMinFPS && val.fps >= 10)) - { - bestGuess = i; - bestGuessMinFPS = val.fps; - bestGuessMinX = val.width; - } - - if(_width && _height) - { - strict = true; - if(val.width != _width || val.height != _height) - continue; - } - - if(_fps && _fps!=15) - { - strict = true; - if(val.fps != _fps) - continue; - } - - if(_pixelFormat != PixelFormat::NO_CHANGE) - { - strict = true; - if(val.pf != _pixelFormat) - continue; - } - - if(strict && (val.fps <= 60 || _fps != 15)) - foundIndex = i; - } - - if(foundIndex < 0 && bestGuess >= 0) - { - if(!autoDiscovery && _width != 0 && _height != 0) - Warning(_log, "Selected resolution not found in supported modes. Set default configuration"); + if (dev[i].width != _width || dev[i].height != _height || dev[i].fps != _fps || dev[i].pf != _pixelFormat) + continue; else - Debug(_log, "Set default configuration"); - - foundIndex = bestGuess; + deviceIndex = i; } - if(foundIndex>=0) + if (deviceIndex >= 0 && SUCCEEDED(init_device(_currentDeviceName, dev[deviceIndex]))) { - if(SUCCEEDED(init_device(foundDevice, dev[foundIndex]))) - _initialized = true; + _initialized = true; + _newDeviceName = _currentDeviceName; } else - Error(_log, "Could not find any capture device settings"); + { + Debug(_log, "Configured device '%s' is not available.", QSTRING_CSTR(_currentDeviceName)); + return false; + } + } return _initialized; @@ -157,9 +158,9 @@ bool MFGrabber::init() void MFGrabber::uninit() { // stop if the grabber was not stopped - if(_initialized) + if (_initialized) { - Debug(_log,"uninit grabber: %s", QSTRING_CSTR(_newDeviceName)); + Debug(_log,"Uninit grabber: %s", QSTRING_CSTR(_newDeviceName)); stop(); } } @@ -175,36 +176,36 @@ HRESULT MFGrabber::init_device(QString deviceName, DeviceProperties props) HRESULT hr = S_OK; Debug(_log, "Init %s, %d x %d @ %d fps (%s)", QSTRING_CSTR(deviceName), props.width, props.height, props.fps, QSTRING_CSTR(pixelFormatToString(pixelformat))); - DebugIf(verbose, _log, "Symbolic link: %s", QSTRING_CSTR(props.symlink)); + DebugIf (verbose, _log, "Symbolic link: %s", QSTRING_CSTR(props.symlink)); hr = MFCreateAttributes(&deviceAttributes, 2); - if(FAILED(hr)) + if (FAILED(hr)) { error = QString("Could not create device attributes (%1)").arg(hr); goto done; } hr = deviceAttributes->SetGUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID); - if(FAILED(hr)) + if (FAILED(hr)) { error = QString("SetGUID_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE (%1)").arg(hr); goto done; } - if(FAILED(deviceAttributes->SetString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, (LPCWSTR)props.symlink.utf16())) && _sourceReaderCB) + if (FAILED(deviceAttributes->SetString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, (LPCWSTR)props.symlink.utf16())) && _sourceReaderCB) { error = QString("IMFAttributes_SetString_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK (%1)").arg(hr); goto done; } hr = MFCreateDeviceSource(deviceAttributes, &device); - if(FAILED(hr)) + if (FAILED(hr)) { error = QString("MFCreateDeviceSource (%1)").arg(hr); goto done; } - if(!device) + if (!device) { error = QString("Could not open device (%1)").arg(hr); goto done; @@ -297,14 +298,14 @@ HRESULT MFGrabber::init_device(QString deviceName, DeviceProperties props) } hr = MFCreateAttributes(&sourceReaderAttributes, 1); - if(FAILED(hr)) + if (FAILED(hr)) { error = QString("Could not create Source Reader attributes (%1)").arg(hr); goto done; } hr = sourceReaderAttributes->SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK, (IMFSourceReaderCallback *)_sourceReaderCB); - if(FAILED(hr)) + if (FAILED(hr)) { error = QString("Could not set stream parameter: SetUnknown_MF_SOURCE_READER_ASYNC_CALLBACK (%1)").arg(hr); hr = E_INVALIDARG; @@ -312,49 +313,49 @@ HRESULT MFGrabber::init_device(QString deviceName, DeviceProperties props) } hr = MFCreateSourceReaderFromMediaSource(device, sourceReaderAttributes, &_sourceReader); - if(FAILED(hr)) + if (FAILED(hr)) { error = QString("Could not create the Source Reader (%1)").arg(hr); goto done; } hr = MFCreateMediaType(&type); - if(FAILED(hr)) + if (FAILED(hr)) { error = QString("Could not create an empty media type (%1)").arg(hr); goto done; } hr = type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); - if(FAILED(hr)) + if (FAILED(hr)) { error = QString("Could not set stream parameter: SetGUID_MF_MT_MAJOR_TYPE (%1)").arg(hr); goto done; } hr = type->SetGUID(MF_MT_SUBTYPE, props.guid); - if(FAILED(hr)) + if (FAILED(hr)) { error = QString("Could not set stream parameter: SetGUID_MF_MT_SUBTYPE (%1)").arg(hr); goto done; } hr = MFSetAttributeSize(type, MF_MT_FRAME_SIZE, props.width, props.height); - if(FAILED(hr)) + if (FAILED(hr)) { error = QString("Could not set stream parameter: SMFSetAttributeSize_MF_MT_FRAME_SIZE (%1)").arg(hr); goto done; } hr = MFSetAttributeSize(type, MF_MT_FRAME_RATE, props.numerator, props.denominator); - if(FAILED(hr)) + if (FAILED(hr)) { error = QString("Could not set stream parameter: MFSetAttributeSize_MF_MT_FRAME_RATE (%1)").arg(hr); goto done; } hr = MFSetAttributeRatio(type, MF_MT_PIXEL_ASPECT_RATIO, 1, 1); - if(FAILED(hr)) + if (FAILED(hr)) { error = QString("Could not set stream parameter: MFSetAttributeRatio_MF_MT_PIXEL_ASPECT_RATIO (%1)").arg(hr); goto done; @@ -374,9 +375,9 @@ HRESULT MFGrabber::init_device(QString deviceName, DeviceProperties props) } done: - if(FAILED(hr)) + if (FAILED(hr)) { - Error(_log, "%s", QSTRING_CSTR(error)); + emit readError(QSTRING_CSTR(error)); SAFE_RELEASE(_sourceReader); } else @@ -398,52 +399,41 @@ done: return hr; } -void MFGrabber::uninit_device() -{ - SAFE_RELEASE(_sourceReader); -} - void MFGrabber::enumVideoCaptureDevices() { - if(FAILED(_hr)) - { - Error(_log, "enumVideoCaptureDevices(): Media Foundation not initialized"); - return; - } - _deviceProperties.clear(); IMFAttributes* attr; - if(SUCCEEDED(MFCreateAttributes(&attr, 1))) + if (SUCCEEDED(MFCreateAttributes(&attr, 1))) { - if(SUCCEEDED(attr->SetGUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID))) + if (SUCCEEDED(attr->SetGUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID))) { UINT32 count; IMFActivate** devices; - if(SUCCEEDED(MFEnumDeviceSources(attr, &devices, &count))) + if (SUCCEEDED(MFEnumDeviceSources(attr, &devices, &count))) { - DebugIf(verbose, _log, "Detected devices: %u", count); - for(UINT32 i = 0; i < count; i++) + DebugIf (verbose, _log, "Detected devices: %u", count); + for (UINT32 i = 0; i < count; i++) { UINT32 length; LPWSTR name; LPWSTR symlink; - if(SUCCEEDED(devices[i]->GetAllocatedString(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, &name, &length))) + if (SUCCEEDED(devices[i]->GetAllocatedString(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, &name, &length))) { - if(SUCCEEDED(devices[i]->GetAllocatedString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, &symlink, &length))) + if (SUCCEEDED(devices[i]->GetAllocatedString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, &symlink, &length))) { QList devicePropertyList; QString dev = QString::fromUtf16((const ushort*)name); IMFMediaSource *pSource = nullptr; - if(SUCCEEDED(devices[i]->ActivateObject(IID_PPV_ARGS(&pSource)))) + if (SUCCEEDED(devices[i]->ActivateObject(IID_PPV_ARGS(&pSource)))) { - Debug(_log, "Found capture device: %s", QSTRING_CSTR(dev)); + DebugIf (verbose, _log, "Found capture device: %s", QSTRING_CSTR(dev)); IMFMediaType *pType = nullptr; IMFSourceReader* reader; - if(SUCCEEDED(MFCreateSourceReaderFromMediaSource(pSource, NULL, &reader))) + if (SUCCEEDED(MFCreateSourceReaderFromMediaSource(pSource, NULL, &reader))) { for (DWORD i = 0; ; i++) { @@ -453,7 +443,7 @@ void MFGrabber::enumVideoCaptureDevices() GUID format; UINT32 width = 0, height = 0, numerator = 0, denominator = 0; - if( SUCCEEDED(pType->GetGUID(MF_MT_SUBTYPE, &format)) && + if ( SUCCEEDED(pType->GetGUID(MF_MT_SUBTYPE, &format)) && SUCCEEDED(MFGetAttributeSize(pType, MF_MT_FRAME_SIZE, &width, &height)) && SUCCEEDED(MFGetAttributeRatio(pType, MF_MT_FRAME_RATE, &numerator, &denominator))) { @@ -471,7 +461,7 @@ void MFGrabber::enumVideoCaptureDevices() properties.guid = format; devicePropertyList.append(properties); - DebugIf(verbose, _log, "%s %d x %d @ %d fps (%s)", QSTRING_CSTR(dev), properties.width, properties.height, properties.fps, QSTRING_CSTR(pixelFormatToString(properties.pf))); + DebugIf (verbose, _log, "%s %d x %d @ %d fps (%s)", QSTRING_CSTR(dev), properties.width, properties.height, properties.fps, QSTRING_CSTR(pixelFormatToString(properties.pf))); } } @@ -503,7 +493,7 @@ void MFGrabber::enumVideoCaptureDevices() void MFGrabber::start_capturing() { - if (_initialized && _sourceReader) + if (_initialized && _sourceReader && _threadManager) { HRESULT hr = _sourceReader->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, NULL, NULL, NULL, NULL); if (!SUCCEEDED(hr)) @@ -513,53 +503,143 @@ void MFGrabber::start_capturing() void MFGrabber::process_image(const void *frameImageBuffer, int size) { - unsigned int processFrameIndex = _currentFrame++; + int processFrameIndex = _currentFrame++; // frame skipping - if((processFrameIndex % (_fpsSoftwareDecimation + 1) != 0) && (_fpsSoftwareDecimation > 0)) - return; - - // CEC detection - if(_cecDetectionEnabled) + if ((processFrameIndex % (_fpsSoftwareDecimation + 1) != 0) && (_fpsSoftwareDecimation > 0)) return; // We do want a new frame... if (size < _frameByteSize && _pixelFormat != PixelFormat::MJPEG) Error(_log, "Frame too small: %d != %d", size, _frameByteSize); - else + else if (_threadManager != nullptr) { - if (_threadManager.isActive()) + for (int i = 0; i < _threadManager->_threadCount; i++) { - if (_threadManager._threads == nullptr) + if (!_threadManager->_threads[i]->isBusy()) { - _threadManager.initThreads(); - Debug(_log, "Max thread count = %d", _threadManager._maxThreads); - - for (unsigned int i=0; i < _threadManager._maxThreads && _threadManager._threads != nullptr; i++) - { - MFThread* _thread = _threadManager._threads[i]; - connect(_thread, SIGNAL(newFrame(unsigned int, const Image &,unsigned int)), this , SLOT(newThreadFrame(unsigned int, const Image &, unsigned int))); - } - } - - for (unsigned int i = 0;_threadManager.isActive() && i < _threadManager._maxThreads && _threadManager._threads != nullptr; i++) - { - if ((_threadManager._threads[i]->isFinished() || !_threadManager._threads[i]->isRunning())) - { - // aquire lock - if ( _threadManager._threads[i]->isBusy() == false) - { - MFThread* _thread = _threadManager._threads[i]; - _thread->setup(i, _pixelFormat, (uint8_t *)frameImageBuffer, size, _width, _height, _lineLength, _subsamp, _cropLeft, _cropTop, _cropBottom, _cropRight, _videoMode, _flipMode, processFrameIndex, _pixelDecimation); - _threadManager._threads[i]->start(); - break; - } - } + _threadManager->_threads[i]->setup(_pixelFormat, (uint8_t*)frameImageBuffer, size, _width, _height, _lineLength, _subsamp, _cropLeft, _cropTop, _cropBottom, _cropRight, _videoMode, _flipMode, _pixelDecimation); + _threadManager->_threads[i]->process(); + break; } } } } +void MFGrabber::receive_image(const void *frameImageBuffer, int size) +{ + process_image(frameImageBuffer, size); + start_capturing(); +} + +void MFGrabber::newThreadFrame(Image image) +{ + if (_signalDetectionEnabled) + { + // check signal (only in center of the resulting image, because some grabbers have noise values along the borders) + bool noSignal = true; + + // top left + unsigned xOffset = image.width() * _x_frac_min; + unsigned yOffset = image.height() * _y_frac_min; + + // bottom right + unsigned xMax = image.width() * _x_frac_max; + unsigned yMax = image.height() * _y_frac_max; + + for (unsigned x = xOffset; noSignal && x < xMax; ++x) + for (unsigned y = yOffset; noSignal && y < yMax; ++y) + noSignal &= (ColorRgb&)image(x, y) <= _noSignalThresholdColor; + + if (noSignal) + ++_noSignalCounter; + else + { + if (_noSignalCounter >= _noSignalCounterThreshold) + { + _noSignalDetected = true; + Info(_log, "Signal detected"); + } + + _noSignalCounter = 0; + } + + if ( _noSignalCounter < _noSignalCounterThreshold) + { + emit newFrame(image); + } + else if (_noSignalCounter == _noSignalCounterThreshold) + { + _noSignalDetected = false; + Info(_log, "Signal lost"); + } + } + else + emit newFrame(image); +} + +void MFGrabber::setDevice(const QString& device) +{ + if (_currentDeviceName != device) + { + _currentDeviceName = device; + _reload = true; + } +} + +bool MFGrabber::setInput(int input) +{ + if (Grabber::setInput(input)) + { + _reload = true; + return true; + } + + return false; +} + +bool MFGrabber::setWidthHeight(int width, int height) +{ + if (Grabber::setWidthHeight(width, height)) + { + _reload = true; + return true; + } + + return false; +} + +void MFGrabber::setEncoding(QString enc) +{ + if (_pixelFormatConfig != parsePixelFormat(enc)) + { + _pixelFormatConfig = parsePixelFormat(enc); + if (_initialized) + { + Debug(_log,"Set hardware encoding to: %s", QSTRING_CSTR(enc.toUpper())); + _reload = true; + } + else + _pixelFormat = _pixelFormatConfig; + } +} + +void MFGrabber::setBrightnessContrastSaturationHue(int brightness, int contrast, int saturation, int hue) +{ + if (_brightness != brightness || _contrast != contrast || _saturation != saturation || _hue != hue) + { + if (_initialized) + Debug(_log,"Set brightness to %i, contrast to %i, saturation to %i, hue to %i", _brightness, _contrast, _saturation, _hue); + + _brightness = brightness; + _contrast = contrast; + _saturation = saturation; + _hue = hue; + + _reload = true; + } +} + void MFGrabber::setSignalThreshold(double redSignalThreshold, double greenSignalThreshold, double blueSignalThreshold, int noSignalCounterThreshold) { _noSignalThresholdColor.red = uint8_t(255*redSignalThreshold); @@ -567,7 +647,7 @@ void MFGrabber::setSignalThreshold(double redSignalThreshold, double greenSignal _noSignalThresholdColor.blue = uint8_t(255*blueSignalThreshold); _noSignalCounterThreshold = qMax(1, noSignalCounterThreshold); - if(_signalDetectionEnabled) + if (_signalDetectionEnabled) Info(_log, "Signal threshold set to: {%d, %d, %d} and frames: %d", _noSignalThresholdColor.red, _noSignalThresholdColor.green, _noSignalThresholdColor.blue, _noSignalCounterThreshold ); } @@ -581,274 +661,106 @@ void MFGrabber::setSignalDetectionOffset(double horizontalMin, double verticalMi _x_frac_max = horizontalMax; _y_frac_max = verticalMax; - if(_signalDetectionEnabled) + if (_signalDetectionEnabled) Info(_log, "Signal detection area set to: %f,%f x %f,%f", _x_frac_min, _y_frac_min, _x_frac_max, _y_frac_max ); } -bool MFGrabber::start() -{ - try - { - if(!_initialized) - { - _threadManager.start(); - DebugIf(verbose, _log, "Decoding threads: %d",_threadManager._maxThreads); - - if(init()) - { - start_capturing(); - Info(_log, "Started"); - return true; - } - } - } - catch(std::exception& e) - { - Error(_log, "Start failed (%s)", e.what()); - } - - return false; -} - -void MFGrabber::stop() -{ - if(_initialized) - { - _initialized = false; - _threadManager.stop(); - uninit_device(); - // restore pixelformat to configs value if it is not auto or device name has not changed - if(_pixelFormatConfig != PixelFormat::NO_CHANGE || _newDeviceName != _currentDeviceName) - _pixelFormat = _pixelFormatConfig; - _deviceProperties.clear(); - Info(_log, "Stopped"); - } -} - -void MFGrabber::receive_image(const void *frameImageBuffer, int size) -{ - process_image(frameImageBuffer, size); - start_capturing(); -} - -void MFGrabber::newThreadFrame(unsigned int threadIndex, const Image& image, unsigned int sourceCount) -{ - checkSignalDetectionEnabled(image); - - // get next frame - if (threadIndex >_threadManager._maxThreads) - Error(_log, "Frame index %d out of range", sourceCount); - - if (threadIndex <= _threadManager._maxThreads) - _threadManager._threads[threadIndex]->noBusy(); -} - -void MFGrabber::checkSignalDetectionEnabled(Image image) -{ - if(_signalDetectionEnabled) - { - // check signal (only in center of the resulting image, because some grabbers have noise values along the borders) - bool noSignal = true; - - // top left - unsigned xOffset = image.width() * _x_frac_min; - unsigned yOffset = image.height() * _y_frac_min; - - // bottom right - unsigned xMax = image.width() * _x_frac_max; - unsigned yMax = image.height() * _y_frac_max; - - for(unsigned x = xOffset; noSignal && x < xMax; ++x) - for(unsigned y = yOffset; noSignal && y < yMax; ++y) - noSignal &= (ColorRgb&)image(x, y) <= _noSignalThresholdColor; - - if(noSignal) - ++_noSignalCounter; - else - { - if(_noSignalCounter >= _noSignalCounterThreshold) - { - _noSignalDetected = true; - Info(_log, "Signal detected"); - } - - _noSignalCounter = 0; - } - - if( _noSignalCounter < _noSignalCounterThreshold) - { - emit newFrame(image); - } - else if(_noSignalCounter == _noSignalCounterThreshold) - { - _noSignalDetected = false; - Info(_log, "Signal lost"); - } - } - else - emit newFrame(image); -} - -QStringList MFGrabber::getDevices() const -{ - QStringList result = QStringList(); - for(auto it = _deviceProperties.begin(); it != _deviceProperties.end(); ++it) - result << it.key(); - - return result; -} - -QStringList MFGrabber::getAvailableEncodingFormats(const QString& devicePath, const int& /*device input not used on windows*/) const -{ - QStringList result = QStringList(); - - for(int i = 0; i < _deviceProperties[devicePath].count(); ++i ) - if(!result.contains(pixelFormatToString(_deviceProperties[devicePath][i].pf), Qt::CaseInsensitive)) - result << pixelFormatToString(_deviceProperties[devicePath][i].pf).toLower(); - - return result; -} - -QMultiMap MFGrabber::getAvailableDeviceResolutions(const QString& devicePath, const int& /*device input not used on windows*/, const PixelFormat& encFormat) const -{ - QMultiMap result = QMultiMap(); - - for(int i = 0; i < _deviceProperties[devicePath].count(); ++i ) - if(!result.contains(_deviceProperties[devicePath][i].width, _deviceProperties[devicePath][i].height) && _deviceProperties[devicePath][i].pf == encFormat) - result.insert(_deviceProperties[devicePath][i].width, _deviceProperties[devicePath][i].height); - - return result; -} - -QIntList MFGrabber::getAvailableDeviceFramerates(const QString& devicePath, const int& /*device input not used on windows*/, const PixelFormat& encFormat, const unsigned width, const unsigned height) const -{ - QIntList result = QIntList(); - - for(int i = 0; i < _deviceProperties[devicePath].count(); ++i ) - { - int fps = _deviceProperties[devicePath][i].numerator / _deviceProperties[devicePath][i].denominator; - if(!result.contains(fps) && _deviceProperties[devicePath][i].pf == encFormat && _deviceProperties[devicePath][i].width == width && _deviceProperties[devicePath][i].height == height) - result << fps; - } - - return result; -} - void MFGrabber::setSignalDetectionEnable(bool enable) { - if(_signalDetectionEnabled != enable) + if (_signalDetectionEnabled != enable) { _signalDetectionEnabled = enable; - Info(_log, "Signal detection is now %s", enable ? "enabled" : "disabled"); + if (_initialized) + Info(_log, "Signal detection is now %s", enable ? "enabled" : "disabled"); } } -void MFGrabber::setCecDetectionEnable(bool enable) +bool MFGrabber::reload(bool force) { - if(_cecDetectionEnabled != enable) + if (_sourceReader && (_reload || force)) { - _cecDetectionEnabled = enable; - Info(_log, QString("CEC detection is now %1").arg(enable ? "enabled" : "disabled").toLocal8Bit()); - } -} - -bool MFGrabber::setDevice(QString device) -{ - if(_currentDeviceName != device) - { - _currentDeviceName = device; - return true; - } - return false; -} - -void MFGrabber::setPixelDecimation(int pixelDecimation) -{ - if(_pixelDecimation != pixelDecimation) - _pixelDecimation = pixelDecimation; -} - -void MFGrabber::setFlipMode(QString flipMode) -{ - if(_flipMode != parseFlipMode(flipMode)) - Grabber::setFlipMode(parseFlipMode(flipMode)); -} - -bool MFGrabber::setWidthHeight(int width, int height) -{ - if(Grabber::setWidthHeight(width, height)) - { - Debug(_log,"Set device resolution to width: %i, height: %i", width, height); - return true; - } - else if(width == 0 && height == 0) - { - _width = _height = 0; - Debug(_log,"Set device resolution to 'Automatic'"); - return true; - } - - return false; -} - -bool MFGrabber::setFramerate(int fps) -{ - if(Grabber::setFramerate(fps)) - { - Debug(_log,"Set fps to: %i", fps); - return true; - } - return false; -} - -void MFGrabber::setFpsSoftwareDecimation(int decimation) -{ - _fpsSoftwareDecimation = decimation; - if(decimation > 0) - Debug(_log,"Skip %i frame per second", decimation); -} - -bool MFGrabber::setEncoding(QString enc) -{ - if(_pixelFormatConfig != parsePixelFormat(enc)) - { - Debug(_log,"Set hardware encoding to: %s", QSTRING_CSTR(enc.toUpper())); - _pixelFormatConfig = parsePixelFormat(enc); - if(!_initialized) - _pixelFormat = _pixelFormatConfig; - return true; - } - return false; -} - -bool MFGrabber::setBrightnessContrastSaturationHue(int brightness, int contrast, int saturation, int hue) -{ - if(_brightness != brightness || _contrast != contrast || _saturation != saturation || _hue != hue) - { - _brightness = brightness; - _contrast = contrast; - _saturation = saturation; - _hue = hue; - - Debug(_log,"Set brightness to %i, contrast to %i, saturation to %i, hue to %i", _brightness, _contrast, _saturation, _hue); - return true; - } - return false; -} - -void MFGrabber::reloadGrabber() -{ - if(_initialized) - { - Debug(_log,"Reloading Media Foundation Grabber"); - // stop grabber + Info(_log,"Reloading Media Foundation Grabber"); uninit(); - // restore pixelformat to configs value if it is not auto or device name has not changed - if(_pixelFormatConfig != PixelFormat::NO_CHANGE || _newDeviceName != _currentDeviceName) - _pixelFormat = _pixelFormatConfig; - // set _newDeviceName + _pixelFormat = _pixelFormatConfig; _newDeviceName = _currentDeviceName; - // start grabber - start(); + _reload = false; + return start(); } + + return false; +} + +QJsonArray MFGrabber::discover(const QJsonObject& params) +{ + DebugIf (verbose, _log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData()); + + enumVideoCaptureDevices(); + + QJsonArray inputsDiscovered; + for (auto it = _deviceProperties.begin(); it != _deviceProperties.end(); ++it) + { + QJsonObject device, in; + QJsonArray video_inputs, formats; + + device["device"] = it.key(); + device["device_name"] = it.key(); + device["type"] = "v4l2"; + + in["name"] = ""; + in["inputIdx"] = 0; + + QStringList encodingFormats = QStringList(); + for (int i = 0; i < _deviceProperties[it.key()].count(); ++i ) + if (!encodingFormats.contains(pixelFormatToString(_deviceProperties[it.key()][i].pf), Qt::CaseInsensitive)) + encodingFormats << pixelFormatToString(_deviceProperties[it.key()][i].pf).toLower(); + + for (auto encodingFormat : encodingFormats) + { + QJsonObject format; + QJsonArray resolutionArray; + + format["format"] = encodingFormat; + + QMultiMap deviceResolutions = QMultiMap(); + for (int i = 0; i < _deviceProperties[it.key()].count(); ++i ) + if (!deviceResolutions.contains(_deviceProperties[it.key()][i].width, _deviceProperties[it.key()][i].height) && _deviceProperties[it.key()][i].pf == parsePixelFormat(encodingFormat)) + deviceResolutions.insert(_deviceProperties[it.key()][i].width, _deviceProperties[it.key()][i].height); + + for (auto width_height = deviceResolutions.begin(); width_height != deviceResolutions.end(); width_height++) + { + QJsonObject resolution; + QJsonArray fps; + + resolution["width"] = width_height.key(); + resolution["height"] = width_height.value(); + + QIntList framerates = QIntList(); + for (int i = 0; i < _deviceProperties[it.key()].count(); ++i ) + { + int fps = _deviceProperties[it.key()][i].numerator / _deviceProperties[it.key()][i].denominator; + if (!framerates.contains(fps) && _deviceProperties[it.key()][i].pf == parsePixelFormat(encodingFormat) && _deviceProperties[it.key()][i].width == width_height.key() && _deviceProperties[it.key()][i].height == width_height.value()) + framerates << fps; + } + + for (auto framerate : framerates) + fps.append(framerate); + + resolution["fps"] = fps; + resolutionArray.append(resolution); + } + + format["resolutions"] = resolutionArray; + formats.append(format); + } + in["formats"] = formats; + video_inputs.append(in); + + device["video_inputs"] = video_inputs; + inputsDiscovered.append(device); + } + + _deviceProperties.clear(); + DebugIf (verbose, _log, "device: [%s]", QString(QJsonDocument(inputsDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData()); + + return inputsDiscovered; } diff --git a/libsrc/grabber/mediafoundation/MFSourceReaderCB.h b/libsrc/grabber/video/mediafoundation/MFSourceReaderCB.h similarity index 89% rename from libsrc/grabber/mediafoundation/MFSourceReaderCB.h rename to libsrc/grabber/video/mediafoundation/MFSourceReaderCB.h index 87c5fd13..cb70c961 100644 --- a/libsrc/grabber/mediafoundation/MFSourceReaderCB.h +++ b/libsrc/grabber/video/mediafoundation/MFSourceReaderCB.h @@ -44,9 +44,11 @@ public: , _grabber(grabber) , _bEOS(FALSE) , _hrStatus(S_OK) + , _isBusy(false) , _transform(nullptr) , _pixelformat(PixelFormat::NO_CHANGE) { + // Initialize critical section. InitializeCriticalSection(&_critsec); } @@ -78,21 +80,29 @@ public: // IMFSourceReaderCallback methods STDMETHODIMP OnReadSample(HRESULT hrStatus, DWORD /*dwStreamIndex*/, - DWORD dwStreamFlags, LONGLONG llTimestamp, IMFSample *pSample) + DWORD dwStreamFlags, LONGLONG llTimestamp, IMFSample* pSample) { EnterCriticalSection(&_critsec); + _isBusy = true; - if(dwStreamFlags & MF_SOURCE_READERF_STREAMTICK) + if (_grabber->_sourceReader == nullptr) + { + _isBusy = false; + LeaveCriticalSection(&_critsec); + return S_OK; + } + + if (dwStreamFlags & MF_SOURCE_READERF_STREAMTICK) { Debug(_grabber->_log, "Skipping stream gap"); LeaveCriticalSection(&_critsec); - _grabber->_sourceReader->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, NULL, NULL, NULL, NULL); + _grabber->_sourceReader->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, nullptr, nullptr, nullptr, nullptr); return S_OK; - } + } if (dwStreamFlags & MF_SOURCE_READERF_NATIVEMEDIATYPECHANGED) { - IMFMediaType *type = nullptr; + IMFMediaType* type = nullptr; GUID format; _grabber->_sourceReader->GetNativeMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM, MF_SOURCE_READER_CURRENT_TYPE_INDEX, &type); type->GetGUID(MF_MT_SUBTYPE, &format); @@ -103,7 +113,7 @@ public: if (dwStreamFlags & MF_SOURCE_READERF_CURRENTMEDIATYPECHANGED) { - IMFMediaType *type = nullptr; + IMFMediaType* type = nullptr; GUID format; _grabber->_sourceReader->GetCurrentMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM, &type); type->GetGUID(MF_MT_SUBTYPE, &format); @@ -119,7 +129,7 @@ public: { _hrStatus = hrStatus; _com_error error(_hrStatus); - Error(_grabber->_log, "Source Reader error => %s", error.ErrorMessage()); + Error(_grabber->_log, "%s", error.ErrorMessage()); goto done; } @@ -129,7 +139,7 @@ public: goto done; } - if(_pixelformat != PixelFormat::MJPEG && _pixelformat != PixelFormat::NO_CHANGE) + if (_pixelformat != PixelFormat::MJPEG && _pixelformat != PixelFormat::BGR24 && _pixelformat != PixelFormat::NO_CHANGE) pSample = TransformSample(_transform, pSample); _hrStatus = pSample->ConvertToContiguousBuffer(&buffer); @@ -150,7 +160,7 @@ public: goto done; } - _grabber->receive_image(data,currentLength); + _grabber->receive_image(data, currentLength); _hrStatus = buffer->Unlock(); if (FAILED(_hrStatus)) @@ -165,6 +175,7 @@ public: if (MF_SOURCE_READERF_ENDOFSTREAM & dwStreamFlags) _bEOS = TRUE; // Reached the end of the stream. + _isBusy = false; LeaveCriticalSection(&_critsec); return _hrStatus; } @@ -172,11 +183,11 @@ public: HRESULT SourceReaderCB::InitializeVideoEncoder(IMFMediaType* type, PixelFormat format) { _pixelformat = format; - if (format == PixelFormat::MJPEG || format == PixelFormat::NO_CHANGE) + if (format == PixelFormat::MJPEG || format == PixelFormat::BGR24 || format == PixelFormat::NO_CHANGE) return S_OK; // Variable declaration - IMFMediaType *output = nullptr; + IMFMediaType* output = nullptr; DWORD mftStatus = 0; QString error = ""; @@ -269,7 +280,16 @@ public: return _hrStatus; } - STDMETHODIMP OnEvent(DWORD, IMFMediaEvent *) { return S_OK; } + BOOL SourceReaderCB::isBusy() + { + EnterCriticalSection(&_critsec); + BOOL result = _isBusy; + LeaveCriticalSection(&_critsec); + + return result; + } + + STDMETHODIMP OnEvent(DWORD, IMFMediaEvent*) { return S_OK; } STDMETHODIMP OnFlush(DWORD) { return S_OK; } private: @@ -282,13 +302,16 @@ private: } SAFE_RELEASE(_transform); + + // Delete critical section. + DeleteCriticalSection(&_critsec); } IMFSample* SourceReaderCB::TransformSample(IMFTransform* transform, IMFSample* in_sample) { IMFSample* result = nullptr; IMFMediaBuffer* out_buffer = nullptr; - MFT_OUTPUT_DATA_BUFFER outputDataBuffer = {0}; + MFT_OUTPUT_DATA_BUFFER outputDataBuffer = { 0 }; // Process the input sample _hrStatus = transform->ProcessInput(0, in_sample, 0); @@ -371,4 +394,5 @@ private: HRESULT _hrStatus; IMFTransform* _transform; PixelFormat _pixelformat; + std::atomic _isBusy; }; diff --git a/libsrc/grabber/mediafoundation/MFThread.cpp b/libsrc/grabber/video/mediafoundation/MFThread.cpp similarity index 84% rename from libsrc/grabber/mediafoundation/MFThread.cpp rename to libsrc/grabber/video/mediafoundation/MFThread.cpp index 95390ccb..24785935 100644 --- a/libsrc/grabber/mediafoundation/MFThread.cpp +++ b/libsrc/grabber/video/mediafoundation/MFThread.cpp @@ -1,19 +1,14 @@ #include "grabber/MFThread.h" -volatile bool MFThread::_isActive = false; - MFThread::MFThread() - : _isBusy(false) - , _semaphore(1) - , _localData(nullptr) + : _localData(nullptr) , _scalingFactorsCount(0) , _scalingFactors(nullptr) , _transform(nullptr) , _decompress(nullptr) , _xform(nullptr) , _imageResampler() -{ -} +{} MFThread::~MFThread() { @@ -28,12 +23,11 @@ MFThread::~MFThread() } void MFThread::setup( - unsigned int threadIndex, PixelFormat pixelFormat, uint8_t* sharedData, + PixelFormat pixelFormat, uint8_t* sharedData, int size, int width, int height, int lineLength, int subsamp, unsigned cropLeft, unsigned cropTop, unsigned cropBottom, unsigned cropRight, - VideoMode videoMode, FlipMode flipMode, int currentFrame, int pixelDecimation) + VideoMode videoMode, FlipMode flipMode, int pixelDecimation) { - _threadIndex = threadIndex; _lineLength = lineLength; _pixelFormat = pixelFormat; _size = (unsigned long) size; @@ -45,7 +39,6 @@ void MFThread::setup( _cropBottom = cropBottom; _cropRight = cropRight; _flipMode = flipMode; - _currentFrame = currentFrame; _pixelDecimation = pixelDecimation; _imageResampler.setVideoMode(videoMode); @@ -61,9 +54,10 @@ void MFThread::setup( memcpy(_localData, sharedData, size); } -void MFThread::run() +void MFThread::process() { - if (_isActive && _width > 0 && _height > 0) + _busy = true; + if (_width > 0 && _height > 0) { if (_pixelFormat == PixelFormat::MJPEG) { @@ -85,31 +79,10 @@ void MFThread::run() Image image = Image(); _imageResampler.processImage(_localData, _width, _height, _lineLength, PixelFormat::BGR24, image); - emit newFrame(_threadIndex, image, _currentFrame); + emit newFrame(image); } } -} - -bool MFThread::isBusy() -{ - bool temp; - _semaphore.acquire(); - if (_isBusy) - temp = true; - else - { - temp = false; - _isBusy = true; - } - _semaphore.release(); - return temp; -} - -void MFThread::noBusy() -{ - _semaphore.acquire(); - _isBusy = false; - _semaphore.release(); + _busy = false; } void MFThread::processImageMjpeg() @@ -176,7 +149,7 @@ void MFThread::processImageMjpeg() // got image, process it if ( !(_cropLeft > 0 || _cropTop > 0 || _cropBottom > 0 || _cropRight > 0)) - emit newFrame(_threadIndex, srcImage, _currentFrame); + emit newFrame(srcImage); else { // calculate the output size @@ -200,6 +173,6 @@ void MFThread::processImageMjpeg() } // emit - emit newFrame(_threadIndex, destImage, _currentFrame); + emit newFrame(destImage); } } diff --git a/libsrc/grabber/v4l2/V4L2Grabber.cpp b/libsrc/grabber/video/v4l2/V4L2Grabber.cpp similarity index 73% rename from libsrc/grabber/v4l2/V4L2Grabber.cpp rename to libsrc/grabber/video/v4l2/V4L2Grabber.cpp index 84d0151e..cfedd009 100644 --- a/libsrc/grabber/v4l2/V4L2Grabber.cpp +++ b/libsrc/grabber/video/v4l2/V4L2Grabber.cpp @@ -27,37 +27,41 @@ #define CLEAR(x) memset(&(x), 0, sizeof(x)) #ifndef V4L2_CAP_META_CAPTURE -#define V4L2_CAP_META_CAPTURE 0x00800000 // Specified in kernel header v4.16. Required for backward compatibility. + #define V4L2_CAP_META_CAPTURE 0x00800000 // Specified in kernel header v4.16. Required for backward compatibility. #endif +// Constants +namespace { const bool verbose = false; } + static PixelFormat GetPixelFormat(const unsigned int format) { if (format == V4L2_PIX_FMT_RGB32) return PixelFormat::RGB32; if (format == V4L2_PIX_FMT_RGB24) return PixelFormat::BGR24; if (format == V4L2_PIX_FMT_YUYV) return PixelFormat::YUYV; if (format == V4L2_PIX_FMT_UYVY) return PixelFormat::UYVY; - if (format == V4L2_PIX_FMT_MJPEG) return PixelFormat::MJPEG; if (format == V4L2_PIX_FMT_NV12) return PixelFormat::NV12; if (format == V4L2_PIX_FMT_YUV420) return PixelFormat::I420; +#ifdef HAVE_JPEG_DECODER + if (format == V4L2_PIX_FMT_MJPEG) return PixelFormat::MJPEG; +#endif return PixelFormat::NO_CHANGE; }; -V4L2Grabber::V4L2Grabber(const QString & device, unsigned width, unsigned height, unsigned fps, unsigned input, VideoStandard videoStandard, PixelFormat pixelFormat, int pixelDecimation) - : Grabber("V4L2:"+device) - , _deviceName() - , _videoStandard(videoStandard) +V4L2Grabber::V4L2Grabber() + : Grabber("V4L2") + , _currentDeviceName("none") + , _newDeviceName("none") , _ioMethod(IO_METHOD_MMAP) , _fileDescriptor(-1) - , _buffers() - , _pixelFormat(pixelFormat) - , _pixelDecimation(pixelDecimation) + , _pixelFormat(PixelFormat::NO_CHANGE) + , _pixelFormatConfig(PixelFormat::NO_CHANGE) , _lineLength(-1) , _frameByteSize(-1) , _noSignalCounterThreshold(40) , _noSignalThresholdColor(ColorRgb{0,0,0}) - , _signalDetectionEnabled(true) , _cecDetectionEnabled(true) , _cecStandbyActivated(false) + , _signalDetectionEnabled(true) , _noSignalDetected(false) , _noSignalCounter(0) , _x_frac_min(0.25) @@ -66,17 +70,8 @@ V4L2Grabber::V4L2Grabber(const QString & device, unsigned width, unsigned height , _y_frac_max(0.75) , _streamNotifier(nullptr) , _initialized(false) - , _deviceAutoDiscoverEnabled(false) + , _reload(false) { - setPixelDecimation(pixelDecimation); - getV4Ldevices(); - - // init - setInput(input); - setWidthHeight(width, height); - setFramerate(fps); - setDeviceVideoStandard(device, videoStandard); - Debug(_log,"Init pixel format: %i", static_cast(_pixelFormat)); } V4L2Grabber::~V4L2Grabber() @@ -89,7 +84,7 @@ void V4L2Grabber::uninit() // stop if the grabber was not stopped if (_initialized) { - Debug(_log,"uninit grabber: %s", QSTRING_CSTR(_deviceName)); + Debug(_log,"Uninit grabber: %s", QSTRING_CSTR(_newDeviceName)); stop(); } } @@ -98,66 +93,47 @@ bool V4L2Grabber::init() { if (!_initialized) { - getV4Ldevices(); - QString v4lDevices_str; + bool noDeviceName = _currentDeviceName.compare("none", Qt::CaseInsensitive) == 0 || _currentDeviceName.compare("auto", Qt::CaseInsensitive) == 0; - // show list only once - if (!_deviceName.startsWith("/dev/")) + // enumerate the video capture devices on the user's system + enumVideoCaptureDevices(); + + if(noDeviceName) + return false; + + if(!_deviceProperties.contains(_currentDeviceName)) { - for (auto& dev: _v4lDevices) - { - v4lDevices_str += "\t"+ dev.first + "\t" + dev.second + "\n"; - } - if (!v4lDevices_str.isEmpty()) - Info(_log, "available V4L2 devices:\n%s", QSTRING_CSTR(v4lDevices_str)); + Debug(_log, "Configured device at '%s' is not available.", QSTRING_CSTR(_currentDeviceName)); + _currentDeviceName = "none"; + return false; } - if (_deviceName == "auto") + bool valid = false; + for(auto i = _deviceProperties.begin(); i != _deviceProperties.end(); ++i) + if (i.key() == _currentDeviceName && valid == false) + for (auto y = i.value().inputs.begin(); y != i.value().inputs.end(); y++) + if (y.key() == _input && valid == false) + for (auto enc = y.value().encodingFormats.begin(); enc != y.value().encodingFormats.end(); enc++) + if(enc.key() == _pixelFormat && enc.value().width == _width && enc.value().height == _height && valid == false) + for (auto fps = enc.value().framerates.begin(); fps != enc.value().framerates.end(); fps++) + if(*fps == _fps && valid == false) + valid = true; + + if (!valid) { - _deviceAutoDiscoverEnabled = true; - _deviceName = "unknown"; - Info( _log, "search for usable video devices" ); - for (auto& dev: _v4lDevices) - { - _deviceName = dev.first; - if (init()) - { - Info(_log, "found usable v4l2 device: %s (%s)",QSTRING_CSTR(dev.first), QSTRING_CSTR(dev.second)); - _deviceAutoDiscoverEnabled = false; - return _initialized; - } - } - Info(_log, "no usable device found"); - } - else if (!_deviceName.startsWith("/dev/")) - { - for (auto& dev: _v4lDevices) - { - if (_deviceName.toLower() == dev.second.toLower()) - { - _deviceName = dev.first; - Info(_log, "found v4l2 device with configured name: %s (%s)", QSTRING_CSTR(dev.second), QSTRING_CSTR(dev.first) ); - break; - } - } - } - else - { - Info(_log, "%s v4l device: %s", (_deviceAutoDiscoverEnabled? "test" : "configured"), QSTRING_CSTR(_deviceName)); + Debug(_log, "Configured device at '%s' is not available.", QSTRING_CSTR(_currentDeviceName)); + _currentDeviceName = "none"; + return false; } bool opened = false; try { - // do not init with unknown device - if (_deviceName != "unknown") + if (open_device()) { - if (open_device()) - { - opened = true; - init_device(_videoStandard); - _initialized = true; - } + opened = true; + init_device(_videoStandard); + _initialized = true; } } catch(std::exception& e) @@ -167,14 +143,15 @@ bool V4L2Grabber::init() uninit_device(); close_device(); } - ErrorIf( !_deviceAutoDiscoverEnabled, _log, "V4l2 init failed (%s)", e.what()); + + Error(_log, "V4l2 init failed (%s)", e.what()); } } return _initialized; } -void V4L2Grabber::getV4Ldevices() +void V4L2Grabber::enumVideoCaptureDevices() { QDirIterator it("/sys/class/video4linux/", QDirIterator::NoIteratorFlags); _deviceProperties.clear(); @@ -319,35 +296,12 @@ void V4L2Grabber::getV4Ldevices() properties.name = devName; devNameFile.close(); } - _v4lDevices.emplace("/dev/"+it.fileName(), devName); + _deviceProperties.insert("/dev/"+it.fileName(), properties); } } } -void V4L2Grabber::setSignalThreshold(double redSignalThreshold, double greenSignalThreshold, double blueSignalThreshold, int noSignalCounterThreshold) -{ - _noSignalThresholdColor.red = uint8_t(255*redSignalThreshold); - _noSignalThresholdColor.green = uint8_t(255*greenSignalThreshold); - _noSignalThresholdColor.blue = uint8_t(255*blueSignalThreshold); - _noSignalCounterThreshold = qMax(1, noSignalCounterThreshold); - - Info(_log, "Signal threshold set to: {%d, %d, %d}", _noSignalThresholdColor.red, _noSignalThresholdColor.green, _noSignalThresholdColor.blue ); -} - -void V4L2Grabber::setSignalDetectionOffset(double horizontalMin, double verticalMin, double horizontalMax, double verticalMax) -{ - // rainbow 16 stripes 0.47 0.2 0.49 0.8 - // unicolor: 0.25 0.25 0.75 0.75 - - _x_frac_min = horizontalMin; - _y_frac_min = verticalMin; - _x_frac_max = horizontalMax; - _y_frac_max = verticalMax; - - Info(_log, "Signal detection area set to: %f,%f x %f,%f", _x_frac_min, _y_frac_min, _x_frac_max, _y_frac_max ); -} - bool V4L2Grabber::start() { try @@ -386,23 +340,23 @@ bool V4L2Grabber::open_device() { struct stat st; - if (-1 == stat(QSTRING_CSTR(_deviceName), &st)) + if (-1 == stat(QSTRING_CSTR(_currentDeviceName), &st)) { - throw_errno_exception("Cannot identify '" + _deviceName + "'"); + throw_errno_exception("Cannot identify '" + _currentDeviceName + "'"); return false; } if (!S_ISCHR(st.st_mode)) { - throw_exception("'" + _deviceName + "' is no device"); + throw_exception("'" + _currentDeviceName + "' is no device"); return false; } - _fileDescriptor = open(QSTRING_CSTR(_deviceName), O_RDWR | O_NONBLOCK, 0); + _fileDescriptor = open(QSTRING_CSTR(_currentDeviceName), O_RDWR | O_NONBLOCK, 0); if (-1 == _fileDescriptor) { - throw_errno_exception("Cannot open '" + _deviceName + "'"); + throw_errno_exception("Cannot open '" + _currentDeviceName + "'"); return false; } @@ -455,7 +409,7 @@ void V4L2Grabber::init_mmap() { if (EINVAL == errno) { - throw_exception("'" + _deviceName + "' does not support memory mapping"); + throw_exception("'" + _currentDeviceName + "' does not support memory mapping"); return; } else @@ -467,7 +421,7 @@ void V4L2Grabber::init_mmap() if (req.count < 2) { - throw_exception("Insufficient buffer memory on " + _deviceName); + throw_exception("Insufficient buffer memory on " + _currentDeviceName); return; } @@ -519,7 +473,7 @@ void V4L2Grabber::init_userp(unsigned int buffer_size) { if (EINVAL == errno) { - throw_exception("'" + _deviceName + "' does not support user pointer"); + throw_exception("'" + _currentDeviceName + "' does not support user pointer"); return; } else @@ -553,7 +507,7 @@ void V4L2Grabber::init_device(VideoStandard videoStandard) { if (EINVAL == errno) { - throw_exception("'" + _deviceName + "' is no V4L2 device"); + throw_exception("'" + _currentDeviceName + "' is no V4L2 device"); return; } else @@ -565,7 +519,7 @@ void V4L2Grabber::init_device(VideoStandard videoStandard) if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { - throw_exception("'" + _deviceName + "' is no video capture device"); + throw_exception("'" + _currentDeviceName + "' is no video capture device"); return; } @@ -575,7 +529,7 @@ void V4L2Grabber::init_device(VideoStandard videoStandard) { if (!(cap.capabilities & V4L2_CAP_READWRITE)) { - throw_exception("'" + _deviceName + "' does not support read i/o"); + throw_exception("'" + _currentDeviceName + "' does not support read i/o"); return; } } @@ -586,7 +540,7 @@ void V4L2Grabber::init_device(VideoStandard videoStandard) { if (!(cap.capabilities & V4L2_CAP_STREAMING)) { - throw_exception("'" + _deviceName + "' does not support streaming i/o"); + throw_exception("'" + _currentDeviceName + "' does not support streaming i/o"); return; } } @@ -699,16 +653,28 @@ void V4L2Grabber::init_device(VideoStandard videoStandard) // set the requested pixel format switch (_pixelFormat) { - case PixelFormat::UYVY: - fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; + case PixelFormat::RGB32: + fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB32; + break; + + case PixelFormat::BGR24: + fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24; break; case PixelFormat::YUYV: fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; break; - case PixelFormat::RGB32: - fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB32; + case PixelFormat::UYVY: + fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY; + break; + + case PixelFormat::NV12: + fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_NV12; + break; + + case PixelFormat::I420: + fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; break; #ifdef HAVE_JPEG_DECODER @@ -727,7 +693,7 @@ void V4L2Grabber::init_device(VideoStandard videoStandard) } // set custom resolution for width and height if they are not zero - if(_width && _height) + if(_width != 0 && _height != 0) { fmt.fmt.pix.width = _width; fmt.fmt.pix.height = _height; @@ -772,14 +738,23 @@ void V4L2Grabber::init_device(VideoStandard videoStandard) // check pixel format and frame size switch (fmt.fmt.pix.pixelformat) { - case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_RGB32: { - _pixelFormat = PixelFormat::UYVY; - _frameByteSize = _width * _height * 2; - Debug(_log, "Pixel format=UYVY"); + _pixelFormat = PixelFormat::RGB32; + _frameByteSize = _width * _height * 4; + Debug(_log, "Pixel format=RGB32"); } break; + case V4L2_PIX_FMT_RGB24: + { + _pixelFormat = PixelFormat::BGR24; + _frameByteSize = _width * _height * 3; + Debug(_log, "Pixel format=BGR24"); + } + break; + + case V4L2_PIX_FMT_YUYV: { _pixelFormat = PixelFormat::YUYV; @@ -788,11 +763,27 @@ void V4L2Grabber::init_device(VideoStandard videoStandard) } break; - case V4L2_PIX_FMT_RGB32: + case V4L2_PIX_FMT_UYVY: { - _pixelFormat = PixelFormat::RGB32; - _frameByteSize = _width * _height * 4; - Debug(_log, "Pixel format=RGB32"); + _pixelFormat = PixelFormat::UYVY; + _frameByteSize = _width * _height * 2; + Debug(_log, "Pixel format=UYVY"); + } + break; + + case V4L2_PIX_FMT_NV12: + { + _pixelFormat = PixelFormat::NV12; + _frameByteSize = (_width * _height * 6) / 4; + Debug(_log, "Pixel format=NV12"); + } + break; + + case V4L2_PIX_FMT_YUV420: + { + _pixelFormat = PixelFormat::I420; + _frameByteSize = (_width * _height * 6) / 4; + Debug(_log, "Pixel format=I420"); } break; @@ -807,9 +798,9 @@ void V4L2Grabber::init_device(VideoStandard videoStandard) default: #ifdef HAVE_JPEG_DECODER - throw_exception("Only pixel formats UYVY, YUYV, RGB32 and MJPEG are supported"); + throw_exception("Only pixel formats RGB32, BGR24, YUYV, UYVY, NV12, I420 and MJPEG are supported"); #else - throw_exception("Only pixel formats UYVY, YUYV, and RGB32 are supported"); + throw_exception("Only pixel formats RGB32, BGR24, YUYV, UYVY, NV12 and I420 are supported"); #endif return; } @@ -992,7 +983,7 @@ int V4L2Grabber::read_frame() { throw_errno_exception("VIDIOC_DQBUF"); stop(); - getV4Ldevices(); + enumVideoCaptureDevices(); } return 0; } @@ -1029,7 +1020,7 @@ int V4L2Grabber::read_frame() { throw_errno_exception("VIDIOC_DQBUF"); stop(); - getV4Ldevices(); + enumVideoCaptureDevices(); } return 0; } @@ -1298,6 +1289,254 @@ int V4L2Grabber::xioctl(int fileDescriptor, int request, void *arg) return r; } +void V4L2Grabber::setDevice(const QString& device) +{ + if (_currentDeviceName != device) + { + (_initialized) + ? _newDeviceName = device + : _currentDeviceName = _newDeviceName = device; + + _reload = true; + } +} + +bool V4L2Grabber::setInput(int input) +{ + if(Grabber::setInput(input)) + { + _reload = true; + return true; + } + + return false; +} + +bool V4L2Grabber::setWidthHeight(int width, int height) +{ + if(Grabber::setWidthHeight(width, height)) + { + _reload = true; + return true; + } + + return false; +} + +void V4L2Grabber::setEncoding(QString enc) +{ + if(_pixelFormatConfig != parsePixelFormat(enc)) + { + _pixelFormatConfig = parsePixelFormat(enc); + if(_initialized) + { + Debug(_log,"Set hardware encoding to: %s", QSTRING_CSTR(enc.toUpper())); + _reload = true; + } + else + _pixelFormat = _pixelFormatConfig; + } +} + +void V4L2Grabber::setBrightnessContrastSaturationHue(int brightness, int contrast, int saturation, int hue) +{ + if(_initialized) + DebugIf(verbose, _log,"TODO: Set brightness to %i, contrast to %i, saturation to %i, hue to %i", brightness, contrast, saturation, hue); +} + +void V4L2Grabber::setSignalThreshold(double redSignalThreshold, double greenSignalThreshold, double blueSignalThreshold, int noSignalCounterThreshold) +{ + _noSignalThresholdColor.red = uint8_t(255*redSignalThreshold); + _noSignalThresholdColor.green = uint8_t(255*greenSignalThreshold); + _noSignalThresholdColor.blue = uint8_t(255*blueSignalThreshold); + _noSignalCounterThreshold = qMax(1, noSignalCounterThreshold); + + if(_signalDetectionEnabled) + Info(_log, "Signal threshold set to: {%d, %d, %d}", _noSignalThresholdColor.red, _noSignalThresholdColor.green, _noSignalThresholdColor.blue ); +} + +void V4L2Grabber::setSignalDetectionOffset(double horizontalMin, double verticalMin, double horizontalMax, double verticalMax) +{ + // rainbow 16 stripes 0.47 0.2 0.49 0.8 + // unicolor: 0.25 0.25 0.75 0.75 + + _x_frac_min = horizontalMin; + _y_frac_min = verticalMin; + _x_frac_max = horizontalMax; + _y_frac_max = verticalMax; + + if(_signalDetectionEnabled) + Info(_log, "Signal detection area set to: %f,%f x %f,%f", _x_frac_min, _y_frac_min, _x_frac_max, _y_frac_max ); +} + +void V4L2Grabber::setSignalDetectionEnable(bool enable) +{ + if (_signalDetectionEnabled != enable) + { + _signalDetectionEnabled = enable; + if(_initialized) + Info(_log, "Signal detection is now %s", enable ? "enabled" : "disabled"); + } +} + +void V4L2Grabber::setCecDetectionEnable(bool enable) +{ + if (_cecDetectionEnabled != enable) + { + _cecDetectionEnabled = enable; + if(_initialized) + Info(_log, QString("CEC detection is now %1").arg(enable ? "enabled" : "disabled").toLocal8Bit()); + } +} + +bool V4L2Grabber::reload(bool force) +{ + if (_streamNotifier != nullptr && _streamNotifier->isEnabled() && (_reload || force)) + { + Info(_log,"Reloading V4L2 Grabber"); + uninit(); + _pixelFormat = _pixelFormatConfig; + _newDeviceName = _currentDeviceName; + _reload = false; + return start(); + } + + return false; +} + +#if defined(ENABLE_CEC) + +void V4L2Grabber::handleCecEvent(CECEvent event) +{ + switch (event) + { + case CECEvent::On : + Debug(_log,"CEC on event received"); + _cecStandbyActivated = false; + return; + case CECEvent::Off : + Debug(_log,"CEC off event received"); + _cecStandbyActivated = true; + return; + default: break; + } +} + +#endif + +QJsonArray V4L2Grabber::discover(const QJsonObject& params) +{ + DebugIf(verbose, _log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData()); + + enumVideoCaptureDevices(); + + QJsonArray inputsDiscovered; + for(auto it = _deviceProperties.begin(); it != _deviceProperties.end(); ++it) + { + QJsonObject device, in; + QJsonArray video_inputs, formats; + + device["device"] = it.key(); + device["device_name"] = _deviceProperties.value(it.key()).name; + device["type"] = "v4l2"; + + QMultiMap inputs = QMultiMap(); + for(auto i = _deviceProperties.begin(); i != _deviceProperties.end(); ++i) + if (i.key() == it.key()) + for (auto y = i.value().inputs.begin(); y != i.value().inputs.end(); y++) + if (!inputs.contains(y.value().inputName, y.key())) + inputs.insert(y.value().inputName, y.key()); + + for (auto input = inputs.begin(); input != inputs.end(); input++) + { + in["name"] = input.key(); + in["inputIdx"] = input.value(); + + QJsonArray standards; + QList videoStandards = QList(); + for(auto i = _deviceProperties.begin(); i != _deviceProperties.end(); ++i) + if (i.key() == it.key()) + for (auto y = i.value().inputs.begin(); y != i.value().inputs.end(); y++) + if (y.key() == input.value()) + for (auto std = y.value().standards.begin(); std != y.value().standards.end(); std++) + if(!videoStandards.contains(*std)) + videoStandards << *std; + + for (auto standard : videoStandards) + standards.append(VideoStandard2String(standard)); + + if (!standards.isEmpty()) + in["standards"] = standards; + + QList encodingFormats = QList(); + for(auto i = _deviceProperties.begin(); i != _deviceProperties.end(); ++i) + if (i.key() == it.key()) + for (auto y = i.value().inputs.begin(); y != i.value().inputs.end(); y++) + if (y.key() == input.value()) + for (auto enc = y.value().encodingFormats.begin(); enc != y.value().encodingFormats.end(); enc++) + if (!encodingFormats.contains(enc.key())) + encodingFormats << enc.key(); + + for (auto encodingFormat : encodingFormats) + { + QJsonObject format; + QJsonArray resolutionArray; + + format["format"] = pixelFormatToString(encodingFormat); + + QMultiMap deviceResolutions = QMultiMap(); + for(auto i = _deviceProperties.begin(); i != _deviceProperties.end(); ++i) + if (i.key() == it.key()) + for (auto y = i.value().inputs.begin(); y != i.value().inputs.end(); y++) + if (y.key() == input.value()) + for (auto enc = y.value().encodingFormats.begin(); enc != y.value().encodingFormats.end(); enc++) + if (enc.key() == encodingFormat && !deviceResolutions.contains(enc.value().width, enc.value().height)) + deviceResolutions.insert(enc.value().width, enc.value().height); + + for (auto width_height = deviceResolutions.begin(); width_height != deviceResolutions.end(); width_height++) + { + QJsonObject resolution; + QJsonArray fps; + + resolution["width"] = int(width_height.key()); + resolution["height"] = int(width_height.value()); + + QIntList framerates = QIntList(); + for(auto i = _deviceProperties.begin(); i != _deviceProperties.end(); ++i) + if (i.key() == it.key()) + for (auto y = i.value().inputs.begin(); y != i.value().inputs.end(); y++) + if (y.key() == input.value()) + for (auto enc = y.value().encodingFormats.begin(); enc != y.value().encodingFormats.end(); enc++) + if(enc.key() == encodingFormat && enc.value().width == width_height.key() && enc.value().height == width_height.value()) + for (auto fps = enc.value().framerates.begin(); fps != enc.value().framerates.end(); fps++) + if(!framerates.contains(*fps)) + framerates << *fps; + + for (auto framerate : framerates) + fps.append(framerate); + + resolution["fps"] = fps; + resolutionArray.append(resolution); + } + + format["resolutions"] = resolutionArray; + formats.append(format); + } + in["formats"] = formats; + video_inputs.append(in); + + } + + device["video_inputs"] = video_inputs; + inputsDiscovered.append(device); + } + + _deviceProperties.clear(); + DebugIf(verbose, _log, "device: [%s]", QString(QJsonDocument(inputsDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData()); + + return inputsDiscovered; +} + void V4L2Grabber::enumFrameIntervals(QList &framerates, int fileDescriptor, int pixelformat, int width, int height) { // collect available frame rates @@ -1349,188 +1588,3 @@ void V4L2Grabber::enumFrameIntervals(QList &framerates, int fileDescriptor, framerates.append(streamparms.parm.capture.timeperframe.denominator / streamparms.parm.capture.timeperframe.numerator); } } - -void V4L2Grabber::setSignalDetectionEnable(bool enable) -{ - if (_signalDetectionEnabled != enable) - { - _signalDetectionEnabled = enable; - Info(_log, "Signal detection is now %s", enable ? "enabled" : "disabled"); - } -} - -void V4L2Grabber::setCecDetectionEnable(bool enable) -{ - if (_cecDetectionEnabled != enable) - { - _cecDetectionEnabled = enable; - Info(_log, QString("CEC detection is now %1").arg(enable ? "enabled" : "disabled").toLocal8Bit()); - } -} - -void V4L2Grabber::setPixelDecimation(int pixelDecimation) -{ - if (_pixelDecimation != pixelDecimation) - { - _pixelDecimation = pixelDecimation; - _imageResampler.setHorizontalPixelDecimation(pixelDecimation); - _imageResampler.setVerticalPixelDecimation(pixelDecimation); - } -} - -void V4L2Grabber::setDeviceVideoStandard(QString device, VideoStandard videoStandard) -{ - if (_deviceName != device || _videoStandard != videoStandard) - { - // extract input of device - QChar input = device.at(device.size() - 1); - _input = input.isNumber() ? input.digitValue() : -1; - - bool started = _initialized; - uninit(); - _deviceName = device; - _videoStandard = videoStandard; - - if(started) start(); - } -} - -bool V4L2Grabber::setInput(int input) -{ - if(Grabber::setInput(input)) - { - bool started = _initialized; - uninit(); - if(started) start(); - return true; - } - return false; -} - -bool V4L2Grabber::setWidthHeight(int width, int height) -{ - if(Grabber::setWidthHeight(width,height)) - { - bool started = _initialized; - uninit(); - if(started) start(); - return true; - } - return false; -} - -bool V4L2Grabber::setFramerate(int fps) -{ - if(Grabber::setFramerate(fps)) - { - bool started = _initialized; - uninit(); - if(started) start(); - return true; - } - return false; -} - -QStringList V4L2Grabber::getDevices() const -{ - QStringList result = QStringList(); - for(auto it = _deviceProperties.begin(); it != _deviceProperties.end(); ++it) - result << it.key(); - - return result; -} - -QString V4L2Grabber::getDeviceName(const QString& devicePath) const -{ - return _deviceProperties.value(devicePath).name; -} - -QMultiMap V4L2Grabber::getDeviceInputs(const QString& devicePath) const -{ - QMultiMap result = QMultiMap(); - for(auto it = _deviceProperties.begin(); it != _deviceProperties.end(); ++it) - if (it.key() == devicePath) - for (auto input = it.value().inputs.begin(); input != it.value().inputs.end(); input++) - if (!result.contains(input.value().inputName, input.key())) - result.insert(input.value().inputName, input.key()); - - return result; -} - -QList V4L2Grabber::getAvailableDeviceStandards(const QString& devicePath, const int& deviceInput) const -{ - QList result =QList(); - - for(auto it = _deviceProperties.begin(); it != _deviceProperties.end(); ++it) - if (it.key() == devicePath) - for (auto input = it.value().inputs.begin(); input != it.value().inputs.end(); input++) - if (input.key() == deviceInput) - for (auto standard = input.value().standards.begin(); standard != input.value().standards.end(); standard++) - if(!result.contains(*standard)) - result << *standard; - - return result; -} - -QStringList V4L2Grabber::getAvailableEncodingFormats(const QString& devicePath, const int& deviceInput) const -{ - QStringList result = QStringList(); - - for(auto it = _deviceProperties.begin(); it != _deviceProperties.end(); ++it) - if (it.key() == devicePath) - for (auto input = it.value().inputs.begin(); input != it.value().inputs.end(); input++) - if (input.key() == deviceInput) - for (auto enc = input.value().encodingFormats.begin(); enc != input.value().encodingFormats.end(); enc++) - if (!result.contains(pixelFormatToString(enc.key()).toLower(), Qt::CaseInsensitive)) - result << pixelFormatToString(enc.key()).toLower(); - - return result; -} - -QMultiMap V4L2Grabber::getAvailableDeviceResolutions(const QString& devicePath, const int& deviceInput, const PixelFormat& encFormat) const -{ - QMultiMap result = QMultiMap(); - - for(auto it = _deviceProperties.begin(); it != _deviceProperties.end(); ++it) - if (it.key() == devicePath) - for (auto input = it.value().inputs.begin(); input != it.value().inputs.end(); input++) - if (input.key() == deviceInput) - for (auto enc = input.value().encodingFormats.begin(); enc != input.value().encodingFormats.end(); enc++) - if (!result.contains(enc.value().width, enc.value().height)) - result.insert(enc.value().width, enc.value().height); - - return result; -} - -QIntList V4L2Grabber::getAvailableDeviceFramerates(const QString& devicePath, const int& deviceInput, const PixelFormat& encFormat, const unsigned width, const unsigned height) const -{ - QIntList result = QIntList(); - - for(auto it = _deviceProperties.begin(); it != _deviceProperties.end(); ++it) - if (it.key() == devicePath) - for (auto input = it.value().inputs.begin(); input != it.value().inputs.end(); input++) - if (input.key() == deviceInput) - for (auto enc = input.value().encodingFormats.begin(); enc != input.value().encodingFormats.end(); enc++) - if(enc.key() == encFormat && enc.value().width == width && enc.value().height == height) - for (auto fps = enc.value().framerates.begin(); fps != enc.value().framerates.end(); fps++) - if(!result.contains(*fps)) - result << *fps; - - return result; -} - -void V4L2Grabber::handleCecEvent(CECEvent event) -{ - switch (event) - { - case CECEvent::On : - Debug(_log,"CEC on event received"); - _cecStandbyActivated = false; - return; - case CECEvent::Off : - Debug(_log,"CEC off event received"); - _cecStandbyActivated = true; - return; - default: break; - } -} diff --git a/libsrc/grabber/x11/X11Grabber.cpp b/libsrc/grabber/x11/X11Grabber.cpp index 99cdb712..db50b80c 100644 --- a/libsrc/grabber/x11/X11Grabber.cpp +++ b/libsrc/grabber/x11/X11Grabber.cpp @@ -4,9 +4,15 @@ #include #include +// Constants +namespace { + const bool verbose = false; +} //End of constants + X11Grabber::X11Grabber(int cropLeft, int cropRight, int cropTop, int cropBottom, int pixelDecimation) : Grabber("X11GRABBER", 0, 0, cropLeft, cropRight, cropTop, cropBottom) , _x11Display(nullptr) + , _xImage(nullptr) , _pixmap(None) , _srcFormat(nullptr) , _dstFormat(nullptr) @@ -17,8 +23,15 @@ X11Grabber::X11Grabber(int cropLeft, int cropRight, int cropTop, int cropBottom, , _calculatedHeight(0) , _src_x(cropLeft) , _src_y(cropTop) + , _XShmAvailable(false) + , _XRenderAvailable(false) + , _XRandRAvailable(false) + , _isWayland (false) + , _logger{} , _image(0,0) { + _logger = Logger::getInstance("X11"); + _useImageResampler = false; _imageResampler.setCropping(0, 0, 0, 0); // cropping is performed by XRender, XShmGetImage or XGetImage memset(&_pictAttr, 0, sizeof(_pictAttr)); @@ -37,7 +50,10 @@ X11Grabber::~X11Grabber() void X11Grabber::freeResources() { // Cleanup allocated resources of the X11 grab - XDestroyImage(_xImage); + if (_xImage != nullptr) + { + XDestroyImage(_xImage); + } if (_XRandRAvailable) { qApp->removeNativeEventFilter(this); @@ -100,39 +116,72 @@ void X11Grabber::setupResources() _imageResampler.setHorizontalPixelDecimation(_pixelDecimation); _imageResampler.setVerticalPixelDecimation(_pixelDecimation); } - } -bool X11Grabber::Setup() +bool X11Grabber::open() { - _x11Display = XOpenDisplay(NULL); - if (_x11Display == nullptr) + bool rc = false; + + if (getenv("WAYLAND_DISPLAY") != nullptr) { - Error(_log, "Unable to open display"); - if (getenv("DISPLAY")) + _isWayland = true; + } + else + { + _x11Display = XOpenDisplay(nullptr); + if (_x11Display != nullptr) { - Error(_log, "%s",getenv("DISPLAY")); + rc = true; + } + } + return rc; +} + +bool X11Grabber::setupDisplay() +{ + bool result = false; + + if ( ! open() ) + { + if ( _isWayland ) + { + Error(_log, "Grabber does not work under Wayland!"); } else { - Error(_log, "DISPLAY environment variable not set"); + if (getenv("DISPLAY") != nullptr) + { + Error(_log, "Unable to open display [%s]",getenv("DISPLAY")); + } + else + { + Error(_log, "DISPLAY environment variable not set"); + } } - return false; } + else + { + _window = DefaultRootWindow(_x11Display); - _window = DefaultRootWindow(_x11Display); + int dummy, pixmaps_supported; - int dummy, pixmaps_supported; + _XRandRAvailable = XRRQueryExtension(_x11Display, &_XRandREventBase, &dummy); + _XRenderAvailable = XRenderQueryExtension(_x11Display, &dummy, &dummy); + _XShmAvailable = XShmQueryExtension(_x11Display); + XShmQueryVersion(_x11Display, &dummy, &dummy, &pixmaps_supported); + _XShmPixmapAvailable = pixmaps_supported && XShmPixmapFormat(_x11Display) == ZPixmap; - _XRandRAvailable = XRRQueryExtension(_x11Display, &_XRandREventBase, &dummy); - _XRenderAvailable = XRenderQueryExtension(_x11Display, &dummy, &dummy); - _XShmAvailable = XShmQueryExtension(_x11Display); - XShmQueryVersion(_x11Display, &dummy, &dummy, &pixmaps_supported); - _XShmPixmapAvailable = pixmaps_supported && XShmPixmapFormat(_x11Display) == ZPixmap; + Info(_log, QString("XRandR=[%1] XRender=[%2] XShm=[%3] XPixmap=[%4]") + .arg(_XRandRAvailable ? "available" : "unavailable") + .arg(_XRenderAvailable ? "available" : "unavailable") + .arg(_XShmAvailable ? "available" : "unavailable") + .arg(_XShmPixmapAvailable ? "available" : "unavailable") + .toStdString().c_str()); - bool result = (updateScreenDimensions(true) >=0); - ErrorIf(!result, _log, "X11 Grabber start failed"); - setEnabled(result); + result = (updateScreenDimensions(true) >=0); + ErrorIf(!result, _log, "X11 Grabber start failed"); + setEnabled(result); + } return result; } @@ -235,7 +284,8 @@ int X11Grabber::updateScreenDimensions(bool force) _width = _windowAttr.width; _height = _windowAttr.height; - int width=0, height=0; + int width=0; + int height=0; // Image scaling is performed by XRender when available, otherwise by ImageResampler if (_XRenderAvailable) @@ -301,19 +351,24 @@ void X11Grabber::setVideoMode(VideoMode mode) updateScreenDimensions(true); } -void X11Grabber::setPixelDecimation(int pixelDecimation) +bool X11Grabber::setPixelDecimation(int pixelDecimation) { - if(_pixelDecimation != pixelDecimation) + if(Grabber::setPixelDecimation(pixelDecimation)) { - _pixelDecimation = pixelDecimation; updateScreenDimensions(true); + return true; } + + return false; } void X11Grabber::setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom) { Grabber::setCropping(cropLeft, cropRight, cropTop, cropBottom); - if(_x11Display != nullptr) updateScreenDimensions(true); // segfault on init + if(_x11Display != nullptr) + { + updateScreenDimensions(true); // segfault on init + } } bool X11Grabber::nativeEventFilter(const QByteArray & eventType, void * message, long int * /*result*/) @@ -332,3 +387,78 @@ bool X11Grabber::nativeEventFilter(const QByteArray & eventType, void * message, return false; } + +QJsonObject X11Grabber::discover(const QJsonObject& params) +{ + DebugIf(verbose, _log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData()); + + QJsonObject inputsDiscovered; + if ( open() ) + { + inputsDiscovered["device"] = "x11"; + inputsDiscovered["device_name"] = "X11"; + inputsDiscovered["type"] = "screen"; + + QJsonArray video_inputs; + + if (_x11Display != nullptr) + { + QJsonArray fps = { 1, 5, 10, 15, 20, 25, 30, 40, 50, 60 }; + + // Iterate through all X screens + for (int i = 0; i < XScreenCount(_x11Display); ++i) + { + _window = DefaultRootWindow(_x11Display); + + const Status status = XGetWindowAttributes(_x11Display, _window, &_windowAttr); + if (status == 0) + { + Debug(_log, "Failed to obtain window attributes"); + } + else + { + QJsonObject in; + + QString displayName; + char* name; + if ( XFetchName(_x11Display, _window, &name) > 0 ) + { + displayName = name; + } + else { + displayName = QString("Display:%1").arg(i); + } + + in["name"] = displayName; + in["inputIdx"] = i; + + QJsonArray formats; + QJsonArray resolutionArray; + QJsonObject format; + QJsonObject resolution; + + resolution["width"] = _windowAttr.width; + resolution["height"] = _windowAttr.height; + resolution["fps"] = fps; + + resolutionArray.append(resolution); + + format["resolutions"] = resolutionArray; + formats.append(format); + + in["formats"] = formats; + video_inputs.append(in); + } + } + + if ( !video_inputs.isEmpty() ) + { + inputsDiscovered["video_inputs"] = video_inputs; + } + } + } + DebugIf(verbose, _log, "device: [%s]", QString(QJsonDocument(inputsDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData()); + + return inputsDiscovered; +} + diff --git a/libsrc/grabber/x11/X11Wrapper.cpp b/libsrc/grabber/x11/X11Wrapper.cpp index a02e3627..f21f0abe 100644 --- a/libsrc/grabber/x11/X11Wrapper.cpp +++ b/libsrc/grabber/x11/X11Wrapper.cpp @@ -19,7 +19,7 @@ void X11Wrapper::action() if (! _init ) { _init = true; - if ( ! _grabber.Setup() ) + if ( ! _grabber.setupDisplay() ) { stop(); } diff --git a/libsrc/grabber/xcb/XcbCommandExecutor.h b/libsrc/grabber/xcb/XcbCommandExecutor.h index f87f4c70..b58a43fc 100644 --- a/libsrc/grabber/xcb/XcbCommandExecutor.h +++ b/libsrc/grabber/xcb/XcbCommandExecutor.h @@ -22,7 +22,7 @@ void check_error(xcb_generic_error_t * error) // Requests with void response type template typename std::enable_if::value, void>::type - query(xcb_connection_t * connection, Args&& ...args) + static query(xcb_connection_t * connection, Args&& ...args) { auto cookie = Request::RequestFunction(connection, std::forward(args)...); @@ -33,9 +33,8 @@ template // Requests with non-void response type template - typename std::enable_if::value, - std::unique_ptr>::type - query(xcb_connection_t * connection, Args&& ...args) + typename std::enable_if::value, std::unique_ptr>::type + static query(xcb_connection_t * connection, Args&& ...args) { auto cookie = Request::RequestFunction(connection, std::forward(args)...); diff --git a/libsrc/grabber/xcb/XcbCommands.h b/libsrc/grabber/xcb/XcbCommands.h index 973e87bf..6f42b7cf 100644 --- a/libsrc/grabber/xcb/XcbCommands.h +++ b/libsrc/grabber/xcb/XcbCommands.h @@ -21,6 +21,14 @@ struct GetGeometry static constexpr auto ReplyFunction = xcb_get_geometry_reply; }; +struct GetProperty +{ + typedef xcb_get_property_reply_t ResponseType; + + static constexpr auto RequestFunction = xcb_get_property; + static constexpr auto ReplyFunction = xcb_get_property_reply; +}; + struct ShmQueryVersion { typedef xcb_shm_query_version_reply_t ResponseType; diff --git a/libsrc/grabber/xcb/XcbGrabber.cpp b/libsrc/grabber/xcb/XcbGrabber.cpp index ffffc0c7..9f4f626a 100644 --- a/libsrc/grabber/xcb/XcbGrabber.cpp +++ b/libsrc/grabber/xcb/XcbGrabber.cpp @@ -14,6 +14,11 @@ #include +// Constants +namespace { + const bool verbose = false; +} //End of constants + #define DOUBLE_TO_FIXED(d) ((xcb_render_fixed_t) ((d) * 65536)) XcbGrabber::XcbGrabber(int cropLeft, int cropRight, int cropTop, int cropBottom, int pixelDecimation) @@ -36,6 +41,7 @@ XcbGrabber::XcbGrabber(int cropLeft, int cropRight, int cropTop, int cropBottom, , _XcbRandRAvailable{} , _XcbShmAvailable{} , _XcbShmPixmapAvailable{} + , _isWayland (false) , _logger{} , _shmData{} , _XcbRandREventBase{-1} @@ -181,48 +187,77 @@ void XcbGrabber::setupShm() } } -bool XcbGrabber::Setup() +bool XcbGrabber::open() { - int screen_num; - _connection = xcb_connect(nullptr, &screen_num); + bool rc = false; - int ret = xcb_connection_has_error(_connection); - if (ret != 0) + if (getenv("WAYLAND_DISPLAY") != nullptr) { - Error(_logger, "Cannot open display, error %d", ret); - return false; + _isWayland = true; } - - const xcb_setup_t * setup = xcb_get_setup(_connection); - _screen = getScreen(setup, screen_num); - - if (!_screen) + else { - Error(_log, "Unable to open display, screen %d does not exist", screen_num); + _connection = xcb_connect(nullptr, &_screen_num); - if (getenv("DISPLAY")) - Error(_log, "%s", getenv("DISPLAY")); + int ret = xcb_connection_has_error(_connection); + if (ret != 0) + { + Debug(_logger, "Cannot open display, error %d", ret); + } else - Error(_log, "DISPLAY environment variable not set"); - - freeResources(); - return false; + { + const xcb_setup_t * setup = xcb_get_setup(_connection); + _screen = getScreen(setup, _screen_num); + if ( _screen != nullptr) + { + rc = true; + } + } } - setupRandr(); - setupRender(); - setupShm(); + return rc; +} - Info(_log, QString("XcbRandR=[%1] XcbRender=[%2] XcbShm=[%3] XcbPixmap=[%4]") - .arg(_XcbRandRAvailable ? "available" : "unavailable") - .arg(_XcbRenderAvailable ? "available" : "unavailable") - .arg(_XcbShmAvailable ? "available" : "unavailable") - .arg(_XcbShmPixmapAvailable ? "available" : "unavailable") - .toStdString().c_str()); +bool XcbGrabber::setupDisplay() +{ + bool result = false; - bool result = (updateScreenDimensions(true) >= 0); - ErrorIf(!result, _log, "XCB Grabber start failed"); - setEnabled(result); + if ( ! open() ) + { + if ( _isWayland ) + { + Error(_log, "Grabber does not work under Wayland!"); + } + else + { + if (getenv("DISPLAY") != nullptr) + { + Error(_log, "Unable to open display [%s], screen %d does not exist", getenv("DISPLAY"), _screen_num); + } + else + { + Error(_log, "DISPLAY environment variable not set"); + } + freeResources(); + } + } + else + { + setupRandr(); + setupRender(); + setupShm(); + + Info(_log, QString("XcbRandR=[%1] XcbRender=[%2] XcbShm=[%3] XcbPixmap=[%4]") + .arg(_XcbRandRAvailable ? "available" : "unavailable") + .arg(_XcbRenderAvailable ? "available" : "unavailable") + .arg(_XcbShmAvailable ? "available" : "unavailable") + .arg(_XcbShmPixmapAvailable ? "available" : "unavailable") + .toStdString().c_str()); + + result = (updateScreenDimensions(true) >= 0); + ErrorIf(!result, _log, "XCB Grabber start failed"); + setEnabled(result); + } return result; } @@ -394,13 +429,15 @@ void XcbGrabber::setVideoMode(VideoMode mode) updateScreenDimensions(true); } -void XcbGrabber::setPixelDecimation(int pixelDecimation) +bool XcbGrabber::setPixelDecimation(int pixelDecimation) { - if(_pixelDecimation != pixelDecimation) + if(Grabber::setPixelDecimation(pixelDecimation)) { - _pixelDecimation = pixelDecimation; updateScreenDimensions(true); + return true; } + + return false; } void XcbGrabber::setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom) @@ -459,3 +496,89 @@ xcb_render_pictformat_t XcbGrabber::findFormatForVisual(xcb_visualid_t visual) c } return {}; } + +QJsonObject XcbGrabber::discover(const QJsonObject& params) +{ + DebugIf(verbose, _log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData()); + + QJsonObject inputsDiscovered; + if ( open() ) + { + inputsDiscovered["device"] = "xcb"; + inputsDiscovered["device_name"] = "XCB"; + inputsDiscovered["type"] = "screen"; + + QJsonArray video_inputs; + + if (_connection != nullptr && _screen != nullptr ) + { + QJsonArray fps = { 1, 5, 10, 15, 20, 25, 30, 40, 50, 60 }; + + const xcb_setup_t * setup = xcb_get_setup(_connection); + + xcb_screen_iterator_t it = xcb_setup_roots_iterator(setup); + xcb_screen_t * screen = nullptr; + + int i = 0; + // Iterate through all X screens + for (; it.rem > 0; xcb_screen_next(&it)) + { + screen = it.data; + + auto geometry = query(_connection, screen->root); + if (geometry == nullptr) + { + Debug(_log, "Failed to obtain screen geometry for screen [%d]", i); + } + else + { + QJsonObject in; + + QString displayName; + auto property = query(_connection, 0, screen->root, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 0, 0); + if ( property != nullptr ) + { + if ( xcb_get_property_value_length(property.get()) > 0 ) + { + displayName = (char *) xcb_get_property_value(property.get()); + } + } + + if (displayName.isEmpty()) + { + displayName = QString("Display:%1").arg(i); + } + + in["name"] = displayName; + in["inputIdx"] = i; + + QJsonArray formats; + QJsonArray resolutionArray; + QJsonObject format; + QJsonObject resolution; + + resolution["width"] = geometry->width; + resolution["height"] = geometry->height; + resolution["fps"] = fps; + + resolutionArray.append(resolution); + + format["resolutions"] = resolutionArray; + formats.append(format); + + in["formats"] = formats; + video_inputs.append(in); + } + ++i; + } + + if ( !video_inputs.isEmpty() ) + { + inputsDiscovered["video_inputs"] = video_inputs; + } + } + } + DebugIf(verbose, _log, "device: [%s]", QString(QJsonDocument(inputsDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData()); + + return inputsDiscovered; +} diff --git a/libsrc/grabber/xcb/XcbWrapper.cpp b/libsrc/grabber/xcb/XcbWrapper.cpp index 699b5bd4..ba715f06 100644 --- a/libsrc/grabber/xcb/XcbWrapper.cpp +++ b/libsrc/grabber/xcb/XcbWrapper.cpp @@ -19,7 +19,7 @@ void XcbWrapper::action() if (! _init ) { _init = true; - if ( ! _grabber.Setup() ) + if ( ! _grabber.setupDisplay() ) { stop(); } diff --git a/libsrc/hyperion/Grabber.cpp b/libsrc/hyperion/Grabber.cpp index 5a2d1fc2..3a6a95de 100644 --- a/libsrc/hyperion/Grabber.cpp +++ b/libsrc/hyperion/Grabber.cpp @@ -1,22 +1,25 @@ #include Grabber::Grabber(const QString& grabberName, int width, int height, int cropLeft, int cropRight, int cropTop, int cropBottom) - : _imageResampler() + : _grabberName(grabberName) + , _imageResampler() , _useImageResampler(true) , _videoMode(VideoMode::VIDEO_2D) + , _videoStandard(VideoStandard::NO_CHANGE) + , _pixelDecimation(8) , _flipMode(FlipMode::NO_CHANGE) , _width(width) , _height(height) , _fps(15) + , _fpsSoftwareDecimation(0) , _input(-1) , _cropLeft(0) , _cropRight(0) , _cropTop(0) , _cropBottom(0) , _enabled(true) - , _log(Logger::getInstance(grabberName.toUpper())) + , _log(Logger::getInstance(_grabberName.toUpper())) { - Grabber::setVideoMode(VideoMode::VIDEO_2D); Grabber::setCropping(cropLeft, cropRight, cropTop, cropBottom); } @@ -36,6 +39,27 @@ void Grabber::setVideoMode(VideoMode mode) } } +void Grabber::setVideoStandard(VideoStandard videoStandard) +{ + if (_videoStandard != videoStandard) + _videoStandard = videoStandard; +} + +bool Grabber::setPixelDecimation(int pixelDecimation) +{ + if (_pixelDecimation != pixelDecimation) + { + Debug(_log,"Set image size decimation to %d", pixelDecimation); + _pixelDecimation = pixelDecimation; + _imageResampler.setHorizontalPixelDecimation(pixelDecimation); + _imageResampler.setVerticalPixelDecimation(pixelDecimation); + + return true; + } + + return false; +} + void Grabber::setFlipMode(FlipMode mode) { Debug(_log,"Set flipmode to %s", QSTRING_CSTR(flipModeToString(mode))); @@ -111,9 +135,20 @@ bool Grabber::setFramerate(int fps) { if((fps > 0) && (_fps != fps)) { + Debug(_log,"Set new frames per second to: %i fps", fps); _fps = fps; return true; } return false; } + +void Grabber::setFpsSoftwareDecimation(int decimation) +{ + if((_fpsSoftwareDecimation != decimation)) + { + _fpsSoftwareDecimation = decimation; + if(decimation > 0) + Debug(_log,"Skip %i frame per second", decimation); + } +} diff --git a/libsrc/hyperion/GrabberWrapper.cpp b/libsrc/hyperion/GrabberWrapper.cpp index 102a0b64..68002181 100644 --- a/libsrc/hyperion/GrabberWrapper.cpp +++ b/libsrc/hyperion/GrabberWrapper.cpp @@ -44,14 +44,19 @@ GrabberWrapper::~GrabberWrapper() bool GrabberWrapper::start() { - if (!_timer->isActive()) + bool rc = false; + if ( open() ) { - // Start the timer with the pre configured interval - Debug(_log,"Grabber start()"); - _timer->start(); - } + if (!_timer->isActive()) + { + // Start the timer with the pre configured interval + Debug(_log,"Grabber start()"); + _timer->start(); + } - return _timer->isActive(); + rc = _timer->isActive(); + } + return rc; } void GrabberWrapper::stop() @@ -129,11 +134,16 @@ void GrabberWrapper::setVideoMode(VideoMode mode) { if (_ggrabber != nullptr) { - Info(_log,"setvideomode"); + Info(_log,"setVideoMode"); _ggrabber->setVideoMode(mode); } } +void GrabberWrapper::setFlipMode(QString flipMode) +{ + _ggrabber->setFlipMode(parseFlipMode(flipMode)); +} + void GrabberWrapper::setCropping(unsigned cropLeft, unsigned cropRight, unsigned cropTop, unsigned cropBottom) { _ggrabber->setCropping(cropLeft, cropRight, cropTop, cropBottom); @@ -165,7 +175,7 @@ void GrabberWrapper::handleSettingsUpdate(settings::type type, const QJsonDocume _ggrabber->setWidthHeight(obj["width"].toInt(96), obj["height"].toInt(96)); // display index for MAC - _ggrabber->setDisplayIndex(obj["display"].toInt(0)); + _ggrabber->setDisplayIndex(obj["input"].toInt(0)); // device path for Framebuffer _ggrabber->setDevicePath(obj["device"].toString("/dev/fb0")); @@ -181,7 +191,7 @@ void GrabberWrapper::handleSettingsUpdate(settings::type type, const QJsonDocume obj["cropBottom"].toInt(0)); // eval new update time - updateTimer(1000/obj["frequency_Hz"].toInt(10)); + updateTimer(1000/obj["fps"].toInt(10)); } } @@ -221,59 +231,3 @@ void GrabberWrapper::tryStart() start(); } } - -QStringList GrabberWrapper::getDevices() const -{ - if(_grabberName.startsWith("V4L")) - return _ggrabber->getDevices(); - - return QStringList(); -} - -QString GrabberWrapper::getDeviceName(const QString& devicePath) const -{ - if(_grabberName.startsWith("V4L")) - return _ggrabber->getDeviceName(devicePath); - - return QString(); -} - -QMultiMap GrabberWrapper::getDeviceInputs(const QString& devicePath) const -{ - if(_grabberName.startsWith("V4L")) - return _ggrabber->getDeviceInputs(devicePath); - - return QMultiMap(); -} - -QList GrabberWrapper::getAvailableDeviceStandards(const QString& devicePath, const int& deviceInput) const -{ - if(_grabberName.startsWith("V4L")) - return _ggrabber->getAvailableDeviceStandards(devicePath, deviceInput); - - return QList(); -} - -QStringList GrabberWrapper::getAvailableEncodingFormats(const QString& devicePath, const int& deviceInput) const -{ - if(_grabberName.startsWith("V4L")) - return _ggrabber->getAvailableEncodingFormats(devicePath, deviceInput); - - return QStringList(); -} - -QMultiMap GrabberWrapper::getAvailableDeviceResolutions(const QString& devicePath, const int& deviceInput, const PixelFormat& encFormat) const -{ - if(_grabberName.startsWith("V4L")) - return _ggrabber->getAvailableDeviceResolutions(devicePath, deviceInput, encFormat); - - return QMultiMap(); -} - -QIntList GrabberWrapper::getAvailableDeviceFramerates(const QString& devicePath, const int& deviceInput, const PixelFormat& encFormat, const unsigned width, const unsigned height) const -{ - if(_grabberName.startsWith("V4L")) - return _ggrabber->getAvailableDeviceFramerates(devicePath, deviceInput, encFormat, width, height); - - return QIntList(); -} diff --git a/libsrc/hyperion/PriorityMuxer.cpp b/libsrc/hyperion/PriorityMuxer.cpp index 4ba0189f..6e4d4709 100644 --- a/libsrc/hyperion/PriorityMuxer.cpp +++ b/libsrc/hyperion/PriorityMuxer.cpp @@ -5,7 +5,6 @@ // qt incl #include #include -#include // Hyperion includes #include @@ -13,6 +12,8 @@ // utils #include +const int PriorityMuxer::FG_PRIORITY = 1; +const int PriorityMuxer::BG_PRIORITY = 254; const int PriorityMuxer::LOWEST_PRIORITY = std::numeric_limits::max(); PriorityMuxer::PriorityMuxer(int ledCount, QObject * parent) @@ -322,7 +323,7 @@ void PriorityMuxer::setCurrentTime() newPriority = qMin(newPriority, infoIt->priority); // call timeTrigger when effect or color is running with timeout > 0, blacklist prio 255 - if(infoIt->priority < 254 && infoIt->timeoutTime_ms > 0 && (infoIt->componentId == hyperion::COMP_EFFECT || infoIt->componentId == hyperion::COMP_COLOR || infoIt->componentId == hyperion::COMP_IMAGE)) + if(infoIt->priority < BG_PRIORITY && infoIt->timeoutTime_ms > 0 && (infoIt->componentId == hyperion::COMP_EFFECT || infoIt->componentId == hyperion::COMP_COLOR || infoIt->componentId == hyperion::COMP_IMAGE)) emit signalTimeTrigger(); // as signal to prevent Threading issues ++infoIt; diff --git a/libsrc/hyperion/schema/schema-device.json b/libsrc/hyperion/schema/schema-device.json index 23deb34a..4c337200 100644 --- a/libsrc/hyperion/schema/schema-device.json +++ b/libsrc/hyperion/schema/schema-device.json @@ -16,7 +16,6 @@ "title" : "edt_dev_general_hardwareLedCount_title", "minimum" : 1, "default" : 1, - "access" : "expert", "propertyOrder" : 2 }, "colorOrder" : @@ -25,9 +24,11 @@ "title" : "edt_dev_general_colorOrder_title", "enum" : ["rgb", "bgr", "rbg", "brg", "gbr", "grb"], "default" : "rgb", - "options" : { - "enum_titles" : ["edt_conf_enum_rgb", "edt_conf_enum_bgr", "edt_conf_enum_rbg", "edt_conf_enum_brg", "edt_conf_enum_gbr", "edt_conf_enum_grb"] + "required" : true, + "options": { + "enum_titles": [ "edt_conf_enum_rgb", "edt_conf_enum_bgr", "edt_conf_enum_rbg", "edt_conf_enum_brg", "edt_conf_enum_gbr", "edt_conf_enum_grb" ] }, + "access" : "expert", "propertyOrder" : 3 } }, diff --git a/libsrc/hyperion/schema/schema-framegrabber.json b/libsrc/hyperion/schema/schema-framegrabber.json index 12709f07..d7a1a482 100644 --- a/libsrc/hyperion/schema/schema-framegrabber.json +++ b/libsrc/hyperion/schema/schema-framegrabber.json @@ -2,79 +2,87 @@ "type" : "object", "title" : "edt_conf_fg_heading_title", "properties": { - "type": { + "available_devices": { "type": "string", - "title": "edt_conf_fg_type_title", - "enum": [ "auto", "amlogic", "dispmanx", "dx", "framebuffer", "osx", "qt", "x11", "xcb" ], - "options": { - "enum_titles": [ "edt_conf_enum_automatic", "AMLogic", "DispmanX", "DirectX9", "Framebuffer", "OSX", "QT", "X11", "XCB" ] - - }, - "default": "auto", - "propertyOrder": 1 + "title": "edt_conf_v4l2_device_title", + "propertyOrder": 1, + "required": false }, - "display": { + "device": { + "type": "string", + "title": "edt_conf_enum_custom", + "options": { + "hidden": true + }, + "required": true, + "comment": "The 'available_devices' settings are dynamically inserted into the WebUI under PropertyOrder '1'.", + "propertyOrder": 2 + }, + "device_inputs": { + "type": "string", + "title": "edt_conf_v4l2_input_title", + "propertyOrder": 3, + "required": false + }, + "input": { "type": "integer", - "title": "edt_conf_fg_display_title", + "title": "edt_conf_enum_custom", "minimum": 0, "default": 0, - "propertyOrder": 2 + "options": { + "hidden": true + }, + "required": true, + "propertyOrder": 4, + "comment": "The 'device_inputs' settings are dynamically inserted into the WebUI under PropertyOrder '3'." + }, + "resolutions": { + "type": "string", + "title": "edt_conf_v4l2_resolution_title", + "propertyOrder": 5, + "required": false }, "width": { "type": "integer", - "title": "edt_conf_fg_width_title", + "title": "edt_conf_enum_custom", "minimum": 10, "default": 80, "append": "edt_append_pixel", - "propertyOrder": 3 + "options": { + "hidden": true + }, + "required": true, + "propertyOrder": 8, + "comment": "The 'resolutions' settings are dynamically inserted into the WebUI under PropertyOrder '5'." }, "height": { "type": "integer", - "title": "edt_conf_fg_height_title", - "minimum": 10, - "default": 45, + "title": "edt_conf_enum_custom", "append": "edt_append_pixel", - "propertyOrder": 4 + "options": { + "hidden": true + }, + "required": true, + "propertyOrder": 9, + "comment": "The 'resolutions' settings are dynamically inserted into the WebUI under PropertyOrder '5'." }, - "frequency_Hz": { - "type": "integer", + "framerates": { + "type": "string", "title": "edt_conf_fg_frequency_Hz_title", + "propertyOrder": 10, + "required": false + }, + "fps": { + "type": "integer", + "title": "edt_conf_enum_custom", "minimum": 1, - "default": 10, - "append": "edt_append_hz", - "propertyOrder": 5 - }, - "cropLeft": { - "type": "integer", - "title": "edt_conf_v4l2_cropLeft_title", - "minimum": 0, - "default": 0, - "append": "edt_append_pixel", - "propertyOrder": 6 - }, - "cropRight": { - "type": "integer", - "title": "edt_conf_v4l2_cropRight_title", - "minimum": 0, - "default": 0, - "append": "edt_append_pixel", - "propertyOrder": 7 - }, - "cropTop": { - "type": "integer", - "title": "edt_conf_v4l2_cropTop_title", - "minimum": 0, - "default": 0, - "append": "edt_append_pixel", - "propertyOrder": 8 - }, - "cropBottom": { - "type": "integer", - "title": "edt_conf_v4l2_cropBottom_title", - "minimum": 0, - "default": 0, - "append": "edt_append_pixel", - "propertyOrder": 9 + "append": "fps", + "options": { + "hidden": true + }, + "required": true, + "propertyOrder": 11, + "comment": "The 'framerates' setting is dynamically inserted into the WebUI under PropertyOrder '10'." }, "pixelDecimation": { "type": "integer", @@ -82,9 +90,41 @@ "minimum": 1, "maximum": 30, "default": 8, - "propertyOrder": 10 + "required": true, + "propertyOrder": 12 + }, + "cropLeft": { + "type": "integer", + "title": "edt_conf_v4l2_cropLeft_title", + "minimum": 0, + "default": 0, + "append": "edt_append_pixel", + "propertyOrder": 13 + }, + "cropRight": { + "type": "integer", + "title": "edt_conf_v4l2_cropRight_title", + "minimum": 0, + "default": 0, + "append": "edt_append_pixel", + "propertyOrder": 14 + }, + "cropTop": { + "type": "integer", + "title": "edt_conf_v4l2_cropTop_title", + "minimum": 0, + "default": 0, + "append": "edt_append_pixel", + "propertyOrder": 15 + }, + "cropBottom": { + "type": "integer", + "title": "edt_conf_v4l2_cropBottom_title", + "minimum": 0, + "default": 0, + "append": "edt_append_pixel", + "propertyOrder": 16 } - }, "additionalProperties" : false } diff --git a/libsrc/leddevice/LedDevice.cpp b/libsrc/leddevice/LedDevice.cpp index 16a1d8da..2ab15bf0 100644 --- a/libsrc/leddevice/LedDevice.cpp +++ b/libsrc/leddevice/LedDevice.cpp @@ -265,12 +265,13 @@ bool LedDevice::switchOn() { if ( _isEnabled &&_isDeviceInitialised ) { - storeState(); - - if ( powerOn() ) + if ( storeState() ) { - _isOn = true; - rc = true; + if ( powerOn() ) + { + _isOn = true; + rc = true; + } } } } diff --git a/libsrc/leddevice/dev_net/LedDeviceAtmoOrb.cpp b/libsrc/leddevice/dev_net/LedDeviceAtmoOrb.cpp index e95f408d..b5bb2140 100644 --- a/libsrc/leddevice/dev_net/LedDeviceAtmoOrb.cpp +++ b/libsrc/leddevice/dev_net/LedDeviceAtmoOrb.cpp @@ -13,6 +13,8 @@ // Constants namespace { +const bool verbose = false; +const bool verbose3 = false; const QString MULTICAST_GROUP_DEFAULT_ADDRESS = "239.255.255.250"; const quint16 MULTICAST_GROUP_DEFAULT_PORT = 49692; @@ -272,13 +274,13 @@ void LedDeviceAtmoOrb::setColor(int orbId, const ColorRgb &color, int commandTyp void LedDeviceAtmoOrb::sendCommand(const QByteArray &bytes) { - //Debug ( _log, "command: [%s] -> %s:%u", QSTRING_CSTR( QString(bytes.toHex())), QSTRING_CSTR(_groupAddress.toString()), _multiCastGroupPort ); + DebugIf(verbose3, _log, "command: [%s] -> %s:%u", QSTRING_CSTR( QString(bytes.toHex())), QSTRING_CSTR(_groupAddress.toString()), _multiCastGroupPort ); _udpSocket->writeDatagram(bytes.data(), bytes.size(), _groupAddress, _multiCastGroupPort); } QJsonObject LedDeviceAtmoOrb::discover(const QJsonObject& params) { - //Debug(_log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData()); + DebugIf(verbose, _log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData()); QJsonObject devicesDiscovered; devicesDiscovered.insert("ledDeviceType", _activeDeviceType ); @@ -353,14 +355,14 @@ QJsonObject LedDeviceAtmoOrb::discover(const QJsonObject& params) } devicesDiscovered.insert("devices", deviceList); - Debug(_log, "devicesDiscovered: [%s]", QString(QJsonDocument(devicesDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData() ); + DebugIf(verbose, _log, "devicesDiscovered: [%s]", QString(QJsonDocument(devicesDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData() ); return devicesDiscovered; } void LedDeviceAtmoOrb::identify(const QJsonObject& params) { - //Debug(_log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData()); + DebugIf(verbose, _log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData()); int orbId = 0; if ( params["id"].isString() ) diff --git a/libsrc/leddevice/dev_net/LedDeviceCololight.cpp b/libsrc/leddevice/dev_net/LedDeviceCololight.cpp index a6bac06f..8905a7a5 100644 --- a/libsrc/leddevice/dev_net/LedDeviceCololight.cpp +++ b/libsrc/leddevice/dev_net/LedDeviceCololight.cpp @@ -1,50 +1,50 @@ #include "LedDeviceCololight.h" #include +#include #include #include #include -#include #include // Constants namespace { -const bool verbose = false; -const bool verbose3 = false; + const bool verbose = false; + const bool verbose3 = false; -// Configuration settings + // Configuration settings -const char CONFIG_HW_LED_COUNT[] = "hardwareLedCount"; + const char CONFIG_HW_LED_COUNT[] = "hardwareLedCount"; -const int COLOLIGHT_BEADS_PER_MODULE = 19; + const int COLOLIGHT_BEADS_PER_MODULE = 19; -// Cololight discovery service + // Cololight discovery service -const int API_DEFAULT_PORT = 8900; + const int API_DEFAULT_PORT = 8900; -const char DISCOVERY_ADDRESS[] = "255.255.255.255"; -const quint16 DISCOVERY_PORT = 12345; -const char DISCOVERY_MESSAGE[] = "Z-SEARCH * \r\n"; -constexpr std::chrono::milliseconds DEFAULT_DISCOVERY_TIMEOUT{ 2000 }; -constexpr std::chrono::milliseconds DEFAULT_READ_TIMEOUT{ 1000 }; -constexpr std::chrono::milliseconds DEFAULT_IDENTIFY_TIME{ 2000 }; + const char DISCOVERY_ADDRESS[] = "255.255.255.255"; + const quint16 DISCOVERY_PORT = 12345; + const char DISCOVERY_MESSAGE[] = "Z-SEARCH * \r\n"; + constexpr std::chrono::milliseconds DEFAULT_DISCOVERY_TIMEOUT{ 2000 }; + constexpr std::chrono::milliseconds DEFAULT_READ_TIMEOUT{ 1000 }; + constexpr std::chrono::milliseconds DEFAULT_IDENTIFY_TIME{ 2000 }; -const char COLOLIGHT_MODEL[] = "mod"; -const char COLOLIGHT_MODEL_TYPE[] = "subkey"; -const char COLOLIGHT_MAC[] = "sn"; -const char COLOLIGHT_NAME[] = "name"; + const char COLOLIGHT_MODEL[] = "mod"; + const char COLOLIGHT_MODEL_TYPE[] = "subkey"; + const char COLOLIGHT_MAC[] = "sn"; + const char COLOLIGHT_NAME[] = "name"; -const char COLOLIGHT_MODEL_IDENTIFIER[] = "OD_WE_QUAN"; + const char COLOLIGHT_MODEL_IDENTIFIER[] = "OD_WE_QUAN"; } //End of constants LedDeviceCololight::LedDeviceCololight(const QJsonObject& deviceConfig) : ProviderUdp(deviceConfig) - , _modelType(-1) - , _ledLayoutType(-1) - , _ledBeadCount(0) - , _distance(0) - , _sequenceNumber(1) + , _modelType(-1) + , _ledLayoutType(-1) + , _ledBeadCount(0) + , _distance(0) + , _sequenceNumber(1) { _packetFixPart.append(reinterpret_cast(PACKET_HEADER), sizeof(PACKET_HEADER)); _packetFixPart.append(reinterpret_cast(PACKET_SECU), sizeof(PACKET_SECU)); @@ -186,7 +186,7 @@ bool LedDeviceCololight::getInfo() QByteArray response; if (readResponse(response)) { - DebugIf(verbose, _log, "#[0x%x], Data returned: [%s]", _sequenceNumber, QSTRING_CSTR(toHex(response))); + DebugIf(verbose,_log, "#[0x%x], Data returned: [%s]", _sequenceNumber, QSTRING_CSTR(toHex(response))); quint16 ledNum = qFromBigEndian(response.data() + 1); @@ -267,7 +267,7 @@ bool LedDeviceCololight::setColor(const uint32_t color) QByteArray response; if (readResponse(response)) { - DebugIf(verbose, _log, "#[0x%x], Data returned: [%s]", _sequenceNumber, QSTRING_CSTR(toHex(response))); + DebugIf(verbose,_log, "#[0x%x], Data returned: [%s]", _sequenceNumber, QSTRING_CSTR(toHex(response))); isCmdOK = true; } } @@ -303,7 +303,7 @@ bool LedDeviceCololight::setState(bool isOn) QByteArray response; if (readResponse(response)) { - DebugIf(verbose, _log, "#[0x%x], Data returned: [%s]", _sequenceNumber, QSTRING_CSTR(toHex(response))); + DebugIf(verbose,_log, "#[0x%x], Data returned: [%s]", _sequenceNumber, QSTRING_CSTR(toHex(response))); isCmdOK = true; } } @@ -327,7 +327,7 @@ bool LedDeviceCololight::setStateDirect(bool isOn) QByteArray response; if (readResponse(response)) { - DebugIf(verbose, _log, "#[0x%x], Data returned: [%s]", _sequenceNumber, QSTRING_CSTR(toHex(response))); + DebugIf(verbose,_log, "#[0x%x], Data returned: [%s]", _sequenceNumber, QSTRING_CSTR(toHex(response))); isCmdOK = true; } } @@ -381,7 +381,7 @@ bool LedDeviceCololight::setTL1CommandMode(bool isOn) QByteArray response; if (readResponse(response)) { - DebugIf(verbose, _log, "#[0x%x], Data returned: [%s]", _sequenceNumber, QSTRING_CSTR(toHex(response))); + DebugIf(verbose,_log, "#[0x%x], Data returned: [%s]", _sequenceNumber, QSTRING_CSTR(toHex(response))); isCmdOK = true; } } @@ -498,7 +498,7 @@ bool LedDeviceCololight::readResponse(QByteArray& response) } else { - DebugIf(verbose, _log, "No additional data returned"); + DebugIf(verbose,_log, "No additional data returned"); } } isRequestOK = true; @@ -605,7 +605,7 @@ QJsonArray LedDeviceCololight::discover() { QJsonObject obj; - QString ipAddress = i.key(); + const QString& ipAddress = i.key(); obj.insert("ip", ipAddress); obj.insert("model", i.value().value(COLOLIGHT_MODEL)); obj.insert("type", i.value().value(COLOLIGHT_MODEL_TYPE)); @@ -661,26 +661,27 @@ QJsonObject LedDeviceCololight::discover(const QJsonObject& /*params*/) devicesDiscovered.insert("discoveryMethod", discoveryMethod); devicesDiscovered.insert("devices", deviceList); - //Debug(_log, "devicesDiscovered: [%s]", QString(QJsonDocument(devicesDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData()); + DebugIf(verbose,_log, "devicesDiscovered: [%s]", QString(QJsonDocument(devicesDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData()); return devicesDiscovered; } QJsonObject LedDeviceCololight::getProperties(const QJsonObject& params) { - DebugIf(verbose, _log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData()); + DebugIf(verbose,_log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData()); QJsonObject properties; - QString apiHostname = params["host"].toString(""); + QString hostName = params["host"].toString(""); quint16 apiPort = static_cast(params["port"].toInt(API_DEFAULT_PORT)); QJsonObject propertiesDetails; - if (!apiHostname.isEmpty()) + if (!hostName.isEmpty()) { QJsonObject deviceConfig; - deviceConfig.insert("host", apiHostname); + deviceConfig.insert("host", hostName); deviceConfig.insert("port", apiPort); + if (ProviderUdp::init(deviceConfig)) { if (getInfo()) @@ -708,23 +709,23 @@ QJsonObject LedDeviceCololight::getProperties(const QJsonObject& params) properties.insert("properties", propertiesDetails); - DebugIf(verbose, _log, "properties: [%s]", QString(QJsonDocument(properties).toJson(QJsonDocument::Compact)).toUtf8().constData()); + DebugIf(verbose,_log, "properties: [%s]", QString(QJsonDocument(properties).toJson(QJsonDocument::Compact)).toUtf8().constData()); return properties; } void LedDeviceCololight::identify(const QJsonObject& params) { - DebugIf(verbose, _log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData()); + DebugIf(verbose,_log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData()); - QString apiHostname = params["host"].toString(""); + QString hostName = params["host"].toString(""); quint16 apiPort = static_cast(params["port"].toInt(API_DEFAULT_PORT)); - if (!apiHostname.isEmpty()) + if (!hostName.isEmpty()) { QJsonObject deviceConfig; - deviceConfig.insert("host", apiHostname); + deviceConfig.insert("host", hostName); deviceConfig.insert("port", apiPort); if (ProviderUdp::init(deviceConfig)) { @@ -732,9 +733,7 @@ void LedDeviceCololight::identify(const QJsonObject& params) { setEffect(THE_CIRCUS); - QEventLoop loop; - QTimer::singleShot(DEFAULT_IDENTIFY_TIME.count(), &loop, &QEventLoop::quit); - loop.exec(); + wait(DEFAULT_IDENTIFY_TIME); setColor(ColorRgb::BLACK); } diff --git a/libsrc/leddevice/dev_net/LedDeviceNanoleaf.cpp b/libsrc/leddevice/dev_net/LedDeviceNanoleaf.cpp index f76c29b8..fdc50dcb 100644 --- a/libsrc/leddevice/dev_net/LedDeviceNanoleaf.cpp +++ b/libsrc/leddevice/dev_net/LedDeviceNanoleaf.cpp @@ -5,7 +5,6 @@ #include // Qt includes -#include #include #include @@ -78,12 +77,16 @@ const char SSDP_LIGHTPANELS[] = "nanoleaf_aurora:light"; // Nanoleaf Panel Shapetypes enum SHAPETYPES { - TRIANGLE, - RHYTM, - SQUARE, - CONTROL_SQUARE_PRIMARY, - CONTROL_SQUARE_PASSIVE, - POWER_SUPPLY, + TRIANGLE = 0, + RHYTM = 1, + SQUARE = 2, + CONTROL_SQUARE_PRIMARY = 3, + CONTROL_SQUARE_PASSIVE = 4, + POWER_SUPPLY= 5, + HEXAGON_SHAPES = 7, + TRIANGE_SHAPES = 8, + MINI_TRIANGE_SHAPES = 8, + SHAPES_CONTROLLER = 12 }; // Nanoleaf external control versions @@ -100,8 +103,8 @@ LedDeviceNanoleaf::LedDeviceNanoleaf(const QJsonObject& deviceConfig) , _leftRight(true) , _startPos(0) , _endPos(0) - , _extControlVersion(EXTCTRLVER_V2), - _panelLedCount(0) + , _extControlVersion(EXTCTRLVER_V2) + , _panelLedCount(0) { } @@ -127,7 +130,7 @@ bool LedDeviceNanoleaf::init(const QJsonObject& deviceConfig) Info(_log, "Device Nanoleaf does not require rewrites. Refresh time is ignored."); } - DebugIf(verbose, _log, "deviceConfig: [%s]", QString(QJsonDocument(_devConfig).toJson(QJsonDocument::Compact)).toUtf8().constData()); + DebugIf(verbose,_log, "deviceConfig: [%s]", QString(QJsonDocument(_devConfig).toJson(QJsonDocument::Compact)).toUtf8().constData()); bool isInitOK = false; @@ -164,29 +167,29 @@ bool LedDeviceNanoleaf::init(const QJsonObject& deviceConfig) // TODO: Allow to handle port dynamically //Set hostname as per configuration and_defaultHost default port - _hostname = deviceConfig[CONFIG_ADDRESS].toString(); + _hostName = deviceConfig[CONFIG_ADDRESS].toString(); _apiPort = API_DEFAULT_PORT; _authToken = deviceConfig[CONFIG_AUTH_TOKEN].toString(); //If host not configured the init failed - if (_hostname.isEmpty()) + if (_hostName.isEmpty()) { this->setInError("No target hostname nor IP defined"); isInitOK = false; } else { - if (initRestAPI(_hostname, _apiPort, _authToken)) + if (initRestAPI(_hostName, _apiPort, _authToken)) { // Read LedDevice configuration and validate against device configuration if (initLedsConfiguration()) { // Set UDP streaming host and port - _devConfig["host"] = _hostname; + _devConfig["host"] = _hostName; _devConfig["port"] = STREAM_CONTROL_DEFAULT_PORT; isInitOK = ProviderUdp::init(_devConfig); - Debug(_log, "Hostname/IP : %s", QSTRING_CSTR(_hostname)); + Debug(_log, "Hostname/IP : %s", QSTRING_CSTR(_hostName)); Debug(_log, "Port : %d", _port); } } @@ -206,7 +209,8 @@ bool LedDeviceNanoleaf::initLedsConfiguration() httpResponse response = _restApi->get(); if (response.error()) { - this->setInError(response.getErrorReason()); + QString errorReason = QString("Getting device details failed with error: '%1'").arg(response.getErrorReason()); + this->setInError ( errorReason ); isInitOK = false; } else @@ -243,16 +247,16 @@ bool LedDeviceNanoleaf::initLedsConfiguration() int panelshapeType = panelObj[PANEL_SHAPE_TYPE].toInt(); //int panelOrientation = panelObj[PANEL_ORIENTATION].toInt(); - DebugIf(verbose, _log, "Panel [%d] (%d,%d) - Type: [%d]", panelId, panelX, panelY, panelshapeType); + DebugIf(verbose,_log, "Panel [%d] (%d,%d) - Type: [%d]", panelId, panelX, panelY, panelshapeType); - // Skip Rhythm panels - if (panelshapeType != RHYTM) + // Skip Rhythm and Shapes controller panels + if (panelshapeType != RHYTM && panelshapeType != SHAPES_CONTROLLER) { panelMap[panelY][panelX] = panelId; } else { // Reset non support/required features - Info(_log, "Rhythm panel skipped."); + Info(_log, "Rhythm/Shape Controller panel skipped."); } } @@ -360,32 +364,31 @@ int LedDeviceNanoleaf::open() int retval = -1; _isDeviceReady = false; - QJsonDocument responseDoc = changeToExternalControlMode(); - // Resolve port for Light Panels - QJsonObject jsonStreamControllInfo = responseDoc.object(); - if (!jsonStreamControllInfo.isEmpty()) + QJsonDocument responseDoc; + if (changeToExternalControlMode(responseDoc)) { - //Set default streaming port - _port = static_cast(jsonStreamControllInfo[STREAM_CONTROL_PORT].toInt()); - } + // Resolve port for Light Panels + QJsonObject jsonStreamControllInfo = responseDoc.object(); + if (!jsonStreamControllInfo.isEmpty()) + { + //Set default streaming port + _port = static_cast(jsonStreamControllInfo[STREAM_CONTROL_PORT].toInt()); + } - if (ProviderUdp::open() == 0) - { - // Everything is OK, device is ready - _isDeviceReady = true; - retval = 0; + if (ProviderUdp::open() == 0) + { + // Everything is OK, device is ready + _isDeviceReady = true; + retval = 0; + } } return retval; } -QJsonObject LedDeviceNanoleaf::discover(const QJsonObject& /*params*/) +QJsonArray LedDeviceNanoleaf::discover() { - QJsonObject devicesDiscovered; - devicesDiscovered.insert("ledDeviceType", _activeDeviceType); - QJsonArray deviceList; - // Discover Nanoleaf Devices SSDPDiscover discover; // Search for Canvas and Light-Panels @@ -399,26 +402,41 @@ QJsonObject LedDeviceNanoleaf::discover(const QJsonObject& /*params*/) deviceList = discover.getServicesDiscoveredJson(); } + return deviceList; +} + +QJsonObject LedDeviceNanoleaf::discover(const QJsonObject& /*params*/) +{ + QJsonObject devicesDiscovered; + devicesDiscovered.insert("ledDeviceType", _activeDeviceType); + + QString discoveryMethod("ssdp"); + QJsonArray deviceList; + + deviceList = discover(); + + devicesDiscovered.insert("discoveryMethod", discoveryMethod); devicesDiscovered.insert("devices", deviceList); - Debug(_log, "devicesDiscovered: [%s]", QString(QJsonDocument(devicesDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData()); + DebugIf(verbose,_log, "devicesDiscovered: [%s]", QString(QJsonDocument(devicesDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData()); return devicesDiscovered; } QJsonObject LedDeviceNanoleaf::getProperties(const QJsonObject& params) { - Debug(_log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData()); + DebugIf(verbose,_log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData()); QJsonObject properties; // Get Nanoleaf device properties - QString host = params["host"].toString(""); - if (!host.isEmpty()) + QString hostName = params["host"].toString(""); + + if (!hostName.isEmpty()) { QString authToken = params["token"].toString(""); QString filter = params["filter"].toString(""); // Resolve hostname and port (or use default API port) - QStringList addressparts = QStringUtils::split(host, ":", QStringUtils::SplitBehavior::SkipEmptyParts); + QStringList addressparts = QStringUtils::split(hostName, ":", QStringUtils::SplitBehavior::SkipEmptyParts); QString apiHost = addressparts[0]; int apiPort; @@ -443,22 +461,22 @@ QJsonObject LedDeviceNanoleaf::getProperties(const QJsonObject& params) properties.insert("properties", response.getBody().object()); - Debug(_log, "properties: [%s]", QString(QJsonDocument(properties).toJson(QJsonDocument::Compact)).toUtf8().constData()); + DebugIf(verbose,_log, "properties: [%s]", QString(QJsonDocument(properties).toJson(QJsonDocument::Compact)).toUtf8().constData()); } return properties; } void LedDeviceNanoleaf::identify(const QJsonObject& params) { - Debug(_log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData()); + DebugIf(verbose,_log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData()); - QString host = params["host"].toString(""); - if (!host.isEmpty()) + QString hostName = params["host"].toString(""); + if (!hostName.isEmpty()) { QString authToken = params["token"].toString(""); // Resolve hostname and port (or use default API port) - QStringList addressparts = QStringUtils::split(host, ":", QStringUtils::SplitBehavior::SkipEmptyParts); + QStringList addressparts = QStringUtils::split(hostName, ":", QStringUtils::SplitBehavior::SkipEmptyParts); QString apiHost = addressparts[0]; int apiPort; @@ -485,26 +503,41 @@ void LedDeviceNanoleaf::identify(const QJsonObject& params) bool LedDeviceNanoleaf::powerOn() { + bool on = false; if (_isDeviceReady) { - changeToExternalControlMode(); - - //Power-on Nanoleaf device - _restApi->setPath(API_STATE); - _restApi->put(getOnOffRequest(true)); + if (changeToExternalControlMode()) + { + //Power-on Nanoleaf device + _restApi->setPath(API_STATE); + httpResponse response = _restApi->put(getOnOffRequest(true)); + if (response.error()) + { + QString errorReason = QString("Power-on request failed with error: '%1'").arg(response.getErrorReason()); + this->setInError ( errorReason ); + on = false; + } + } } - return true; + return on; } bool LedDeviceNanoleaf::powerOff() { + bool off = true; if (_isDeviceReady) { //Power-off the Nanoleaf device physically _restApi->setPath(API_STATE); - _restApi->put(getOnOffRequest(false)); + httpResponse response = _restApi->put(getOnOffRequest(false)); + if (response.error()) + { + QString errorReason = QString("Power-off request failed with error: '%1'").arg(response.getErrorReason()); + this->setInError ( errorReason ); + off = false; + } } - return true; + return off; } QString LedDeviceNanoleaf::getOnOffRequest(bool isOn) const @@ -513,16 +546,33 @@ QString LedDeviceNanoleaf::getOnOffRequest(bool isOn) const return QString("{\"%1\":{\"%2\":%3}}").arg(STATE_ON, STATE_ONOFF_VALUE, state); } -QJsonDocument LedDeviceNanoleaf::changeToExternalControlMode() +bool LedDeviceNanoleaf::changeToExternalControlMode() { + QJsonDocument resp; + return changeToExternalControlMode(resp); +} + +bool LedDeviceNanoleaf::changeToExternalControlMode(QJsonDocument& resp) +{ + bool success = false; Debug(_log, "Set Nanoleaf to External Control (UDP) streaming mode"); _extControlVersion = EXTCTRLVER_V2; //Enable UDP Mode v2 _restApi->setPath(API_EFFECT); httpResponse response = _restApi->put(API_EXT_MODE_STRING_V2); + if (response.error()) + { + QString errorReason = QString("Change to external control mode failed with error: '%1'").arg(response.getErrorReason()); + this->setInError ( errorReason ); + } + else + { + resp = response.getBody(); + success = true; + } - return response.getBody(); + return success; } int LedDeviceNanoleaf::write(const std::vector& ledValues) diff --git a/libsrc/leddevice/dev_net/LedDeviceNanoleaf.h b/libsrc/leddevice/dev_net/LedDeviceNanoleaf.h index f6d53c08..ab736165 100644 --- a/libsrc/leddevice/dev_net/LedDeviceNanoleaf.h +++ b/libsrc/leddevice/dev_net/LedDeviceNanoleaf.h @@ -149,9 +149,15 @@ private: /// /// @brief Change Nanoleaf device to External Control (UDP) mode /// - /// @return Response from device - ///@brief - QJsonDocument changeToExternalControlMode(); + /// @return True, if success + bool changeToExternalControlMode(); + /// + /// @brief Change Nanoleaf device to External Control (UDP) mode + /// + /// @param[out] response from device + /// + /// @return True, if success + bool changeToExternalControlMode(QJsonDocument& resp); /// /// @brief Get command to power Nanoleaf device on or off @@ -161,10 +167,18 @@ private: /// QString getOnOffRequest(bool isOn) const; + /// + /// @brief Discover Nanoleaf devices available (for configuration). + /// Nanoleaf specific ssdp discovery + /// + /// @return A JSON structure holding a list of devices found + /// + QJsonArray discover(); + ///REST-API wrapper ProviderRestApi* _restApi; - QString _hostname; + QString _hostName; int _apiPort; QString _authToken; diff --git a/libsrc/leddevice/dev_net/LedDevicePhilipsHue.cpp b/libsrc/leddevice/dev_net/LedDevicePhilipsHue.cpp index 88910f19..46e2c4b7 100644 --- a/libsrc/leddevice/dev_net/LedDevicePhilipsHue.cpp +++ b/libsrc/leddevice/dev_net/LedDevicePhilipsHue.cpp @@ -115,7 +115,7 @@ CiColor CiColor::rgbToCiColor(double red, double green, double blue, const CiCol double cy; double bri; - if(red + green + blue > 0) + if( (red + green + blue) > 0) { // Apply gamma correction. double r = (red > 0.04045) ? pow((red + 0.055) / (1.0 + 0.055), 2.4) : (red / 12.92); @@ -157,7 +157,7 @@ CiColor CiColor::rgbToCiColor(double red, double green, double blue, const CiCol CiColor xy = { cx, cy, bri }; - if(red + green + blue > 0) + if( (red + green + blue) > 0) { // Check if the given XY value is within the color reach of our lamps. if (!isPointInLampsReach(xy, colorSpace)) @@ -387,8 +387,11 @@ void LedDevicePhilipsHueBridge::log(const char* msg, const char* type, ...) cons vsnprintf(val, max_val_length, type, args); va_end(args); std::string s = msg; - int max = 30; - s.append(max - s.length(), ' '); + size_t max = 30; + if (max > s.length()) + { + s.append(max - s.length(), ' '); + } Debug( _log, "%s: %s", s.c_str(), val ); } @@ -859,7 +862,7 @@ bool LedDevicePhilipsHue::init(const QJsonObject &deviceConfig) if( _groupId == 0 ) { - log( "Group-ID is invalid", "%d", _groupId ); + Error(_log, "Disabling Entertainment API as Group-ID is invalid" ); _useHueEntertainmentAPI = false; } } @@ -888,7 +891,7 @@ bool LedDevicePhilipsHue::setLights() if( _useHueEntertainmentAPI ) { _useHueEntertainmentAPI = false; - Debug(_log, "Group-ID [%u] is not usable - Entertainment API usage was disabled!", _groupId ); + Error(_log, "Group-ID [%u] is not usable - Entertainment API usage was disabled!", _groupId ); } lArray = _devConfig[ CONFIG_LIGHTIDS ].toArray(); } @@ -1018,7 +1021,7 @@ bool LedDevicePhilipsHue::updateLights(const QMap &map) if( lightsCount == 0 ) { - Debug(_log, "No usable lights found!" ); + Error(_log, "No usable lights found!" ); isInitOK = false; } @@ -1073,18 +1076,18 @@ bool LedDevicePhilipsHue::openStream() if( isInitOK ) { - Info(_log, "Philips Hue Entertaiment API successful connected! Start Streaming." ); + Info(_log, "Philips Hue Entertainment API successful connected! Start Streaming." ); _allLightsBlack = true; noSignalDetection(); } else { - Error(_log, "Philips Hue Entertaiment API not connected!" ); + Error(_log, "Philips Hue Entertainment API not connected!" ); } } else { - Error(_log, "Philips Hue Entertaiment API could not initialisized!" ); + Error(_log, "Philips Hue Entertainment API could not be initialised!" ); } return isInitOK; @@ -1235,7 +1238,7 @@ QByteArray LedDevicePhilipsHue::prepareStreamData() const CiColor lightC = light.getColor(); quint64 R = lightC.x * 0xffff; quint64 G = lightC.y * 0xffff; - quint64 B = lightC.bri * 0xffff; + quint64 B = (lightC.x || lightC.y) ? lightC.bri * 0xffff : 0; unsigned int id = light.getId(); const uint8_t payload[] = { 0x00, 0x00, static_cast(id), @@ -1315,7 +1318,7 @@ bool LedDevicePhilipsHue::switchOff() stop_retry_left = 3; if (_useHueEntertainmentAPI) { - stopStream(); + stopStream(); } return LedDevicePhilipsHueBridge::switchOff(); @@ -1467,7 +1470,7 @@ void LedDevicePhilipsHue::setColor(PhilipsHueLight& light, CiColor& color) if( !_useHueEntertainmentAPI ) { const int bri = qRound(qMin(254.0, _brightnessFactor * qMax(1.0, color.bri * 254.0))); - QString stateCmd = QString("\"%1\":[%2,%3],\"%4\":%5").arg( API_XY_COORDINATES ).arg( color.x, 0, 'd', 4 ).arg( color.y, 0, 'd', 4 ).arg( API_BRIGHTNESS ).arg( bri ); + QString stateCmd = QString("{\"%1\":[%2,%3],\"%4\":%5}").arg( API_XY_COORDINATES ).arg( color.x, 0, 'd', 4 ).arg( color.y, 0, 'd', 4 ).arg( API_BRIGHTNESS ).arg( bri ); setLightState( light.getId(), stateCmd ); } else diff --git a/libsrc/leddevice/dev_net/LedDeviceTpm2net.cpp b/libsrc/leddevice/dev_net/LedDeviceTpm2net.cpp index 99d6b701..6bff67f7 100644 --- a/libsrc/leddevice/dev_net/LedDeviceTpm2net.cpp +++ b/libsrc/leddevice/dev_net/LedDeviceTpm2net.cpp @@ -23,7 +23,7 @@ bool LedDeviceTpm2net::init(const QJsonObject &deviceConfig) { _tpm2_max = deviceConfig["max-packet"].toInt(170); _tpm2ByteCount = 3 * _ledCount; - _tpm2TotalPackets = 1 + _tpm2ByteCount / _tpm2_max; + _tpm2TotalPackets = (_tpm2ByteCount / _tpm2_max) + ((_tpm2ByteCount % _tpm2_max) != 0); isInitOK = true; } diff --git a/libsrc/leddevice/dev_net/LedDeviceWled.cpp b/libsrc/leddevice/dev_net/LedDeviceWled.cpp index 80c24680..1f5511cb 100644 --- a/libsrc/leddevice/dev_net/LedDeviceWled.cpp +++ b/libsrc/leddevice/dev_net/LedDeviceWled.cpp @@ -1,14 +1,20 @@ // Local-Hyperion includes #include "LedDeviceWled.h" -#include #include +#include +#include + +#include // Constants namespace { +const bool verbose = false; + // Configuration settings const char CONFIG_ADDRESS[] = "host"; +const char CONFIG_RESTORE_STATE[] = "restoreOriginalState"; // UDP elements const quint16 STREAM_DEFAULT_PORT = 19446; @@ -24,12 +30,11 @@ const char API_PATH_STATE[] = "state"; const char STATE_ON[] = "on"; const char STATE_VALUE_TRUE[] = "true"; const char STATE_VALUE_FALSE[] = "false"; +const char STATE_LIVE[] = "live"; -// WLED ssdp services -// TODO: WLED - Update ssdp discovery parameters when available -const char SSDP_ID[] = "ssdp:all"; -const char SSDP_FILTER[] = "(.*)"; -const char SSDP_FILTER_HEADER[] = "ST"; +const int BRI_MAX = 255; + +constexpr std::chrono::milliseconds DEFAULT_IDENTIFY_TIME{ 2000 }; } //End of constants @@ -53,7 +58,6 @@ LedDevice* LedDeviceWled::construct(const QJsonObject &deviceConfig) bool LedDeviceWled::init(const QJsonObject &deviceConfig) { - Debug(_log, ""); bool isInitOK = false; // Initialise LedDevice sub-class, ProviderUdp::init will be executed later, if connectivity is defined @@ -66,18 +70,21 @@ bool LedDeviceWled::init(const QJsonObject &deviceConfig) Debug(_log, "ColorOrder : %s", QSTRING_CSTR( this->getColorOrder() )); Debug(_log, "LatchTime : %d", this->getLatchTime()); + _isRestoreOrigState = _devConfig[CONFIG_RESTORE_STATE].toBool(false); + Debug(_log, "RestoreOrigState : %d", _isRestoreOrigState); + //Set hostname as per configuration - QString address = deviceConfig[ CONFIG_ADDRESS ].toString(); + QString hostName = deviceConfig[ CONFIG_ADDRESS ].toString(); //If host not configured the init fails - if ( address.isEmpty() ) + if ( hostName.isEmpty() ) { this->setInError("No target hostname nor IP defined"); return false; } else { - QStringList addressparts = QStringUtils::split(address,":", QStringUtils::SplitBehavior::SkipEmptyParts); + QStringList addressparts = QStringUtils::split(hostName,":", QStringUtils::SplitBehavior::SkipEmptyParts); _hostname = addressparts[0]; if ( addressparts.size() > 1 ) { @@ -100,13 +107,11 @@ bool LedDeviceWled::init(const QJsonObject &deviceConfig) } } } - Debug(_log, "[%d]", isInitOK); return isInitOK; } bool LedDeviceWled::initRestAPI(const QString &hostname, int port) { - Debug(_log, ""); bool isInitOK = false; if ( _restApi == nullptr ) @@ -116,38 +121,68 @@ bool LedDeviceWled::initRestAPI(const QString &hostname, int port) isInitOK = true; } - - Debug(_log, "[%d]", isInitOK); return isInitOK; } QString LedDeviceWled::getOnOffRequest(bool isOn) const { QString state = isOn ? STATE_VALUE_TRUE : STATE_VALUE_FALSE; - return QString( "{\"%1\":%2}" ).arg( STATE_ON, state); + return QString( "\"%1\":%2,\"%3\":%4" ).arg( STATE_ON, state).arg( STATE_LIVE, state); } +QString LedDeviceWled::getBrightnessRequest(int bri) const +{ + return QString( "\"bri\":%1" ).arg(bri); +} + +QString LedDeviceWled::getEffectRequest(int effect, int speed) const +{ + return QString( "\"seg\":{\"fx\":%1,\"sx\":%2}" ).arg(effect).arg(speed); +} + +QString LedDeviceWled::getLorRequest(int lor) const +{ + return QString( "\"lor\":%1" ).arg(lor); +} + +bool LedDeviceWled::sendStateUpdateRequest(const QString &request) +{ + bool rc = true; + + _restApi->setPath(API_PATH_STATE); + + httpResponse response1 = _restApi->put(QString("{%1}").arg(request)); + if ( response1.error() ) + { + rc = false; + } + return rc; +} bool LedDeviceWled::powerOn() { - Debug(_log, ""); - bool on = true; + bool on = false; if ( _isDeviceReady) { //Power-on WLED device _restApi->setPath(API_PATH_STATE); - httpResponse response = _restApi->put(getOnOffRequest(true)); + + httpResponse response = _restApi->put(QString("{%1,%2}").arg(getOnOffRequest(true)).arg(getBrightnessRequest(BRI_MAX))); if ( response.error() ) { - this->setInError ( response.getErrorReason() ); + QString errorReason = QString("Power-on request failed with error: '%1'").arg(response.getErrorReason()); + this->setInError ( errorReason ); on = false; } + else + { + on = true; + } } return on; } bool LedDeviceWled::powerOff() { - Debug(_log, ""); bool off = true; if ( _isDeviceReady) { @@ -156,53 +191,89 @@ bool LedDeviceWled::powerOff() //Power-off the WLED device physically _restApi->setPath(API_PATH_STATE); - httpResponse response = _restApi->put(getOnOffRequest(false)); + httpResponse response = _restApi->put(QString("{%1}").arg(getOnOffRequest(false))); if ( response.error() ) { - this->setInError ( response.getErrorReason() ); + QString errorReason = QString("Power-off request failed with error: '%1'").arg(response.getErrorReason()); + this->setInError ( errorReason ); off = false; } } return off; } +bool LedDeviceWled::storeState() +{ + bool rc = true; + + if ( _isRestoreOrigState ) + { + _restApi->setPath(API_PATH_STATE); + + httpResponse response = _restApi->get(); + if ( response.error() ) + { + QString errorReason = QString("Storing device state failed with error: '%1'").arg(response.getErrorReason()); + setInError(errorReason); + rc = false; + } + else + { + _originalStateProperties = response.getBody().object(); + DebugIf(verbose, _log, "state: [%s]", QString(QJsonDocument(_originalStateProperties).toJson(QJsonDocument::Compact)).toUtf8().constData() ); + } + } + + return rc; +} + +bool LedDeviceWled::restoreState() +{ + bool rc = true; + + if ( _isRestoreOrigState ) + { + //powerOff(); + _restApi->setPath(API_PATH_STATE); + + _originalStateProperties[STATE_LIVE] = false; + + httpResponse response = _restApi->put(QString(QJsonDocument(_originalStateProperties).toJson(QJsonDocument::Compact)).toUtf8().constData()); + + if ( response.error() ) + { + Warning (_log, "%s restoring state failed with error: '%s'", QSTRING_CSTR(_activeDeviceType), QSTRING_CSTR(response.getErrorReason())); + } + } + + return rc; +} + QJsonObject LedDeviceWled::discover(const QJsonObject& /*params*/) { QJsonObject devicesDiscovered; devicesDiscovered.insert("ledDeviceType", _activeDeviceType ); QJsonArray deviceList; - - // Discover WLED Devices - SSDPDiscover discover; - discover.skipDuplicateKeys(true); - discover.setSearchFilter(SSDP_FILTER, SSDP_FILTER_HEADER); - QString searchTarget = SSDP_ID; - - if ( discover.discoverServices(searchTarget) > 0 ) - { - deviceList = discover.getServicesDiscoveredJson(); - } - devicesDiscovered.insert("devices", deviceList); - Debug(_log, "devicesDiscovered: [%s]", QString(QJsonDocument(devicesDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData() ); + DebugIf(verbose, _log, "devicesDiscovered: [%s]", QString(QJsonDocument(devicesDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData() ); return devicesDiscovered; } QJsonObject LedDeviceWled::getProperties(const QJsonObject& params) { - Debug(_log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData() ); + DebugIf(verbose, _log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData() ); QJsonObject properties; - // Get Nanoleaf device properties - QString host = params["host"].toString(""); - if ( !host.isEmpty() ) + QString hostName = params["host"].toString(""); + + if ( !hostName.isEmpty() ) { QString filter = params["filter"].toString(""); // Resolve hostname and port (or use default API port) - QStringList addressparts = QStringUtils::split(host,":", QStringUtils::SplitBehavior::SkipEmptyParts); + QStringList addressparts = QStringUtils::split(hostName,":", QStringUtils::SplitBehavior::SkipEmptyParts); QString apiHost = addressparts[0]; int apiPort; @@ -226,49 +297,45 @@ QJsonObject LedDeviceWled::getProperties(const QJsonObject& params) properties.insert("properties", response.getBody().object()); - Debug(_log, "properties: [%s]", QString(QJsonDocument(properties).toJson(QJsonDocument::Compact)).toUtf8().constData() ); + DebugIf(verbose, _log, "properties: [%s]", QString(QJsonDocument(properties).toJson(QJsonDocument::Compact)).toUtf8().constData() ); } return properties; } -void LedDeviceWled::identify(const QJsonObject& /*params*/) +void LedDeviceWled::identify(const QJsonObject& params) { -#if 0 - Debug(_log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData()); + DebugIf(verbose, _log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData()); - QString host = params["host"].toString(""); - if ( !host.isEmpty() ) + QString hostName = params["host"].toString(""); + + if ( !hostName.isEmpty() ) { // Resolve hostname and port (or use default API port) - QStringList addressparts = QStringUtils::split(host,":", QStringUtils::SplitBehavior::SkipEmptyParts); + QStringList addressparts = QStringUtils::split(hostName,":", QStringUtils::SplitBehavior::SkipEmptyParts); QString apiHost = addressparts[0]; int apiPort; if ( addressparts.size() > 1) + { apiPort = addressparts[1].toInt(); + } else + { apiPort = API_DEFAULT_PORT; + } - // TODO: WLED::identify - Replace with valid identification code + initRestAPI(apiHost, apiPort); - // initRestAPI(apiHost, apiPort); + _isRestoreOrigState = true; + storeState(); - // QString resource = QString("%1/%2/%3").arg( API_LIGHTS ).arg( lightId ).arg( API_STATE); - // _restApi->setPath(resource); + QString request = getOnOffRequest(true) + "," + getLorRequest(1) + "," + getEffectRequest(25); + sendStateUpdateRequest(request); - // QString stateCmd; - // stateCmd += QString("\"%1\":%2,").arg( API_STATE_ON ).arg( API_STATE_VALUE_TRUE ); - // stateCmd += QString("\"%1\":\"%2\"").arg( "alert" ).arg( "select" ); - // stateCmd = "{" + stateCmd + "}"; + wait(DEFAULT_IDENTIFY_TIME); - // // Perform request - // httpResponse response = _restApi->put(stateCmd); - // if ( response.error() ) - // { - // Warning (_log, "%s identification failed with error: '%s'", QSTRING_CSTR(_activeDeviceType), QSTRING_CSTR(response.getErrorReason())); - // } + restoreState(); } -#endif } int LedDeviceWled::write(const std::vector &ledValues) diff --git a/libsrc/leddevice/dev_net/LedDeviceWled.h b/libsrc/leddevice/dev_net/LedDeviceWled.h index 114519cc..5871a44a 100644 --- a/libsrc/leddevice/dev_net/LedDeviceWled.h +++ b/libsrc/leddevice/dev_net/LedDeviceWled.h @@ -8,8 +8,6 @@ /// /// Implementation of a WLED-device -/// ... -/// /// class LedDeviceWled : public ProviderUdp { @@ -105,6 +103,25 @@ protected: /// bool powerOff() override; + /// + /// @brief Store the device's original state. + /// + /// Save the device's state before hyperion color streaming starts allowing to restore state during switchOff(). + /// + /// @return True if success + /// + bool storeState() override; + + /// + /// @brief Restore the device's original state. + /// + /// Restore the device's state as before hyperion color streaming started. + /// This includes the on/off state of the device. + /// + /// @return True, if success + /// + bool restoreState() override; + private: /// @@ -123,12 +140,20 @@ private: /// @return Command to switch device on/off /// QString getOnOffRequest (bool isOn ) const; + QString getBrightnessRequest (int bri ) const; + QString getEffectRequest(int effect, int speed=128) const; + QString getLorRequest(int lor) const; + + bool sendStateUpdateRequest(const QString &request); ///REST-API wrapper ProviderRestApi* _restApi; QString _hostname; int _apiPort; + + QJsonObject _originalStateProperties; + }; #endif // LEDDEVICEWLED_H diff --git a/libsrc/leddevice/dev_net/LedDeviceYeelight.cpp b/libsrc/leddevice/dev_net/LedDeviceYeelight.cpp index cca03b9b..3a14cb0b 100644 --- a/libsrc/leddevice/dev_net/LedDeviceYeelight.cpp +++ b/libsrc/leddevice/dev_net/LedDeviceYeelight.cpp @@ -234,12 +234,12 @@ int YeelightLight::writeCommand( const QJsonDocument &command, QJsonArray &resul if ( ! _tcpSocket->waitForBytesWritten(WRITE_TIMEOUT.count()) ) { QString errorReason = QString ("(%1) %2").arg(_tcpSocket->error()).arg( _tcpSocket->errorString()); - log ( 2, "Error:", "bytesWritten: [%ll], %s", bytesWritten, QSTRING_CSTR(errorReason)); + log ( 2, "Error:", "bytesWritten: [%d], %s", bytesWritten, QSTRING_CSTR(errorReason)); this->setInError ( errorReason ); } else { - log ( 3, "Success:", "Bytes written [%ll]", bytesWritten ); + log ( 3, "Success:", "Bytes written [%d]", bytesWritten ); // Avoid to overrun the Yeelight Command Quota qint64 elapsedTime = QDateTime::currentMSecsSinceEpoch() - _lastWriteTime; @@ -258,7 +258,7 @@ int YeelightLight::writeCommand( const QJsonDocument &command, QJsonArray &resul { do { - log ( 3, "Reading:", "Bytes available [%ll]", _tcpSocket->bytesAvailable() ); + log ( 3, "Reading:", "Bytes available [%d]", _tcpSocket->bytesAvailable() ); while ( _tcpSocket->canReadLine() ) { QByteArray response = _tcpSocket->readLine(); @@ -338,7 +338,7 @@ bool YeelightLight::streamCommand( const QJsonDocument &command ) { int error = _tcpStreamSocket->error(); QString errorReason = QString ("(%1) %2").arg(error).arg( _tcpStreamSocket->errorString()); - log ( 1, "Error:", "bytesWritten: [%ll], %s", bytesWritten, QSTRING_CSTR(errorReason)); + log ( 1, "Error:", "bytesWritten: [%d], %s", bytesWritten, QSTRING_CSTR(errorReason)); if ( error == QAbstractSocket::RemoteHostClosedError ) { @@ -353,7 +353,7 @@ bool YeelightLight::streamCommand( const QJsonDocument &command ) } else { - log ( 3, "Success:", "Bytes written [%ll]", bytesWritten ); + log ( 3, "Success:", "Bytes written [%d]", bytesWritten ); rc = true; } } @@ -956,7 +956,10 @@ void YeelightLight::log(int logLevel, const char* msg, const char* type, ...) va_end(args); std::string s = msg; uint max = 20; - s.append(max - s.length(), ' '); + if (max > s.length()) + { + s.append(max - s.length(), ' '); + } Debug( _log, "%d|%15.15s| %s: %s", logLevel, QSTRING_CSTR(_name), s.c_str(), val); } @@ -1076,12 +1079,12 @@ bool LedDeviceYeelight::init(const QJsonObject &deviceConfig) int configuredYeelightsCount = 0; for (const QJsonValueRef light : configuredYeelightLights) { - QString host = light.toObject().value("host").toString(); + QString hostName = light.toObject().value("host").toString(); int port = light.toObject().value("port").toInt(API_DEFAULT_PORT); - if ( !host.isEmpty() ) + if ( !hostName.isEmpty() ) { QString name = light.toObject().value("name").toString(); - Debug(_log, "Light [%u] - %s (%s:%d)", configuredYeelightsCount, QSTRING_CSTR(name), QSTRING_CSTR(host), port ); + Debug(_log, "Light [%u] - %s (%s:%d)", configuredYeelightsCount, QSTRING_CSTR(name), QSTRING_CSTR(hostName), port ); ++configuredYeelightsCount; } } @@ -1107,10 +1110,10 @@ bool LedDeviceYeelight::init(const QJsonObject &deviceConfig) _lightsAddressList.clear(); for (int j = 0; j < static_cast( configuredLedCount ); ++j) { - QString address = configuredYeelightLights[j].toObject().value("host").toString(); + QString hostName = configuredYeelightLights[j].toObject().value("host").toString(); int port = configuredYeelightLights[j].toObject().value("port").toInt(API_DEFAULT_PORT); - QStringList addressparts = QStringUtils::split(address,":", QStringUtils::SplitBehavior::SkipEmptyParts); + QStringList addressparts = QStringUtils::split(hostName,":", QStringUtils::SplitBehavior::SkipEmptyParts); QString apiHost = addressparts[0]; int apiPort = port; @@ -1347,14 +1350,10 @@ bool LedDeviceYeelight::restoreState() return rc; } -QJsonObject LedDeviceYeelight::discover(const QJsonObject& /*params*/) +QJsonArray LedDeviceYeelight::discover() { - QJsonObject devicesDiscovered; - devicesDiscovered.insert("ledDeviceType", _activeDeviceType ); - QJsonArray deviceList; - // Discover Yeelight Devices SSDPDiscover discover; discover.setPort(SSDP_PORT); discover.skipDuplicateKeys(true); @@ -1365,25 +1364,36 @@ QJsonObject LedDeviceYeelight::discover(const QJsonObject& /*params*/) { deviceList = discover.getServicesDiscoveredJson(); } + return deviceList; +} + +QJsonObject LedDeviceYeelight::discover(const QJsonObject& /*params*/) +{ + QJsonObject devicesDiscovered; + devicesDiscovered.insert("ledDeviceType", _activeDeviceType ); + + QString discoveryMethod("ssdp"); + QJsonArray deviceList; + deviceList = discover(); devicesDiscovered.insert("devices", deviceList); - Debug(_log, "devicesDiscovered: [%s]", QString(QJsonDocument(devicesDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData() ); + + DebugIf(verbose,_log, "devicesDiscovered: [%s]", QString(QJsonDocument(devicesDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData() ); return devicesDiscovered; } QJsonObject LedDeviceYeelight::getProperties(const QJsonObject& params) { - Debug(_log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData() ); + DebugIf(verbose,_log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData() ); QJsonObject properties; - QString apiHostname = params["hostname"].toString(""); + QString hostName = params["hostname"].toString(""); quint16 apiPort = static_cast( params["port"].toInt(API_DEFAULT_PORT) ); - Debug (_log, "apiHost [%s], apiPort [%d]", QSTRING_CSTR(apiHostname), apiPort); - if ( !apiHostname.isEmpty() ) + if ( !hostName.isEmpty() ) { - YeelightLight yeelight(_log, apiHostname, apiPort); + YeelightLight yeelight(_log, hostName, apiPort); //yeelight.setDebuglevel(3); if ( yeelight.open() ) @@ -1399,15 +1409,15 @@ QJsonObject LedDeviceYeelight::getProperties(const QJsonObject& params) void LedDeviceYeelight::identify(const QJsonObject& params) { - Debug(_log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData() ); + DebugIf(verbose,_log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData() ); - QString apiHostname = params["hostname"].toString(""); + QString hostName = params["hostname"].toString(""); quint16 apiPort = static_cast( params["port"].toInt(API_DEFAULT_PORT) ); - Debug (_log, "apiHost [%s], apiPort [%d]", QSTRING_CSTR(apiHostname), apiPort); + Debug (_log, "apiHost [%s], apiPort [%d]", QSTRING_CSTR(hostName), apiPort); - if ( !apiHostname.isEmpty() ) + if ( !hostName.isEmpty() ) { - YeelightLight yeelight(_log, apiHostname, apiPort); + YeelightLight yeelight(_log, hostName, apiPort); //yeelight.setDebuglevel(3); if ( yeelight.open() ) diff --git a/libsrc/leddevice/dev_net/LedDeviceYeelight.h b/libsrc/leddevice/dev_net/LedDeviceYeelight.h index ff37c5ea..481ac91d 100644 --- a/libsrc/leddevice/dev_net/LedDeviceYeelight.h +++ b/libsrc/leddevice/dev_net/LedDeviceYeelight.h @@ -591,6 +591,14 @@ private: /// uint getLightsCount() const { return _lightsCount; } + /// + /// @brief Discover Yeelight devices available (for configuration). + /// Yeelight specific UDP Broadcast discovery + /// + /// @return A JSON structure holding a list of devices found + /// + QJsonArray discover(); + /// Array of the Yeelight addresses handled by the LED-device QVector _lightsAddressList; diff --git a/libsrc/leddevice/dev_net/ProviderRestApi.cpp b/libsrc/leddevice/dev_net/ProviderRestApi.cpp index 29ba212d..d625b667 100644 --- a/libsrc/leddevice/dev_net/ProviderRestApi.cpp +++ b/libsrc/leddevice/dev_net/ProviderRestApi.cpp @@ -8,12 +8,20 @@ //std includes #include +#include // Constants namespace { const QChar ONE_SLASH = '/'; +const int HTTP_STATUS_NO_CONTENT = 204; +const int HTTP_STATUS_BAD_REQUEST = 400; +const int HTTP_STATUS_UNAUTHORIZED = 401; +const int HTTP_STATUS_NOT_FOUND = 404; + +constexpr std::chrono::milliseconds DEFAULT_REST_TIMEOUT{ 400 }; + } //End of constants ProviderRestApi::ProviderRestApi(const QString &host, int port, const QString &basePath) @@ -59,7 +67,7 @@ void ProviderRestApi::appendPath ( const QString &path ) appendPath (_path, path ); } -void ProviderRestApi::appendPath ( QString& path, const QString &appendPath) const +void ProviderRestApi::appendPath ( QString& path, const QString &appendPath) { if ( !appendPath.isEmpty() && appendPath != ONE_SLASH ) { @@ -118,20 +126,26 @@ httpResponse ProviderRestApi::get() httpResponse ProviderRestApi::get(const QUrl &url) { - Debug(_log, "GET: [%s]", QSTRING_CSTR( url.toString() )); - // Perform request QNetworkRequest request(url); QNetworkReply* reply = _networkManager->get(request); + // Connect requestFinished signal to quit slot of the loop. QEventLoop loop; - loop.connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); + QEventLoop::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); + + ReplyTimeout::set(reply, DEFAULT_REST_TIMEOUT.count()); + // Go into the loop until the request is finished. loop.exec(); httpResponse response; if(reply->operation() == QNetworkAccessManager::GetOperation) { + if(reply->error() != QNetworkReply::NoError) + { + Debug(_log, "GET: [%s]", QSTRING_CSTR( url.toString() )); + } response = getResponse(reply ); } // Free space. @@ -147,19 +161,25 @@ httpResponse ProviderRestApi::put(const QString &body) httpResponse ProviderRestApi::put(const QUrl &url, const QString &body) { - Debug(_log, "PUT: [%s] [%s]", QSTRING_CSTR( url.toString() ), QSTRING_CSTR( body ) ); // Perform request QNetworkRequest request(url); QNetworkReply* reply = _networkManager->put(request, body.toUtf8()); // Connect requestFinished signal to quit slot of the loop. QEventLoop loop; - loop.connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); + QEventLoop::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); + + ReplyTimeout::set(reply, DEFAULT_REST_TIMEOUT.count()); + // Go into the loop until the request is finished. loop.exec(); httpResponse response; if(reply->operation() == QNetworkAccessManager::PutOperation) { + if(reply->error() != QNetworkReply::NoError) + { + Debug(_log, "PUT: [%s] [%s]", QSTRING_CSTR( url.toString() ), QSTRING_CSTR( body ) ); + } response = getResponse(reply); } // Free space. @@ -175,14 +195,11 @@ httpResponse ProviderRestApi::getResponse(QNetworkReply* const &reply) int httpStatusCode = reply->attribute( QNetworkRequest::HttpStatusCodeAttribute ).toInt(); response.setHttpStatusCode(httpStatusCode); - - Debug(_log, "Reply.httpStatusCode [%d]", httpStatusCode ); - response.setNetworkReplyError(reply->error()); if(reply->error() == QNetworkReply::NoError) { - if ( httpStatusCode != 204 ){ + if ( httpStatusCode != HTTP_STATUS_NO_CONTENT ){ QByteArray replyData = reply->readAll(); if ( !replyData.isEmpty()) @@ -211,18 +228,19 @@ httpResponse ProviderRestApi::getResponse(QNetworkReply* const &reply) } else { + Debug(_log, "Reply.httpStatusCode [%d]", httpStatusCode ); QString errorReason; if ( httpStatusCode > 0 ) { QString httpReason = reply->attribute( QNetworkRequest::HttpReasonPhraseAttribute ).toString(); QString advise; switch ( httpStatusCode ) { - case 400: + case HTTP_STATUS_BAD_REQUEST: advise = "Check Request Body"; break; - case 401: + case HTTP_STATUS_UNAUTHORIZED: advise = "Check Authentication Token (API Key)"; break; - case 404: + case HTTP_STATUS_NOT_FOUND: advise = "Check Resource given"; break; default: @@ -231,10 +249,20 @@ httpResponse ProviderRestApi::getResponse(QNetworkReply* const &reply) errorReason = QString ("[%3 %4] - %5").arg(QString(httpStatusCode) , httpReason, advise); } else { + errorReason = reply->errorString(); + + if ( reply->error() == QNetworkReply::OperationCanceledError ) + { + //Do not report errors caused by request cancellation because of timeouts + Debug(_log, "Reply: [%s]", QSTRING_CSTR(errorReason) ); + } + else + { + response.setError(true); + response.setErrorReason(errorReason); + } } - response.setError(true); - response.setErrorReason(errorReason); // Create valid body which is empty response.setBody( QJsonDocument() ); diff --git a/libsrc/leddevice/dev_net/ProviderRestApi.h b/libsrc/leddevice/dev_net/ProviderRestApi.h index 5a66bb20..d59709d1 100644 --- a/libsrc/leddevice/dev_net/ProviderRestApi.h +++ b/libsrc/leddevice/dev_net/ProviderRestApi.h @@ -10,6 +10,48 @@ #include #include +#include +#include + +//Set QNetworkReply timeout without external timer +//https://stackoverflow.com/questions/37444539/how-to-set-qnetworkreply-timeout-without-external-timer + +class ReplyTimeout : public QObject { + Q_OBJECT +public: + enum HandleMethod { Abort, Close }; + ReplyTimeout(QNetworkReply* reply, const int timeout, HandleMethod method = Abort) : + QObject(reply), m_method(method) + { + Q_ASSERT(reply); + if (reply && reply->isRunning()) { + m_timer.start(timeout, this); + connect(reply, &QNetworkReply::finished, this, &QObject::deleteLater); + } + } + static void set(QNetworkReply* reply, const int timeout, HandleMethod method = Abort) + { + new ReplyTimeout(reply, timeout, method); + } + +protected: + QBasicTimer m_timer; + HandleMethod m_method; + void timerEvent(QTimerEvent * ev) override { + if (!m_timer.isActive() || ev->timerId() != m_timer.timerId()) + return; + auto reply = static_cast(parent()); + if (reply->isRunning()) + { + if (m_method == Close) + reply->close(); + else if (m_method == Abort) + reply->abort(); + m_timer.stop(); + } + } +}; + /// /// Response object for REST-API calls and JSON-responses /// @@ -191,7 +233,7 @@ private: /// @param[in/out] path to be updated /// @param[in] path, element to be appended /// - void appendPath (QString &path, const QString &appendPath) const; + static void appendPath (QString &path, const QString &appendPath) ; Logger* _log; diff --git a/libsrc/leddevice/dev_serial/LedDeviceAtmo.cpp b/libsrc/leddevice/dev_serial/LedDeviceAtmo.cpp index 464bbde7..c062baa5 100644 --- a/libsrc/leddevice/dev_serial/LedDeviceAtmo.cpp +++ b/libsrc/leddevice/dev_serial/LedDeviceAtmo.cpp @@ -1,6 +1,10 @@ // hyperion local includes #include "LedDeviceAtmo.h" +namespace { + const bool verbose = false; +} //End of constants + LedDeviceAtmo::LedDeviceAtmo(const QJsonObject &deviceConfig) : ProviderRs232(deviceConfig) { @@ -43,3 +47,20 @@ int LedDeviceAtmo::write(const std::vector &ledValues) memcpy(4 + _ledBuffer.data(), ledValues.data(), _ledCount * sizeof(ColorRgb)); return writeBytes(_ledBuffer.size(), _ledBuffer.data()); } + +QJsonObject LedDeviceAtmo::getProperties(const QJsonObject& params) +{ + DebugIf(verbose, _log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData()); + QJsonObject properties; + + QString serialPort = params["serialPort"].toString(""); + + QJsonObject propertiesDetails; + QJsonArray possibleLedCounts = { 5 }; + propertiesDetails.insert("ledCount", possibleLedCounts); + + properties.insert("properties", propertiesDetails); + + DebugIf(verbose, _log, "properties: [%s]", QString(QJsonDocument(properties).toJson(QJsonDocument::Compact)).toUtf8().constData()); + return properties; +} diff --git a/libsrc/leddevice/dev_serial/LedDeviceAtmo.h b/libsrc/leddevice/dev_serial/LedDeviceAtmo.h index 0bb316d9..49665068 100644 --- a/libsrc/leddevice/dev_serial/LedDeviceAtmo.h +++ b/libsrc/leddevice/dev_serial/LedDeviceAtmo.h @@ -23,6 +23,14 @@ public: /// static LedDevice* construct(const QJsonObject &deviceConfig); + /// + /// @brief Get a Atmo device's resource properties + /// + /// @param[in] params Parameters to query device + /// @return A JSON structure holding the device's properties + /// + QJsonObject getProperties(const QJsonObject& params) override; + private: /// diff --git a/libsrc/leddevice/dev_serial/LedDeviceKarate.cpp b/libsrc/leddevice/dev_serial/LedDeviceKarate.cpp index ccbd9598..e99ccce0 100644 --- a/libsrc/leddevice/dev_serial/LedDeviceKarate.cpp +++ b/libsrc/leddevice/dev_serial/LedDeviceKarate.cpp @@ -1,27 +1,31 @@ // hyperion local includes #include "LedDeviceKarate.h" -LedDeviceKarate::LedDeviceKarate(const QJsonObject &deviceConfig) +namespace { + const bool verbose = false; +} //End of constants + +LedDeviceKarate::LedDeviceKarate(const QJsonObject& deviceConfig) : ProviderRs232(deviceConfig) { } -LedDevice* LedDeviceKarate::construct(const QJsonObject &deviceConfig) +LedDevice* LedDeviceKarate::construct(const QJsonObject& deviceConfig) { return new LedDeviceKarate(deviceConfig); } -bool LedDeviceKarate::init(const QJsonObject &deviceConfig) +bool LedDeviceKarate::init(const QJsonObject& deviceConfig) { bool isInitOK = false; // Initialise sub-class - if ( ProviderRs232::init(deviceConfig) ) + if (ProviderRs232::init(deviceConfig)) { if (_ledCount != 8 && _ledCount != 16) { //Error( _log, "%d channels configured. This should always be 16!", _ledCount); - QString errortext = QString ("%1 channels configured. This should always be 8 or 16!").arg(_ledCount); + QString errortext = QString("%1 channels configured. This should always be 8 or 16!").arg(_ledCount); this->setInError(errortext); isInitOK = false; } @@ -33,8 +37,8 @@ bool LedDeviceKarate::init(const QJsonObject &deviceConfig) _ledBuffer[2] = 0x00; // Checksum _ledBuffer[3] = _ledCount * 3; // Number of Databytes send - Debug( _log, "Karatelight header for %d leds: 0x%02x 0x%02x 0x%02x 0x%02x", _ledCount, - _ledBuffer[0], _ledBuffer[1], _ledBuffer[2], _ledBuffer[3] ); + Debug(_log, "Karatelight header for %d leds: 0x%02x 0x%02x 0x%02x 0x%02x", _ledCount, + _ledBuffer[0], _ledBuffer[1], _ledBuffer[2], _ledBuffer[3]); isInitOK = true; } @@ -42,20 +46,37 @@ bool LedDeviceKarate::init(const QJsonObject &deviceConfig) return isInitOK; } -int LedDeviceKarate::write(const std::vector &ledValues) +int LedDeviceKarate::write(const std::vector& ledValues) { - for (signed iLed=0; iLed< static_cast(_ledCount); iLed++) - { - const ColorRgb& rgb = ledValues[iLed]; - _ledBuffer[iLed*3+4] = rgb.green; - _ledBuffer[iLed*3+5] = rgb.blue; - _ledBuffer[iLed*3+6] = rgb.red; - } + for (signed iLed = 0; iLed < static_cast(_ledCount); iLed++) + { + const ColorRgb& rgb = ledValues[iLed]; + _ledBuffer[iLed * 3 + 4] = rgb.green; + _ledBuffer[iLed * 3 + 5] = rgb.blue; + _ledBuffer[iLed * 3 + 6] = rgb.red; + } // Calc Checksum - _ledBuffer[2] = _ledBuffer[0] ^ _ledBuffer[1]; - for (unsigned int i = 3; i < _ledBuffer.size(); i++) - _ledBuffer[2] ^= _ledBuffer[i]; + _ledBuffer[2] = _ledBuffer[0] ^ _ledBuffer[1]; + for (unsigned int i = 3; i < _ledBuffer.size(); i++) + _ledBuffer[2] ^= _ledBuffer[i]; return writeBytes(_ledBuffer.size(), _ledBuffer.data()); } + +QJsonObject LedDeviceKarate::getProperties(const QJsonObject& params) +{ + DebugIf(verbose, _log, "params: [%s]", QString(QJsonDocument(params).toJson(QJsonDocument::Compact)).toUtf8().constData()); + QJsonObject properties; + + QString serialPort = params["serialPort"].toString(""); + + QJsonObject propertiesDetails; + QJsonArray possibleLedCounts = { 16, 8 }; + propertiesDetails.insert("ledCount", possibleLedCounts); + + properties.insert("properties", propertiesDetails); + + DebugIf(verbose, _log, "properties: [%s]", QString(QJsonDocument(properties).toJson(QJsonDocument::Compact)).toUtf8().constData()); + return properties; +} diff --git a/libsrc/leddevice/dev_serial/LedDeviceKarate.h b/libsrc/leddevice/dev_serial/LedDeviceKarate.h index f0b4329c..33762823 100644 --- a/libsrc/leddevice/dev_serial/LedDeviceKarate.h +++ b/libsrc/leddevice/dev_serial/LedDeviceKarate.h @@ -26,6 +26,14 @@ public: /// @return LedDevice constructed static LedDevice* construct(const QJsonObject &deviceConfig); + /// + /// @brief Get a Karate device's resource properties + /// + /// @param[in] params Parameters to query device + /// @return A JSON structure holding the device's properties + /// + QJsonObject getProperties(const QJsonObject& params) override; + private: /// diff --git a/libsrc/leddevice/dev_serial/ProviderRs232.cpp b/libsrc/leddevice/dev_serial/ProviderRs232.cpp index efc730aa..f6796749 100644 --- a/libsrc/leddevice/dev_serial/ProviderRs232.cpp +++ b/libsrc/leddevice/dev_serial/ProviderRs232.cpp @@ -43,7 +43,9 @@ bool ProviderRs232::init(const QJsonObject &deviceConfig) // If device name was given as unix /dev/ system-location, get port name if ( _deviceName.startsWith(QLatin1String("/dev/")) ) + { _deviceName = _deviceName.mid(5); + } _isAutoDeviceName = _deviceName.toLower() == "auto"; _baudRate_Hz = deviceConfig["rate"].toInt(); @@ -141,18 +143,16 @@ bool ProviderRs232::tryOpen(int delayAfterConnect_ms) Debug(_log, "_rs232Port.open(QIODevice::ReadWrite): %s, Baud rate [%d]bps", QSTRING_CSTR(_deviceName), _baudRate_Hz); QSerialPortInfo serialPortInfo(_deviceName); - - QJsonObject portInfo; - Debug(_log, "portName: %s", QSTRING_CSTR(serialPortInfo.portName())); - Debug(_log, "systemLocation: %s", QSTRING_CSTR(serialPortInfo.systemLocation())); - Debug(_log, "description: %s", QSTRING_CSTR(serialPortInfo.description())); - Debug(_log, "manufacturer: %s", QSTRING_CSTR(serialPortInfo.manufacturer())); - Debug(_log, "productIdentifier: %s", QSTRING_CSTR(QString("0x%1").arg(serialPortInfo.productIdentifier(), 0, 16))); - Debug(_log, "vendorIdentifier: %s", QSTRING_CSTR(QString("0x%1").arg(serialPortInfo.vendorIdentifier(), 0, 16))); - Debug(_log, "serialNumber: %s", QSTRING_CSTR(serialPortInfo.serialNumber())); - if (!serialPortInfo.isNull() ) { + Debug(_log, "portName: %s", QSTRING_CSTR(serialPortInfo.portName())); + Debug(_log, "systemLocation: %s", QSTRING_CSTR(serialPortInfo.systemLocation())); + Debug(_log, "description: %s", QSTRING_CSTR(serialPortInfo.description())); + Debug(_log, "manufacturer: %s", QSTRING_CSTR(serialPortInfo.manufacturer())); + Debug(_log, "vendorIdentifier: %s", QSTRING_CSTR(QString("0x%1").arg(serialPortInfo.vendorIdentifier(), 0, 16))); + Debug(_log, "productIdentifier: %s", QSTRING_CSTR(QString("0x%1").arg(serialPortInfo.productIdentifier(), 0, 16))); + Debug(_log, "serialNumber: %s", QSTRING_CSTR(serialPortInfo.serialNumber())); + if ( !_rs232Port.open(QIODevice::ReadWrite) ) { this->setInError(_rs232Port.errorString()); @@ -163,6 +163,18 @@ bool ProviderRs232::tryOpen(int delayAfterConnect_ms) { QString errortext = QString("Invalid serial device name: [%1]!").arg(_deviceName); this->setInError( errortext ); + + // List available device + for (auto &port : QSerialPortInfo::availablePorts() ) { + Debug(_log, "Avail. serial device: [%s]-(%s|%s), Manufacturer: %s, Description: %s", + QSTRING_CSTR(port.portName()), + QSTRING_CSTR(QString("0x%1").arg(port.vendorIdentifier(), 0, 16)), + QSTRING_CSTR(QString("0x%1").arg(port.productIdentifier(), 0, 16)), + QSTRING_CSTR(port.manufacturer()), + QSTRING_CSTR(port.description()) + ); + } + return false; } } @@ -215,7 +227,7 @@ int ProviderRs232::writeBytes(const qint64 size, const uint8_t *data) { if ( _rs232Port.error() == QSerialPort::TimeoutError ) { - Debug(_log, "Timeout after %dms: %d frames already dropped", WRITE_TIMEOUT, _frameDropCounter); + Debug(_log, "Timeout after %dms: %d frames already dropped", WRITE_TIMEOUT.count(), _frameDropCounter); ++_frameDropCounter; @@ -245,7 +257,7 @@ int ProviderRs232::writeBytes(const qint64 size, const uint8_t *data) QString ProviderRs232::discoverFirst() { // take first available USB serial port - currently no probing! - for (auto const & port : QSerialPortInfo::availablePorts()) + for (auto & port : QSerialPortInfo::availablePorts()) { if (!port.isNull() && !port.isBusy()) { @@ -266,7 +278,7 @@ QJsonObject ProviderRs232::discover(const QJsonObject& /*params*/) // Discover serial Devices for (auto &port : QSerialPortInfo::availablePorts() ) { - if ( !port.isNull() ) + if ( !port.isNull() && !port.portName().startsWith("ttyS")) { QJsonObject portInfo; portInfo.insert("description", port.description()); diff --git a/libsrc/leddevice/schemas/schema-wled.json b/libsrc/leddevice/schemas/schema-wled.json index bd609223..bb00f3de 100644 --- a/libsrc/leddevice/schemas/schema-wled.json +++ b/libsrc/leddevice/schemas/schema-wled.json @@ -4,8 +4,16 @@ "properties":{ "host" : { "type": "string", - "title":"edt_dev_spec_targetIpHost_title", - "propertyOrder" : 1 + "title": "edt_dev_spec_targetIpHost_title", + "required": true, + "propertyOrder": 1 + }, + "restoreOriginalState": { + "type": "boolean", + "title": "edt_dev_spec_restoreOriginalState_title", + "default": false, + "required": true, + "propertyOrder": 2 }, "latchTime": { "type": "integer", @@ -15,7 +23,7 @@ "minimum": 0, "maximum": 1000, "access" : "expert", - "propertyOrder" : 2 + "propertyOrder" : 3 } }, "additionalProperties": true diff --git a/libsrc/protoserver/ProtoClientConnection.cpp b/libsrc/protoserver/ProtoClientConnection.cpp index e8bf1d91..051ca3e7 100644 --- a/libsrc/protoserver/ProtoClientConnection.cpp +++ b/libsrc/protoserver/ProtoClientConnection.cpp @@ -1,12 +1,13 @@ -// project includes -#include "ProtoClientConnection.h" - // qt #include #include #include #include +// project includes +#include "ProtoClientConnection.h" + + // TODO Remove this class if third-party apps have been migrated (eg. Hyperion Android Grabber, Windows Screen grabber etc.) ProtoClientConnection::ProtoClientConnection(QTcpSocket* socket, int timeout, QObject *parent) diff --git a/libsrc/protoserver/ProtoClientConnection.h b/libsrc/protoserver/ProtoClientConnection.h index 6d8ce378..e08658dc 100644 --- a/libsrc/protoserver/ProtoClientConnection.h +++ b/libsrc/protoserver/ProtoClientConnection.h @@ -1,14 +1,16 @@ #pragma once +// protobuffer PROTO +// protobuf defines an Error() function itself, so undef it here +#undef Error +#include "message.pb.h" + // util #include #include #include #include -// protobuffer PROTO -#include "message.pb.h" - class QTcpSocket; class QTimer; diff --git a/libsrc/protoserver/ProtoServer.cpp b/libsrc/protoserver/ProtoServer.cpp index 7bfc2954..fb45ae60 100644 --- a/libsrc/protoserver/ProtoServer.cpp +++ b/libsrc/protoserver/ProtoServer.cpp @@ -1,5 +1,5 @@ -#include #include "ProtoClientConnection.h" +#include // util #include diff --git a/libsrc/utils/FileUtils.cpp b/libsrc/utils/FileUtils.cpp index faf5e67f..0784ef88 100644 --- a/libsrc/utils/FileUtils.cpp +++ b/libsrc/utils/FileUtils.cpp @@ -3,7 +3,6 @@ // qt incl #include #include -#include // hyperion include #include diff --git a/libsrc/utils/ImageResampler.cpp b/libsrc/utils/ImageResampler.cpp index 15a32466..6ab8364d 100644 --- a/libsrc/utils/ImageResampler.cpp +++ b/libsrc/utils/ImageResampler.cpp @@ -3,8 +3,8 @@ #include ImageResampler::ImageResampler() - : _horizontalDecimation(1) - , _verticalDecimation(1) + : _horizontalDecimation(8) + , _verticalDecimation(8) , _cropLeft(0) , _cropRight(0) , _cropTop(0) @@ -27,7 +27,7 @@ void ImageResampler::processImage(const uint8_t * data, int width, int height, i int cropRight = _cropRight; int cropBottom = _cropBottom; int xDestFlip = 0, yDestFlip = 0; - int uOffset, vOffset; + int uOffset = 0, vOffset = 0; // handle 3D mode switch (_videoMode) diff --git a/libsrc/webserver/CMakeLists.txt b/libsrc/webserver/CMakeLists.txt index 175df60e..3a6843dd 100644 --- a/libsrc/webserver/CMakeLists.txt +++ b/libsrc/webserver/CMakeLists.txt @@ -5,9 +5,10 @@ set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/webserver) FILE ( GLOB WebConfig_SOURCES "${CURRENT_HEADER_DIR}/*.h" "${CURRENT_SOURCE_DIR}/*.h" "${CURRENT_SOURCE_DIR}/*.cpp" ) FILE ( GLOB_RECURSE webFiles RELATIVE ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/assets/webconfig/* ) +FILE ( RELATIVE_PATH webConfigPath ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/assets/webconfig) FOREACH( f ${webFiles} ) - STRING ( REPLACE "../assets/webconfig/" "" fname ${f}) + STRING ( REPLACE "${webConfigPath}/" "" fname ${f}) SET(HYPERION_WEBCONFIG_RES "${HYPERION_WEBCONFIG_RES}\n\t\t${f}") ENDFOREACH() CONFIGURE_FILE(${CURRENT_SOURCE_DIR}/WebConfig.qrc.in ${CMAKE_BINARY_DIR}/WebConfig.qrc ) diff --git a/libsrc/webserver/WebSocketClient.cpp b/libsrc/webserver/WebSocketClient.cpp index 0e522072..0d04d65f 100644 --- a/libsrc/webserver/WebSocketClient.cpp +++ b/libsrc/webserver/WebSocketClient.cpp @@ -85,6 +85,17 @@ void WebSocketClient::handleWebSocketFrame() case OPCODE::BINARY: case OPCODE::TEXT: { + // A fragmented message consists of a single frame with the FIN bit + // clear and an opcode other than 0, followed by zero or more frames + // with the FIN bit clear and the opcode set to 0, and terminated by + // a single frame with the FIN bit set and an opcode of 0. + // + // Store frame type given by first frame + if (_wsh.opCode != OPCODE::CONTINUATION ) + { + _frameOpCode = _wsh.opCode; + } + // check for protocol violations if (_onContinuation && !isContinuation) { @@ -117,15 +128,15 @@ void WebSocketClient::handleWebSocketFrame() if (_wsh.fin) { _onContinuation = false; - if (_wsh.opCode == OPCODE::TEXT) - { + if (_frameOpCode == OPCODE::TEXT) + { _jsonAPI->handleMessage(QString(_wsReceiveBuffer)); - } - else - { - handleBinaryMessage(_wsReceiveBuffer); - } + } + else + { + handleBinaryMessage(_wsReceiveBuffer); + } _wsReceiveBuffer.clear(); } diff --git a/libsrc/webserver/WebSocketClient.h b/libsrc/webserver/WebSocketClient.h index 5c90f8cb..0b056fb1 100644 --- a/libsrc/webserver/WebSocketClient.h +++ b/libsrc/webserver/WebSocketClient.h @@ -52,6 +52,9 @@ private: // websocket header store WebSocketHeader _wsh; + //opCode of first frame (in case of fragmented frames) + quint8 _frameOpCode; + // masks for fields in the basic header static uint8_t const BHB0_OPCODE = 0x0F; static uint8_t const BHB0_RSV3 = 0x10; diff --git a/src/hyperion-qt/QtWrapper.cpp b/src/hyperion-qt/QtWrapper.cpp index 31c98745..278c9e69 100644 --- a/src/hyperion-qt/QtWrapper.cpp +++ b/src/hyperion-qt/QtWrapper.cpp @@ -27,6 +27,11 @@ void QtWrapper::stop() _timer.stop(); } +bool QtWrapper::displayInit() +{ + return _grabber.setupDisplay(); +} + void QtWrapper::capture() { if(unsigned(_grabber.getImageWidth()) != unsigned(_screenshot.width()) || unsigned(_grabber.getImageHeight()) != unsigned(_screenshot.height())) diff --git a/src/hyperion-qt/QtWrapper.h b/src/hyperion-qt/QtWrapper.h index 7ffaad1d..8be38ca9 100644 --- a/src/hyperion-qt/QtWrapper.h +++ b/src/hyperion-qt/QtWrapper.h @@ -24,6 +24,8 @@ public: void stop(); + bool displayInit(); + signals: void sig_screenshot(const Image & screenshot); diff --git a/src/hyperion-qt/hyperion-qt.cpp b/src/hyperion-qt/hyperion-qt.cpp index 5dff785d..3eff980e 100644 --- a/src/hyperion-qt/hyperion-qt.cpp +++ b/src/hyperion-qt/hyperion-qt.cpp @@ -56,7 +56,7 @@ int main(int argc, char ** argv) parser.showHelp(0); } - QtWrapper grabber( + QtWrapper qtWrapper( 1000 / argFps.getInt(parser), argCropLeft.getInt(parser), argCropRight.getInt(parser), @@ -65,10 +65,13 @@ int main(int argc, char ** argv) argSizeDecimation.getInt(parser), argDisplay.getInt(parser)); + if (!qtWrapper.displayInit()) + return -1; + if (parser.isSet(argScreenshot)) { // Capture a single screenshot and finish - const Image &screenshot = grabber.getScreenshot(); + const Image &screenshot = qtWrapper.getScreenshot(); saveScreenshot("screenshot.png", screenshot); } else @@ -89,10 +92,10 @@ int main(int argc, char ** argv) FlatBufferConnection flatbuf("Qt Standalone", address, argPriority.getInt(parser), parser.isSet(argSkipReply)); // Connect the screen capturing to flatbuf connection processing - QObject::connect(&grabber, SIGNAL(sig_screenshot(const Image &)), &flatbuf, SLOT(setImage(Image))); + QObject::connect(&qtWrapper, SIGNAL(sig_screenshot(const Image &)), &flatbuf, SLOT(setImage(Image))); // Start the capturing - grabber.start(); + qtWrapper.start(); // Start the application app.exec(); diff --git a/src/hyperion-v4l2/hyperion-v4l2.cpp b/src/hyperion-v4l2/hyperion-v4l2.cpp index 6c7c6dc2..29b8f987 100644 --- a/src/hyperion-v4l2/hyperion-v4l2.cpp +++ b/src/hyperion-v4l2/hyperion-v4l2.cpp @@ -59,6 +59,7 @@ int main(int argc, char** argv) IntOption & argFps = parser.add ('f', "framerate", "Capture frame rate [default: %1]", "15", 1, 25); IntOption & argWidth = parser.add (0x0, "width", "Width of the captured image [default: %1]", "160", 160); IntOption & argHeight = parser.add (0x0, "height", "Height of the captured image [default: %1]", "160", 160); + SwitchOption & argFlipMode = parser.add>(0x0, "flip-mode", "The used image flip mode. Valid values are HORIZONTAL, VERTICAL, BOTH or no-change. [default: %1]", "no-change"); IntOption & argCropWidth = parser.add (0x0, "crop-width", "Number of pixels to crop from the left and right sides of the picture before decimation [default: %1]", "0"); IntOption & argCropHeight = parser.add (0x0, "crop-height", "Number of pixels to crop from the top and the bottom of the picture before decimation [default: %1]", "0"); IntOption & argCropLeft = parser.add (0x0, "crop-left", "Number of pixels to crop from the left of the picture before decimation (overrides --crop-width)"); @@ -99,6 +100,11 @@ int main(int argc, char** argv) #endif argPixelFormat.addSwitch("no-change", PixelFormat::NO_CHANGE); + argFlipMode.addSwitch("horizontal", FlipMode::HORIZONTAL); + argFlipMode.addSwitch("vertical", FlipMode::VERTICAL); + argFlipMode.addSwitch("both", FlipMode::BOTH); + argFlipMode.addSwitch("no-change", FlipMode::NO_CHANGE); + // parse all options parser.process(app); @@ -109,15 +115,31 @@ int main(int argc, char** argv) } // initialize the grabber - V4L2Grabber grabber( - argDevice.value(parser), - argWidth.getInt(parser), - argHeight.getInt(parser), - 1000 / argFps.getInt(parser), - argInput.getInt(parser), - argVideoStandard.switchValue(parser), - argPixelFormat.switchValue(parser), - std::max(1, argSizeDecimation.getInt(parser))); + V4L2Grabber grabber; + + // set device + grabber.setDevice(argDevice.value(parser)); + + // set input + grabber.setInput(argInput.getInt(parser)); + + // set resolution + grabber.setWidthHeight(argWidth.getInt(parser), argHeight.getInt(parser)); + + // set fps + grabber.setFramerate(1000 / argFps.getInt(parser)); + + // TODO set encoding format + // grabber.setEncoding(argPixelFormat.switchValue(parser)); + + // set video standard + grabber.setVideoStandard(argVideoStandard.switchValue(parser)); + + // set image size decimation + grabber.setPixelDecimation(std::max(1, argSizeDecimation.getInt(parser))); + + // set flip mode + grabber.setFlipMode(argFlipMode.switchValue(parser)); // set signal detection grabber.setSignalDetectionEnable(! parser.isSet(argSignalDetection)); diff --git a/src/hyperion-x11/X11Wrapper.cpp b/src/hyperion-x11/X11Wrapper.cpp index f3363111..8553b3e8 100644 --- a/src/hyperion-x11/X11Wrapper.cpp +++ b/src/hyperion-x11/X11Wrapper.cpp @@ -31,7 +31,7 @@ void X11Wrapper::stop() bool X11Wrapper::displayInit() { - return _grabber.Setup(); + return _grabber.setupDisplay(); } void X11Wrapper::capture() diff --git a/src/hyperion-xcb/XcbWrapper.cpp b/src/hyperion-xcb/XcbWrapper.cpp index c7436571..75b2a88c 100644 --- a/src/hyperion-xcb/XcbWrapper.cpp +++ b/src/hyperion-xcb/XcbWrapper.cpp @@ -31,7 +31,7 @@ void XcbWrapper::stop() bool XcbWrapper::displayInit() { - return _grabber.Setup(); + return _grabber.setupDisplay(); } void XcbWrapper::capture() diff --git a/src/hyperiond/hyperiond.cpp b/src/hyperiond/hyperiond.cpp index 29a82d5e..c00cf3a9 100644 --- a/src/hyperiond/hyperiond.cpp +++ b/src/hyperiond/hyperiond.cpp @@ -73,8 +73,7 @@ HyperionDaemon::HyperionDaemon(const QString& rootPath, QObject* parent, bool lo , _webserver(nullptr) , _sslWebserver(nullptr) , _jsonServer(nullptr) - , _v4l2Grabber(nullptr) - , _mfGrabber(nullptr) + , _videoGrabber(nullptr) , _dispmanx(nullptr) , _x11Grabber(nullptr) , _xcbGrabber(nullptr) @@ -253,11 +252,9 @@ void HyperionDaemon::freeObjects() delete _osxGrabber; delete _qtGrabber; delete _dxGrabber; - delete _v4l2Grabber; - delete _mfGrabber; + delete _videoGrabber; - _v4l2Grabber = nullptr; - _mfGrabber = nullptr; + _videoGrabber = nullptr; _amlGrabber = nullptr; _dispmanx = nullptr; _fbGrabber = nullptr; @@ -373,7 +370,7 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs #ifdef ENABLE_OSX QString type = "osx"; #else - QString type = grabberConfig["type"].toString("auto"); + QString type = grabberConfig["device"].toString("auto"); #endif // auto eval of type @@ -596,101 +593,23 @@ void HyperionDaemon::handleSettingsUpdate(settings::type settingsType, const QJs } #endif -#if defined(ENABLE_MF) - if (_mfGrabber == nullptr) +#if defined(ENABLE_V4L2) || defined(ENABLE_MF) + if (_videoGrabber == nullptr) { - _mfGrabber = new MFWrapper( - grabberConfig["device"].toString("auto"), - grabberConfig["width"].toInt(0), - grabberConfig["height"].toInt(0), - grabberConfig["fps"].toInt(15), - grabberConfig["sizeDecimation"].toInt(8), - grabberConfig["flip"].toString("auto")); - - // Image cropping - _mfGrabber->setCropping( - grabberConfig["cropLeft"].toInt(0), - grabberConfig["cropRight"].toInt(0), - grabberConfig["cropTop"].toInt(0), - grabberConfig["cropBottom"].toInt(0)); - - // Software frame decimation - _mfGrabber->setFpsSoftwareDecimation(grabberConfig["fpsSoftwareDecimation"].toInt(1)); - - // Hardware encoding format - _mfGrabber->setEncoding(grabberConfig["encoding"].toString("NO_CHANGE")); - - // Signal detection - _mfGrabber->setSignalDetectionEnable(grabberConfig["signalDetection"].toBool(true)); - _mfGrabber->setSignalDetectionOffset( - grabberConfig["sDHOffsetMin"].toDouble(0.25), - grabberConfig["sDVOffsetMin"].toDouble(0.25), - grabberConfig["sDHOffsetMax"].toDouble(0.75), - grabberConfig["sDVOffsetMax"].toDouble(0.75)); - _mfGrabber->setSignalThreshold( - grabberConfig["redSignalThreshold"].toDouble(0.0) / 100.0, - grabberConfig["greenSignalThreshold"].toDouble(0.0) / 100.0, - grabberConfig["blueSignalThreshold"].toDouble(0.0) / 100.0, - grabberConfig["noSignalCounterThreshold"].toInt(50) ); - - // CEC Standby - _mfGrabber->setCecDetectionEnable(grabberConfig["cecDetection"].toBool(true)); - - // Brightness, Contrast, Saturation, Hue - _mfGrabber->setBrightnessContrastSaturationHue(grabberConfig["hardware_brightness"].toInt(0), - grabberConfig["hardware_contrast"].toInt(0), - grabberConfig["hardware_saturation"].toInt(0), - grabberConfig["hardware_hue"].toInt(0)); + _videoGrabber = new VideoWrapper(); + _videoGrabber->handleSettingsUpdate(settings::V4L2, QJsonDocument(grabberConfig)); +#if defined(ENABLE_MF) Debug(_log, "Media Foundation grabber created"); - - // connect to HyperionDaemon signal - connect(this, &HyperionDaemon::videoMode, _mfGrabber, &MFWrapper::setVideoMode); - connect(this, &HyperionDaemon::settingsChanged, _mfGrabber, &MFWrapper::handleSettingsUpdate); - } -#elif !defined(ENABLE_V4L2) - Warning(_log, "The Media Foundation grabber can not be instantiated, because it has been left out from the build"); +#elif defined(ENABLE_V4L2) + Debug(_log, "V4L2 grabber created"); #endif - if (_v4l2Grabber != nullptr) - { - return; + // connect to HyperionDaemon signal + connect(this, &HyperionDaemon::videoMode, _videoGrabber, &VideoWrapper::setVideoMode); + connect(this, &HyperionDaemon::settingsChanged, _videoGrabber, &VideoWrapper::handleSettingsUpdate); } - -#ifdef ENABLE_V4L2 - _v4l2Grabber = new V4L2Wrapper( - grabberConfig["device"].toString("auto"), - grabberConfig["width"].toInt(0), - grabberConfig["height"].toInt(0), - grabberConfig["fps"].toInt(15), - grabberConfig["input"].toInt(-1), - parseVideoStandard(grabberConfig["standard"].toString("no-change")), - parsePixelFormat(grabberConfig["pixelFormat"].toString("no-change")), - grabberConfig["sizeDecimation"].toInt(8)); - - _v4l2Grabber->setSignalThreshold( - grabberConfig["redSignalThreshold"].toDouble(0.0) / 100.0, - grabberConfig["greenSignalThreshold"].toDouble(0.0) / 100.0, - grabberConfig["blueSignalThreshold"].toDouble(0.0) / 100.0); - _v4l2Grabber->setCropping( - grabberConfig["cropLeft"].toInt(0), - grabberConfig["cropRight"].toInt(0), - grabberConfig["cropTop"].toInt(0), - grabberConfig["cropBottom"].toInt(0)); - - _v4l2Grabber->setCecDetectionEnable(grabberConfig["cecDetection"].toBool(true)); - _v4l2Grabber->setSignalDetectionEnable(grabberConfig["signalDetection"].toBool(true)); - _v4l2Grabber->setSignalDetectionOffset( - grabberConfig["sDHOffsetMin"].toDouble(0.25), - grabberConfig["sDVOffsetMin"].toDouble(0.25), - grabberConfig["sDHOffsetMax"].toDouble(0.75), - grabberConfig["sDVOffsetMax"].toDouble(0.75)); - Debug(_log, "V4L2 grabber created"); - - // connect to HyperionDaemon signal - connect(this, &HyperionDaemon::videoMode, _v4l2Grabber, &V4L2Wrapper::setVideoMode); - connect(this, &HyperionDaemon::settingsChanged, _v4l2Grabber, &V4L2Wrapper::handleSettingsUpdate); -#elif !defined(ENABLE_MF) +#else Debug(_log, "The v4l2 grabber is not supported on this platform"); #endif } @@ -772,7 +691,7 @@ void HyperionDaemon::createGrabberQt(const QJsonObject& grabberConfig) _qtGrabber = new QtWrapper( _grabber_cropLeft, _grabber_cropRight, _grabber_cropTop, _grabber_cropBottom, grabberConfig["pixelDecimation"].toInt(8), - grabberConfig["display"].toInt(0), + grabberConfig["input"].toInt(0), _grabber_frequency); // connect to HyperionDaemon signal @@ -851,9 +770,9 @@ void HyperionDaemon::createCecHandler() thread->start(); connect(_cecHandler, &CECHandler::cecEvent, [&](CECEvent event) { - if (_v4l2Grabber != nullptr) + if (_videoGrabber != nullptr) { - _v4l2Grabber->handleCecEvent(event); + _videoGrabber->handleCecEvent(event); } }); diff --git a/src/hyperiond/hyperiond.h b/src/hyperiond/hyperiond.h index 6f0d790f..9407b0cc 100644 --- a/src/hyperiond/hyperiond.h +++ b/src/hyperiond/hyperiond.h @@ -10,16 +10,10 @@ typedef QObject DispmanxWrapper; #endif -#ifdef ENABLE_V4L2 - #include +#if defined(ENABLE_V4L2) || defined(ENABLE_MF) + #include #else - typedef QObject V4L2Wrapper; -#endif - -#ifdef ENABLE_MF - #include -#else - typedef QObject MFWrapper; + typedef QObject VideoWrapper; #endif #ifdef ENABLE_FB @@ -176,8 +170,7 @@ private: WebServer* _webserver; WebServer* _sslWebserver; JsonServer* _jsonServer; - V4L2Wrapper* _v4l2Grabber; - MFWrapper* _mfGrabber; + VideoWrapper* _videoGrabber; DispmanxWrapper* _dispmanx; X11Wrapper* _x11Grabber; XcbWrapper* _xcbGrabber; diff --git a/src/hyperiond/systray.cpp b/src/hyperiond/systray.cpp index a1891e84..f06a011e 100644 --- a/src/hyperiond/systray.cpp +++ b/src/hyperiond/systray.cpp @@ -15,7 +15,9 @@ #include #include +#include #include +#include #include "hyperiond.h" #include "systray.h" @@ -185,7 +187,7 @@ void SysTray::closeEvent(QCloseEvent *event) event->ignore(); } -void SysTray::settings() +void SysTray::settings() const { #ifndef _WIN32 // Hide error messages when opening webbrowser @@ -221,7 +223,7 @@ void SysTray::settings() void SysTray::setEffect() { QString efxName = qobject_cast(sender())->text(); - _hyperion->setEffect(efxName, 1); + _hyperion->setEffect(efxName, PriorityMuxer::FG_PRIORITY, Effect::ENDLESS); } void SysTray::clearEfxColor() @@ -229,7 +231,7 @@ void SysTray::clearEfxColor() _hyperion->clear(1); } -void SysTray::handleInstanceStateChange(InstanceState state, quint8 instance, const QString& name) +void SysTray::handleInstanceStateChange(InstanceState state, quint8 instance, const QString& /*name*/) { switch(state){ case InstanceState::H_STARTED: diff --git a/src/hyperiond/systray.h b/src/hyperiond/systray.h index 454a5b09..732d910b 100644 --- a/src/hyperiond/systray.h +++ b/src/hyperiond/systray.h @@ -24,7 +24,7 @@ public slots: void showColorDialog(); void setColor(const QColor & color); void closeEvent(QCloseEvent *event); - void settings(); + void settings() const; void setEffect(); void clearEfxColor(); void setAutorunState();