From 8bf465d30ad505cec7dbbcf7bb91aa665b23fafd Mon Sep 17 00:00:00 2001 From: Nir Azkiel Date: Thu, 15 Dec 2022 13:05:05 +0200 Subject: [PATCH] PR #11216 from Nir-Az: remove_nodejs_wrapper # Conflicts: # .github/workflows/buildsCI.yaml --- .github/workflows/buildsCI.yaml | 46 +- CMake/lrs_options.cmake | 1 - CONTRIBUTING.md | 9 +- appveyor.yml | 146 - readme.md | 2 +- wrappers/CMakeLists.txt | 3 - wrappers/nodejs/.eslintrc.json | 24 - wrappers/nodejs/.gitignore | 13 - wrappers/nodejs/.jshintrc | 4 - wrappers/nodejs/CMakeLists.txt | 24 - wrappers/nodejs/README.md | 147 - wrappers/nodejs/binding.gyp | 129 - wrappers/nodejs/doc/jsdoc-template/README.md | 12 - wrappers/nodejs/doc/jsdoc-template/publish.js | 703 -- .../static/fonts/OpenSans-Bold-webfont.eot | Bin 19544 -> 0 bytes .../static/fonts/OpenSans-Bold-webfont.svg | 1830 ----- .../static/fonts/OpenSans-Bold-webfont.woff | Bin 22432 -> 0 bytes .../fonts/OpenSans-BoldItalic-webfont.eot | Bin 20133 -> 0 bytes .../fonts/OpenSans-BoldItalic-webfont.svg | 1830 ----- .../fonts/OpenSans-BoldItalic-webfont.woff | Bin 23048 -> 0 bytes .../static/fonts/OpenSans-Italic-webfont.eot | Bin 20265 -> 0 bytes .../static/fonts/OpenSans-Italic-webfont.svg | 1830 ----- .../static/fonts/OpenSans-Italic-webfont.woff | Bin 23188 -> 0 bytes .../static/fonts/OpenSans-Light-webfont.eot | Bin 19514 -> 0 bytes .../static/fonts/OpenSans-Light-webfont.svg | 1831 ----- .../static/fonts/OpenSans-Light-webfont.woff | Bin 22248 -> 0 bytes .../fonts/OpenSans-LightItalic-webfont.eot | Bin 20535 -> 0 bytes .../fonts/OpenSans-LightItalic-webfont.svg | 1835 ----- .../fonts/OpenSans-LightItalic-webfont.woff | Bin 23400 -> 0 bytes .../static/fonts/OpenSans-Regular-webfont.eot | Bin 19836 -> 0 bytes .../static/fonts/OpenSans-Regular-webfont.svg | 1831 ----- .../fonts/OpenSans-Regular-webfont.woff | Bin 22660 -> 0 bytes .../static/scripts/linenumber.js | 29 - .../static/scripts/prettify/lang-css.js | 2 - .../static/scripts/prettify/prettify.js | 28 - .../static/styles/jsdoc-default.css | 362 - .../static/styles/prettify-jsdoc.css | 111 - .../static/styles/prettify-tomorrow.css | 132 - .../doc/jsdoc-template/tmpl/augments.tmpl | 10 - .../doc/jsdoc-template/tmpl/container.tmpl | 184 - .../doc/jsdoc-template/tmpl/details.tmpl | 143 - .../doc/jsdoc-template/tmpl/example.tmpl | 2 - .../doc/jsdoc-template/tmpl/examples.tmpl | 13 - .../doc/jsdoc-template/tmpl/exceptions.tmpl | 32 - .../doc/jsdoc-template/tmpl/layout.tmpl | 38 - .../doc/jsdoc-template/tmpl/mainpage.tmpl | 14 - .../doc/jsdoc-template/tmpl/members.tmpl | 38 - .../doc/jsdoc-template/tmpl/method.tmpl | 119 - .../doc/jsdoc-template/tmpl/params.tmpl | 131 - .../doc/jsdoc-template/tmpl/properties.tmpl | 108 - .../doc/jsdoc-template/tmpl/returns.tmpl | 19 - .../doc/jsdoc-template/tmpl/source.tmpl | 8 - .../doc/jsdoc-template/tmpl/tutorial.tmpl | 19 - .../nodejs/doc/jsdoc-template/tmpl/type.tmpl | 7 - wrappers/nodejs/examples/glfw-window.js | 165 - wrappers/nodejs/examples/nodejs-align.js | 124 - wrappers/nodejs/examples/nodejs-capture.js | 43 - wrappers/nodejs/examples/nodejs-pointcloud.js | 51 - .../nodejs/examples/nodejs-save-to-disk.js | 39 - wrappers/nodejs/examples/package-lock.json | 305 - wrappers/nodejs/examples/package.json | 13 - .../nodejs/examples/realsense_viewer/index.js | 404 - .../examples/realsense_viewer/package.json | 16 - .../examples/realsense_viewer/public/app.js | 519 -- .../realsense_viewer/public/common.js | 164 - .../realsense_viewer/public/index.html | 74 - .../examples/realsense_viewer/public/vue | 6 - .../sensor_control/nodejs-sensor-control.js | 314 - wrappers/nodejs/index.js | 6754 ----------------- wrappers/nodejs/package-lock.json | 228 - wrappers/nodejs/package.json | 37 - .../nodejs/scripts/generate-dist-package.js | 50 - wrappers/nodejs/scripts/generate-doc.js | 36 - wrappers/nodejs/scripts/npm_dist/.gitignore | 1 - wrappers/nodejs/scripts/npm_dist/README.md | 107 - wrappers/nodejs/scripts/npm_dist/binding.gyp | 105 - .../nodejs/scripts/npm_dist/build-dist-mac.sh | 33 - .../nodejs/scripts/npm_dist/build-dist.bat | 33 - .../nodejs/scripts/npm_dist/build-dist.sh | 36 - .../scripts/npm_dist/build-librealsense.js | 71 - wrappers/nodejs/scripts/npm_dist/gen-dist.sh | 39 - wrappers/nodejs/src/addon.cpp | 5092 ------------- wrappers/nodejs/test/README.md | 18 - wrappers/nodejs/test/package.json | 10 - wrappers/nodejs/test/test-align.js | 80 - wrappers/nodejs/test/test-colorizer.js | 92 - wrappers/nodejs/test/test-config.js | 322 - wrappers/nodejs/test/test-context.js | 182 - wrappers/nodejs/test/test-depthframe.js | 195 - wrappers/nodejs/test/test-depthsensor.js | 55 - wrappers/nodejs/test/test-device.js | 137 - wrappers/nodejs/test/test-devicehub.js | 96 - wrappers/nodejs/test/test-devicelist.js | 144 - wrappers/nodejs/test/test-frame.js | 182 - wrappers/nodejs/test/test-frameset.js | 130 - .../nodejs/test/test-functional-online.js | 661 -- wrappers/nodejs/test/test-functional.js | 909 --- wrappers/nodejs/test/test-pipeline.js | 272 - wrappers/nodejs/test/test-pipelineprofile.js | 144 - wrappers/nodejs/test/test-playbackdevice.js | 482 -- wrappers/nodejs/test/test-pointcloud.js | 117 - wrappers/nodejs/test/test-points.js | 227 - wrappers/nodejs/test/test-recorderdevice.js | 375 - .../nodejs/test/test-sensor-extensions.js | 105 - wrappers/nodejs/test/test-sensor.js | 545 -- wrappers/nodejs/test/test-streamprofile.js | 154 - wrappers/nodejs/test/test-videoframe.js | 187 - .../nodejs/test/test-videostreamprofile.js | 136 - wrappers/nodejs/tools/enums.py | 75 - wrappers/nodejs/tools/linter.js | 78 - wrappers/nodejs/tools/package-lock.json | 1219 --- wrappers/nodejs/tools/package.json | 22 - 112 files changed, 18 insertions(+), 35991 deletions(-) delete mode 100644 appveyor.yml delete mode 100644 wrappers/nodejs/.eslintrc.json delete mode 100644 wrappers/nodejs/.gitignore delete mode 100644 wrappers/nodejs/.jshintrc delete mode 100644 wrappers/nodejs/CMakeLists.txt delete mode 100644 wrappers/nodejs/README.md delete mode 100644 wrappers/nodejs/binding.gyp delete mode 100644 wrappers/nodejs/doc/jsdoc-template/README.md delete mode 100644 wrappers/nodejs/doc/jsdoc-template/publish.js delete mode 100644 wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-Bold-webfont.eot delete mode 100644 wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-Bold-webfont.svg delete mode 100644 wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-Bold-webfont.woff delete mode 100644 wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-BoldItalic-webfont.eot delete mode 100644 wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-BoldItalic-webfont.svg delete mode 100644 wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-BoldItalic-webfont.woff delete mode 100644 wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-Italic-webfont.eot delete mode 100644 wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-Italic-webfont.svg delete mode 100644 wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-Italic-webfont.woff delete mode 100644 wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-Light-webfont.eot delete mode 100644 wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-Light-webfont.svg delete mode 100644 wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-Light-webfont.woff delete mode 100644 wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-LightItalic-webfont.eot delete mode 100644 wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-LightItalic-webfont.svg delete mode 100644 wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-LightItalic-webfont.woff delete mode 100644 wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-Regular-webfont.eot delete mode 100644 wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-Regular-webfont.svg delete mode 100644 wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-Regular-webfont.woff delete mode 100644 wrappers/nodejs/doc/jsdoc-template/static/scripts/linenumber.js delete mode 100644 wrappers/nodejs/doc/jsdoc-template/static/scripts/prettify/lang-css.js delete mode 100644 wrappers/nodejs/doc/jsdoc-template/static/scripts/prettify/prettify.js delete mode 100644 wrappers/nodejs/doc/jsdoc-template/static/styles/jsdoc-default.css delete mode 100644 wrappers/nodejs/doc/jsdoc-template/static/styles/prettify-jsdoc.css delete mode 100644 wrappers/nodejs/doc/jsdoc-template/static/styles/prettify-tomorrow.css delete mode 100644 wrappers/nodejs/doc/jsdoc-template/tmpl/augments.tmpl delete mode 100644 wrappers/nodejs/doc/jsdoc-template/tmpl/container.tmpl delete mode 100644 wrappers/nodejs/doc/jsdoc-template/tmpl/details.tmpl delete mode 100644 wrappers/nodejs/doc/jsdoc-template/tmpl/example.tmpl delete mode 100644 wrappers/nodejs/doc/jsdoc-template/tmpl/examples.tmpl delete mode 100644 wrappers/nodejs/doc/jsdoc-template/tmpl/exceptions.tmpl delete mode 100644 wrappers/nodejs/doc/jsdoc-template/tmpl/layout.tmpl delete mode 100644 wrappers/nodejs/doc/jsdoc-template/tmpl/mainpage.tmpl delete mode 100644 wrappers/nodejs/doc/jsdoc-template/tmpl/members.tmpl delete mode 100644 wrappers/nodejs/doc/jsdoc-template/tmpl/method.tmpl delete mode 100644 wrappers/nodejs/doc/jsdoc-template/tmpl/params.tmpl delete mode 100644 wrappers/nodejs/doc/jsdoc-template/tmpl/properties.tmpl delete mode 100644 wrappers/nodejs/doc/jsdoc-template/tmpl/returns.tmpl delete mode 100644 wrappers/nodejs/doc/jsdoc-template/tmpl/source.tmpl delete mode 100644 wrappers/nodejs/doc/jsdoc-template/tmpl/tutorial.tmpl delete mode 100644 wrappers/nodejs/doc/jsdoc-template/tmpl/type.tmpl delete mode 100644 wrappers/nodejs/examples/glfw-window.js delete mode 100755 wrappers/nodejs/examples/nodejs-align.js delete mode 100755 wrappers/nodejs/examples/nodejs-capture.js delete mode 100755 wrappers/nodejs/examples/nodejs-pointcloud.js delete mode 100755 wrappers/nodejs/examples/nodejs-save-to-disk.js delete mode 100644 wrappers/nodejs/examples/package-lock.json delete mode 100644 wrappers/nodejs/examples/package.json delete mode 100644 wrappers/nodejs/examples/realsense_viewer/index.js delete mode 100644 wrappers/nodejs/examples/realsense_viewer/package.json delete mode 100644 wrappers/nodejs/examples/realsense_viewer/public/app.js delete mode 100644 wrappers/nodejs/examples/realsense_viewer/public/common.js delete mode 100644 wrappers/nodejs/examples/realsense_viewer/public/index.html delete mode 100644 wrappers/nodejs/examples/realsense_viewer/public/vue delete mode 100644 wrappers/nodejs/examples/sensor_control/nodejs-sensor-control.js delete mode 100644 wrappers/nodejs/index.js delete mode 100644 wrappers/nodejs/package-lock.json delete mode 100644 wrappers/nodejs/package.json delete mode 100644 wrappers/nodejs/scripts/generate-dist-package.js delete mode 100644 wrappers/nodejs/scripts/generate-doc.js delete mode 100644 wrappers/nodejs/scripts/npm_dist/.gitignore delete mode 100644 wrappers/nodejs/scripts/npm_dist/README.md delete mode 100644 wrappers/nodejs/scripts/npm_dist/binding.gyp delete mode 100755 wrappers/nodejs/scripts/npm_dist/build-dist-mac.sh delete mode 100644 wrappers/nodejs/scripts/npm_dist/build-dist.bat delete mode 100755 wrappers/nodejs/scripts/npm_dist/build-dist.sh delete mode 100644 wrappers/nodejs/scripts/npm_dist/build-librealsense.js delete mode 100755 wrappers/nodejs/scripts/npm_dist/gen-dist.sh delete mode 100644 wrappers/nodejs/src/addon.cpp delete mode 100644 wrappers/nodejs/test/README.md delete mode 100644 wrappers/nodejs/test/package.json delete mode 100644 wrappers/nodejs/test/test-align.js delete mode 100644 wrappers/nodejs/test/test-colorizer.js delete mode 100644 wrappers/nodejs/test/test-config.js delete mode 100644 wrappers/nodejs/test/test-context.js delete mode 100644 wrappers/nodejs/test/test-depthframe.js delete mode 100644 wrappers/nodejs/test/test-depthsensor.js delete mode 100644 wrappers/nodejs/test/test-device.js delete mode 100644 wrappers/nodejs/test/test-devicehub.js delete mode 100644 wrappers/nodejs/test/test-devicelist.js delete mode 100644 wrappers/nodejs/test/test-frame.js delete mode 100644 wrappers/nodejs/test/test-frameset.js delete mode 100644 wrappers/nodejs/test/test-functional-online.js delete mode 100644 wrappers/nodejs/test/test-functional.js delete mode 100644 wrappers/nodejs/test/test-pipeline.js delete mode 100644 wrappers/nodejs/test/test-pipelineprofile.js delete mode 100644 wrappers/nodejs/test/test-playbackdevice.js delete mode 100644 wrappers/nodejs/test/test-pointcloud.js delete mode 100644 wrappers/nodejs/test/test-points.js delete mode 100644 wrappers/nodejs/test/test-recorderdevice.js delete mode 100644 wrappers/nodejs/test/test-sensor-extensions.js delete mode 100644 wrappers/nodejs/test/test-sensor.js delete mode 100644 wrappers/nodejs/test/test-streamprofile.js delete mode 100644 wrappers/nodejs/test/test-videoframe.js delete mode 100644 wrappers/nodejs/test/test-videostreamprofile.js delete mode 100644 wrappers/nodejs/tools/enums.py delete mode 100755 wrappers/nodejs/tools/linter.js delete mode 100644 wrappers/nodejs/tools/package-lock.json delete mode 100644 wrappers/nodejs/tools/package.json diff --git a/.github/workflows/buildsCI.yaml b/.github/workflows/buildsCI.yaml index 34a0c3e0dd..1eba05bbb5 100644 --- a/.github/workflows/buildsCI.yaml +++ b/.github/workflows/buildsCI.yaml @@ -277,11 +277,10 @@ jobs: cmake --build . --config ${{env.LRS_BUILD_CONFIG}} -- -j4 - Linux_python_nodejs: + Linux_python: runs-on: ubuntu-18.04 timeout-minutes: 60 - env: - LRS_BUILD_NODEJS: true + steps: - uses: actions/checkout@v2 @@ -296,42 +295,23 @@ jobs: - name: Prebuild shell: bash run: | - set -x - # Workaround for nvm failure: https://github.com/appleboy/ssh-action/issues/70 - export NVM_DIR="$HOME/.nvm" - [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" - nvm install 10.15.3; - nvm use 10.15.3; - npm install -g node-gyp; - npm install -g mocha; - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git; - export OLDPATH=$PATH - echo OLDPATH=$OLDPATH - export PATH=$PATH:$(pwd)/depot_tools; - echo PATH=$PATH - cd wrappers/nodejs/tools && npm install && cd ..; - node ./tools/linter.js; - python ./tools/enums.py -i ../../include/librealsense2 -a ./src -v - export PATH=$OLDPATH && unset OLDPATH && cd ../../; - mkdir build - sudo add-apt-repository --yes ppa:ubuntu-toolchain-r/test; - sudo apt-get update; - sudo apt-get install -qq build-essential xorg-dev libgl1-mesa-dev libglu1-mesa-dev libglew-dev libglm-dev; - sudo apt-get install -qq libusb-1.0-0-dev; - sudo apt-get install -qq libgtk-3-dev; - sudo apt-get install gcc-5 g++-5; - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 60 --slave /usr/bin/g++ g++ /usr/bin/g++-5; - sudo apt-get install libglfw3-dev libglfw3; + set -x + mkdir build + sudo add-apt-repository --yes ppa:ubuntu-toolchain-r/test; + sudo apt-get update; + sudo apt-get install -qq build-essential xorg-dev libgl1-mesa-dev libglu1-mesa-dev libglew-dev libglm-dev; + sudo apt-get install -qq libusb-1.0-0-dev; + sudo apt-get install -qq libgtk-3-dev; + sudo apt-get install gcc-5 g++-5; + sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 60 --slave /usr/bin/g++ g++ /usr/bin/g++-5; + sudo apt-get install libglfw3-dev libglfw3; - name: Build shell: bash run: | - python ./wrappers/nodejs/tools/enums.py -i ./include/librealsense2 -a ./wrappers/nodejs/src -v cd build - cmake .. -DBUILD_PYTHON_BINDINGS=true -DBUILD_NODEJS_BINDINGS=true -DPYBIND11_PYTHON_VERSION=2.7 -DCHECK_FOR_UPDATES=true + cmake .. -DBUILD_PYTHON_BINDINGS=true -DPYBIND11_PYTHON_VERSION=2.7 -DCHECK_FOR_UPDATES=true cmake --build . --config $LRS_BUILD_CONFIG -- -j4 - cd ../wrappers/nodejs/ && npm install && cd - - Mac_cpp: runs-on: macos-10.15 diff --git a/CMake/lrs_options.cmake b/CMake/lrs_options.cmake index 3e54a3b382..0c088e9cfe 100644 --- a/CMake/lrs_options.cmake +++ b/CMake/lrs_options.cmake @@ -25,7 +25,6 @@ option(BUILD_MATLAB_BINDINGS "Build Matlab bindings" OFF) option(BUILD_UNITY_BINDINGS "Copy the unity project to the build folder with the required dependencies" OFF) option(BUILD_OPENVINO_EXAMPLES "Build Intel OpenVINO Toolkit examples - requires INTEL_OPENVINO_DIR" OFF) option(BUILD_OPEN3D_EXAMPLES "Build Open3D examples" OFF) -option(BUILD_NODEJS_BINDINGS "Build Node.js bindings" OFF) option(BUILD_OPENNI2_BINDINGS "Build OpenNI bindings" OFF) option(IMPORT_DEPTH_CAM_FW "Download the latest firmware for the depth cameras" ON) option(BUILD_CV_KINFU_EXAMPLE "Build OpenCV KinectFusion example" OFF) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6fe055350d..505972f195 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -64,10 +64,9 @@ The pull request will be automatically updated For example, when adding new value to [`rs2_option`](https://github.com/IntelRealSense/librealsense/blob/master/include/librealsense2/h/rs_option.h) enum, please also add it to: 1. The list of Matlab options under [`wrappers/matlab/option.m`](https://github.com/IntelRealSense/librealsense/blob/master/wrappers/matlab/option.m#L3-L46) -2. The list of Node.js options [here](https://github.com/IntelRealSense/librealsense/blob/v2.32.1/wrappers/nodejs/index.js#L4661), [here](https://github.com/IntelRealSense/librealsense/blob/v2.32.1/wrappers/nodejs/index.js#L4927) and [here](https://github.com/IntelRealSense/librealsense/blob/v2.32.1/wrappers/nodejs/src/addon.cpp#L4629-L4692) -3. The list of options for [Unreal Engine](https://github.com/IntelRealSense/librealsense/blob/v2.32.1/wrappers/unrealengine4/Plugins/RealSense/Source/RealSense/Public/RealSenseTypes.h#L56-L118) integration -4. The list of options in the C# wrapper - [`wrappers/csharp/Intel.RealSense/Types/Enums/Option.cs`](https://github.com/IntelRealSense/librealsense/blob/v2.32.1/wrappers/csharp/Intel.RealSense/Types/Enums/Option.cs) -5. The list of Java options used for Android integration - [`wrappers/android/librealsense/src/main/java/com/intel/realsense/librealsense/Option.java`](https://github.com/IntelRealSense/librealsense/blob/v2.32.1/wrappers/android/librealsense/src/main/java/com/intel/realsense/librealsense/Option.java#L4-L64) -6. The list of options in the [python](https://github.com/IntelRealSense/librealsense/blob/v2.32.1/wrappers/python/pybackend.cpp#L102-L165) wrapper +2. The list of options for [Unreal Engine](https://github.com/IntelRealSense/librealsense/blob/v2.32.1/wrappers/unrealengine4/Plugins/RealSense/Source/RealSense/Public/RealSenseTypes.h#L56-L118) integration +3. The list of options in the C# wrapper - [`wrappers/csharp/Intel.RealSense/Types/Enums/Option.cs`](https://github.com/IntelRealSense/librealsense/blob/v2.32.1/wrappers/csharp/Intel.RealSense/Types/Enums/Option.cs) +4. The list of Java options used for Android integration - [`wrappers/android/librealsense/src/main/java/com/intel/realsense/librealsense/Option.java`](https://github.com/IntelRealSense/librealsense/blob/v2.32.1/wrappers/android/librealsense/src/main/java/com/intel/realsense/librealsense/Option.java#L4-L64) +5. The list of options in the [python](https://github.com/IntelRealSense/librealsense/blob/v2.32.1/wrappers/python/pybackend.cpp#L102-L165) wrapper Once all are updated [travis-ci](https://travis-ci.org/IntelRealSense/librealsense) will give clear indication that each of the wrappers is still passing compilation. diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 3ee3bab4f3..0000000000 --- a/appveyor.yml +++ /dev/null @@ -1,146 +0,0 @@ -# Copyright (c) 2017 Intel Corporation. All rights reserved. -# Use of this source code is governed by a Apache License -# Version 2.0 license that can be found in the LICENSE file. -version: 2.1.{build} -branches: - only: - - development -skip_tags: true -environment: - nodejs_version: "6" -image: Visual Studio 2015 -clone_folder: c:\projects\librealsense -init: -- ps: >- - $startTime = (Get-Date) - - echo "Script started on $startTime" -- cmd: -install: -- ps: Install-Product node $env:nodejs_version -- cmd: >- - cd c:\projects\librealsense\.. && git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git - - set OLDPATH=%PATH% && set PATH=%PATH%;c:\projects\depot_tools - - cd c:\projects\librealsense\wrappers\nodejs\tools && npm install - - cd c:\projects\librealsense\wrappers\nodejs && node .\tools\linter.js && set PATH=%OLDPATH% && set OLDPATH= -before_build: -- cmd: >- - cd c:\projects\librealsense && mkdir build && cd build - - cmake .. -DBUILD_EXAMPLES=true -DBUILD_PYTHON_BINDINGS=true -DBUILD_NODEJS_BINDINGS:BOOL=true -DBUILD_UNIT_TESTS:BOOL=true -build: - project: ./build/librealsense2.sln - parallel: true # Is not in use on "Free" plans - https://github.com/appveyor/ci/issues/216. Leaved for future consideration - verbosity: minimal - -#Unit-Test Suite -# Each successful build will invoke a set of predefined unit-test that will run from recorded live test sessions -# The records are available for download from the location specified in the tests, and are arranged in the following convention -# | -# |---| .. -# | | Records.txt -# | | -# | | single_cam -# | | .. -# | | Recorded_Test_1 -# | | Recorded_Test_2 -# | | ...... -# | -# | | multi_cam -# | | .. -# | | Recorded_Test_3 -# | | Recorded_Test_4 -# | | ...... -# | -# The content of Records.txt is a list of all record paths one per line, e.g: -# single_cam/Recorded_Test_1 -# single_cam/Recorded_Test_2 -# multi_cam/Recorded_Test_3 -# multi_cam/Recorded_Test_4 -# -test_script: -- ps: >- - $url_records_path = "https://librealsense.intel.com/rs-tests/lrs_2.8.3/" - - $url_records_list = $url_records_path + "records.txt" - - $out_records_list = "records.txt" - - Invoke-WebRequest -Uri $url_records_list -OutFile $out_records_list - - $records = Get-Content $out_records_list - - mkdir single_cam - - mkdir multi_cam - - foreach ($element in $records) - { - - $url_cur = $url_records_path + $element - - Invoke-WebRequest -Uri $url_cur -OutFile $element - } - - $test_failed = @() - - & cmd.exe /c C:/projects/librealsense/build/Debug/live-test.exe -d yes -i [software-device] - - if ($LASTEXITCODE -ne 0) - { - $test_failed += "software-device" - } - - foreach ($element in $records) - { - - $url_cur = $url_records_path + $element - - & cmd.exe /c C:/projects/librealsense/build/Debug/live-test.exe from $element -d yes -i - - if ($LASTEXITCODE -ne 0) - { - $test_failed += $element - } - } - - if ($test_failed.length -ne 0) - { - $err_msg = "The following tests failed: " - - foreach ($elem in $test_failed) - { - - $err_msg = $err_msg + $elem + ", " - - } - - throw $err_msg - } - # TODO(halton): Add unit test for Node.js binding - -#---------------------------------# -# global handlers # -#---------------------------------# - -# on successful build -on_success: -- ps: >- - echo Script completed successfuly - -# on build failure -on_failure: -- ps: >- - echo "Script Failed" - -# after build failure or success -on_finish: -- ps: >- - $endTime = (Get-Date) - - echo "Ended on $endTime" - - ($endTime-$startTime).ToString('''Execution time: ''mm'' min ''ss'' sec''') diff --git a/readme.md b/readme.md index 074e254455..a5da602576 100644 --- a/readme.md +++ b/readme.md @@ -52,7 +52,7 @@ The librealsense port in vcpkg is kept up to date by Microsoft team members and | **[Depth Quality Tool](./tools/depth-quality)** | This application allows you to test the camera’s depth quality, including: standard deviation from plane fit, normalized RMS – the subpixel accuracy, distance accuracy and fill rate. You should be able to easily get and interpret several of the depth quality metrics and record and save the data for offline analysis. |[**Depth.Quality.Tool.exe**](https://github.com/IntelRealSense/librealsense/releases) | | **[Debug Tools](./tools/)** | Device enumeration, FW logger, etc as can be seen at the tools directory | Included in [**Intel.RealSense.SDK.exe**](https://github.com/IntelRealSense/librealsense/releases)| | **[Code Samples](./examples)** |These simple examples demonstrate how to easily use the SDK to include code snippets that access the camera into your applications. Check some of the [**C++ examples**](./examples) including capture, pointcloud and more and basic [**C examples**](./examples/C) | Included in [**Intel.RealSense.SDK.exe**](https://github.com/IntelRealSense/librealsense/releases) | -| **[Wrappers](https://github.com/IntelRealSense/librealsense/tree/development/wrappers)** | [Python](./wrappers/python), [C#/.NET](./wrappers/csharp), [Node.js](./wrappers/nodejs) API, as well as integration with the following 3rd-party technologies: [ROS1](https://github.com/IntelRealSense/realsense-ros/tree/ros1-legacy), [ROS2](https://github.com/IntelRealSense/realsense-ros/tree/ros2-development), [LabVIEW](./wrappers/labview), [OpenCV](./wrappers/opencv), [PCL](./wrappers/pcl), [Unity](./wrappers/unity), [Matlab](./wrappers/matlab), [OpenNI](./wrappers/openni2), [UnrealEngine4](./wrappers/unrealengine4) and more to come. | | +| **[Wrappers](https://github.com/IntelRealSense/librealsense/tree/development/wrappers)** | [Python](./wrappers/python), [C#/.NET](./wrappers/csharp) API, as well as integration with the following 3rd-party technologies: [ROS1](https://github.com/IntelRealSense/realsense-ros/tree/ros1-legacy), [ROS2](https://github.com/IntelRealSense/realsense-ros/tree/ros2-development), [LabVIEW](./wrappers/labview), [OpenCV](./wrappers/opencv), [PCL](./wrappers/pcl), [Unity](./wrappers/unity), [Matlab](./wrappers/matlab), [OpenNI](./wrappers/openni2), [UnrealEngine4](./wrappers/unrealengine4) and more to come. | | ## Ready to Hack! diff --git a/wrappers/CMakeLists.txt b/wrappers/CMakeLists.txt index abf75abf33..dff91af8f4 100644 --- a/wrappers/CMakeLists.txt +++ b/wrappers/CMakeLists.txt @@ -13,9 +13,6 @@ if (BUILD_PYTHON_BINDINGS OR BUILD_PYTHON_DOCS) endif() -if (BUILD_NODEJS_BINDINGS) - add_subdirectory(nodejs) -endif() if (BUILD_CV_EXAMPLES) add_subdirectory(opencv) diff --git a/wrappers/nodejs/.eslintrc.json b/wrappers/nodejs/.eslintrc.json deleted file mode 100644 index 87e3147bb6..0000000000 --- a/wrappers/nodejs/.eslintrc.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "extends": "google", - "parserOptions": { - "ecmaVersion": 2017 - }, - "plugins": [ - "header" - ], - "rules": { - "header/header": [2, "line", - [{"pattern": "^ Copyright \\(c\\) 201\\d Intel Corporation\\. All rights reserved\\.$"}, - {"pattern": "^ Use of this source code is governed by an Apache 2\\.0 license$"}, - {"pattern": "^ that can be found in the LICENSE file\\.$"}]], - "max-len": ["error", 100, 2, { "ignoreUrls": true }], - "quotes": ["error", "single"], - "require-jsdoc": ["error", { - "require": { - "FunctionDeclaration": false, - "MethodDefinition": false, - "ClassDeclaration": false - } - }] - } -} diff --git a/wrappers/nodejs/.gitignore b/wrappers/nodejs/.gitignore deleted file mode 100644 index c6de385ae6..0000000000 --- a/wrappers/nodejs/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -# Ignore files -build -doc/* -node_modules/ -*.png -*.csv -dist - -# Uningore files -!.eslintrc.json -!doc/jsdoc-template -!package-lock.json -!package.json diff --git a/wrappers/nodejs/.jshintrc b/wrappers/nodejs/.jshintrc deleted file mode 100644 index 6203bee692..0000000000 --- a/wrappers/nodejs/.jshintrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "esversion": 6, - "node": true -} diff --git a/wrappers/nodejs/CMakeLists.txt b/wrappers/nodejs/CMakeLists.txt deleted file mode 100644 index 94e8ffa2c1..0000000000 --- a/wrappers/nodejs/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (c) 2017 Intel Corporation. All rights reserved. -# Use of this source code is governed by an Apache 2.0 license -# that can be found in the LICENSE file. - -cmake_minimum_required(VERSION 3.1.0) - -project(RealsenseNodeJSWrappers) - -# Compile realsense addon -add_custom_command( - OUTPUT ${PROJECT_SOURCE_DIR}/build/Release/node_librealsense.node - COMMAND env GYP_DEFINES="vs_configuration=$" npm install - DEPENDS realsense2 index.js binding.gyp package.json src/addon.cpp - WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" -) -add_custom_target( - BUILD_NODE_ADDON ALL - DEPENDS ${PROJECT_SOURCE_DIR}/build/Release/node_librealsense.node -) -set_target_properties(BUILD_NODE_ADDON PROPERTIES FOLDER Wrappers/NodeJS) - -add_custom_target(RealsenseNodeJSWrappers) -set_target_properties(RealsenseNodeJSWrappers PROPERTIES FOLDER Wrappers/NodeJS) - diff --git a/wrappers/nodejs/README.md b/wrappers/nodejs/README.md deleted file mode 100644 index 40b7119f44..0000000000 --- a/wrappers/nodejs/README.md +++ /dev/null @@ -1,147 +0,0 @@ -# librealsense2 Node.js Wrapper -This is the Node.js wrapper for the C++ `librealsense2` for Intel® RealSense™ depth cameras (D400 series and the SR300). - -## Notice: Before You Go Further ## - -**To librealsense contributors**: this document is for developers who want to fork [librealsense](https://github.com/IntelRealSense/librealsense) and make changes to source code. (pull requests are welcome) - -**To Node.js users**: if you're using Node.js and want to use [Node.js librealsense API](https://www.npmjs.com/package/node-librealsense), please use the following command to install it directly: -``` -npm install --save node-librealsense -``` -If it fails to install, please refer to [install prerequisites](https://www.npmjs.com/package/node-librealsense#1-install-prerequisites). Usage examples can be found in `node_modules/node-librealsense/examples` dir. - -# 1. Build from Source # - -## 1.1. Install Build Prerequisites - -### Install Node.js - -#### Ubuntu 16.04 -In Ubuntu16.04, the default apt-get installed version is lower than v6.x. The following command could install the latest v6.x release: - -``` -curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash - -sudo apt-get install -y nodejs -``` -#### Windows 10 -Please download the latest .msi from [here](https://nodejs.org/en/download/) and install it. - -#### Mac OS -**Note:** OSX support for the full range of functionality offered by the SDK is not yet complete. - -Install the [Homebrew package manager](http://brew.sh/) via terminal if not installed, then run the following command to install node: -``` -brew install node -``` - -#### Verfication -The version can be checked through this command: - -``` -node -v -``` -#### Install required modules -After Node.js is installed, run the following command to install required modules. - -``` -npm install -g jsdoc # Required for document generation -npm install -g node-gyp # This is optional -``` - -You will probably need to setup [proxy of npm](https://docs.npmjs.com/misc/config#proxy) or [https proxy of npm](https://docs.npmjs.com/misc/config#https-proxy), if you don't have direct internet connection. - -### Setup Build Environment - -Environment is ready if you're using Ubuntu 16.04. - -If you're using Windows 10, please do the following steps: - - 1. Install Python 2.7.xx, make sure "`Add python.exe to Path`" is checked during the installation. - - 1. Install Visual Studio 2015 or 2017. The `Community` version also works. - - 1. Install CMake, make sure `CMake` is in system PATH (Choose "`Add CMake to the system PATH for all users`" or "`Add CMake to the system PATH for the current user`" during the installation). This step is for `npm install` of Node.js GLFW module that is used in `wrappers/nodejs/examples`. - -Note#1: The npm module `windows-build-tools` also works for `npm install` Node.js bindings, but it's not suffcient to build the native C++ librealsense2. - -Note#2: for Node.js GLFW module, add `msbuild` to system PATH, e.g "`C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin`" - -Note#3: When running `Node.js` 6.x, you might need to [upgrade npm-bundled `node-gyp`](https://github.com/nodejs/node-gyp/wiki/Updating-npm%27s-bundled-node-gyp) to support Visual Studio 2017 (if you're using it) - -## 1.2. Build Native C++ `librealsense` ## - -Please refer to [Linux installation doc](../../doc/installation.md) or [Windows installation doc](../../doc/installation_windows.md) or [Mac OS installation doc](../../doc/installation_osx.md) to build native C++ librealsense2. - -## 1.3. Build Node.js Module/Addon ## - -There are two options to do it: "manually bulid" or "build with CMake". -The former one is for `Node.js` language binding developers who frequently change module/addon source code; the latter one is for all-in-one build scenarios. - -### Manually Build - -After C++ `librealsense` library is Built, run the following commands: - -``` -cd wrappers/nodejs -npm install -``` -Note: on Windows only, the default libraries are taken from the librealsense Debug build output. You can specify from which build configuration to obtain the sources by installing with the vs_configuration flag. e.g: ``` npm install --vs_configuration=Release ``` or alternatively ``` npm install --vs_configuration=Debug # this is the default for windows ``` -### Build with CMake - -Before building C++ `librealsense` library, enable the following option when calling `cmake`. -``` -cmake -DBUILD_NODEJS_BINDINGS=1 -make # Will build both C++ library & Node.js binding. -``` - - -Note: when doing "Build with CMake" on Windows, `node-gyp` module of 'npm install' command requires one or many of the following Visual Studio 2017 components (if you're using it): - - `.NET Framework 4.7 development tools` - - `.NET Framework 4.6.2 development tools` - - `.NET Framework 4-4.6 development tools` - -If it still doens't work, try pass an environment variable to `node-gyp`: `set GYP_MSVS_VERSION=2015` - -# 2. Run Examples - -When Node.js wrapper is built, you can run examples to see if it works. Plug in your Intel® RealSense™ camera and run the following commands - -``` -cd wrappers/nodejs/examples -npm install -node nodejs-capture.js -``` - -# 3. API Reference Document -Open `wrappers/nodejs/doc/index.html` for full reference document. If it isn't there, run the following commands to generate it: - -``` -cd wrappers/nodejs -node scripts/generate-doc.js -``` - -# 4. Contribution -## Coding style guideline -We're following [Chromium coding style](https://chromium.googlesource.com/chromium/src/+/master/styleguide/styleguide.md) for different languages: [C++](https://chromium.googlesource.com/chromium/src/+/master/styleguide/c++/c++.md), [Python](https://google.github.io/styleguide/pyguide.html) and [JavaScript](https://google.github.io/styleguide/javascriptguide.xml). - -### Run linter - 1. Install [depot_tools](https://www.chromium.org/developers/how-tos/install-depot-tools) and added to `PATH` env. - 1. Install Required npm modules, `cd src/tools && npm install`. - 1. Run `./tools/linter.js` before submitting your code. - -## Commit message guideline -We use same [Chromium commit log guideline](https://www.chromium.org/developers/contributing-code) and [Github closing isses via commit messages](https://help.github.com/articles/closing-issues-via-commit-messages/). Use the following form: - -``` -Summary of change. - -Longer description of change addressing as appropriate: why the change is made, -context if it is part of many changes, description of previous behavior and -newly introduced differences, etc. - -Long lines should be wrapped to 80 columns for easier log message viewing in -terminals. - -Fixes #123456 -``` diff --git a/wrappers/nodejs/binding.gyp b/wrappers/nodejs/binding.gyp deleted file mode 100644 index ae7bcc5497..0000000000 --- a/wrappers/nodejs/binding.gyp +++ /dev/null @@ -1,129 +0,0 @@ -{ - 'variables': { - 'configuration%': '${BUILDTYPE}', - 'build_arch': '). -2. Click on the 'Webfont Kit' tab. -3. Either leave the subset drop-down as 'Western Latin (Default)', or, if we decide we need more glyphs, than change it to 'No Subsetting'. -4. Click the 'DOWNLOAD @FONT-FACE KIT' button. -5. For each typeface variant we plan to use, copy the 'eot', 'svg' and 'woff' files into the 'templates/default/static/fonts' directory. diff --git a/wrappers/nodejs/doc/jsdoc-template/publish.js b/wrappers/nodejs/doc/jsdoc-template/publish.js deleted file mode 100644 index 304913c6c5..0000000000 --- a/wrappers/nodejs/doc/jsdoc-template/publish.js +++ /dev/null @@ -1,703 +0,0 @@ -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -const doop = require('jsdoc/util/doop'); -const env = require('jsdoc/env'); -const fs = require('jsdoc/fs'); -const helper = require('jsdoc/util/templateHelper'); -const logger = require('jsdoc/util/logger'); -const path = require('jsdoc/path'); -const taffy = require('taffydb').taffy; -const template = require('jsdoc/template'); -const util = require('util'); - -let htmlsafe = helper.htmlsafe; -let linkto = helper.linkto; -let resolveAuthorLinks = helper.resolveAuthorLinks; -let hasOwnProp = Object.prototype.hasOwnProperty; - -let data; -let view; - -let outdir = path.normalize(env.opts.destination); - -function find(spec) { - return helper.find(data, spec); -} - -function tutoriallink(tutorial) { - return helper.toTutorial(tutorial, null, { - tag: 'em', - classname: 'disabled', - prefix: 'Tutorial: ', - }); -} - -function getAncestorLinks(doclet) { - return helper.getAncestorLinks(data, doclet); -} - -function hashToLink(doclet, hash) { - let url; - - if ( !/^(#.+)/.test(hash) ) { - return hash; - } - - url = helper.createLink(doclet); - url = url.replace(/(#.+|$)/, hash); - - return '' + hash + ''; -} - -function needsSignature(doclet) { - let needsSig = false; - - // function and class definitions always get a signature - if (doclet.kind === 'function' || doclet.kind === 'class') { - needsSig = true; - } else if (doclet.kind === 'typedef' && - doclet.type && doclet.type.names && - doclet.type.names.length) { - // typedefs that contain functions get a signature, too - for (let i = 0, l = doclet.type.names.length; i < l; i++) { - if (doclet.type.names[i].toLowerCase() === 'function') { - needsSig = true; - break; - } - } - } else if (doclet.kind === 'namespace' && doclet.meta && doclet.meta.code && - doclet.meta.code.type && doclet.meta.code.type.match(/[Ff]unction/)) { - // and namespaces that are functions get a signature (but finding them is a - // bit messy) - needsSig = true; - } - - return needsSig; -} - -function getSignatureAttributes(item) { - let attributes = []; - - if (item.optional) { - attributes.push('opt'); - } - - if (item.nullable === true) { - attributes.push('nullable'); - } else if (item.nullable === false) { - attributes.push('non-null'); - } - - return attributes; -} - -function updateItemName(item) { - let attributes = getSignatureAttributes(item); - let itemName = item.name || ''; - - if (item.variable) { - itemName = '…' + itemName; - } - - if (attributes && attributes.length) { - itemName = util.format( '%s%s', itemName, - attributes.join(', ') ); - } - - return itemName; -} - -function addParamAttributes(params) { - return params.filter(function(param) { - return param.name && param.name.indexOf('.') === -1; - }).map(updateItemName); -} - -function buildItemTypeStrings(item) { - let types = []; - - if (item && item.type && item.type.names) { - item.type.names.forEach(function(name) { - types.push( linkto(name, htmlsafe(name)) ); - }); - } - - return types; -} - -function buildAttribsString(attribs) { - let attribsString = ''; - - if (attribs && attribs.length) { - attribsString = htmlsafe( util.format('(%s) ', attribs.join(', ')) ); - } - - return attribsString; -} - -function addNonParamAttributes(items) { - let types = []; - - items.forEach(function(item) { - types = types.concat( buildItemTypeStrings(item) ); - }); - - return types; -} - -function addSignatureParams(f) { - let params = f.params ? addParamAttributes(f.params) : []; - - f.signature = util.format( '%s(%s)', (f.signature || ''), params.join(', ') ); -} - -function addSignatureReturns(f) { - let attribs = []; - let attribsString = ''; - let returnTypes = []; - let returnTypesString = ''; - let source = f.yields || f.returns; - - // jam all the return-type attributes into an array. this could create odd results (for example, - // if there are both nullable and non-nullable return types), but let's assume that most people - // who use multiple @return tags aren't using Closure Compiler type annotations, and vice-versa. - if (source) { - source.forEach(function(item) { - helper.getAttribs(item).forEach(function(attrib) { - if (attribs.indexOf(attrib) === -1) { - attribs.push(attrib); - } - }); - }); - - attribsString = buildAttribsString(attribs); - } - - if (source) { - returnTypes = addNonParamAttributes(source); - } - if (returnTypes.length) { - returnTypesString = util.format( ' → %s{%s}', attribsString, returnTypes.join('|') ); - } - - f.signature = '' + - (f.signature || '') + '' + - '' + - returnTypesString + ''; -} - -function addSignatureTypes(f) { - let types = f.type ? buildItemTypeStrings(f) : []; - - f.signature = (f.signature || '') + '' + - (types.length ? ' :' + types.join('|') : '') + ''; -} - -function addAttribs(f) { - let attribs = helper.getAttribs(f); - let attribsString = buildAttribsString(attribs); - - f.attribs = util.format('%s', attribsString); -} - -function shortenPaths(files, commonPrefix) { - Object.keys(files).forEach(function(file) { - files[file].shortened = files[file].resolved.replace(commonPrefix, '') - // always use forward slashes - .replace(/\\/g, '/'); - }); - - return files; -} - -function getPathFromDoclet(doclet) { - if (!doclet.meta) { - return null; - } - - return doclet.meta.path && doclet.meta.path !== 'null' ? - path.join(doclet.meta.path, doclet.meta.filename) : - doclet.meta.filename; -} - -function generate(title, docs, filename, resolveLinks) { - let docData; - let html; - let outpath; - - resolveLinks = resolveLinks !== false; - - docData = { - env: env, - title: title, - docs: docs, - }; - - outpath = path.join(outdir, filename); - html = view.render('container.tmpl', docData); - - if (resolveLinks) { - html = helper.resolveLinks(html); // turn {@link foo} into foo - } - - fs.writeFileSync(outpath, html, 'utf8'); -} - -function generateSourceFiles(sourceFiles, encoding) { - encoding = encoding || 'utf8'; - Object.keys(sourceFiles).forEach(function(file) { - let source; - // links are keyed to the shortened path in each doclet's `meta.shortpath` property - let sourceOutfile = helper.getUniqueFilename(sourceFiles[file].shortened); - - helper.registerLink(sourceFiles[file].shortened, sourceOutfile); - - try { - source = { - kind: 'source', - code: helper.htmlsafe( fs.readFileSync(sourceFiles[file].resolved, encoding) ), - }; - } catch (e) { - logger.error('Error while generating source file %s: %s', file, e.message); - } - - generate('Source: ' + sourceFiles[file].shortened, [source], sourceOutfile, false); - }); -} - -/** - * Look for classes or functions with the same name as modules (which indicates that the module - * exports only that class or function), then attach the classes or functions to the `module` - * property of the appropriate module doclets. The name of each class or function is also updated - * for display purposes. This function mutates the original arrays. - * - * @private - * @param {Array.} doclets - The array of classes and functions to - * check. - * @param {Array.} modules - The array of module doclets to search. - */ -function attachModuleSymbols(doclets, modules) { - let symbols = {}; - - // build a lookup table - doclets.forEach(function(symbol) { - symbols[symbol.longname] = symbols[symbol.longname] || []; - symbols[symbol.longname].push(symbol); - }); - - modules.forEach(function(module) { - if (symbols[module.longname]) { - module.modules = symbols[module.longname] - // Only show symbols that have a description. Make an exception for classes, because - // we want to show the constructor-signature heading no matter what. - .filter(function(symbol) { - return symbol.description || symbol.kind === 'class'; - }) - .map(function(symbol) { - symbol = doop(symbol); - - if (symbol.kind === 'class' || symbol.kind === 'function') { - symbol.name = symbol.name.replace('module:', '(require("') + '"))'; - } - - return symbol; - }); - } - }); -} - -function buildMemberNav(items, itemHeading, itemsSeen, linktoFn) { - let nav = ''; - - if (items.length) { - let itemsNav = ''; - - items.forEach(function(item) { - let displayName; - - if ( !hasOwnProp.call(item, 'longname') ) { - itemsNav += '
  • ' + linktoFn('', item.name) + '
  • '; - } else if ( !hasOwnProp.call(itemsSeen, item.longname) ) { - if (env.conf.templates.default.useLongnameInNav) { - displayName = item.longname; - } else { - displayName = item.name; - } - itemsNav += '
  • ' + - linktoFn(item.longname, displayName.replace(/\b(module|event):/g, '')) + - '
  • '; - - itemsSeen[item.longname] = true; - } - }); - - if (itemsNav !== '') { - nav += '

    ' + itemHeading + '

      ' + itemsNav + '
    '; - } - } - - return nav; -} - -function linktoTutorial(longName, name) { - return tutoriallink(name); -} - -function linktoExternal(longName, name) { - return linkto(longName, name.replace(/(^"|"$)/g, '')); -} - -/** - * Create the navigation sidebar. - * @param {object} members The members that will be used to create the sidebar. - * @param {array} members.classes - * @param {array} members.externals - * @param {array} members.globals - * @param {array} members.mixins - * @param {array} members.modules - * @param {array} members.namespaces - * @param {array} members.tutorials - * @param {array} members.events - * @param {array} members.interfaces - * @return {string} The HTML for the navigation sidebar. - */ -function buildNav(members) { - let globalNav; - let nav = '

    Home

    '; - let seen = {}; - let seenTutorials = {}; - - nav += buildMemberNav(members.modules, 'Modules', {}, linkto); - nav += buildMemberNav(members.externals, 'Externals', seen, linktoExternal); - nav += buildMemberNav(members.classes, 'Classes', seen, linkto); - nav += buildMemberNav(members.events, 'Events', seen, linkto); - nav += buildMemberNav(members.namespaces, 'Namespaces', seen, linkto); - nav += buildMemberNav(members.mixins, 'Mixins', seen, linkto); - nav += buildMemberNav(members.tutorials, 'Tutorials', seenTutorials, linktoTutorial); - nav += buildMemberNav(members.interfaces, 'Interfaces', seen, linkto); - - if (members.globals.length) { - globalNav = ''; - - members.globals.forEach(function(g) { - if (g.kind !== 'typedef' && !hasOwnProp.call(seen, g.longname) ) { - globalNav += '
  • ' + linkto(g.longname, g.name) + '
  • '; - } - seen[g.longname] = true; - }); - - if (!globalNav) { - // turn the heading into a link so you can actually get to the global page - nav += '

    ' + linkto('global', 'Global') + '

    '; - } else { - nav += '

    Global

      ' + globalNav + '
    '; - } - } - - return nav; -} - -/** - @param {TAFFY} taffyData See . - @param {object} opts - @param {Tutorial} tutorials - */ -exports.publish = function(taffyData, opts, tutorials) { - let classes; - let conf; - let externals; - let files; - let fromDir; - let globalUrl; - let indexUrl; - let interfaces; - let members; - let mixins; - let modules; - let namespaces; - let outputSourceFiles; - let packageInfo; - let packages; - let sourceFilePaths = []; - let sourceFiles = {}; - let staticFileFilter; - let staticFilePaths; - let staticFiles; - let staticFileScanner; - let templatePath; - - data = taffyData; - - conf = env.conf.templates || {}; - conf.default = conf.default || {}; - - templatePath = path.normalize(opts.template); - view = new template.Template( path.join(templatePath, 'tmpl') ); - - // claim some special filenames in advance, so the All-Powerful Overseer of Filename Uniqueness - // doesn't try to hand them out later - indexUrl = helper.getUniqueFilename('index'); - // don't call registerLink() on this one! 'index' is also a valid longname - - globalUrl = helper.getUniqueFilename('global'); - helper.registerLink('global', globalUrl); - - // set up templating - view.layout = conf.default.layoutFile ? - path.getResourcePath(path.dirname(conf.default.layoutFile), - path.basename(conf.default.layoutFile) ) : - 'layout.tmpl'; - - // set up tutorials for helper - helper.setTutorials(tutorials); - - data = helper.prune(data); - data.sort('longname, version, since'); - helper.addEventListeners(data); - - data().each(function(doclet) { - let sourcePath; - - doclet.attribs = ''; - - if (doclet.examples) { - doclet.examples = doclet.examples.map(function(example) { - let caption; - let code; - - if (example.match(/^\s*([\s\S]+?)<\/caption>(\s*[\n\r])([\s\S]+)$/i)) { - caption = RegExp.$1; - code = RegExp.$3; - } - - return { - caption: caption || '', - code: code || example, - }; - }); - } - if (doclet.see) { - doclet.see.forEach(function(seeItem, i) { - doclet.see[i] = hashToLink(doclet, seeItem); - }); - } - - // build a list of source files - if (doclet.meta) { - sourcePath = getPathFromDoclet(doclet); - sourceFiles[sourcePath] = { - resolved: sourcePath, - shortened: null, - }; - if (sourceFilePaths.indexOf(sourcePath) === -1) { - sourceFilePaths.push(sourcePath); - } - } - }); - - // update outdir if necessary, then create outdir - packageInfo = ( find({kind: 'package'}) || [] )[0]; - if (packageInfo && packageInfo.name) { - outdir = path.join( outdir, packageInfo.name, (packageInfo.version || '') ); - } - fs.mkPath(outdir); - - // copy the template's static files to outdir - fromDir = path.join(templatePath, 'static'); - staticFiles = fs.ls(fromDir, 3); - - staticFiles.forEach(function(fileName) { - let toDir = fs.toDir( fileName.replace(fromDir, outdir) ); - - fs.mkPath(toDir); - fs.copyFileSync(fileName, toDir); - }); - - // copy user-specified static files to outdir - if (conf.default.staticFiles) { - // The canonical property name is `include`. We accept `paths` for backwards compatibility - // with a bug in JSDoc 3.2.x. - staticFilePaths = conf.default.staticFiles.include || - conf.default.staticFiles.paths || []; - staticFileFilter = new (require('jsdoc/src/filter')).Filter(conf.default.staticFiles); - staticFileScanner = new (require('jsdoc/src/scanner')).Scanner(); - - staticFilePaths.forEach(function(filePath) { - let extraStaticFiles; - - filePath = path.resolve(env.pwd, filePath); - extraStaticFiles = staticFileScanner.scan([filePath], 10, staticFileFilter); - - extraStaticFiles.forEach(function(fileName) { - let sourcePath = fs.toDir(filePath); - let toDir = fs.toDir( fileName.replace(sourcePath, outdir) ); - - fs.mkPath(toDir); - fs.copyFileSync(fileName, toDir); - }); - }); - } - - if (sourceFilePaths.length) { - sourceFiles = shortenPaths( sourceFiles, path.commonPrefix(sourceFilePaths) ); - } - data().each(function(doclet) { - let docletPath; - let url = helper.createLink(doclet); - - helper.registerLink(doclet.longname, url); - - // add a shortened version of the full path - if (doclet.meta) { - docletPath = getPathFromDoclet(doclet); - docletPath = sourceFiles[docletPath].shortened; - if (docletPath) { - doclet.meta.shortpath = docletPath; - } - } - }); - - data().each(function(doclet) { - let url = helper.longnameToUrl[doclet.longname]; - - if (url.indexOf('#') > -1) { - doclet.id = helper.longnameToUrl[doclet.longname].split(/#/).pop(); - } else { - doclet.id = doclet.name; - } - - if (needsSignature(doclet) ) { - addSignatureParams(doclet); - addSignatureReturns(doclet); - addAttribs(doclet); - } - }); - - // do this after the urls have all been generated - data().each(function(doclet) { - doclet.ancestors = getAncestorLinks(doclet); - - if (doclet.kind === 'member') { - addSignatureTypes(doclet); - addAttribs(doclet); - } - - if (doclet.kind === 'constant') { - addSignatureTypes(doclet); - addAttribs(doclet); - doclet.kind = 'member'; - } - }); - - members = helper.getMembers(data); - members.tutorials = tutorials.children; - - // output pretty-printed source files by default - outputSourceFiles = conf.default && conf.default.outputSourceFiles !== false; - - // add template helpers - view.find = find; - view.linkto = linkto; - view.resolveAuthorLinks = resolveAuthorLinks; - view.tutoriallink = tutoriallink; - view.htmlsafe = htmlsafe; - view.outputSourceFiles = outputSourceFiles; - - // once for all - view.nav = buildNav(members); - attachModuleSymbols( find({longname: {left: 'module:'}}), members.modules ); - - // generate the pretty-printed source files first so other pages can link to them - if (outputSourceFiles) { - generateSourceFiles(sourceFiles, opts.encoding); - } - - if (members.globals.length) { - generate('Global', [{kind: 'globalobj'}], globalUrl); -} - - // index page displays information from package.json and lists files - files = find({kind: 'file'}); - packages = find({kind: 'package'}); - - generate('Home', - packages.concat( - [{ - kind: 'mainpage', - readme: opts.readme, - longname: (opts.mainpagetitle) ? opts.mainpagetitle : 'Main Page', - }] - ).concat(files), indexUrl); - - // set up the lists that we'll use to generate pages - classes = taffy(members.classes); - modules = taffy(members.modules); - namespaces = taffy(members.namespaces); - mixins = taffy(members.mixins); - externals = taffy(members.externals); - interfaces = taffy(members.interfaces); - - Object.keys(helper.longnameToUrl).forEach(function(longname) { - let myClasses = helper.find(classes, {longname: longname}); - let myExternals = helper.find(externals, {longname: longname}); - let myInterfaces = helper.find(interfaces, {longname: longname}); - let myMixins = helper.find(mixins, {longname: longname}); - let myModules = helper.find(modules, {longname: longname}); - let myNamespaces = helper.find(namespaces, {longname: longname}); - - if (myModules.length) { - generate('Module: ' + myModules[0].name, myModules, helper.longnameToUrl[longname]); - } - - if (myClasses.length) { - generate('Class: ' + myClasses[0].name, myClasses, helper.longnameToUrl[longname]); - } - - if (myNamespaces.length) { - generate('Namespace: ' + myNamespaces[0].name, myNamespaces, helper.longnameToUrl[longname]); - } - - if (myMixins.length) { - generate('Mixin: ' + myMixins[0].name, myMixins, helper.longnameToUrl[longname]); - } - - if (myExternals.length) { - generate('External: ' + myExternals[0].name, myExternals, helper.longnameToUrl[longname]); - } - - if (myInterfaces.length) { - generate('Interface: ' + myInterfaces[0].name, myInterfaces, helper.longnameToUrl[longname]); - } - }); - - // TODO: move the tutorial functions to templateHelper.js - function generateTutorial(title, tutorial, filename) { - let tutorialData = { - title: title, - header: tutorial.title, - content: tutorial.parse(), - children: tutorial.children, - }; - let tutorialPath = path.join(outdir, filename); - let html = view.render('tutorial.tmpl', tutorialData); - - // yes, you can use {@link} in tutorials too! - html = helper.resolveLinks(html); // turn {@link foo} into foo - - fs.writeFileSync(tutorialPath, html, 'utf8'); - } - - // tutorials can have only one parent so there is no risk for loops - function saveChildren(node) { - node.children.forEach(function(child) { - generateTutorial('Tutorial: ' + child.title, child, helper.tutorialToUrl(child.name)); - saveChildren(child); - }); - } - - saveChildren(tutorials); -}; diff --git a/wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-Bold-webfont.eot b/wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-Bold-webfont.eot deleted file mode 100644 index 5d20d916338a5890a033952e2e07ba7380f5a7d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19544 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 diff --git a/wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-Bold-webfont.svg b/wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-Bold-webfont.svg deleted file mode 100644 index 3ed7be4bc5..0000000000 --- a/wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-Bold-webfont.svg +++ /dev/null @@ -1,1830 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-Bold-webfont.woff b/wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-Bold-webfont.woff deleted file mode 100644 index 1205787b0ed50db71ebd4f8a7f85d106721ff258..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22432 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 ig3W - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-BoldItalic-webfont.woff b/wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-BoldItalic-webfont.woff deleted file mode 100644 index ed760c0628b6a0026041f5b8bba466a0471fd2e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23048 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-Italic-webfont.woff b/wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-Italic-webfont.woff deleted file mode 100644 index ff652e64356b538c001423b6aedefcf1ee66cd17..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23188 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 diff --git a/wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-Light-webfont.svg b/wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-Light-webfont.svg deleted file mode 100644 index 11a472ca8a..0000000000 --- a/wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-Light-webfont.svg +++ /dev/null @@ -1,1831 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-Light-webfont.woff b/wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-Light-webfont.woff deleted file mode 100644 index e786074813a27d0a7a249047832988d5bf0fe756..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22248 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 diff --git a/wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-LightItalic-webfont.eot b/wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-LightItalic-webfont.eot deleted file mode 100644 index 8f445929ffb03b50e98c2a2f7d831a0cb1b276a2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20535 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 Z%0#`NexefPFV?Xj51H#Y#AC7WXn+Jg($4?@ diff --git a/wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-LightItalic-webfont.svg b/wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-LightItalic-webfont.svg deleted file mode 100644 index 431d7e3546..0000000000 --- a/wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-LightItalic-webfont.svg +++ /dev/null @@ -1,1835 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-LightItalic-webfont.woff b/wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-LightItalic-webfont.woff deleted file mode 100644 index 43e8b9e6cc061ff17fd2903075cbde12715512b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23400 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 - diff --git a/wrappers/nodejs/doc/jsdoc-template/tmpl/container.tmpl b/wrappers/nodejs/doc/jsdoc-template/tmpl/container.tmpl deleted file mode 100644 index 7491fd42e1..0000000000 --- a/wrappers/nodejs/doc/jsdoc-template/tmpl/container.tmpl +++ /dev/null @@ -1,184 +0,0 @@ - - - - - - - - - -
    - -
    - -

    - -

    - -
    - - - - -
    - - - -
    - -
    -
    - - -
    - - - - - - - - - -
    - - - - - -

    Example 1? 's':'' ?>

    - - - -
    - - -

    Extends

    - - - - - -

    Requires

    - -
      -
    • -
    - - - -

    Classes

    - -
    -
    -
    -
    - - - -

    Mixins

    - -
    -
    -
    -
    - - - -

    Namespaces

    - -
    -
    -
    -
    - - - -

    Members

    - - - - - - - -

    Methods

    - - - - - - - -

    Type Definitions

    - - - - - - - - - -

    Events

    - - - - - -
    - -
    - - - diff --git a/wrappers/nodejs/doc/jsdoc-template/tmpl/details.tmpl b/wrappers/nodejs/doc/jsdoc-template/tmpl/details.tmpl deleted file mode 100644 index 4a5bd49fb9..0000000000 --- a/wrappers/nodejs/doc/jsdoc-template/tmpl/details.tmpl +++ /dev/null @@ -1,143 +0,0 @@ -" + data.defaultvalue + ""; - defaultObjectClass = ' class="object-value"'; -} -?> - - -
    Properties:
    - - - - - -
    - - -
    Version:
    -
    - - - -
    Since:
    -
    - - - -
    Inherited From:
    -
    • - -
    - - - -
    Overrides:
    -
    • - -
    - - - -
    Implementations:
    -
      - -
    • - -
    - - - -
    Implements:
    -
      - -
    • - -
    - - - -
    Mixes In:
    - -
      - -
    • - -
    - - - -
    Deprecated:
    • Yes
    - - - -
    Author:
    -
    -
      -
    • -
    -
    - - - - - - - - -
    License:
    -
    - - - -
    Default Value:
    -
      - > -
    - - - -
    Source:
    -
    • - , -
    - - - -
    Tutorials:
    -
    -
      -
    • -
    -
    - - - -
    See:
    -
    -
      -
    • -
    -
    - - - -
    To Do:
    -
    -
      -
    • -
    -
    - -
    diff --git a/wrappers/nodejs/doc/jsdoc-template/tmpl/example.tmpl b/wrappers/nodejs/doc/jsdoc-template/tmpl/example.tmpl deleted file mode 100644 index e87caa5b72..0000000000 --- a/wrappers/nodejs/doc/jsdoc-template/tmpl/example.tmpl +++ /dev/null @@ -1,2 +0,0 @@ - -
    diff --git a/wrappers/nodejs/doc/jsdoc-template/tmpl/examples.tmpl b/wrappers/nodejs/doc/jsdoc-template/tmpl/examples.tmpl deleted file mode 100644 index 04d975e96d..0000000000 --- a/wrappers/nodejs/doc/jsdoc-template/tmpl/examples.tmpl +++ /dev/null @@ -1,13 +0,0 @@ - -

    - -
    - \ No newline at end of file diff --git a/wrappers/nodejs/doc/jsdoc-template/tmpl/exceptions.tmpl b/wrappers/nodejs/doc/jsdoc-template/tmpl/exceptions.tmpl deleted file mode 100644 index 9cef6c7d95..0000000000 --- a/wrappers/nodejs/doc/jsdoc-template/tmpl/exceptions.tmpl +++ /dev/null @@ -1,32 +0,0 @@ - - -
    -
    -
    - -
    -
    -
    -
    -
    -
    - Type -
    -
    - -
    -
    -
    -
    -
    - -
    - - - - - -
    - diff --git a/wrappers/nodejs/doc/jsdoc-template/tmpl/layout.tmpl b/wrappers/nodejs/doc/jsdoc-template/tmpl/layout.tmpl deleted file mode 100644 index 8a9a6b9659..0000000000 --- a/wrappers/nodejs/doc/jsdoc-template/tmpl/layout.tmpl +++ /dev/null @@ -1,38 +0,0 @@ - - - - - JSDoc: <?js= title ?> - - - - - - - - - - -
    - -

    - - -
    - - - -
    - -
    - - - - - diff --git a/wrappers/nodejs/doc/jsdoc-template/tmpl/mainpage.tmpl b/wrappers/nodejs/doc/jsdoc-template/tmpl/mainpage.tmpl deleted file mode 100644 index 64e9e5943a..0000000000 --- a/wrappers/nodejs/doc/jsdoc-template/tmpl/mainpage.tmpl +++ /dev/null @@ -1,14 +0,0 @@ - - - -

    - - - -
    -
    -
    - diff --git a/wrappers/nodejs/doc/jsdoc-template/tmpl/members.tmpl b/wrappers/nodejs/doc/jsdoc-template/tmpl/members.tmpl deleted file mode 100644 index 154c17b6ee..0000000000 --- a/wrappers/nodejs/doc/jsdoc-template/tmpl/members.tmpl +++ /dev/null @@ -1,38 +0,0 @@ - -

    - - -

    - - - -
    - -
    - - - -
    Type:
    -
      -
    • - -
    • -
    - - - - - -
    Fires:
    -
      -
    • -
    - - - -
    Example 1? 's':'' ?>
    - - diff --git a/wrappers/nodejs/doc/jsdoc-template/tmpl/method.tmpl b/wrappers/nodejs/doc/jsdoc-template/tmpl/method.tmpl deleted file mode 100644 index 718a29ed2f..0000000000 --- a/wrappers/nodejs/doc/jsdoc-template/tmpl/method.tmpl +++ /dev/null @@ -1,119 +0,0 @@ - - - -

    Constructor

    - - - -

    - - - -

    - - - - -
    - -
    - - - -
    Extends:
    - - - - -
    Type:
    -
      -
    • - -
    • -
    - - - -
    This:
    -
    - - - -
    Parameters:
    - - - - - - -
    Requires:
    -
      -
    • -
    - - - -
    Fires:
    -
      -
    • -
    - - - -
    Listens to Events:
    -
      -
    • -
    - - - -
    Listeners of This Event:
    -
      -
    • -
    - - - -
    Throws:
    - 1) { ?>
      -
    • -
    - - - - -
    Returns:
    - 1) { ?>
      -
    • -
    - - - - -
    Yields:
    - 1) { ?>
      -
    • -
    - - - - -
    Example 1? 's':'' ?>
    - - diff --git a/wrappers/nodejs/doc/jsdoc-template/tmpl/params.tmpl b/wrappers/nodejs/doc/jsdoc-template/tmpl/params.tmpl deleted file mode 100644 index 1fb4049c1e..0000000000 --- a/wrappers/nodejs/doc/jsdoc-template/tmpl/params.tmpl +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    NameTypeAttributesDefaultDescription
    - - - - - - <optional>
    - - - - <nullable>
    - - - - <repeatable>
    - -
    - - - - -
    Properties
    - -
    diff --git a/wrappers/nodejs/doc/jsdoc-template/tmpl/properties.tmpl b/wrappers/nodejs/doc/jsdoc-template/tmpl/properties.tmpl deleted file mode 100644 index 40e0909712..0000000000 --- a/wrappers/nodejs/doc/jsdoc-template/tmpl/properties.tmpl +++ /dev/null @@ -1,108 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    NameTypeAttributesDefaultDescription
    - - - - - - <optional>
    - - - - <nullable>
    - -
    - - - - -
    Properties
    -
    diff --git a/wrappers/nodejs/doc/jsdoc-template/tmpl/returns.tmpl b/wrappers/nodejs/doc/jsdoc-template/tmpl/returns.tmpl deleted file mode 100644 index d07045920a..0000000000 --- a/wrappers/nodejs/doc/jsdoc-template/tmpl/returns.tmpl +++ /dev/null @@ -1,19 +0,0 @@ - -
    - -
    - - - -
    -
    - Type -
    -
    - -
    -
    - \ No newline at end of file diff --git a/wrappers/nodejs/doc/jsdoc-template/tmpl/source.tmpl b/wrappers/nodejs/doc/jsdoc-template/tmpl/source.tmpl deleted file mode 100644 index e559b5d103..0000000000 --- a/wrappers/nodejs/doc/jsdoc-template/tmpl/source.tmpl +++ /dev/null @@ -1,8 +0,0 @@ - -
    -
    -
    -
    -
    \ No newline at end of file diff --git a/wrappers/nodejs/doc/jsdoc-template/tmpl/tutorial.tmpl b/wrappers/nodejs/doc/jsdoc-template/tmpl/tutorial.tmpl deleted file mode 100644 index 88a0ad52aa..0000000000 --- a/wrappers/nodejs/doc/jsdoc-template/tmpl/tutorial.tmpl +++ /dev/null @@ -1,19 +0,0 @@ -
    - -
    - 0) { ?> -
      -
    • -
    - - -

    -
    - -
    - -
    - -
    diff --git a/wrappers/nodejs/doc/jsdoc-template/tmpl/type.tmpl b/wrappers/nodejs/doc/jsdoc-template/tmpl/type.tmpl deleted file mode 100644 index ec2c6c0df7..0000000000 --- a/wrappers/nodejs/doc/jsdoc-template/tmpl/type.tmpl +++ /dev/null @@ -1,7 +0,0 @@ - - -| - \ No newline at end of file diff --git a/wrappers/nodejs/examples/glfw-window.js b/wrappers/nodejs/examples/glfw-window.js deleted file mode 100644 index 55c728f2a9..0000000000 --- a/wrappers/nodejs/examples/glfw-window.js +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -const glfw = require('node-12-glfw-3'); -const rs2 = require('../index.js'); -const now = require('performance-now'); - -class FPSCounter { - // fps is reported to console for each interval frames - constructor(interval = 10) { - this.cnt = 0; - this.interval = interval; - this.timestamps = []; - } - - count() { - this.timestamps[this.cnt] = now(); - this.cnt++; - if (this.cnt === this.interval) { - this._report(); - this.reset(); - } - } - - reset() { - this.cnt = 0; - } - - _report() { - let duration = this.timestamps[this.cnt - 1] - this.timestamps[0]; - let fps = Math.round((this.cnt - 1) / (duration / 1000)); - console.log('FPS: ', fps); - } -} - -/* eslint-disable new-cap */ -class GLFWWindow { - // TODO(kenny-y): Check disabled jshint errors - constructor(width = 1280, height = 720, title = 'GLFW Window') { - this.width_ = width; - this.height_ = height; - - glfw.Init(); - glfw.DefaultWindowHints(); - this.window_ = glfw.CreateGLFWWindow(width, height, title); - glfw.MakeContextCurrent(this.window_); - - // Enable vertical sync (on cards that support it) - glfw.SwapInterval(1); // 0 for vsync off - this.enableFps = false; - this.fpsCounter = new FPSCounter(); - } - - // Call this method to show or not to show fps to console - showFPS(showOrNot) { - this.enableFps = showOrNot; - this.fpsCounter.reset(); - } - - get width() { - return this.width_; - } - - get height() { - return this.height_; - } - - get window() { - return this.window_; - } - - shouldWindowClose() { - let result = glfw.WindowShouldClose(this.window_); - if (! result) { - result = glfw.GetKey(this.window_, glfw.KEY_ESCAPE); - } - return result; - } - - beginPaint() { - // We don't clear buffer for now, because - // there is currently sync issue between depth & color stream - // - // glfw.ClearColorBuffer(); - } - - endPaint() { - glfw.PopMatrix(); - glfw.SwapBuffers(this.window); - glfw.PollEvents(); - glfw.PushMatrix(); - glfw.Ortho(0, this.width_, this.height_, 0, -1, +1); - if (this.enableFps) { - this.fpsCounter.count(); - } - } - - destroy() { - glfw.DestroyWindow(this.window_); - glfw.Terminate(); - this.window_ = undefined; - } - - setKeyCallback(callback) { - glfw.setKeyCallback(this.window_, function(key, scancode, action, modes) { - callback(key, scancode, action, modes); - }); - } -} - -class Rect { - constructor(x, y, w, h) { - this.x = x; - this.y = y; - this.w = w; - this.h = h; - } - - adjustRatio(size) { - let newH = this.h; - let newW = this.h * size.x / size.y; - if (newW > this.w) { - let scale = this.w / newW; - newW *= scale; - newH *= scale; - } - return new Rect(this.x + (this.w-newW) / 2, this.y + (this.h - newH) / 2, newW, newH); - } -} - -class Texture { - constructor() { - this.glHandle = 0; - } - - render(videoFrame, rect) { - this.upload(videoFrame); - this.show(rect); - } - - upload(videoFrame) { - if (!this.glHandle) { - this.glHandle = glfw.genTexture(); - } - glfw.uploadAsTexture( - this.glHandle, - new Uint8Array(videoFrame.getData().buffer), - videoFrame.width, - videoFrame.height, - rs2.format.formatToString(videoFrame.format)); - this.stream = videoFrame.stream; - } - - show(rect) { - glfw.showInRect(this.glHandle, rect.x, rect.y, rect.w, rect.h); - } -} - -module.exports.GLFWWindow = GLFWWindow; -module.exports.glfw = glfw; -module.exports.Rect = Rect; -module.exports.Texture = Texture; diff --git a/wrappers/nodejs/examples/nodejs-align.js b/wrappers/nodejs/examples/nodejs-align.js deleted file mode 100755 index abd08b435c..0000000000 --- a/wrappers/nodejs/examples/nodejs-align.js +++ /dev/null @@ -1,124 +0,0 @@ -#!/usr/bin/env node - -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -const rs2 = require('../index.js'); -const {GLFWWindow} = require('./glfw-window.js'); -const {Rect} = require('./glfw-window.js'); -const {Texture} = require('./glfw-window.js'); - -function tryGetDepthScale(dev) { - const sensors = dev.querySensors(); - for (let i = 0; i < sensors.length; i++) { - if (sensors[i] instanceof rs2.DepthSensor) { - return sensors[i].depthScale; - } - } - return undefined; -} - -function removeBackground(otherFrame, depthFrame, depthScale, clippingDist) { - let depthData = depthFrame.getData(); - let otherData = otherFrame.getData(); - const width = otherFrame.width; - const height = otherFrame.height; - const otherBpp = otherFrame.bytesPerPixel; - - for (let y = 0; y < height; y++) { - let depthPixelIndex = y * width; - for (let x = 0; x < width; x++, ++depthPixelIndex) { - let pixelDistance = depthScale * depthData[depthPixelIndex]; - if (pixelDistance <= 0 || pixelDistance > clippingDist) { - let offset = depthPixelIndex * otherBpp; - - // Set pixel to background color - for (let i = 0; i < otherBpp; i++) { - otherData[offset+i] = 0x99; - } - } - } - } -} - -// Open a GLFW window -const win = new GLFWWindow(1280, 720, 'Node.js Align Example'); - -const colorizer = new rs2.Colorizer(); -const renderer = new Texture(); -const align = new rs2.Align(rs2.stream.STREAM_COLOR); -const pipeline = new rs2.Pipeline(); -const profile = pipeline.start(pipeline.autoConfig); - -const depthScale = tryGetDepthScale(profile.getDevice()); -if (depthScale === undefined) { - console.error('Device does not have a depth sensor'); - process.exit(1); -} - -let clippingDistance = 1.0; -console.log('Press Up/Down to change the depth clipping distance.'); - -win.setKeyCallback((key, scancode, action, modes) => { - if (action != 0) return; - - if (key === 265) { - // Pressed: Up arrow key - clippingDistance += 0.1; - if (clippingDistance > 6.0) { - clippingDistance = 6.0; - } - } else if (key === 264) { - // Pressed: Down arrow key - clippingDistance -= 0.1; - if (clippingDistance < 0) { - clippingDistance = 0; - } - } - console.log('Depth clipping distance:', clippingDistance.toFixed(3)); -}); - -while (!win.shouldWindowClose()) { - const rawFrameset = pipeline.waitForFrames(); - const alignedFrameset = align.process(rawFrameset); - let colorFrame = alignedFrameset.colorFrame; - let depthFrame = alignedFrameset.depthFrame; - - if (!depthFrame) { - continue; - } - - removeBackground(colorFrame, depthFrame, depthScale, clippingDistance); - let w = win.width; - let h = win.height; - - let colorRect = new Rect(0, 0, w, h); - colorRect = colorRect.adjustRatio({ - x: colorFrame.width, - y: colorFrame.height}); - - let pipStream = new Rect(0, 0, w / 5, h / 5); - pipStream = pipStream.adjustRatio({ - x: depthFrame.width, - y: depthFrame.height}); - pipStream.x = colorRect.x + colorRect.w - pipStream.w - (Math.max(w, h) / 25); - pipStream.y = colorRect.y + colorRect.h - pipStream.h - (Math.max(w, h) / 25); - - const colorizedDepth = colorizer.colorize(depthFrame); - - win.beginPaint(); - renderer.render(colorFrame, colorRect); - renderer.upload(colorizedDepth); - renderer.show(pipStream); - win.endPaint(); -} - -pipeline.stop(); -pipeline.destroy(); -align.destroy(); - -win.destroy(); -rs2.cleanup(); diff --git a/wrappers/nodejs/examples/nodejs-capture.js b/wrappers/nodejs/examples/nodejs-capture.js deleted file mode 100755 index 9a9fedbb07..0000000000 --- a/wrappers/nodejs/examples/nodejs-capture.js +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env node - -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -const rs2 = require('../index.js'); -const {GLFWWindow} = require('./glfw-window.js'); -const {glfw} = require('./glfw-window.js'); - -// A GLFW Window to display the captured image -const win = new GLFWWindow(1280, 720, 'Node.js Capture Example'); - -// Colorizer is used to map distance in depth image into different colors -const colorizer = new rs2.Colorizer(); - -// The main work pipeline of camera -const pipeline = new rs2.Pipeline(); - -// Start the camera -pipeline.start(pipeline.autoConfig); - -while (! win.shouldWindowClose()) { - const frameset = pipeline.waitForFrames(); - // Build the color map - const depthMap = colorizer.colorize(frameset.depthFrame); - if (depthMap) { - // Paint the images onto the window - win.beginPaint(); - const color = frameset.colorFrame; - glfw.draw2x2Streams(win.window, 2, - depthMap.data, 'rgb8', depthMap.width, depthMap.height, - color.data, 'rgb8', color.width, color.height); - win.endPaint(); - } -} - -pipeline.stop(); -pipeline.destroy(); -win.destroy(); -rs2.cleanup(); diff --git a/wrappers/nodejs/examples/nodejs-pointcloud.js b/wrappers/nodejs/examples/nodejs-pointcloud.js deleted file mode 100755 index d62a153dfd..0000000000 --- a/wrappers/nodejs/examples/nodejs-pointcloud.js +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env node - -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -const rs2 = require('../index.js'); -const {GLFWWindow} = require('./glfw-window.js'); -const {glfw} = require('./glfw-window.js'); - -function drawPointCloud(win, color, points) { - win.beginPaint(); - if (points.vertices && points.textureCoordinates ) { - let count = points.size; - glfw.drawDepthAndColorAsPointCloud( - win.window, - new Uint8Array(points.vertices.buffer), - count, - new Uint8Array(points.textureCoordinates.buffer), - color.data, - color.width, - color.height, - 'rgb8'); - } - win.endPaint(); -} - -// Open a GLFW window -const win = new GLFWWindow(1280, 720, 'Node.js PointCloud Example'); -const pc = new rs2.PointCloud(); -const pipeline = new rs2.Pipeline(); - -pipeline.start(pipeline.autoConfig); - -console.log('Drag to change perspective, scroll mouse wheel to zoom in/out.'); - -while (! win.shouldWindowClose()) { - const frameSet = pipeline.waitForFrames(); - const pointsFrame = pc.calculate(frameSet.depthFrame); - pc.mapTo(frameSet.colorFrame); - drawPointCloud(win, frameSet.colorFrame, pointsFrame); -} - -pc.destroy(); -pipeline.stop(); -pipeline.destroy(); -win.destroy(); - -rs2.cleanup(); diff --git a/wrappers/nodejs/examples/nodejs-save-to-disk.js b/wrappers/nodejs/examples/nodejs-save-to-disk.js deleted file mode 100755 index a2ff881ca6..0000000000 --- a/wrappers/nodejs/examples/nodejs-save-to-disk.js +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env node - -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -const rs2 = require('../index.js'); - -let colorizer = new rs2.Colorizer(); -let pipeline = new rs2.Pipeline(); - -pipeline.start(pipeline.autoConfig); - -for (let i = 0; i < 30; i++) { - pipeline.waitForFrames(); -} - -let frameset = pipeline.waitForFrames(); -for (let i = 0; i < frameset.size; i++) { - let frame = frameset.at(i); - if (frame instanceof rs2.VideoFrame) { - if (frame instanceof rs2.DepthFrame) { - frame = colorizer.colorize(frame); - } - let pngFile = 'rs-save-to-disk-output-' + - rs2.stream.streamToString(frame.profile.streamType) + '.png'; - rs2.util.writeFrameToFile(pngFile, frame, 'png'); - console.log('Saved ', pngFile); - - let csvFile = 'rs-save-to-disk-output-' + - rs2.stream.streamToString(frame.profile.streamType) + '-metadata.csv'; - rs2.util.writeFrameMetadataToFile(csvFile, frame); - } -} -pipeline.stop(); -pipeline.destroy(); -rs2.cleanup(); diff --git a/wrappers/nodejs/examples/package-lock.json b/wrappers/nodejs/examples/package-lock.json deleted file mode 100644 index d66d8dd18c..0000000000 --- a/wrappers/nodejs/examples/package-lock.json +++ /dev/null @@ -1,305 +0,0 @@ -{ - "name": "node-librealsense2-examples", - "version": "0.0.1", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "ansi-escapes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", - "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=" - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "babel-runtime": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.25.0.tgz", - "integrity": "sha1-M7mOql1IK7AajRqmtDetKwGuxBw=", - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.10.0" - } - }, - "cli-cursor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", - "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "requires": { - "restore-cursor": "^1.0.1" - } - }, - "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" - }, - "core-js": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz", - "integrity": "sha1-rmh03GaTd4m4B1T/VCjfZoGcpQs=" - }, - "es6-promise": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz", - "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==" - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" - }, - "exit-hook": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", - "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=" - }, - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" - } - }, - "fsm-as-promised": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/fsm-as-promised/-/fsm-as-promised-0.15.1.tgz", - "integrity": "sha512-zd8oB49/5saBoqjyPwHtjTfwen/TyVr1T+49SN1aQXOnPuHzrG8rdILdaZcYmEZFE1mRVWhS8QO5auEq1BRyOg==", - "requires": { - "es6-promise": "^4.0.2", - "lodash": "^4.16.2", - "stampit": "^3.0.1", - "uuid": "^3.0.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "input": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/input/-/input-1.0.1.tgz", - "integrity": "sha1-Jr+1MVlZxAPpMXF1z4+YlOl+V0I=", - "requires": { - "babel-runtime": "^6.6.1", - "chalk": "^1.1.1", - "inquirer": "^0.12.0", - "lodash": "^4.6.1" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "requires": { - "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" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" - } - } - }, - "inquirer": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", - "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", - "requires": { - "ansi-escapes": "^1.1.0", - "ansi-regex": "^2.0.0", - "chalk": "^1.0.0", - "cli-cursor": "^1.0.1", - "cli-width": "^2.0.0", - "figures": "^1.3.5", - "lodash": "^4.3.0", - "readline2": "^1.0.1", - "run-async": "^0.1.0", - "rx-lite": "^3.1.2", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.0", - "through": "^2.3.6" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "requires": { - "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" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" - } - } - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "lodash": { - "version": "4.17.5", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", - "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==" - }, - "mute-stream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", - "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=" - }, - "nan": { - "version": "2.14.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", - "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==" - }, - "node-12-glfw-3": { - "version": "git+https://github.com/whsol/node-glfw.git#7b28c1d63d1cb60a1557e51a9868a30c281c916a", - "from": "git+https://github.com/whsol/node-glfw.git", - "requires": { - "nan": "^2.14.2" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "readline2": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", - "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "mute-stream": "0.0.5" - } - }, - "regenerator-runtime": { - "version": "0.10.5", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", - "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=" - }, - "restore-cursor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", - "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "requires": { - "exit-hook": "^1.0.0", - "onetime": "^1.0.0" - } - }, - "run-async": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", - "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", - "requires": { - "once": "^1.3.0" - } - }, - "rx-lite": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", - "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=" - }, - "stampit": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/stampit/-/stampit-3.2.1.tgz", - "integrity": "sha1-lTpBpJRYoLKG/7HjydbOcDblids=" - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "uuid": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", - "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==" - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - } - } -} diff --git a/wrappers/nodejs/examples/package.json b/wrappers/nodejs/examples/package.json deleted file mode 100644 index 2717d6022b..0000000000 --- a/wrappers/nodejs/examples/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "node-librealsense2-examples", - "version": "0.0.1", - "description": "", - "author": "", - "license": "Apache-2.0", - "dependencies": { - "fsm-as-promised": "^0.15.1", - "input": "^1.0.1", - "node-12-glfw-3": "git+https://github.com/whsol/node-glfw.git", - "performance-now": "^2.1.0" - } -} diff --git a/wrappers/nodejs/examples/realsense_viewer/index.js b/wrappers/nodejs/examples/realsense_viewer/index.js deleted file mode 100644 index 06a9a85476..0000000000 --- a/wrappers/nodejs/examples/realsense_viewer/index.js +++ /dev/null @@ -1,404 +0,0 @@ -// Copyright (c) 2018 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -const {ResponseTag, CommandTag, CommonNames} = require('./public/common.js'); -const WebSocket = require('ws'); -const express = require('express'); -const path = require('path'); -const rsWrapper = require('../../index.js'); -const sharp = require('sharp'); - -const port = 3000; -const wsPort = 3100; -const jpegQuality = 40; - -class Realsense { - constructor(rsWrapper, connectMgr) { - this.wrapper = rsWrapper; - this.connectMgr = connectMgr; - this.sendCount = {}; - for (let name of [ - CommonNames.colorStreamName, - CommonNames.stereoStreamName, - CommonNames.infraredStream1Name, - CommonNames.infraredStream2Name]) { - this.sendCount[name] = 0; - } - } - init() { - this.ctx = new this.wrapper.Context(); - this.colorizer = new this.wrapper.Colorizer(); - this.decimate = new this.wrapper.DecimationFilter(); - this.sensors = this.ctx.querySensors(); - } - stop() {} - get isReady() { - return this.sensors; - } - cleanup() { - this.ctx = null; - this.sensors = null; - this.wrapper.cleanup(); - } - // return the presets response - getPresets() { - let presets = { - tag: ResponseTag.presets, - data: [], - }; - for (let p in this.wrapper.rs400_visual_preset) { - if (typeof this.wrapper.rs400_visual_preset[p] === 'string') { - presets.data.push(this.wrapper.rs400_visual_preset[p]); - } - } - return presets; - } - // return the sensorInfo response - getAllSensorInfo() { - if (!this.sensors) { - return undefined; - } - let info = { - tag: ResponseTag.sensorInfo, - data: [], - }; - this.sensors.forEach((s) => { - info.data.push(this._getSensorInfo(s)); - }); - return info; - } - // return the options response - getOptions() { - if (!this.sensors) { - return undefined; - } - let options = { - tag: ResponseTag.options, - data: {}, - }; - this.sensors.forEach((s) => { - let sensorName = s.getCameraInfo(this.wrapper.camera_info.camera_info_name); - options.data[sensorName] = this._getSensorOptions(s); - }); - return options; - } - // return the defaultCfg response - getDefaultConfig() { - let cfg = { - tag: ResponseTag.defaultCfg, - data: { - preset: 'custom', - resolution: [[CommonNames.stereoSensorName, '1280*720'], - [CommonNames.colorSensorName, '1280*720']], - fps: [[CommonNames.stereoSensorName, 30], [CommonNames.colorSensorName, 30]], - format: [[CommonNames.stereoStreamName, 'z16'], [CommonNames.infraredStream1Name, 'y8'], - [CommonNames.infraredStream2Name, 'y8'], [CommonNames.colorStreamName, 'rgb8']], - streams: [CommonNames.stereoStreamName, CommonNames.colorStreamName, - CommonNames.infraredStream1Name], - }, - }; - return cfg; - } - // process commands from browser - processCommand(cmd) { - switch (cmd.tag) { - case CommandTag.start: - console.log('start command'); - console.log(cmd); - this._handleStart(cmd); - break; - case CommandTag.setOption: - console.log('Set option command'); - console.log(cmd); - this._handleSetOption(cmd); - break; - default: - console.log(`Unrecognized command ${cmd}`); - break; - } - } - _getSensorInfo(sensor) { - let info = { - name: sensor.getCameraInfo(this.wrapper.camera_info.camera_info_name), - resolutions: [], - fpses: [], - streams: [], - }; - let streamMap = new Map(); - let profiles = sensor.getStreamProfiles(); - profiles.forEach((p) => { - // only cares about video stream profile - if (!(p instanceof this.wrapper.VideoStreamProfile)) { - return; - } - - let found = info.resolutions.find((e) => { - return (e.w === p.width && e.h === p.height); - }); - if (!found) { - info.resolutions.push({w: p.width, h: p.height}); - } - found = info.fpses.find((fps) => { - return fps === p.fps; - }); - if (!found) { - info.fpses.push(p.fps); - } - - let streamName = this.wrapper.stream.streamToString(p.streamType); - let formatName = this.wrapper.format.formatToString(p.format); - let index = p.streamIndex; - let key = streamName + index; - - if (!streamMap.has(key)) { - streamMap.set(key, { - index: index, - name: streamName, - formats: [formatName], - }); - } else { - let entry = streamMap.get(key); - found = entry.formats.find((f) => { - return f === formatName; - }); - if (!found) { - entry.formats.push(formatName); - } - } - }); - streamMap.forEach((val, key) => { - info.streams.push({ - index: val.index, - name: val.name, - formats: val.formats, - }); - }); - return info; - } - _getSensorOptions(sensor) { - let opts = { - sensor: sensor.getCameraInfo(this.wrapper.camera_info.camera_info_name), - options: [], - }; - for (let opt in this.wrapper.option) { - if (typeof this.wrapper.option[opt] === 'string') { - if (sensor.supportsOption(this.wrapper.option[opt])) { - console.log(`getoption: ${opt}`); - let obj = { - option: this.wrapper.option[opt], - value: sensor.getOption(this.wrapper.option[opt]), - range: sensor.getOptionRange(this.wrapper.option[opt]), - }; - opts.options.push(obj); - } - } - } - return opts; - } - // find an array of streamProfiles that matches the input streamArray data. - _findMatchingProfiles(sensorName, streamArray) { - let sensor = this._findSensorByName(sensorName); - let profiles = sensor.getStreamProfiles(); - let results = []; - - console.log(streamArray); - streamArray.forEach((s) => { - profiles.forEach((p) => { - if (p instanceof this.wrapper.VideoStreamProfile) { - if (this.wrapper.stream.streamToString(p.streamValue) === s.stream && - this.wrapper.format.formatToString(p.format) === s.format && - p.fps == s.fps && - `${p.width}*${p.height}` === s.resolution && - (s.index === undefined || p.streamIndex == s.index)) { - results.push(p); - } - } - }); - }); - return results; - } - - _findSensorByName(sensorName) { - for (let sensor of this.sensors) { - if (sensor.getCameraInfo(this.wrapper.camera_info.camera_info_name) === sensorName) { - return sensor; - } - } - return undefined; - } - _processFrameBeforeSend(sensor, frame) { - const streamType = frame.streamType; - const width = frame.width; - const height = frame.height; - const streamIndex = frame.profile.streamIndex; - const format = frame.format; - - return new Promise((resolve, reject) => { - if (streamType === this.wrapper.stream.STREAM_COLOR) { - sharp(Buffer.from(frame.data.buffer), { - raw: { - width: width, - height: height, - channels: 3, - }, - }).jpeg({ - quality: jpegQuality, - }).toBuffer().then((data) => { - let result = { - meta: { - stream: this.wrapper.stream.streamToString(streamType), - index: frame.profile.streamIndex, - format: this.wrapper.format.formatToString(format), - width: width, - height: height, - }, - data: data, - }; - resolve(result); - }); - } else if (streamType === this.wrapper.stream.STREAM_DEPTH) { - const depthMap = this.colorizer.colorize(frame); - sharp(Buffer.from(depthMap.data.buffer), { - raw: { - width: width, - height: height, - channels: 3, - }, - }).jpeg({ - quality: jpegQuality, - }).toBuffer().then((data) => { - let result = { - meta: { - stream: this.wrapper.stream.streamToString(streamType), - index: frame.profile.streamIndex, - format: this.wrapper.format.formatToString(format), - width: width, - height: height, - }, - data: data, - }; - resolve(result); - }); - } else if (streamType === this.wrapper.stream.STREAM_INFRARED) { - const infraredFrame = this.decimate.process(frame); - // const infraredFrame = frame; - let result = { - meta: { - stream: this.wrapper.stream.streamToString(streamType)+streamIndex, - index: frame.profile.streamIndex, - format: this.wrapper.format.formatToString(format), - width: infraredFrame.width, - height: infraredFrame.height, - }, - data: infraredFrame.data, - frame: infraredFrame, - }; - resolve(result); - } - }); - } - // process the start command - _handleStart(cmd) { - let profiles = this._findMatchingProfiles(cmd.data.sensor, cmd.data.streams); - let sensor = this._findSensorByName(cmd.data.sensor); - if (profiles && sensor) { - console.log('open profiles:'); - console.log(profiles); - sensor.open(profiles); - sensor.start((frame) => { - this._processFrameBeforeSend(sensor, frame).then((output) => { - connectMgr.sendProcessedFrameData(output); - this.sendCount[output.meta.stream]++; - }); - }); - } - } - // process set option command - _handleSetOption(cmd) { - let sensor = this._findSensorByName(cmd.data.sensor); - sensor.setOption(cmd.data.option, Number(cmd.data.value)); - } -} - -class ConnectionManager { - constructor(port, wsPort) { - this.app = express(); - this.cmdSocket = null; - this.dataSockets = new Map(); - this.dataSocketsReady = new Map(); - this.wsPort = wsPort; - this.port = port; - } - connectionCheck(req, res, next) { - if (connectMgr.cmdSocket) { - res.send('A connection already exist!'); - } else { - next(); - } - } - start() { - this.app.all('*', this.connectionCheck); - this.app.use(express.static(path.join(__dirname, 'public'))); - this.wss = new WebSocket.Server({port: this.wsPort}); - - this.wss.on('connection', (socket) => { - if (!this.cmdSocket) { - this.acceptCommandConnection(socket); - } else { - socket.addEventListener('message', (event) => { - let streamObj = JSON.parse(event.data); - this.dataSockets[streamObj.stream] = socket; - this.dataSocketsReady[streamObj.stream] = true; - console.log( - `${streamObj.stream} connection established! ${this.dataSockets[streamObj.stream]}`); - }); - } - }); - this.app.listen(port); - console.log(`listening on http://localhost:${this.port}`); - } - acceptCommandConnection(socket) { - console.log('Command connection established!'); - this.cmdSocket = socket; - this.cmdSocket.on('close', () => { - rsObj.stop(); - rsObj.cleanup(); - this.cmdSocket = null; - }); - this.cmdSocket.on('message', (msg) => { - rsObj.processCommand(JSON.parse(msg)); - }); - if (rsObj.isReady) { - this.sendCmdObject(rsObj.getAllSensorInfo()); - this.sendCmdObject(rsObj.getPresets()); - this.sendCmdObject(rsObj.getOptions()); - this.sendCmdObject(rsObj.getDefaultConfig()); - } else { - this.sendCmdObject({tag: ResponseTag.error, description: 'No camera found!'}); - } - } - sendProcessedFrameData(data) { - this.sendData(data.meta.stream, data.meta, true); - this.sendData(data.meta.stream, data.data); - } - sendCmdObject(obj) { - this.cmdSocket.send(JSON.stringify(obj)); - } - sendData(streamName, data, isString = false) { - if (!this.dataSocketsReady[streamName]) { - console.error(`${streamName} data connection not established!`); - } - if (isString) { - this.dataSockets[streamName].send(JSON.stringify(data)); - } else { - this.dataSockets[streamName].send(data); - } - } -} -let connectMgr = new ConnectionManager(port, wsPort); -let rsObj = new Realsense(rsWrapper, connectMgr); -rsObj.init(); -connectMgr.start(); diff --git a/wrappers/nodejs/examples/realsense_viewer/package.json b/wrappers/nodejs/examples/realsense_viewer/package.json deleted file mode 100644 index 2362bd1b92..0000000000 --- a/wrappers/nodejs/examples/realsense_viewer/package.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "realsense_viewer", - "version": "1.0.0", - "description": "A webbased realsense viewer", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "Ting Shao ", - "license": "Apache-2.0", - "dependencies": { - "express": "^4.16.3", - "sharp": "^0.27.2", - "ws": "^5.2.0" - } -} diff --git a/wrappers/nodejs/examples/realsense_viewer/public/app.js b/wrappers/nodejs/examples/realsense_viewer/public/app.js deleted file mode 100644 index cae8c48326..0000000000 --- a/wrappers/nodejs/examples/realsense_viewer/public/app.js +++ /dev/null @@ -1,519 +0,0 @@ -// Copyright (c) 2018 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -/* globals Blob, CommandTag, CommonNames, Image, ResponseTag, URL, Vue, WebSocket, document, - serverInfo, window, FileReader, alert */ - -'use strict'; - -class RealsenseProxy { - constructor(cmdPort, callback, dataCallbacks) { - this.url = 'ws://' + window.location.hostname + ':' +cmdPort; - this.cmdSocket = null; - this.cmdSocketReady = false; - this.dataSockets = new Map(); - this.dataSocketReady = new Map(); - this.responseCallback = callback; - this.dataCallbacks = dataCallbacks; - } - connect() { - this.cmdSocket = new WebSocket(this.url); - this.cmdSocket.addEventListener('open', (event) => { - this.cmdSocketReady = true; - }); - this.cmdSocket.addEventListener('message', (event) => { - this.parseMessage(event.data); - }); - for (let stream of [ - CommonNames.colorStreamName, - CommonNames.stereoStreamName, - CommonNames.infraredStream1Name, - CommonNames.infraredStream2Name]) { - this._setupConnectionCallback(stream); - } - } - startStreaming(sensor, selection) { - let cmd = { - tag: CommandTag.start, - data: { - sensor: sensor, - streams: [], - }, - }; - if (sensor === CommonNames.colorSensorName) { - if (selection.selectedStreams[CommonNames.colorStreamName]) { - let stream = { - stream: CommonNames.colorStreamName, - resolution: selection.selectedResolutions[CommonNames.colorSensorName], - format: selection.selectedFormats[CommonNames.colorStreamName], - fps: selection.selectedFpses[CommonNames.colorSensorName], - }; - cmd.data.streams.push(stream); - } else { - console.error('color stream not selected!'); - } - } else if (sensor === CommonNames.stereoSensorName) { - let res = selection.selectedResolutions[CommonNames.stereoSensorName]; - let fps = selection.selectedFpses[CommonNames.stereoSensorName]; - if (selection.selectedStreams[CommonNames.infraredStream1Name]) { - let stream = { - stream: CommonNames.infraredStreamName, - resolution: res, - index: 1, - format: selection.selectedFormats[CommonNames.infraredStream1Name], - fps: fps, - }; - cmd.data.streams.push(stream); - } - if (selection.selectedStreams[CommonNames.infraredStream2Name]) { - let stream = { - stream: CommonNames.infraredStreamName, - resolution: res, - index: 2, - format: selection.selectedFormats[CommonNames.infraredStream2Name], - fps: fps, - }; - cmd.data.streams.push(stream); - } - if (selection.selectedStreams[CommonNames.stereoStreamName]) { - let stream = { - stream: CommonNames.stereoStreamName, - resolution: res, - format: selection.selectedFormats[CommonNames.stereoStreamName], - fps: fps, - }; - cmd.data.streams.push(stream); - } - } - console.log('send start cmd:'); - this._sendCmd(JSON.stringify(cmd)); - } - setOption(sensor, option, value) { - let cmd = { - tag: CommandTag.setOption, - data: { - sensor: sensor, - option: option, - value: value, - }, - }; - console.log('send set option cmd:'); - this._sendCmd(JSON.stringify(cmd)); - } - _setupConnectionCallback(streamVal) { - let inst = this; - this.dataSockets[streamVal] = new WebSocket(this.url); - this.dataSockets[streamVal].addEventListener('open', function(event) { - console.log(`${streamVal} data connection connected`); - inst.dataSocketReady[streamVal] = true; - inst.dataSockets[streamVal].send(JSON.stringify({stream: streamVal})); - }); - this.dataSockets[streamVal].addEventListener('message', function(event) { - inst.parseDataMessage(streamVal, event.data); - }); - } - _sendCmd(cmdString) { - if (!this.cmdSocketReady) { - throw new Error('command channel not connected!'); - } - this.cmdSocket.send(cmdString); - } - parseMessage(msgString) { - this.responseCallback(JSON.parse(msgString)); - } - parseDataMessage(stream, dataMsg) { - if (typeof dataMsg === 'string') { - let obj = JSON.parse(dataMsg); - if (obj) { - if (stream === CommonNames.infraredStream1Name) { - glData.textureWidth[0] = obj.width; - glData.textureHeight[0] = obj.height; - } else if (stream === CommonNames.infraredStream2Name) { - glData.textureWidth[1] = obj.width; - glData.textureHeight[1] = obj.height; - } - } - } else { - // received raw data - this.dataCallbacks[stream](dataMsg); - } - } -} -const dataCallbacks = { - 'color': colorDataCallback, - 'depth': depthDataCallback, - 'infrared1': infrared1DataCallback, - 'infrared2': infrared2DataCallback, -}; -const proxy = new RealsenseProxy(serverInfo.cmdPort, cmdResponseCallback, dataCallbacks); -const vue = new Vue({ - el: '#web-demo', - data: { - sensorInfo: [], - sensorInfoStr: '', - presets: [], - selection: { - selectedPreset: '', - selectedResolutions: {}, - selectedFpses: {}, - selectedStreams: {}, - selectedFormats: {}, - }, - defaultCfg: {}, - canvasData: { - started: new Map(), - width: { - 'color': 0, - 'depth': 0, - 'infrared1': 0, - 'infrared2': 0, - }, - height: { - 'color': 0, - 'depth': 0, - 'infrared1': 0, - 'infrared2': 0, - }, - display: { - 'color': false, - 'depth': false, - 'infrared1': false, - 'infrared2': false, - }, - }, - controls: { - enabled: {}, - options: {}, - }, - }, - mounted: function() { - proxy.connect(); - }, - methods: { - onstartStereo: function(event) { - let size = resolutionStringToNumberPair( - vue.selection.selectedResolutions[CommonNames.stereoSensorName]); - let streams = [CommonNames.stereoStreamName, - CommonNames.infraredStream1Name, - CommonNames.infraredStream2Name]; - streams.forEach((stream) => { - if (vue.selection.selectedStreams[stream]) { - vue.canvasData.started.set(stream, true); - vue.canvasData.width[stream] = size.width; - vue.canvasData.height[stream] = size.height; - vue.canvasData.display[stream] = true; - } - }); - - updateCanvasConfig(); - initGL(); - proxy.startStreaming(CommonNames.stereoSensorName, vue.selection); - console.log('selected Resolutions:', vue.selection.selectedResolutions); - console.log('selected Fpses:', vue.selection.selectedFpses); - console.log('selected Streams:', vue.selection.selectedStreams); - console.log('selected Formats:', vue.selection.selectedFormats); - console.log('selected Preset:', vue.selection.selectedPreset); - }, - onstartColor: function(event) { - vue.canvasData.started.set(CommonNames.colorStreamName, true); - let size = resolutionStringToNumberPair( - vue.selection.selectedResolutions[CommonNames.colorSensorName]); - vue.canvasData.width[CommonNames.colorStreamName] = size.width; - vue.canvasData.height[CommonNames.colorStreamName] = size.height; - vue.canvasData.display[CommonNames.colorStreamName] = true; - updateCanvasConfig(); - proxy.startStreaming(CommonNames.colorSensorName, vue.selection); - console.log('selected Resolutions:', vue.selection.selectedResolutions); - console.log('selected Fpses:', vue.selection.selectedFpses); - console.log('selected Streams:', vue.selection.selectedStreams); - console.log('selected Formats:', vue.selection.selectedFormats); - console.log('selected Preset:', vue.selection.selectedPreset); - }, - onOptionChanged: function(sensorName, optionName, value) { - proxy.setOption(sensorName, optionName, value); - }, - }, -}); - -function cmdResponseCallback(response) { - console.log(response); - switch (response.tag) { - case ResponseTag.presets: - vue.presets = response.data; - break; - case ResponseTag.options: - vue.controls.options =response.data; - break; - case ResponseTag.sensorInfo: - vue.sensorInfo = response.data; - break; - case ResponseTag.defaultCfg: - vue.defaultCfg = response.data; - vue.selection.selectedPreset = vue.defaultCfg.preset; - vue.defaultCfg.resolution.forEach((pair) => { - vue.selection.selectedResolutions[pair[0]] = pair[1]; - }); - vue.defaultCfg.fps.forEach((pair) => { - vue.selection.selectedFpses[pair[0]] = pair[1]; - }); - vue.defaultCfg.format.forEach((pair) => { - vue.selection.selectedFormats[pair[0]] = pair[1]; - }); - vue.defaultCfg.streams.forEach((s) => { - vue.selection.selectedStreams[s] = true; - }); - break; - default: - break; - } -} - -function colorDataCallback(data) { - let blob = new Blob([data], {type: 'image/jpg'}); - let url = URL.createObjectURL(blob); - let img = new Image(); - img.src = url; - let canvas = document.getElementById('color-canvas'); - let ctx = canvas.getContext('2d'); - img.onload = function() { - ctx.drawImage(this, 0, 0); - URL.revokeObjectURL(url); - }; -} - -function depthDataCallback(data) { - let blob = new Blob([data], {type: 'image/jpg'}); - let url = URL.createObjectURL(blob); - let img = new Image(); - img.src = url; - let canvas = document.getElementById('depth-canvas'); - let ctx = canvas.getContext('2d'); - img.onload = function() { - ctx.drawImage(this, 0, 0); - URL.revokeObjectURL(url); - }; -} - -function infrared1DataCallback(data) { - let fileReader = new FileReader(); - fileReader.onload = function(event) { - const arrayBuffer = event.target.result; - drawInfraredToCanvas(0, arrayBuffer, { - width: glData.textureWidth[0], height: glData.textureHeight[0], - }); - }; - fileReader.readAsArrayBuffer(data); -} -function infrared2DataCallback(data) { - let fileReader = new FileReader(); - fileReader.onload = function(event) { - const arrayBuffer = event.target.result; - drawInfraredToCanvas(1, arrayBuffer, { - width: glData.textureWidth[1], height: glData.textureHeight[1], - }); - }; - fileReader.readAsArrayBuffer(data); -} - -function drawInfraredToCanvas(index, arrayBuffer, textureSize) { - const gl = glData.infraredGl[index]; - const texture = glData.texture[index]; - gl.bindTexture(gl.TEXTURE_2D, texture); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, textureSize.width, - textureSize.height, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, - new Uint8Array(arrayBuffer)); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - drawScene(index, { - width: index === 0 ? vue.canvasData.width.infrared1 : vue.canvasData.width.infrared2, - height: index === 0 ? vue.canvasData.height.infrared1 : vue.canvasData.height.infrared2, - }); -} - -function resolutionStringToNumberPair(resolution) { - let pair = resolution.split('*').map((x) => Number(x)); - return {width: pair[0], height: pair[1]}; -} - -function updateCanvasConfig() { - let startedCount = 0; - vue.canvasData.started.forEach((val, key) => { - if (val) { - startedCount++; - } - }); - if (startedCount >= 2) { - vue.canvasData.started.forEach((val, key) => { - if (val) { - let oldWidth = vue.canvasData.width[key]; - let oldHeight = vue.canvasData.height[key]; - - vue.canvasData.width[key] = oldWidth/2; - vue.canvasData.height[key] = oldHeight/2; - } - }); - } -} - -let glData = { - infraredCanvas: [null, null], - infraredGl: [null, null], - texture: [null, null], - shader: [null, null], - buffers: [null, null], - textureWidth: [0, 0], - textureHeight: [0, 0], -}; - -function initShaders(gl) { - const vsSource = ` - attribute vec4 aVertexPosition; - attribute vec2 aTextureCoord; - varying highp vec2 vTextureCoord; - - void main(void) { - gl_Position = aVertexPosition; - vTextureCoord = aTextureCoord; - } - `; - const fsSource = ` - varying highp vec2 vTextureCoord; - uniform sampler2D uSampler; - - void main(void) { - gl_FragColor = texture2D(uSampler, vTextureCoord); - } - `; - const vs = gl.createShader(gl.VERTEX_SHADER); - const fs = gl.createShader(gl.FRAGMENT_SHADER); - gl.shaderSource(vs, vsSource); - gl.shaderSource(fs, fsSource); - gl.compileShader(vs); - gl.compileShader(fs); - - if (!gl.getShaderParameter(vs, gl.COMPILE_STATUS)) { - alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(vs)); - gl.deleteShader(vs); - return null; - } - if (!gl.getShaderParameter(fs, gl.COMPILE_STATUS)) { - alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(fs)); - gl.deleteShader(fs); - return null; - } - - const shaderProgram = gl.createProgram(); - gl.attachShader(shaderProgram, vs); - gl.attachShader(shaderProgram, fs); - gl.linkProgram(shaderProgram); - - if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { - alert('Unable to initialize the shader program: ' + gl.getProgramInfoLog(shaderProgram)); - return null; - } - - return { - program: shaderProgram, - attributeLocations: { - vertexPosition: gl.getAttribLocation(shaderProgram, 'aVertexPosition'), - textureCoord: gl.getAttribLocation(shaderProgram, 'aTextureCoord'), - }, - uniformLocations: { - uSampler: gl.getUniformLocation(shaderProgram, 'uSampler'), - }, - }; -} - -function initBuffers(gl) { - const positionBuffer = gl.createBuffer(); - gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); - const positions = [ - -1.0, 1.0, - 1.0, 1.0, - -1.0, -1.0, - 1.0, -1.0, - ]; - gl.bufferData(gl.ARRAY_BUFFER, - new Float32Array(positions), - gl.STATIC_DRAW); - - const textureCoordBuffer = gl.createBuffer(); - gl.bindBuffer(gl.ARRAY_BUFFER, textureCoordBuffer); - - const textureCoordinates = [ - // Front - 0.0, 0.0, - 1.0, 0.0, - 0.0, 1.0, - 1.0, 1.0, - ]; - - gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoordinates), - gl.STATIC_DRAW); - return { - position: positionBuffer, - textureCoord: textureCoordBuffer, - }; -} - -function initGL() { - glData.infraredCanvas[0] = document.getElementById('infrared1-canvas'); - glData.infraredCanvas[1] = document.getElementById('infrared2-canvas'); - glData.infraredGl[0] = glData.infraredCanvas[0].getContext('webgl'); - glData.infraredGl[1] = glData.infraredCanvas[1].getContext('webgl'); - glData.texture[0] = glData.infraredGl[0].createTexture(); - glData.texture[1] = glData.infraredGl[1].createTexture(); - glData.shader[0] = initShaders(glData.infraredGl[0]); - glData.shader[1] = initShaders(glData.infraredGl[1]); - glData.buffers[0] = initBuffers(glData.infraredGl[0]); - glData.buffers[1] = initBuffers(glData.infraredGl[1]); -} - -function drawScene(index, viewPortSize) { - const gl = glData.infraredGl[index]; - gl.viewport(0, 0, viewPortSize.width, viewPortSize.height); - - { - const numComponents = 2; - const type = gl.FLOAT; - const normalize = false; - const stride = 0; - const offset = 0; - gl.bindBuffer(gl.ARRAY_BUFFER, glData.buffers[index].position); - gl.vertexAttribPointer( - glData.shader[index].attributeLocations.vertexPosition, - numComponents, - type, - normalize, - stride, - offset); - gl.enableVertexAttribArray( - glData.shader[index].attributeLocations.vertexPosition); - } - - { - const num = 2; // every coordinate composed of 2 values - const type = gl.FLOAT; - const normalize = false; // don't normalize - const stride = 0; // how many bytes to get from one set to the next - const offset = 0; // how many bytes inside the buffer to start from - - gl.bindBuffer(gl.ARRAY_BUFFER, glData.buffers[index].textureCoord); - gl.vertexAttribPointer(glData.shader[index].attributeLocations.textureCoord, num, type, - normalize, stride, offset); - gl.enableVertexAttribArray(glData.shader[index].attributeLocations.textureCoord); - } - - gl.useProgram(glData.shader[index].program); - // Tell WebGL we want to affect texture unit 0 - gl.activeTexture(gl.TEXTURE0); - // Tell the shader we bound the texture to texture unit 0 - gl.uniform1i(glData.shader[index].uniformLocations.uSampler, 0); - const offset = 0; - const vertexCount = 4; - gl.bindBuffer(gl.ARRAY_BUFFER, glData.buffers[index].position); - gl.drawArrays(gl.TRIANGLE_STRIP, offset, vertexCount); -} diff --git a/wrappers/nodejs/examples/realsense_viewer/public/common.js b/wrappers/nodejs/examples/realsense_viewer/public/common.js deleted file mode 100644 index c0efba6ac8..0000000000 --- a/wrappers/nodejs/examples/realsense_viewer/public/common.js +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright (c) 2018 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -const ResponseTag = { - /* - structure of genericOkType: - { - tag: 'ok' - } - */ - genericOk: 'ok', - /* - structure of errorType: - { - tag: 'error', - description: string description of the error - } - */ - error: 'error', - /* - structure of presetsType - { - tag: 'presets', - data: array of preset strings - } - */ - presets: 'presets', - /* - structure of optionsType: - { - tag: 'options', - data: array of sensorOptionType - } - structure of sensorOptionType: - { - sensor: sensor name, - options: array of optionType - } - structure of optionType: - { - option: option name, - value: current value, - range: optionRangeType - } - structure of optionRangeType: - { - minValue: min value - maxValue: max value - defaultValue: max value - step: step - } - */ - options: 'options', - /* - structure of sensorInfoType - { - tag: 'sensor-info', - data: array of SensorType - } - - structure of sensorType: - { - name: sensor name - resolutions: array of width and height value paris, for example: [{w1, h1}, {w2, h2}...] - fpses: array of fps values - streams: array of streamType - } - - structure of streamType: - { - index: stream index - name: stream name - formats: array of supported stream formats - } - */ - sensorInfo: 'sensor-info', - /* - structure of defaultCfg - { - tag: 'default-config', - data: cfgType - } - structure of cfgType - { - preset: default preset - resolution: array of sensor name to resolution, example: ['Stereo Module', '1280*720'], - fps: array of sensor name to fps, example: ['Stereo Module', 30] - format: array of stream name to format, example: ['depth', 'z16'], - streams: array of defalt enabled streams. example ['depth', 'color', 'infrared1'] - } - */ - defaultCfg: 'default-config', -}; - -const CommandTag = { - /* - structure of setPresetType: - { - tag: 'set-preset', - data: preset string - } - */ - setPreset: 'set-preset', - /* - structure of setOptionType: - { - tag: 'set-option', - data: { - sensor: sensor name, - option: option name, - value: value - } - } - */ - setOption: 'set-option', - /* - structure of startType: - { - tag: 'start', - data: startDataType - } - structure of startDataType: - { - sensor: sensor name - streams: array of streamConfigType: - } - structure of streamConfigType: - { - stream: stream name, - index: optional, the index the stream. - resolution: example: w*h - format: format string, - fps: fps - } - } - */ - start: 'start', -}; - -const serverInfo = { - cmdPort: 3100, -}; - -const CommonNames = { - colorSensorName: 'RGB Camera', - stereoSensorName: 'Stereo Module', - infraredStreamName: 'infrared', - colorStreamName: 'color', - infraredStream1Name: 'infrared1', - infraredStream2Name: 'infrared2', - stereoStreamName: 'depth', -}; - -if (typeof module !== 'undefined' && module.exports) { - module.exports = { - ResponseTag, - CommandTag, - CommonNames, - serverInfo, - }; -} diff --git a/wrappers/nodejs/examples/realsense_viewer/public/index.html b/wrappers/nodejs/examples/realsense_viewer/public/index.html deleted file mode 100644 index 2296e4316b..0000000000 --- a/wrappers/nodejs/examples/realsense_viewer/public/index.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - -
    -
    -
    - -

    -
    -
    - {{info.name}} - -
    - -
    - -
    - - - -

    - -
    -
    -
    -
    - -
    -
    -

    - - - - - - -
    -
    -
    -
    -
    -
    - > -
    -
    - - - - - - -
    - - - diff --git a/wrappers/nodejs/examples/realsense_viewer/public/vue b/wrappers/nodejs/examples/realsense_viewer/public/vue deleted file mode 100644 index 37febff24c..0000000000 --- a/wrappers/nodejs/examples/realsense_viewer/public/vue +++ /dev/null @@ -1,6 +0,0 @@ -/*! - * Vue.js v2.5.16 - * (c) 2014-2018 Evan You - * Released under the MIT License. - */ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.Vue=t()}(this,function(){"use strict";var y=Object.freeze({});function M(e){return null==e}function D(e){return null!=e}function S(e){return!0===e}function T(e){return"string"==typeof e||"number"==typeof e||"symbol"==typeof e||"boolean"==typeof e}function P(e){return null!==e&&"object"==typeof e}var r=Object.prototype.toString;function l(e){return"[object Object]"===r.call(e)}function i(e){var t=parseFloat(String(e));return 0<=t&&Math.floor(t)===t&&isFinite(e)}function t(e){return null==e?"":"object"==typeof e?JSON.stringify(e,null,2):String(e)}function F(e){var t=parseFloat(e);return isNaN(t)?e:t}function s(e,t){for(var n=Object.create(null),r=e.split(","),i=0;ie.id;)n--;bt.splice(n+1,0,e)}else bt.push(e);Ct||(Ct=!0,Ze(At))}}(this)},St.prototype.run=function(){if(this.active){var e=this.get();if(e!==this.value||P(e)||this.deep){var t=this.value;if(this.value=e,this.user)try{this.cb.call(this.vm,e,t)}catch(e){Fe(e,this.vm,'callback for watcher "'+this.expression+'"')}else this.cb.call(this.vm,e,t)}}},St.prototype.evaluate=function(){this.value=this.get(),this.dirty=!1},St.prototype.depend=function(){for(var e=this.deps.length;e--;)this.deps[e].depend()},St.prototype.teardown=function(){if(this.active){this.vm._isBeingDestroyed||f(this.vm._watchers,this);for(var e=this.deps.length;e--;)this.deps[e].removeSub(this);this.active=!1}};var Tt={enumerable:!0,configurable:!0,get:$,set:$};function Et(e,t,n){Tt.get=function(){return this[t][n]},Tt.set=function(e){this[t][n]=e},Object.defineProperty(e,n,Tt)}function jt(e){e._watchers=[];var t=e.$options;t.props&&function(n,r){var i=n.$options.propsData||{},o=n._props={},a=n.$options._propKeys=[];n.$parent&&ge(!1);var e=function(e){a.push(e);var t=Ie(e,r,i,n);Ce(o,e,t),e in n||Et(n,"_props",e)};for(var t in r)e(t);ge(!0)}(e,t.props),t.methods&&function(e,t){e.$options.props;for(var n in t)e[n]=null==t[n]?$:v(t[n],e)}(e,t.methods),t.data?function(e){var t=e.$options.data;l(t=e._data="function"==typeof t?function(e,t){se();try{return e.call(t,t)}catch(e){return Fe(e,t,"data()"),{}}finally{ce()}}(t,e):t||{})||(t={});var n=Object.keys(t),r=e.$options.props,i=(e.$options.methods,n.length);for(;i--;){var o=n[i];r&&p(r,o)||(void 0,36!==(a=(o+"").charCodeAt(0))&&95!==a&&Et(e,"_data",o))}var a;we(t,!0)}(e):we(e._data={},!0),t.computed&&function(e,t){var n=e._computedWatchers=Object.create(null),r=Y();for(var i in t){var o=t[i],a="function"==typeof o?o:o.get;r||(n[i]=new St(e,a||$,$,Nt)),i in e||Lt(e,i,o)}}(e,t.computed),t.watch&&t.watch!==G&&function(e,t){for(var n in t){var r=t[n];if(Array.isArray(r))for(var i=0;iparseInt(this.max)&&bn(a,s[0],s,this._vnode)),t.data.keepAlive=!0}return t||e&&e[0]}}};$n=hn,Cn={get:function(){return j}},Object.defineProperty($n,"config",Cn),$n.util={warn:re,extend:m,mergeOptions:Ne,defineReactive:Ce},$n.set=xe,$n.delete=ke,$n.nextTick=Ze,$n.options=Object.create(null),k.forEach(function(e){$n.options[e+"s"]=Object.create(null)}),m(($n.options._base=$n).options.components,kn),$n.use=function(e){var t=this._installedPlugins||(this._installedPlugins=[]);if(-1=a&&l()};setTimeout(function(){c\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/,oo="[a-zA-Z_][\\w\\-\\.]*",ao="((?:"+oo+"\\:)?"+oo+")",so=new RegExp("^<"+ao),co=/^\s*(\/?)>/,lo=new RegExp("^<\\/"+ao+"[^>]*>"),uo=/^]+>/i,fo=/^",""":'"',"&":"&"," ":"\n"," ":"\t"},go=/&(?:lt|gt|quot|amp);/g,_o=/&(?:lt|gt|quot|amp|#10|#9);/g,bo=s("pre,textarea",!0),$o=function(e,t){return e&&bo(e)&&"\n"===t[0]};var wo,Co,xo,ko,Ao,Oo,So,To,Eo=/^@|^v-on:/,jo=/^v-|^@|^:/,No=/([^]*?)\s+(?:in|of)\s+([^]*)/,Lo=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,Io=/^\(|\)$/g,Mo=/:(.*)$/,Do=/^:|^v-bind:/,Po=/\.[^.]+/g,Fo=e(eo);function Ro(e,t,n){return{type:1,tag:e,attrsList:t,attrsMap:function(e){for(var t={},n=0,r=e.length;n]*>)","i")),n=i.replace(t,function(e,t,n){return r=n.length,ho(o)||"noscript"===o||(t=t.replace(//g,"$1").replace(//g,"$1")),$o(o,t)&&(t=t.slice(1)),d.chars&&d.chars(t),""});a+=i.length-n.length,i=n,A(o,a-r,a)}else{var s=i.indexOf("<");if(0===s){if(fo.test(i)){var c=i.indexOf("--\x3e");if(0<=c){d.shouldKeepComment&&d.comment(i.substring(4,c)),C(c+3);continue}}if(po.test(i)){var l=i.indexOf("]>");if(0<=l){C(l+2);continue}}var u=i.match(uo);if(u){C(u[0].length);continue}var f=i.match(lo);if(f){var p=a;C(f[0].length),A(f[1],p,a);continue}var _=x();if(_){k(_),$o(v,i)&&C(1);continue}}var b=void 0,$=void 0,w=void 0;if(0<=s){for($=i.slice(s);!(lo.test($)||so.test($)||fo.test($)||po.test($)||(w=$.indexOf("<",1))<0);)s+=w,$=i.slice(s);b=i.substring(0,s),C(s)}s<0&&(b=i,i=""),d.chars&&b&&d.chars(b)}if(i===e){d.chars&&d.chars(i);break}}function C(e){a+=e,i=i.substring(e)}function x(){var e=i.match(so);if(e){var t,n,r={tagName:e[1],attrs:[],start:a};for(C(e[0].length);!(t=i.match(co))&&(n=i.match(io));)C(n[0].length),r.attrs.push(n);if(t)return r.unarySlash=t[1],C(t[0].length),r.end=a,r}}function k(e){var t=e.tagName,n=e.unarySlash;m&&("p"===v&&ro(t)&&A(v),g(t)&&v===t&&A(t));for(var r,i,o,a=y(t)||!!n,s=e.attrs.length,c=new Array(s),l=0;l-1"+("true"===d?":("+l+")":":_q("+l+","+d+")")),Ar(c,"change","var $$a="+l+",$$el=$event.target,$$c=$$el.checked?("+d+"):("+v+");if(Array.isArray($$a)){var $$v="+(f?"_n("+p+")":p)+",$$i=_i($$a,$$v);if($$el.checked){$$i<0&&("+Er(l,"$$a.concat([$$v])")+")}else{$$i>-1&&("+Er(l,"$$a.slice(0,$$i).concat($$a.slice($$i+1))")+")}}else{"+Er(l,"$$c")+"}",null,!0);else if("input"===$&&"radio"===w)r=e,i=_,a=(o=b)&&o.number,s=Or(r,"value")||"null",Cr(r,"checked","_q("+i+","+(s=a?"_n("+s+")":s)+")"),Ar(r,"change",Er(i,s),null,!0);else if("input"===$||"textarea"===$)!function(e,t,n){var r=e.attrsMap.type,i=n||{},o=i.lazy,a=i.number,s=i.trim,c=!o&&"range"!==r,l=o?"change":"range"===r?Pr:"input",u="$event.target.value";s&&(u="$event.target.value.trim()"),a&&(u="_n("+u+")");var f=Er(t,u);c&&(f="if($event.target.composing)return;"+f),Cr(e,"value","("+t+")"),Ar(e,l,f,null,!0),(s||a)&&Ar(e,"blur","$forceUpdate()")}(e,_,b);else if(!j.isReservedTag($))return Tr(e,_,b),!1;return!0},text:function(e,t){t.value&&Cr(e,"textContent","_s("+t.value+")")},html:function(e,t){t.value&&Cr(e,"innerHTML","_s("+t.value+")")}},isPreTag:function(e){return"pre"===e},isUnaryTag:to,mustUseProp:Sn,canBeLeftOpenTag:no,isReservedTag:Un,getTagNamespace:Vn,staticKeys:(Go=Wo,Go.reduce(function(e,t){return e.concat(t.staticKeys||[])},[]).join(","))},Qo=e(function(e){return s("type,tag,attrsList,attrsMap,plain,parent,children,attrs"+(e?","+e:""))});function ea(e,t){e&&(Zo=Qo(t.staticKeys||""),Xo=t.isReservedTag||O,function e(t){t.static=function(e){if(2===e.type)return!1;if(3===e.type)return!0;return!(!e.pre&&(e.hasBindings||e.if||e.for||c(e.tag)||!Xo(e.tag)||function(e){for(;e.parent;){if("template"!==(e=e.parent).tag)return!1;if(e.for)return!0}return!1}(e)||!Object.keys(e).every(Zo)))}(t);if(1===t.type){if(!Xo(t.tag)&&"slot"!==t.tag&&null==t.attrsMap["inline-template"])return;for(var n=0,r=t.children.length;n|^function\s*\(/,na=/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['[^']*?']|\["[^"]*?"]|\[\d+]|\[[A-Za-z_$][\w$]*])*$/,ra={esc:27,tab:9,enter:13,space:32,up:38,left:37,right:39,down:40,delete:[8,46]},ia={esc:"Escape",tab:"Tab",enter:"Enter",space:" ",up:["Up","ArrowUp"],left:["Left","ArrowLeft"],right:["Right","ArrowRight"],down:["Down","ArrowDown"],delete:["Backspace","Delete"]},oa=function(e){return"if("+e+")return null;"},aa={stop:"$event.stopPropagation();",prevent:"$event.preventDefault();",self:oa("$event.target !== $event.currentTarget"),ctrl:oa("!$event.ctrlKey"),shift:oa("!$event.shiftKey"),alt:oa("!$event.altKey"),meta:oa("!$event.metaKey"),left:oa("'button' in $event && $event.button !== 0"),middle:oa("'button' in $event && $event.button !== 1"),right:oa("'button' in $event && $event.button !== 2")};function sa(e,t,n){var r=t?"nativeOn:{":"on:{";for(var i in e)r+='"'+i+'":'+ca(i,e[i])+",";return r.slice(0,-1)+"}"}function ca(t,e){if(!e)return"function(){}";if(Array.isArray(e))return"["+e.map(function(e){return ca(t,e)}).join(",")+"]";var n=na.test(e.value),r=ta.test(e.value);if(e.modifiers){var i="",o="",a=[];for(var s in e.modifiers)if(aa[s])o+=aa[s],ra[s]&&a.push(s);else if("exact"===s){var c=e.modifiers;o+=oa(["ctrl","shift","alt","meta"].filter(function(e){return!c[e]}).map(function(e){return"$event."+e+"Key"}).join("||"))}else a.push(s);return a.length&&(i+="if(!('button' in $event)&&"+a.map(la).join("&&")+")return null;"),o&&(i+=o),"function($event){"+i+(n?"return "+e.value+"($event)":r?"return ("+e.value+")($event)":e.value)+"}"}return n||r?e.value:"function($event){"+e.value+"}"}function la(e){var t=parseInt(e,10);if(t)return"$event.keyCode!=="+t;var n=ra[e],r=ia[e];return"_k($event.keyCode,"+JSON.stringify(e)+","+JSON.stringify(n)+",$event.key,"+JSON.stringify(r)+")"}var ua={on:function(e,t){e.wrapListeners=function(e){return"_g("+e+","+t.value+")"}},bind:function(t,n){t.wrapData=function(e){return"_b("+e+",'"+t.tag+"',"+n.value+","+(n.modifiers&&n.modifiers.prop?"true":"false")+(n.modifiers&&n.modifiers.sync?",true":"")+")"}},cloak:$},fa=function(e){this.options=e,this.warn=e.warn||$r,this.transforms=wr(e.modules,"transformCode"),this.dataGenFns=wr(e.modules,"genData"),this.directives=m(m({},ua),e.directives);var t=e.isReservedTag||O;this.maybeComponent=function(e){return!t(e.tag)},this.onceId=0,this.staticRenderFns=[]};function pa(e,t){var n=new fa(t);return{render:"with(this){return "+(e?da(e,n):'_c("div")')+"}",staticRenderFns:n.staticRenderFns}}function da(e,t){if(e.staticRoot&&!e.staticProcessed)return va(e,t);if(e.once&&!e.onceProcessed)return ha(e,t);if(e.for&&!e.forProcessed)return f=t,v=(u=e).for,h=u.alias,m=u.iterator1?","+u.iterator1:"",y=u.iterator2?","+u.iterator2:"",u.forProcessed=!0,(d||"_l")+"(("+v+"),function("+h+m+y+"){return "+(p||da)(u,f)+"})";if(e.if&&!e.ifProcessed)return ma(e,t);if("template"!==e.tag||e.slotTarget){if("slot"===e.tag)return function(e,t){var n=e.slotName||'"default"',r=_a(e,t),i="_t("+n+(r?","+r:""),o=e.attrs&&"{"+e.attrs.map(function(e){return g(e.name)+":"+e.value}).join(",")+"}",a=e.attrsMap["v-bind"];!o&&!a||r||(i+=",null");o&&(i+=","+o);a&&(i+=(o?"":",null")+","+a);return i+")"}(e,t);var n;if(e.component)a=e.component,c=t,l=(s=e).inlineTemplate?null:_a(s,c,!0),n="_c("+a+","+ya(s,c)+(l?","+l:"")+")";else{var r=e.plain?void 0:ya(e,t),i=e.inlineTemplate?null:_a(e,t,!0);n="_c('"+e.tag+"'"+(r?","+r:"")+(i?","+i:"")+")"}for(var o=0;o':'
    ',0 { - deviceArray.push(index.toString() + ' ' + getDeviceName(dev)); - }); - return getUserSelection(descriptions, deviceArray).then((idx) => { - dev = devices[idx]; - return dev; - }); -} - -function selectSensorImpl(descriptions) { - const sensors = dev.querySensors(); - const moreDescription = 'Device consists of ' + sensors.length + ' sensors.'; - if (sensors.length === 1) { - sensor = sensors[0]; - console.log(moreDescription + getSensorName(sensor) + ' selected'); - return Promise.resolve(sensor); - } - const sensorArray = []; - sensors.forEach((sensor, index) => { - sensorArray.push(index.toString() + ' ' + getSensorName(sensor)); - }); - descriptions.push(moreDescription); - return getUserSelection(descriptions, sensorArray).then((idx) => { - sensor = sensors[idx]; - return sensor; - }); -} - -const actions = [ - {description: 'Control sensor\'s options', operation: controlSensorOptionsAction}, - {description: 'Control sensor\'s streams', operation: controlSensorStreamsAction}, - {description: 'Show stream intrinsics', operation: showStreamIntrinsicsAction}, - {description: 'Show extrinsics between streams', operation: displayExtrinsicsAction}, -]; - -function changeSensorOption(option) { - console.log('Supported range for opton ', rs2.option.optionToString(option), ':'); - console.log(sensor.getOptionRange(option)); - return input.confirm('Change option\'s value?').then((ret) => { - if (ret) { - return input.text('Enter the new value for this option:'); - } - }).then((val) => { - if (val) { - sensor.setOption(option, Number.parseFloat(val)); - } - }); -} - -function controlSensorOptionsAction() { - const choices = []; - const options = []; - for (let i = rs2.option.OPTION_BACKLIGHT_COMPENSATION; i < rs2.option.OPTION_COUNT; i++) { - if (sensor.supportsOption(i)) { - choices.push(i.toString() + ': ' + 'Description: ' + sensor.getOptionDescription(i) + - ' Current Value: ' + sensor.getOption(i)); - options.push(i); - } - } - return getUserSelection( - ['Choose an option between the supported options'], choices).then((idx) => { - return changeSensorOption(options[idx]); - }); -} - -function selectStreamProfile(descriptions, sens, filter) { - const profiles = sens.getStreamProfiles(); - const choices = []; - const indexes = []; - profiles.forEach((profile, index) => { - if (filter && !filter(profile)) { - return; - } - let streamInfo = index.toString() + ' ' + - rs2.stream.streamToString(profile.streamType) + '#' + profile.streamIndex; - if (profile instanceof rs2.VideoStreamProfile) { - streamInfo += '(Video Stream: ' + rs2.format.formatToString(profile.format) + ' ' + - profile.width + 'x' + profile.height + '@' + profile.fps + 'Hz'; - } - choices.push(streamInfo); - indexes.push(index); - }); - return getUserSelection(descriptions, choices).then((idx) => { - return profiles[indexes[idx]]; - }); -} - -function startStreamProfle(profile) { - return new Promise((resolve, reject) => { - const win = new GLFWWindow( - profile.width ? profile.width : 1280, - profile.height ? profile.height : 720, - 'Displaying profile ' + rs2.stream.streamToString(profile.streamType)); - const colorizer = new rs2.Colorizer(); - const decimate = new rs2.DecimationFilter(); - const paintRect = new Rect(0, 0, profile.width, profile.height); - sensor.open(profile); - sensor.start((frame) => { - if (!win.shouldWindowClose()) { - let resultFrame = frame; - if (frame instanceof rs2.DepthFrame) { - resultFrame = colorizer.colorize(decimate.process(frame)); - } - win.beginPaint(); - renderer.render(resultFrame, paintRect); - win.endPaint(); - } else { - setTimeout(() => { - sensor.stop(); - win.destroy(); - resolve(); - }, 0); - } - }); - }); -} - -function controlSensorStreamsAction() { - return selectStreamProfile(['Please select the desired stream profile'], sensor, (profile) => { - if (profile.streamType === rs2.stream.STREAM_DEPTH || - (profile.streamType === rs2.stream.STREAM_COLOR && - profile.format === rs2.format.FORMAT_RGB8)) { - return true; - } - return false; - }).then((profile) => { - return startStreamProfle(profile); - }); -} - -function showStreamIntrinsicsAction() { - return selectStreamProfile( - ['Please select the desired stream profile'], sensor).then((profile) => { - if (profile instanceof rs2.VideoStreamProfile) { - console.log('Intrinsics is:\n\n', profile.getIntrinsics()); - } else if (profile instanceof rs2.MotionStreamProfile) { - console.log('Motion intrinsics is:\n\n', profile.getMotionIntrinsics()); - } - }); -} - -function displayExtrinsicsAction(device, sensor) { - let fromSensor; - let fromProfile; - let toSensor; - let toProfile; - let fromDescriptions = [ - 'Select a sensor as the from sensor', - // eslint-disable-next-line - 'Please choose a sensor and then a stream that will be used as the origin of extrinsic transformation' - ]; - let toDescriptions = [ - 'Select a sensor as the target sensor', - // eslint-disable-next-line - 'Please choose a sensor and then a stream that will be used as the target of extrinsic transformation' - ]; - return selectSensorImpl(fromDescriptions).then((s1) => { - fromSensor = s1; - return selectStreamProfile(['Select a profile as the from profile'], fromSensor); - }).then((p1) => { - fromProfile = p1; - return selectSensorImpl(toDescriptions); - }).then((s2) => { - toSensor = s2; - return selectStreamProfile(['Select a profile as the target profile'], toSensor); - }).then((p2) => { - toProfile = p2; - console.log('Extrinsics is:\n\n', fromProfile.getExtrinsicsTo(toProfile)); - }); -} - -function selectActionImpl(descriptions) { - const actionChoices = []; - actions.forEach((act, index) => { - actionChoices.push(index.toString() + ' ' + act.description); - }); - return getUserSelection(descriptions, actionChoices).then((index) => { - action = actions[index]; - }); -} - -function connectDevice() { - const ctx = new rs2.Context(); - devices = ctx.queryDevices().devices; - if (!devices) { - console.log('No devices connected, waiting for device to be connected...'); - const hub = new rs2.DeviceHub(ctx); - return [hub.waitForDevice()]; - } - return devices; -} - -function getDeviceName(device) { - let name = 'Unknown device'; - if (device.supportsCameraInfo(rs2.camera_info.CAMERA_INFO_NAME)) { - name = device.getCameraInfo(rs2.camera_info.CAMERA_INFO_NAME); - } - if (device.supportsCameraInfo(rs2.camera_info.CAMERA_INFO_SERIAL_NUMBER)) { - sn = device.getCameraInfo(rs2.camera_info.CAMERA_INFO_SERIAL_NUMBER); - } - return name + ' #' + sn; -} - -function getSensorName(sensor) { - if (sensor.supportsCameraInfo(rs2.camera_info.CAMERA_INFO_NAME)) { - return sensor.getCameraInfo(rs2.camera_info.CAMERA_INFO_NAME); - } else { - return 'Unknown Sensor'; - } -} - -function getUserSelection(descriptionArray, choices) { - console.log('\n\n================ ' + descriptionArray[0] + ' ============================'); - for (let i = 1; i < descriptionArray.length; i++) { - console.log(descriptionArray[i]); - } - return input.select('Please select', choices).then((result) => { - for (let i = 0; i < choices.length; i++) { - if (choices[i] === result) { - return i; - } - } - }); -} -const renderer = new Texture(); -machine = new FSM({ - initial: 'stateInit', - events: [ - {name: 'transSelectDev', from: 'stateInit', to: 'stateDevSelected'}, - {name: 'transSelectSensor', from: 'stateDevSelected', to: 'stateSensorSelected'}, - {name: 'transSelectAction', from: 'stateSensorSelected', to: 'stateActionSelected'}, - {name: 'transEnd', from: 'stateActionSelected', to: 'stateEnd'}, - {name: 'transReturnToInit', from: 'stateDevSelected', to: 'stateInit'}, - {name: 'transReturnToDevSelected', from: 'stateSensorSelected', to: 'stateDevSelected'}, - {name: 'transReturnToSensorSelected', from: 'stateActionSelected', to: 'stateSensorSelected'}, - ], - callbacks: { - ontransSelectDev: () => { - return selectDevImpl(['Select a device']); - }, - ontransSelectSensor: () => { - return selectSensorImpl(['Select a sensor']); - }, - ontransSelectAction: () => { - return selectActionImpl(['What would you like to do with the sensor ?']); - }, - onenteredstateInit: () => { - return machine.transSelectDev(); - }, - onenteredstateDevSelected: () => { - printDeviceInfo(dev); - if (devices.length === 1) { - return machine.transSelectSensor(); - } - const choices = ['select a sensor', 'return to select other device']; - const choiceActions = ['transSelectSensor', 'transReturnToInit']; - return getUserSelection(['Choose what to do next'], choices).then((idx) => { - return machine[choiceActions[idx]](); - }); - }, - onenteredstateSensorSelected: () => { - const choices = ['select an action', 'return to select other sensor']; - const choiceActions = ['transSelectAction', 'transReturnToDevSelected']; - return getUserSelection(['Choose what to do next'], choices).then((idx) => { - return machine[choiceActions[idx]](); - }); - }, - onenteredstateActionSelected: () => { - const choices = ['quit', 'return to select other action']; - const choiceActions = ['transEnd', 'transReturnToSensorSelected']; - return action.operation().then(() => { - return getUserSelection(['Choose what to do next'], choices); - }).then((idx) => { - return machine[choiceActions[idx]](); - }); - }, - onenteredstateEnd: () => { - rs2.cleanup(); - }, - }, -}); - -connectDevice(); -machine.transSelectDev(); diff --git a/wrappers/nodejs/index.js b/wrappers/nodejs/index.js deleted file mode 100644 index 7dc9efcabb..0000000000 --- a/wrappers/nodejs/index.js +++ /dev/null @@ -1,6754 +0,0 @@ -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -const RS2 = require('bindings')('node_librealsense'); -const EventEmitter = require('events'); -const PNG = require('pngjs').PNG; -const fs = require('fs'); - -/** - * UnrecoverableError is the type of error that jeopardized the modue that restart - * is needed. - */ -class UnrecoverableError extends Error { - constructor(message) { - super('Unrecoverable! '+ message); - } -} - -// TODO(tingshao): resolve the potential disabled eslint errors -/* eslint-disable prefer-rest-params, valid-jsdoc, no-unused-vars, camelcase */ -/** - * A RealSense camera - */ -class Device { - constructor(cxxDev, autoDelete = true) { - this.cxxDev = cxxDev; - if (autoDelete) { - internal.addObject(this); - } - } - - /** - * Check if everything is OK, e.g. if the device object is connected to underlying hardware - * @return {Boolean} - */ - get isValid() { - return (this.cxxDev !== null); - } - - /** - * get an array of adjacent sensors, sharing the same physical parent composite device - * @return {Sensor[]} - */ - querySensors() { - let sensors = this.cxxDev.querySensors(); - if (!sensors) return undefined; - - const array = []; - sensors.forEach((s) => { - if (s.is(RS2.RS2_EXTENSION_DEPTH_SENSOR)) { - array.push(new DepthSensor(s)); - } else if (s.is(RS2.RS2_EXTENSION_COLOR_SENSOR)) { - array.push(new ColorSensor(s)); - } else if (s.is(RS2.RS2_EXTENSION_MOTION_SENSOR)) { - array.push(new MotionSensor(s)); - } else if (s.is(RS2.RS2_EXTENSION_FISHEYE_SENSOR)) { - array.push(new FisheyeSensor(s)); - } else { - array.push(new Sensor(s)); - } - }); - return array; - } - - /** - * Get the first sensor - * @return {Sensor|undefined} - */ - get first() { - let sensors = this.querySensors(); - if (sensors && sensors.length > 0) { - return sensors[0]; - } - return undefined; - } - - /** - * Information that can be queried from the device. - * Not all information attributes are available on all camera types. - * This information is mainly available for camera debug and troubleshooting and should not be - * used in applications. - * @typedef {Object} CameraInfoObject - * @property {String|undefined} name - Device friendly name.
    undefined is not - * supported. - * @property {String|undefined} serialNumber - Device serial number.
    undefined is not - * supported. - * @property {String|undefined} firmwareVersion - Primary firmware version. - *
    undefined is not supported. - * @property {String|undefined} physicalPort - Unique identifier of the port the device is - * connected to (platform specific).
    undefined is not supported. - * @property {String|undefined} debugOpCode - If device supports firmware logging, this is the - * command to send to get logs from firmware.
    undefined is not supported. - * @property {String|undefined} advancedMode - True if the device is in advanced mode. - *
    undefined is not supported. - * @property {String|undefined} productId - Product ID as reported in the USB descriptor. - *
    undefined is not supported. - * @property {Boolean|undefined} cameraLocked - True if EEPROM is locked.
    undefined is not - * supported. - * @property {String|undefined} usbTypeDescriptor - Designated USB specification: USB2/USB3. - *
    undefined is not supported. - * @property {String|undefined} recommendedFirmwareVersion - Latest firmware version. - *
    undefined is not supported. - * @see [Device.getCameraInfo()]{@link Device#getCameraInfo} - */ - - /** - * Get camera information - * There are 2 acceptable forms of syntax: - *
    
    -   *  Syntax 1. getCameraInfo()
    -   *  Syntax 2. getCameraInfo(info)
    -   * 
    - * - * @param {String|Integer} [info] - the camera_info type, see {@link camera_info} for available - * values - * @return {CameraInfoObject|String|undefined} if no argument is provided, {CameraInfoObject} is - * returned. If a camera_info is provided, the specific camera info value string is returned. - */ - getCameraInfo(info) { - const funcName = 'Device.getCameraInfo()'; - checkArgumentLength(0, 1, arguments.length, funcName); - if (arguments.length === 0) { - let result = {}; - if (this.cxxDev.supportsCameraInfo(camera_info.CAMERA_INFO_NAME)) { - result.name = this.cxxDev.getCameraInfo(camera_info.CAMERA_INFO_NAME); - } - if (this.cxxDev.supportsCameraInfo(camera_info.CAMERA_INFO_SERIAL_NUMBER)) { - result.serialNumber = this.cxxDev.getCameraInfo(camera_info.CAMERA_INFO_SERIAL_NUMBER); - } - if (this.cxxDev.supportsCameraInfo(camera_info.CAMERA_INFO_FIRMWARE_VERSION)) { - result.firmwareVersion = this.cxxDev.getCameraInfo( - camera_info.CAMERA_INFO_FIRMWARE_VERSION); - } - if (this.cxxDev.supportsCameraInfo(camera_info.CAMERA_INFO_PHYSICAL_PORT)) { - result.physicalPort = this.cxxDev.getCameraInfo(camera_info.CAMERA_INFO_PHYSICAL_PORT); - } - if (this.cxxDev.supportsCameraInfo(camera_info.CAMERA_INFO_DEBUG_OP_CODE)) { - result.debugOpCode = this.cxxDev.getCameraInfo(camera_info.CAMERA_INFO_DEBUG_OP_CODE); - } - if (this.cxxDev.supportsCameraInfo(camera_info.CAMERA_INFO_ADVANCED_MODE)) { - result.advancedMode = this.cxxDev.getCameraInfo(camera_info.CAMERA_INFO_ADVANCED_MODE); - } - if (this.cxxDev.supportsCameraInfo(camera_info.CAMERA_INFO_PRODUCT_ID)) { - result.productId = this.cxxDev.getCameraInfo(camera_info.CAMERA_INFO_PRODUCT_ID); - } - if (this.cxxDev.supportsCameraInfo(camera_info.CAMERA_INFO_CAMERA_LOCKED)) { - result.cameraLocked = this.cxxDev.getCameraInfo(camera_info.CAMERA_INFO_CAMERA_LOCKED); - } - if (this.cxxDev.supportsCameraInfo(camera_info.CAMERA_INFO_USB_TYPE_DESCRIPTOR)) { - result.usbTypeDescriptor = this.cxxDev.getCameraInfo( - camera_info.CAMERA_INFO_USB_TYPE_DESCRIPTOR); - } - if (this.cxxDev.supportsCameraInfo(camera_info.CAMERA_INFO_RECOMMENDED_FIRMWARE_VERSION)) { - result.recommendedFirmwareVersion = this.cxxDev.getCameraInfo( - camera_info.CAMERA_INFO_RECOMMENDED_FIRMWARE_VERSION); - } - return result; - } else { - const val = checkArgumentType(arguments, constants.camera_info, 0, funcName); - return (this.cxxDev.supportsCameraInfo(val) ? this.cxxDev.getCameraInfo(val) : undefined); - } - } - - get cameraInfo() { - return this.getCameraInfo(); - } - - /** - * Check if specific camera info is supported. - * @param {String|Integer} info - info type to query. See {@link camera_info} for available values - * @return {Boolean|undefined} Returns undefined if an invalid info type was specified. - * @see enum {@link camera_info} - * @example Example of 3 equivalent calls of the same query - * device.supportsCameraInfo('name'); - * device.supportsCameraInfo(realsense2.camera_info.camera_info_name); - * device.supportsCameraInfo(realsense2.camera_info.CAMERA_INFO_NAME); - */ - supportsCameraInfo(info) { - const funcName = 'Device.supportsCameraInfo()'; - checkArgumentLength(1, 1, arguments.length, funcName); - const i = checkArgumentType(arguments, constants.camera_info, 0, funcName); - return this.cxxDev.supportsCameraInfo(i); - } - - /** - * Send hardware reset request to the device. - * @return {undefined} - */ - reset() { - this.cxxDev.reset(); - } - - /** - * Release resources associated with the object - */ - destroy() { - if (this.cxxDev) { - this.cxxDev.destroy(); - this.cxxDev = undefined; - } - this._events = undefined; - } - - static _internalCreateDevice(cxxDevice) { - return cxxDevice.isTm2() ? new Tm2(cxxDevice) : new Device(cxxDevice); - } -} - -/** - * This class represents the tm2 device - */ -class Tm2 extends Device { - constructor(dev) { - super(dev); - } - - /** - * Enter the given device into loopback operation mode that uses the given file as input for - * raw data - * @param {String} file Path to bag file with raw data for loopback - * @return {undefined} - */ - enableLoopback(file) { - const funcName = 'Tm2.enableLoopback()'; - checkArgumentLength(1, 1, arguments.length, funcName); - checkArgumentType(arguments, 'string', 0, funcName); - checkFileExistence(file); - this.cxxDev.enableLoopback(file); - } - - /** - * Restores the given device into normal operation mode - * @return {undefined} - */ - disableLoopback() { - this.cxxDev.disableLoopback(); - } - - /** - * Checks if the device is in loopback mode or not - * @return {Boolean} - */ - get loopbackEnabled() { - return this.cxxDev.isLoopbackEnabled(); - } -} - -/** - * Class represents a stream configuration - */ -class StreamProfile { - constructor(cxxProfile) { - this.cxxProfile = cxxProfile; - this.streamValue = this.cxxProfile.stream(); - this.formatValue = this.cxxProfile.format(); - this.fpsValue = this.cxxProfile.fps(); - this.indexValue = this.cxxProfile.index(); - this.uidValue = this.cxxProfile.uniqueID(); - this.isDefaultValue = this.cxxProfile.isDefault(); - } - - /** - * Get stream index the input profile in case there are multiple streams of the same type - * - * @return {Integer} - */ - get streamIndex() { - return this.indexValue; - } - - /** - * Get stream type - * - * @return {Integer} - */ - get streamType() { - return this.streamValue; - } - - /** - * Get binary data format - * - * @return {Integer} - */ - get format() { - return this.formatValue; - } - - /** - * Expected rate for data frames to arrive, meaning expected number of frames per second - * - * @return {Integer} - */ - get fps() { - return this.fpsValue; - } - - /** - * Get the identifier for the stream profile, unique within the application - * - * @return {Integer} - */ - get uniqueID() { - return this.uidValue; - } - - /** - * Returns non-zero if selected profile is recommended for the sensor - * This is an optional hint we offer to suggest profiles with best performance-quality tradeof - * - * @return {Boolean} - */ - get isDefault() { - return this.isDefaultValue; - } - - /** - * Extrinsics: - * @typedef {Object} ExtrinsicsObject - * @property {Float32[]} rotation - Array(9), Column-major 3x3 rotation matrix - * @property {Float32[]} translation - Array(3), Three-element translation vector, in meters - * @see [StreamProfile.getExtrinsicsTo()]{@link StreamProfile#getExtrinsicsTo} - */ - - /** - * Get extrinsics from a this stream to the target stream - * - * @param {StreamProfile} toProfile the target stream profile - * @return {ExtrinsicsObject} - */ - getExtrinsicsTo(toProfile) { - const funcName = 'StreamProfile.getExtrinsicsTo()'; - checkArgumentLength(1, 1, arguments.length, funcName); - checkArgumentType(arguments, StreamProfile, 0, funcName); - return this.cxxProfile.getExtrinsicsTo(toProfile.cxxProfile); - } - - destroy() { - if (this.cxxProfile) { - this.cxxProfile.destroy(); - this.cxxProfile = undefined; - } - } - - static _internalCreateStreamProfile(cxxProfile) { - if (cxxProfile.isMotionProfile()) { - return new MotionStreamProfile(cxxProfile); - } else if (cxxProfile.isVideoProfile()) { - return new VideoStreamProfile(cxxProfile); - } else { - return new StreamProfile(cxxProfile); - } - } -} - -/** - * Motion intrinsics: scale, bias, and variances. - * @typedef {Object} MotionIntrinsics - * @property {Float32[]} data - Array(12), Interpret data array values. Indices are: - *
    [0 - Scale X, 1 - cross axis, 2 - cross axis, 3 - Bias X, - *
    4 - cross axis, 5 - Scale Y, 6 - cross axis, 7 - Bias Y, - *
    8 - cross axis, 9 - cross axis, 10 - Scale Z, 11 - Bias Z] - * @property {Float32[]} noiseVariances - Array(3), Variance of noise for X, Y, and Z axis - * @property {Float32[]} biasVariances - Array(3), Variance of bias for X, Y, and Z axis - * @see [MotionStreamProfile.getMotionIntrinsics()]{@link MotionStreamProfile#getMotionIntrinsics} - */ - -/** - * This represent the stream profile of motion stream - */ -class MotionStreamProfile extends StreamProfile { - constructor(cxxProfile) { - super(cxxProfile); - } - - /** - * Returns scale and bias of a motion stream. - * @return {MotionIntrinsics} {@link MotionIntrinsics} - */ - getMotionIntrinsics() { - return this.cxxProfile.getMotionIntrinsics(); - } -} - -/** - * List of devices - */ -class DeviceList { - constructor(cxxList) { - this.cxxList = cxxList; - internal.addObject(this); - } - - /** - * Release resources associated with the object - */ - destroy() { - if (this.cxxList) { - this.cxxList.destroy(); - this.cxxList = undefined; - } - } - - /** - * Checks if a specific device is contained inside a device list. - * - * @param {Device} device the camera to be checked - * @return {Boolean} true if the camera is contained in the list, otherwise false - */ - contains(device) { - const funcName = 'DeviceList.contains()'; - checkArgumentLength(1, 1, arguments.length, funcName); - checkArgumentType(arguments, Device, 0, funcName); - return this.cxxList.contains(device.cxxDev); - } - - /** - * Creates a device by index. The device object represents a physical camera and provides the - * means to manipulate it. - * - * @param {Integer} index the zero based index of the device in the device list - * @return {Device|undefined} - */ - getDevice(index) { - const funcName = 'DeviceList.getDevice()'; - checkArgumentLength(1, 1, arguments.length, funcName); - checkArgumentType(arguments, 'number', 0, funcName, 0, this.size); - let dev = this.cxxList.getDevice(index); - return dev ? Device._internalCreateDevice(dev) : undefined; - } - - get devices() { - let len = this.cxxList.size(); - if (!len) { - return undefined; - } - let output = []; - for (let i = 0; i < len; i++) { - output[i] = Device._internalCreateDevice(this.cxxList.getDevice(i)); - } - return output; - } - /** - * Determines number of devices in a list. - * @return {Integer} - */ - get size() { - return this.cxxList.size(); - } - - /** - * Get the first device - * @return {Device|undefined} - */ - get front() { - return this.getDevice(0); - } - - /** - * Get the last device - * @return {Device|undefined} - */ - get back() { - if (this.size > 0) { - return this.getDevice(this.size - 1); - } - return undefined; - } -} - -class VideoStreamProfile extends StreamProfile { - /** - * Construct a device object, representing a RealSense camera - */ - constructor(cxxProfile) { - super(cxxProfile); - - // TODO(tinshao): determine right width and height value - this.widthValue = this.cxxProfile.width(); - this.heightValue = this.cxxProfile.height(); - } - - /** - * Width in pixels of the video stream - * - * @return {Integer} - */ - get width() { - return this.widthValue; - } - - - /** - * height in pixels of the video stream - * - * @return {Integer} - */ - get height() { - return this.heightValue; - } - - /** - * Stream intrinsics: - * @typedef {Object} IntrinsicsObject - * @property {Integer} width - Width of the image in pixels - * @property {Integer} height - Height of the image in pixels - * @property {Float32} ppx - Horizontal coordinate of the principal point of the image, as a - * pixel offset from the left edge - * @property {Float32} ppy - Vertical coordinate of the principal point of the image, as a pixel - * offset from the top edge - * @property {Float32} fx - Focal length of the image plane, as a multiple of pixel width - * @property {Float32} fy - Focal length of the image plane, as a multiple of pixel height - * @property {Integer} model - Distortion model of the image, see - * @property {Float32[]} coeffs - Array(5), Distortion coefficients - * @see [StreamProfile.getIntrinsics()]{@link StreamProfile#getIntrinsics} - */ - - /** - * When called on a VideoStreamProfile, returns the intrinsics of specific stream configuration - * @return {IntrinsicsObject|undefined} - */ - getIntrinsics() { - return this.cxxProfile.getVideoStreamIntrinsics(); - } -} - -class Options { - constructor(cxxObj) { - this.cxxObj = cxxObj; - } - - setCxxOptionsObject(cxxObj) { - this.cxxObj = cxxObj; - } - /** - * Check if particular option is read-only - * @param {String|Number} option The option to be checked - * @return {Boolean|undefined} true if option is read-only and undefined if not supported - */ - isOptionReadOnly(option) { - const funcName = 'Options.isOptionReadOnly()'; - checkArgumentLength(1, 1, arguments.length, funcName); - const o = checkArgumentType(arguments, constants.option, 0, funcName); - if (!this.cxxObj.supportsOption(o)) { - return undefined; - } - - return this.cxxObj.isOptionReadonly(o); - } - - /** - * Read option value from the sensor. - * @param {String|Number} option The option to be queried - * @return {Float32|undefined} The value of the option, or undefined if invalid - * option - * @see {@link option} - */ - getOption(option) { - const funcName = 'Options.getOption()'; - checkArgumentLength(1, 1, arguments.length, funcName); - const o = checkArgumentType(arguments, constants.option, 0, funcName); - if (!this.cxxObj.supportsOption(o)) { - return undefined; - } - - return this.cxxObj.getOption(o); - } - - /** - * @typedef {Object} OptionRangeObject - * @property {Float32} minValue - the minimum value which will be accepted for this option - * @property {Float32} maxValue - the maximum value which will be accepted for this option - * @property {Float32} defaultValue - the default value of the option - * @property {Float32} step - the granularity of options which accept discrete values, or zero if - * the option accepts continuous values - * @see [Sensor.getOptionRange()]{@link Sensor#getOptionRange} - */ - - /** - * Retrieve the available range of values of a supported option. - * @param {String|Integer} option - the option that is being queried. See {@link option} for - * available values - * @return {OptionRangeObject|undefined} Returns undefined if an invalid option was specified - * @see {@link OptionRangeObject} - * @see {@link option} - * - * @example Example of 3 equivalent calls of the same option range - * Sensor.getOptionRange('backlight-compensation'); - * Sensor.getOptionRange(realsense2.option.option_backlight_compensation); - * Sensor.getOptionRange(realsense2.option.OPTION_BACKLIGHT_COMPENSATION); - */ - getOptionRange(option) { - const funcName = 'Options.getOptionRange()'; - checkArgumentLength(1, 1, arguments.length, funcName); - const o = checkArgumentType(arguments, constants.option, 0, funcName); - if (!this.cxxObj.supportsOption(o)) { - return undefined; - } - return this.cxxObj.getOptionRange(o); - } - - /** - * Write new value to device option. - * @param {String|Integer} option - the option that is being queried. See {@link option} for - * available values - * @param {Float32} value - the new value to be set - * @see {@link option} - * @return {undefined} - */ - setOption(option, value) { - const funcName = 'Options.setOption()'; - checkArgumentLength(2, 2, arguments.length, funcName); - const o = checkArgumentType(arguments, constants.option, 0, funcName); - checkArgumentType(arguments, 'number', 1, funcName); - if (!this.cxxObj.supportsOption(o) || this.cxxObj.isOptionReadonly(o)) { - return undefined; - } - if (!this._internalIsOptionValueInRange(o, value)) { - return undefined; - } - this.cxxObj.setOption(o, value); - } - - /** - * Check if particular option is supported by a subdevice. - * @param {String|Integer} option - the option that is being queried. See {@link option} for - * available values - * @return {Boolean|undefined} Returns undefined if an invalid option was specified - * @see {@link option} - */ - supportsOption(option) { - const funcName = 'Options.supportsOption()'; - checkArgumentLength(1, 1, arguments.length, funcName); - const o = checkArgumentType(arguments, constants.option, 0, funcName); - return this.cxxObj.supportsOption(o); - } - - /** - * Get option description. - * @param {String|Integer} option - the option that is being queried. See {@link option} for - * available values - * @return {String|undefined} the human readable description of the option. Returns undefined if - * an invalid option was specified - * @see {@link option} - */ - getOptionDescription(option) { - const funcName = 'Options.getOptionDescription()'; - checkArgumentLength(1, 1, arguments.length, funcName); - const o = checkArgumentType(arguments, constants.option, 0, funcName); - if (!this.cxxObj.supportsOption(o)) { - return undefined; - } - return this.cxxObj.getOptionDescription(o); - } - - /** - * Get option value description (in case specific option value hold special meaning). - * @param {String|Integer} option - the option that is being queried. See {@link option} for - * available values - * @return {String|undefined} the human readable description of the option value. Returns - * undefined if an invalid option was specified - * @see {@link option} - */ - getOptionValueDescription(option, value) { - const funcName = 'Options.getOptionValueDescription()'; - checkArgumentLength(2, 2, arguments.length, funcName); - const o = checkArgumentType(arguments, constants.option, 0, funcName); - checkArgumentType(arguments, 'number', 1, funcName); - if (!this.cxxObj.supportsOption(o)) { - return undefined; - } - return this.cxxObj.getOptionValueDescription(o, value); - } - - _internalIsOptionValueInRange(option, value) { - let range = this.getOptionRange(option); - return (range && value >= range.minValue && value <= range.maxValue); - } -} - -/** - * A sensor device in a RealSense camera - */ -class Sensor extends Options { - /** - * Construct a Sensor object, representing a RealSense camera subdevice - * By default, native resources associated with a Sensor object are freed - * automatically during cleanup. - */ - constructor(cxxSensor, autoDelete = true) { - super(cxxSensor); - this.cxxSensor = cxxSensor; - this._events = new EventEmitter(); - if (autoDelete === true) { - internal.addObject(this); - } - } - - /** - * Check if everything is OK, e.g. if the device object is connected to underlying hardware - * @return {Boolean} - */ - get isValid() { - return (this.cxxSensor !== null); - } - - /** - * Open subdevice for exclusive access, by committing to a configuration. - * There are 2 acceptable forms of syntax: - *
    
    -   *  Syntax 1. open(streamProfile)
    -   *  Syntax 2. open(profileArray)
    -   * 
    - * Syntax 2 is for opening multiple profiles in one function call and should be used for - * interdependent streams, such as depth and infrared, that have to be configured together. - * - * @param {StreamProfile} streamProfile configuration commited by the device - * @param {StreamProfile[]} profileArray configurations array commited by the device - * @see [Sensor.getStreamProfiles]{@link Sensor#getStreamProfiles} for a list of all supported - * stream profiles - */ - open(streamProfile) { - const funcName = 'Sensor.open()'; - checkArgumentLength(1, 1, arguments.length, funcName); - if (Array.isArray(streamProfile) && streamProfile.length > 0) { - let cxxStreamProfiles = []; - for (let i = 0; i < streamProfile.length; i++) { - if (!(streamProfile[i] instanceof StreamProfile)) { - throw new TypeError( - 'Sensor.open() expects a streamProfile object or an array of streamProfile objects'); // eslint-disable-line - } - cxxStreamProfiles.push(streamProfile[i].cxxProfile); - } - this.cxxSensor.openMultipleStream(cxxStreamProfiles); - } else { - checkArgumentType(arguments, StreamProfile, 0, funcName); - this.cxxSensor.openStream(streamProfile.cxxProfile); - } - } - - /** - * Check if specific camera info is supported - * @param {String|Integer} info - info type to query. See {@link camera_info} for available values - * @return {Boolean|undefined} Returns undefined if an invalid info type was specified. - * @see enum {@link camera_info} - */ - supportsCameraInfo(info) { - const funcName = 'Sensor.supportsCameraInfo()'; - checkArgumentLength(1, 1, arguments.length, funcName); - const i = checkArgumentType(arguments, constants.camera_info, 0, funcName); - return this.cxxSensor.supportsCameraInfo(i); - } - - /** - * Get camera information of the sensor - * - * @param {String|Integer} info - the camera_info type, see {@link camera_info} for available - * values - * @return {String|undefined} - */ - getCameraInfo(info) { - const funcName = 'Sensor.getCameraInfo()'; - checkArgumentLength(1, 1, arguments.length, funcName); - const i = checkArgumentType(arguments, constants.camera_info, 0, funcName); - return (this.cxxSensor.supportsCameraInfo(i) ? this.cxxSensor.getCameraInfo(i) : undefined); - } - - /** - * Stops any streaming and close subdevice. - * @return {undefined} No return value - */ - close() { - this.cxxSensor.close(); - } - - /** - * Delete the resource for accessing the subdevice. The device would not be accessable from - * this object after the operation. - * @return {undefined} No return value - */ - destroy() { - this._events = null; - if (this.cxxSensor) { - this.cxxSensor.destroy(); - this.cxxSensor = undefined; - } - } - - /** - * This callback is called when a frame is captured - * @callback FrameCallback - * @param {Frame} frame - The captured frame - * - * @see [Sensor.start]{@link Sensor#start} - */ - - /** - * Start passing frames into user provided callback - * There are 2 acceptable syntax: - *
    
    -   *  Syntax 1. start(callback)
    -   *  Syntax 2. start(Syncer)
    -   * 
    - * - * @param {FrameCallback} callback - * @param {Syncer} syncer, the syncer to synchronize frames - * - * @example Simply do logging when a frame is captured - * sensor.start((frame) => { - * console.log(frame.timestamp, frame.frameNumber, frame.data); - * }); - * - */ - start(callback) { - const funcName = 'Sensor.start()'; - checkArgumentLength(1, 1, arguments.length, funcName); - if (arguments[0] instanceof Syncer) { - this.cxxSensor.startWithSyncer(arguments[0].cxxSyncer, false, 0); - } else { - checkArgumentType(arguments, 'function', 0, funcName); - // create object to hold frames generated from native. - this.frame = new Frame(); - this.depthFrame = new DepthFrame(); - this.videoFrame = new VideoFrame(); - this.disparityFrame = new DisparityFrame(); - this.motionFrame = new MotionFrame(); - this.poseFrame = new PoseFrame(); - - let inst = this; - this.cxxSensor.frameCallback = function() { - // When the callback is triggered, the underlying frame bas been saved in the objects - // created above, we need to update it and callback. - if (inst.disparityFrame.isValid) { - inst.disparityFrame.updateProfile(); - callback(inst.disparityFrame); - } else if (inst.depthFrame.isValid) { - inst.depthFrame.updateProfile(); - callback(inst.depthFrame); - } else if (inst.videoFrame.isValid) { - inst.videoFrame.updateProfile(); - callback(inst.videoFrame); - } else if (inst.motionFrame.isValid) { - inst.motionFrame.updateProfile(); - callback(inst.motionFrame); - } else if (inst.poseFrame.isValid) { - inst.poseFrame.updateProfile(); - callback(inst.poseFrame); - } else { - inst.frame.updateProfile(); - callback(inst.frame); - } - }; - this.cxxSensor.startWithCallback('frameCallback', this.frame.cxxFrame, - this.depthFrame.cxxFrame, this.videoFrame.cxxFrame, this.disparityFrame.cxxFrame, - this.motionFrame.cxxFrame, this.poseFrame.cxxFrame); - } - } - - /** - * stop streaming - * @return {undefined} No return value - */ - stop() { - if (this.cxxSensor) { - this.cxxSensor.stop(); - } - if (this.frame) this.frame.release(); - if (this.videoFrame) this.videoFrame.release(); - if (this.depthFrame) this.depthFrame.release(); - } - - /** - * @typedef {Object} NotificationEventObject - * @property {String} descr - The human readable literal description of the notification - * @property {Float} timestamp - The timestamp of the notification - * @property {String} severity - The severity of the notification - * @property {String} category - The category of the notification - * @property {String} serializedData - The serialized data of the notification - */ - - /** - * This callback is called when there is a device notification - * @callback NotificationCallback - * @param {NotificationEventObject} info - * @param {String} info.descr - See {@link NotificationEventObject} for details - * @param {Float} info.timestamp - See {@link NotificationEventObject} for details - * @param {String} info.severity - See {@link NotificationEventObject} for details - * @param {String} info.category - See {@link NotificationEventObject} for details - * @param {String} info.serializedData - See {@link NotificationEventObject} for details - * - * @see {@link NotificationEventObject} - * @see [Sensor.setNotificationsCallback()]{@link Sensor#setNotificationsCallback} - */ - - /** - * @event Sensor#notification - * @param {NotificationEventObject} evt - * @param {String} evt.descr - See {@link NotificationEventObject} for details - * @param {Float} evt.timestamp - See {@link NotificationEventObject} for details - * @param {String} evt.severity - See {@link NotificationEventObject} for details - * @param {String} evt.category - See {@link NotificationEventObject} for details - * @param {String} evt.serializedData - See {@link NotificationEventObject} for details - * @see {@link NotificationEventObject} - * @see [Sensor.setNotificationsCallback()]{@link Sensor#setNotificationsCallback} - */ - - /** - * register notifications callback - * @param {NotificationCallback} callback The user-provied notifications callback - * @see {@link NotificationEventObject} - * @see [Sensor 'notification']{@link Sensor#event:notification} event - * @return {undefined} - */ - setNotificationsCallback(callback) { - const funcName = 'Sensor.setNotificationsCallback()'; - checkArgumentLength(1, 1, arguments.length, funcName); - checkArgumentType(arguments, 'function', 0, funcName); - - this._events.on('notification', (info) => { - callback(info); - }); - let inst = this; - if (!this.cxxSensor.notificationCallback) { - this.cxxSensor.notificationCallback = function(info) { - // convert the severity and category properties from numbers to strings to be - // consistent with documentation which are more meaningful to users - info.severity = log_severity.logSeverityToString(info.severity); - info.category = notification_category.notificationCategoryToString(info.category); - inst._events.emit('notification', info); - }; - this.cxxSensor.setNotificationCallback('notificationCallback'); - } - return undefined; - } - - /** - * Get a list of stream profiles that given subdevice can provide. The returned profiles should be - * destroyed by calling its destroy() method. - * - * @return {StreamProfile[]} all of the supported stream profiles - * See {@link StreamProfile} - */ - getStreamProfiles() { - let profiles = this.cxxSensor.getStreamProfiles(); - if (profiles) { - const array = []; - profiles.forEach((profile) => { - array.push(StreamProfile._internalCreateStreamProfile(profile)); - }); - return array; - } - } -} - -/** - * Sensor for managing region of interest. - */ -class ROISensor extends Sensor { - /** - * Create a ROISensor out of another sensor - * @param {Sensor} sensor a sensor object - * @return {ROISensor|undefined} return a ROISensor if the sensor can be - * treated as a ROISensor, otherwise return undefined. - */ - static from(sensor) { - if (sensor.cxxSensor.isROISensor()) { - return new ROISensor(sensor.cxxSensor); - } - return undefined; - } - - /** - * Construct a ROISensor object, representing a RealSense camera subdevice - * The newly created ROISensor object shares native resources with the sensor - * argument. So the new object shouldn't be freed automatically to make - * sure resources released only once during cleanup. - */ - constructor(cxxSensor) { - super(cxxSensor, false); - } - - /** - * @typedef {Object} RegionOfInterestObject - * @property {Float32} minX - lower horizontal bound in pixels - * @property {Float32} minY - lower vertical bound in pixels - * @property {Float32} maxX - upper horizontal bound in pixels - * @property {Float32} maxY - upper vertical bound in pixels - * @see [Device.getRegionOfInterest()]{@link Device#getRegionOfInterest} - */ - - /** - * Get the active region of interest to be used by auto-exposure algorithm. - * @return {RegionOfInterestObject|undefined} Returns undefined if failed - * @see {@link RegionOfInterestObject} - */ - getRegionOfInterest() { - return this.cxxSensor.getRegionOfInterest(); - } - - /** - * Set the active region of interest to be used by auto-exposure algorithm - * There are 2 acceptable forms of syntax: - *
    
    -   *  Syntax 1. setRegionOfInterest(region)
    -   *  Syntax 2. setRegionOfInterest(minX, minY, maxX, maxY)
    -   * 
    - * - * @param {RegionOfInterestObject} region - the region of interest to be used. - * @param {Float32} region.minX - see {@link RegionOfInterestObject} for details. - * @param {Float32} region.minY - see {@link RegionOfInterestObject} for details. - * @param {Float32} region.maxX - see {@link RegionOfInterestObject} for details. - * @param {Float32} region.maxY - see {@link RegionOfInterestObject} for details. - * - * @param {Float32} minX - see {@link RegionOfInterestObject} for details. - * @param {Float32} minY - see {@link RegionOfInterestObject} for details. - * @param {Float32} maxX - see {@link RegionOfInterestObject} for details. - * @param {Float32} maxY - see {@link RegionOfInterestObject} for details. - */ - setRegionOfInterest(region) { - const funcName = 'ROISensor.setRegionOfInterest()'; - checkArgumentLength(1, 4, arguments.length, funcName); - let minX; - let minY; - let maxX; - let maxY; - if (arguments.length === 1) { - checkArgumentType(arguments, 'object', 0, funcName); - minX = region.minX; - minY = region.minY; - maxX = region.maxX; - maxY = region.maxY; - } else if (arguments.length === 4) { - checkArgumentType(arguments, 'number', 0, funcName); - checkArgumentType(arguments, 'number', 1, funcName); - checkArgumentType(arguments, 'number', 2, funcName); - checkArgumentType(arguments, 'number', 3, funcName); - minX = arguments[0]; - minY = arguments[1]; - maxX = arguments[2]; - maxY = arguments[3]; - } else { - throw new TypeError( - 'setRegionOfInterest(region) expects a RegionOfInterestObject as argument'); - } - this.cxxSensor.setRegionOfInterest(minX, minY, maxX, maxY); - } -} - -/** - * Depth sensor - */ -class DepthSensor extends Sensor { - /** - * Construct a device object, representing a RealSense camera - */ - constructor(sensor) { - super(sensor); - } - - /** - * Retrieves mapping between the units of the depth image and meters. - * - * @return {Float} depth in meters corresponding to a depth value of 1 - */ - get depthScale() { - return this.cxxSensor.getDepthScale(); - } -} - -/** - * Color sensor - */ -class ColorSensor extends Sensor { - /** - * Construct a device object, representing a RealSense camera - */ - constructor(sensor) { - super(sensor); - } -} - - -/** - * Motion sensor - */ -class MotionSensor extends Sensor { - /** - * Construct a device object, representing a RealSense camera - */ - constructor(sensor) { - super(sensor); - } -} - - -/** - * Fisheye sensor - */ -class FisheyeSensor extends Sensor { - /** - * Construct a device object, representing a RealSense camera - */ - constructor(sensor) { - super(sensor); - } -} - - -const internal = { - ctx: [], - objs: [], - - // Register error callback to native code - registerErrorCallback: function() { - RS2.registerErrorCallback(this, 'errorCallback'); - }, - - // The callback method called from native side - errorCallback: function(error) { - let msg = 'error native function ' + error.nativeFunction + ': ' + error.description; - if (error.recoverable) { - throw new Error(msg); - } - throw new UnrecoverableError(msg); - }, - - addContext: function(c) { - this.ctx.push(c); - }, - - addObject: function(o) { - this.objs.push(o); - }, - - cleanup: function() { - this.objs.forEach((obj) => { - obj.destroy(); - }); - this.objs = []; - this.ctx.forEach((context) => { - context.destroy(); - }); - this.ctx = []; - }, - - cleanupContext: function() { - let newArray = []; - this.ctx.forEach((c) => { - if (c.cxxCtx) { - newArray.push(c); - } - }); - // Dropping reference to invalid context(s) - this.ctx = newArray; - }, -}; - -/** - * Default librealsense context class, - */ -class Context { - /** - * There are only one acceptable form of syntax to create a Context for users: - *
    
    -   *  new Context();
    -   * 
    - * other forms are reserved for internal use only. - */ - constructor(cxxCtx) { - const funcName = 'Context.constructor()'; - // Internal code will create Context with cxxObject or other params - checkDiscreteArgumentLength([0, 1, 3, 4], arguments.length, funcName); - this._events = new EventEmitter(); - if (arguments.length === 0) { - this.cxxCtx = new RS2.RSContext(); - this.cxxCtx.create(); - } else if (arguments.length === 1) { - checkArgumentType(arguments, RS2.RSContext, 0, funcName); - this.cxxCtx = cxxCtx; - } else { - checkArgumentType(arguments, 'string', 0, funcName); - checkDiscreteArgumentValue(arguments, 0, ['recording', 'playback'], funcName); - this.cxxCtx = new (Function.prototype.bind.apply( - RS2.RSContext, [null].concat(Array.from(arguments))))(); - this.cxxCtx.create(); - } - this.cxxCtx._events = this._events; - internal.addContext(this); - } - - /** - * Cleanup underlying C++ context, and release all resources that were created by this context. - * The JavaScript Context object(s) will not be garbage-collected without call(s) to this function - */ - destroy() { - if (this.cxxCtx) { - this.cxxCtx.destroy(); - this.cxxCtx = undefined; - internal.cleanupContext(); - } - } - - /** - * Get the events object of EventEmitter - * @return {EventEmitter} - */ - get events() { - return this._events; - } - - /** - * Create a static snapshot of all connected devices at the time of the call - * @return {DeviceList|undefined} connected devices at the time of the call - */ - queryDevices() { - let list = this.cxxCtx.queryDevices(); - return (list ? new DeviceList(list) : undefined); - } - - /** - * Generate an array of all available sensors from all RealSense devices - * @return {Sensor[]|undefined} - */ - querySensors() { - let devList = this.queryDevices(); - if (!devList) { - return undefined; - } - let devices = devList.devices; - if (devices && devices.length) { - const array = []; - devices.forEach((dev) => { - const sensors = dev.querySensors(); - sensors.forEach((sensor) => { - array.push(sensor); - }); - }); - return array; - } - return undefined; - } - - /** - * Get the device from one of its sensors - * - * @param {Sensor} sensor - * @return {Device|undefined} - */ - getSensorParent(sensor) { - const funcName = 'Context.getSensorParent()'; - checkArgumentLength(1, 1, arguments.length, funcName); - checkArgumentType(arguments, Sensor, 0, funcName); - - let cxxDev = this.cxxCtx.createDeviceFromSensor(sensor.cxxSensor); - if (!cxxDev) { - return undefined; - } - return Device._internalCreateDevice(cxxDev); - } - - /** - * When one or more devices are plugged or unplugged into the system - * @event Context#device-changed - * @param {DeviceList} removed - The devices removed from the system - * @param {DeviceList} added - The devices added to the system - */ - - /** - * This callback is called when number of devices is changed - * @callback devicesChangedCallback - * @param {DeviceList} removed - The devices removed from the system - * @param {DeviceList} added - The devices added to the system - * - * @see [Context.setDevicesChangedCallback]{@link Context#setDevicesChangedCallback} - */ - - /** - * Register a callback function to receive device-changed notification - * @param {devicesChangedCallback} callback - devices changed callback - */ - setDevicesChangedCallback(callback) { - const funcName = 'Context.setDevicesChangedCallback()'; - checkArgumentLength(1, 1, arguments.length, funcName); - checkArgumentType(arguments, 'function', 0, funcName); - - this._events.on('device-changed', (removed, added) => { - callback(removed, added); - }); - let inst = this; - if (!this.cxxCtx.deviceChangedCallback) { - this.cxxCtx.deviceChangedCallback = function(removed, added) { - let rmList = (removed ? new DeviceList(removed) : undefined); - let addList = (added ? new DeviceList(added) : undefined); - inst._events.emit('device-changed', rmList, addList); - }; - this.cxxCtx.setDevicesChangedCallback('deviceChangedCallback'); - } - } - - /** - * Create a PlaybackDevice to playback recored data file. - * - * @param {String} file - the file path - * @return {PlaybackDevice|undefined} - */ - loadDevice(file) { - const funcName = 'Context.loadDevice()'; - checkArgumentLength(1, 1, arguments.length, funcName); - checkArgumentType(arguments, 'string', 0, funcName); - checkFileExistence(file); - const cxxDev = this.cxxCtx.loadDeviceFile(file); - if (!cxxDev) { - return undefined; - } - return new PlaybackDevice(cxxDev, true); - } - - /** - * Removes a PlaybackDevice from the context, if exists - * - * @param {String} file The file name that was loaded to create the playback device - */ - unloadDevice(file) { - const funcName = 'Context.unloadDevice()'; - checkArgumentLength(1, 1, arguments.length, funcName); - checkArgumentType(arguments, 'string', 0, funcName); - checkFileExistence(file); - this.cxxCtx.unloadDeviceFile(file); - } -} - -/** - * This class is for testing purpose. - * It is used to record all operations over librealsense into a file - * @extends Context - */ -class RecordingContext extends Context { - /** - * @param {String} fileName The file name to store the recorded data - * @param {String} section The section name within the recording - * @param {String|Integer} mode Recording mode, default to 'blank-frames' - * @see [enum recording_mode]{@link recording_mode} - */ - constructor(fileName, section = '', mode = 'blank-frames') { - const funcName = 'RecordingContext.constructor()'; - checkArgumentLength(1, 3, arguments.length, funcName); - checkArgumentType(arguments, 'string', 0, funcName); - checkArgumentType(arguments, 'string', 1, funcName); - let m = checkArgumentType(arguments, constants.recording_mode, 2, funcName); - m = (m === undefined ? recordingMode2Int(mode) : m); - super('recording', fileName, section, m); - } -} - -/** - * This class is for testing purpose. - * It is used to reproduce the same responses for the same operations as - * recording. The user must call the same methods as recorded in the file - * to get correct response. - * @extends Context - */ -class PlaybackContext extends Context { - /** - * @param {String} fileName The file name of the recording - * @param {String} section The section name used in recording - */ - constructor(fileName, section = '') { - const funcName = 'PlaybackContext.constructor()'; - checkArgumentLength(1, 2, arguments.length, funcName); - checkArgumentType(arguments, 'string', 0, funcName); - checkArgumentType(arguments, 'string', 1, funcName); - checkFileExistence(fileName); - super('playback', fileName, section); - } -} - -/** - * This class provides the ability to record a live session of streaming to a file - * - * There are 2 ways for users to create a RecorderDevice: - *
    
    - *  Syntax 1. RecorderDevice.from(device);
    - *  Syntax 2. new RecorderDevice(file, device);
    - * 
    - * - * Syntax 1 can only be applied to device that can be converted to RecorderDevice, see - * below example: - *
    
    - *  const file = 'record.bag';
    - *  let cfg = new rs2.Config();
    - *  cfg.enableRecordToFile(file);
    - *  let pipe = new rs2.Pipeline();
    - *  pipe.start(cfg);
    - *  let device = pipe.getActiveProfile().getDevice();
    - *  let recorder = rs2.RecorderDevice.from(device);
    - *
    - *  // record 10 frames.
    - *  for (let i = 0; i < 10; i++) {
    - *    let frames = pipe.waitForFrames();
    - *  }
    - *
    - *  pipe.stop();
    - *  // cleanup and make sure the recorded frames are flushed to file
    - *  rs2.cleanup();
    - * 
    - * - * Syntax 2 is to create a RecorderDevice from a live device, see below example: - *
    
    - *  let ctx = new rs2.Context();
    - *  let dev = ctx.queryDevices().devices[0];
    - *  // record to file record.bag
    - *  let recorder = new rs2.RecorderDevice('record.bag', dev);
    - *  let sensors = recorder.querySensors();
    - *  let sensor = sensors[0];
    - *  let profiles = sensor.getStreamProfiles();
    - *
    - *  for (let i =0; i < profiles.length; i++) {
    - *    if (profiles[i].streamType === rs2.stream.STREAM_DEPTH &&
    - *        profiles[i].fps === 30 &&
    - *        profiles[i].width === 640 &&
    - *        profiles[i].height === 480 &&
    - *        profiles[i].format === rs2.format.FORMAT_Z16) {
    - *      sensor.open(profiles[i]);
    - *    }
    - *  }
    - *
    - *  // record 10 frames
    - *  let cnt = 0;
    - *  sensor.start((frame) => {
    - *    cnt++;
    - *    if (cnt === 10) {
    - *      // stop recording
    - *      recorder.reset();
    - *      rs2.cleanup();
    - *      console.log('Recorded ', cnt, ' frames');
    - *    }
    - *  })
    - * 
    - * @extends Device - */ -class RecorderDevice extends Device { - /** - * Create a RecorderDevice from another device - * - * @param {Device} device another existing device - * @return {RecorderDevice|undefined} If the the input device can be - * converted to a RecorderDevice, return the newly created RecorderDevice, - * otherwise, undefined is returned. - */ - static from(device) { - return device.cxxDev.isRecorder() ? - new RecorderDevice(null, null, device.cxxDev, false) : undefined; - } - - /** - * @param {String} file the file name to store the recorded data - * @param {Device} device the actual device to be recorded - */ - constructor(file, device, cxxDev = undefined, autoDelete = true) { - const funcName = 'RecorderDevice.constructor()'; - checkArgumentLength(2, 4, arguments.length, funcName); - if (arguments[0] && arguments[1]) { - checkArgumentType(arguments, 'string', 0, funcName); - checkArgumentType(arguments, Device, 1, funcName); - } else if (arguments[2]) { - checkArgumentType(arguments, 'object', 2, funcName); - checkArgumentType(arguments, 'boolean', 3, funcName); - } else { - throw new TypeError('Invalid parameters for new RecorderDevice()'); - } - super(cxxDev ? cxxDev : device.cxxDev.spawnRecorderDevice(file), autoDelete); - } - /** - * Pause the recording device without stopping the actual device from streaming. - */ - pause() { - this.cxxDev.pauseRecord(); - } - /** - * Resume the recording - */ - resume() { - this.cxxDev.resumeRecord(); - } - /** - * Gets the name of the file to which the recorder is writing - * @return {String} - */ - get fileName() { - return this.cxxDev.getFileName(); - } -} - -/** - * This class is used to playback the file recorded by RecorderDevice - * There are 2 ways for users to create a PlaybackDevice: - *
    
    - *  Syntax 1: PlaybackDevice.from(device)
    - *  Syntax 2: Context.loadDevice(filePath)
    - * 
    - * - * Syntax 1 is to convert an existing device to a PlaybackDevice which can only be - * applied to device that can be converted. Here is an example: - *
    
    - *  const file = 'record.bag';
    - *  let cfg = new rs2.Config();
    - *  cfg.enableDeviceFromFile(file);
    - *  let pipe = new rs2.Pipeline();
    - *  pipe.start(cfg);
    - *  let device = pipe.getActiveProfile().getDevice();
    - *  let playback = rs2.PlaybackDevice.from(device);
    - *
    - *  for (let i = 0; i < 10; i++) {
    - *    let frames = pipe.waitForFrames();
    - *  }
    - *
    - *  pipe.stop();
    - *  rs2.cleanup();
    - * 
    - * - * Syntax 2 is to create a PlaybackDevice through Context. Here is an example: - *
    
    - *  let ctx = new rs2.Context();
    - *  // load the recorded file
    - *  let dev = ctx.loadDevice('record.bag');
    - *  let sensors = dev.querySensors();
    - *  let sensor = sensors[0];
    - *  let profiles = sensor.getStreamProfiles();
    - *  let cnt = 0;
    - *
    - *  // when received 'stopped' status, stop playback
    - *  dev.setStatusChangedCallback((status) => {
    - *    console.log('playback status: ', status);
    - *    if (status.description === 'stopped') {
    - *      dev.stop();
    - *      ctx.unloadDevice('record.bag');
    - *      rs2.cleanup();
    - *      console.log('Playback ', cnt, ' frames');
    - *    }
    - *  });
    - *
    - *  // start playback
    - *  sensor.open(profiles);
    - *  sensor.start((frame) => {
    - *    cnt ++;
    - *  });
    - * 
    - * @extends Device - * @see [Context.loadDevice]{@link Context#loadDevice} - */ -class PlaybackDevice extends Device { - /** - * Create a PlaybackDevice from another device - * - * @param {Device} device another existing device that can be converted to a - * PlaybackDevice - * @return {PlaybackDevice|undefined} If the the input device can be - * converted to a PlaybackDevice, return the newly created PlaybackDevice, - * otherwise, undefined is returned. - */ - static from(device) { - return device.cxxDev.isPlayback() ? - new PlaybackDevice(device.cxxDev, false) : undefined; - } - - constructor(cxxdevice, autoDelete) { - super(cxxdevice, autoDelete); - this._events = new EventEmitter(); - } - /** - * Pauses the playback - * Calling pause() in "paused" status does nothing - * If pause() is called while playback status is "playing" or "stopped", the playback will not - * play until resume() is called - * @return {undefined} - */ - pause() { - this.cxxDev.pausePlayback(); - } - /** - * Resumes the playback - * Calling resume() while playback status is "playing" or "stopped" does nothing - * @return {undefined} - */ - resume() { - this.cxxDev.resumePlayback(); - } - /** - * Stops playback - * @return {undefined} - */ - stop() { - this.cxxDev.stopPlayback(); - } - /** - * Retrieves the name of the playback file - * @return {String} - */ - get fileName() { - return this.cxxDev.getFileName(); - } - /** - * Retrieves the current position of the playback in the file in terms of time. Unit is - * millisecond - * @return {Integer} - */ - get position() { - return this.cxxDev.getPosition(); - } - /** - * Retrieves the total duration of the file, unit is millisecond. - * @return {Integer} - */ - get duration() { - return this.cxxDev.getDuration(); - } - /** - * Sets the playback to a specified time point of the played data - * @param {time} time the target time to seek to, unit is millisecond - * @return {undefined} - */ - seek(time) { - const funcName = 'PlaybackDevice.seek()'; - checkArgumentLength(1, 1, arguments.length, funcName); - checkArgumentType(arguments, 'number', 0, funcName); - this.cxxDev.seek(time); - } - /** - * Indicates if playback is in real time mode or non real time - * In real time mode, playback will play the same way the file was recorded. If the application - * takes too long to handle the callback, frames may be dropped. - * In non real time mode, playback will wait for each callback to finish handling the data before - * reading the next frame. In this mode no frames will be dropped, and the application controls - * the frame rate of the playback (according to the callback handler duration). - * @return {Boolean} - */ - get isRealTime() { - return this.cxxDev.isRealTime(); - } - /** - * Set the playback to work in real time or non real time - * @param {boolean} val whether real time mode is used - * @return {undefined} - */ - set isRealTime(val) { - const funcName = 'PlaybackDevice.isRealTime()'; - checkArgumentLength(1, 1, arguments.length, funcName); - checkArgumentType(arguments, 'boolean', 0, funcName); - this.cxxDev.setIsRealTime(val); - } - /** - * Set the playing speed - * @param {Float} speed indicates a multiplication of the speed to play (e.g: 1 = normal, - * 0.5 half normal speed) - */ - setPlaybackSpeed(speed) { - const funcName = 'PlaybackDevice.setPlaybackSpeed()'; - checkArgumentLength(1, 1, arguments.length, funcName); - checkArgumentType(arguments, 'number', 0, funcName); - this.cxxDev.setPlaybackSpeed(speed); - } - - /** - * @typedef {Object} PlaybackStatusObject - * @property {Integer} status - The status of the notification, see {@link playback_status} - * for details - * @property {String} description - The human readable literal description of the status - */ - - /** - * This callback is called when the status of the playback device changed - * @callback StatusChangedCallback - * @param {PlaybackStatusObject} status - * - * @see [PlaybackDevice.setStatusChangedCallback]{@link PlaybackDevice#setStatusChangedCallback} - */ - - /** - * Returns the current state of the playback device - * @return {PlaybackStatusObject} - */ - get currentStatus() { - let cxxStatus = this.cxxDev.getCurrentStatus(); - if (!cxxStatus) { - return undefined; - } - return {status: cxxStatus, description: playback_status.playbackStatusToString(cxxStatus)}; - } - - /** - * Register a callback to receive the playback device's status changes - * @param {StatusChangedCallback} callback the callback method - * @return {undefined} - */ - setStatusChangedCallback(callback) { - const funcName = 'PlaybackDevice.setStatusChangedCallback()'; - checkArgumentLength(1, 1, arguments.length, funcName); - checkArgumentType(arguments, 'function', 0, funcName); - this._events.on('status-changed', (status) => { - callback({status: status, description: playback_status.playbackStatusToString(status)}); - }); - let inst = this; - if (!this.cxxDev.statusChangedCallback) { - this.cxxDev.statusChangedCallback = (status) => { - inst._events.emit('status-changed', status); - }; - this.cxxDev.setStatusChangedCallbackMethodName('statusChangedCallback'); - } - } -} - -internal.RecordingContext = RecordingContext; -internal.PlaybackContext = PlaybackContext; - -/** - * PointCloud accepts depth frames and outputs Points frames - * In addition, given non-depth frame, the block will align texture coordinate to the non-depth - * stream - */ -class PointCloud extends Options { - constructor() { - super(); - this.cxxPointCloud = new RS2.RSPointCloud(); - this.setCxxOptionsObject(this.cxxPointCloud); - this.pointsFrame = new Points(); - } - - /** - * Calculate to get a frame of type {@link Points}, from the data of specified DepthFrame - * @param {DepthFrame} depthFrame the depth frame - * @return {Points|undefined} - */ - calculate(depthFrame) { - const funcName = 'PointCloud.calculate()'; - checkArgumentLength(1, 1, arguments.length, funcName); - checkArgumentType(arguments, DepthFrame, 0, funcName); - this.pointsFrame.release(); - if (this.cxxPointCloud.calculate(depthFrame.cxxFrame, this.pointsFrame.cxxFrame)) { - return this.pointsFrame; - } - return undefined; - } - - /** - * Align texture coordinate to the mappedFrame - * @param {Frame} mappedFrame the frame being mapped to - * @return {undefined} - */ - mapTo(mappedFrame) { - const funcName = 'PointCloud.mapTo()'; - checkArgumentLength(1, 1, arguments.length, funcName); - checkArgumentType(arguments, Frame, 0, funcName); - this.cxxPointCloud.mapTo(mappedFrame.cxxFrame); - } - - release() { - if (this.cxxPointCloud) this.cxxPointCloud.destroy(); - if (this.pointsFrame) this.pointsFrame.destroy(); - } - - /** - * Destroy all resources associated with the object - */ - destroy() { - this.release(); - this.cxxPointCloud = undefined; - this.pointsFrame = undefined; - } -} - -/** - * The Colorizer can be used to quickly visualize the depth data by tranform data into RGB8 format - */ -class Colorizer extends Options { - constructor() { - super(); - this.cxxColorizer = new RS2.RSColorizer(); - this.cxxColorizer.create(); - this.setCxxOptionsObject(this.cxxColorizer); - this.depthRGB = new VideoFrame(); - } - - release() { - if (this.cxxColorizer) this.cxxColorizer.destroy(); - if (this.depthRGB) this.depthRGB.destroy(); - } - - /** - * Destroy all resources associated with the colorizer - */ - destroy() { - this.release(); - this.cxxColorizer = undefined; - this.depthRGB = undefined; - } - - get colorizedFrame() { - return this.depthRGB; - } - - /** - * Tranform depth data into RGB8 format - * - * @param {DepthFrame} depthFrame the depth frame - * @return {VideoFrame|undefined} - */ - colorize(depthFrame) { - const funcName = 'Colorizer.colorize()'; - checkArgumentLength(1, 1, arguments.length, funcName); - // Though depth frame is expected, color frame could also be processed, so - // only check whether the type is Frame - checkArgumentType(arguments, Frame, 0, funcName); - const success = this.cxxColorizer.colorize(depthFrame.cxxFrame, this.depthRGB.cxxFrame); - this.depthRGB.updateProfile(); - return success ? this.depthRGB : undefined; - } -} - -/** - * This class can be used to perform alignment between a depth frame and another frame. - */ -class Align { - /** - * @param {Integer|String} stream the stream type to be aligned to. see {@link stream} for - * avaiable values. To perform alignment of a depth frame to the other frame, set the stream - * argument to the other stream type. To perform alignment of a non depth frame to a depth frame, - * set the stream argument to stream type of depth. - */ - constructor(stream) { - const funcName = 'Align.constructor()'; - checkArgumentLength(1, 1, arguments.length, funcName); - const s = checkArgumentType(arguments, constants.stream, 0, funcName); - this.cxxAlign = new RS2.RSAlign(s); - this.frameSet = new FrameSet(); - internal.addObject(this); - } - - /** - * Run the alignment process on the given frameset to get an aligned set of frames - * @param {FrameSet} frameSet the frames which at least has a depth frame - * @return {FrameSet} - */ - process(frameSet) { - const funcName = 'Align.process()'; - checkArgumentLength(1, 1, arguments.length, funcName); - checkArgumentType(arguments, FrameSet, 0, funcName); - this.frameSet.release(); // Destroy all attached-frames (depth/color/etc.) - if (this.cxxAlign.process(frameSet.cxxFrameSet, this.frameSet.cxxFrameSet)) { - this.frameSet.__update(); - return this.frameSet; - } - return undefined; - } - - release() { - if (this.cxxAlign) this.cxxAlign.destroy(); - if (this.frameSet) this.frameSet.destroy(); - } - - /** - * Destroy resources associated with the object - */ - destroy() { - this.release(); - this.cxxAlign = undefined; - this.frameSet = undefined; - } -} - -/** - * This class resprents a picture frame - * - * @property {Boolean} isValid - True if the frame is valid, otherwise false. - * @property {Uint16Array|Uint8Array} data - A typed array representing the data. - *
    The type of the typed array depends on the format specified in camera - * configuration. - * @property {Integer} width - The width of the frame. - * @property {Integer} height - The height of the frame. - * @property {Integer|Int64} frameNumber - An integer or an object representing the frame number. - *
    If the frame number is less than 2^53, then the return value is an integer number; - *
    Otherwise it will be an Int64 object defined in npm module "node-int64" - * @property {Number} timestamp - The timestamp of the frame. - * @property {Integer} streamType - The stream type of the frame. - * see enum {@link stream} - * @property {Integer} bitsPerPixel - The number of bits per pixel - * @property {Integer} timestampDomain - Get the domain (clock name) of timestamp value. - */ -class Frame { - constructor(cxxFrame) { - this.cxxFrame = cxxFrame || new RS2.RSFrame(); - this.updateProfile(); - internal.addObject(this); - // called from native to reset this.arrayBuffer and this.typedArray when the - // underlying frame was replaced. The arrayBuffer and typedArray must be reset - // to avoid deprecated data to be used. - const jsWrapper = this; - this.cxxFrame._internalResetBuffer = function() { - jsWrapper.typedArray = undefined; - jsWrapper.arrayBuffer = undefined; - }; - } - - updateProfile() { - this.streamProfile = undefined; - if (this.cxxFrame) { - let cxxProfile = this.cxxFrame.getStreamProfile(); - if (cxxProfile) { - this.streamProfile = StreamProfile._internalCreateStreamProfile(cxxProfile); - } - } - } - - release() { - if (this.cxxFrame) this.cxxFrame.destroy(); - if (this.streamProfile) this.streamProfile.destroy(); - this.arrayBuffer = undefined; - this.typedArray = undefined; - } - - /** - * Destroy the frame and its resource - */ - destroy() { - this.release(); - this.cxxFrame = undefined; - this.StreamProfile = undefined; - } - - /** - * Retrieve pixel format of the frame - * @return {Integer} see enum {@link format} for available values - */ - get format() { - return this.streamProfile.format; - } - - /** - * Retrieve the origin stream type that produced the frame - * @return {Integer} see {@link stream} for avaiable values - */ - get streamType() { - return this.streamProfile.streamType; - } - - get profile() { - return this.streamProfile; - } - - get width() { - return this.streamProfile.width ? this.streamProfile.width : this.cxxFrame.getWidth(); - } - - get height() { - return this.streamProfile.height ? this.streamProfile.height : this.cxxFrame.getHeight(); - } - - /** - * Check if the frame is valid - * @return {Boolean} - */ - get isValid() { - return (this.cxxFrame && this.cxxFrame.isValid()); - } - - /** - * Retrieve timestamp from the frame in milliseconds - * @return {Integer} - */ - get timestamp() { - return this.cxxFrame.getTimestamp(); - } - - /** - * Retrieve timestamp domain. timestamps can only be comparable if they are in common domain - * (for example, depth timestamp might come from system time while color timestamp might come - * from the device) - * this method is used to check if two timestamp values are comparable (generated from the same - * clock) - * @return {Integer} see {@link timestamp_domain} for avaiable values - */ - get timestampDomain() { - return this.cxxFrame.getTimestampDomain(); - } - - /** - * Retrieve the current value of a single frame metadata - * @param {String|Number} metadata the type of metadata, see {@link frame_metadata} for avaiable - * values - * @return {Uint8Array} The metadata value, 8 bytes, byte order is bigendian. - */ - frameMetadata(metadata) { - const funcName = 'Frame.frameMetadata()'; - checkArgumentLength(1, 1, arguments.length, funcName); - const m = checkArgumentType(arguments, constants.frame_metadata, 0, funcName); - const array = new Uint8Array(8); - return this.cxxFrame.getFrameMetadata(m, array) ? array : undefined; - } - - /** - * Determine if the device allows a specific metadata to be queried - * @param {String|Number} metadata The type of metadata - * @return {Boolean} true if supported, and false if not - */ - supportsFrameMetadata(metadata) { - const funcName = 'Frame.supportsFrameMetadata()'; - checkArgumentLength(1, 1, arguments.length, funcName); - const m = checkArgumentType(arguments, constants.frame_metadata, 0, funcName); - return this.cxxFrame.supportsFrameMetadata(m); - } - - /** - * Retrieve frame number - * @return {Integer} - */ - get frameNumber() { - return this.cxxFrame.getFrameNumber(); - } - - /** - * Retrieve the frame data - * @return {Float32Array|Uint16Array|Uint8Array|undefined} - * if the frame is from the depth stream, the return value is Uint16Array; - * if the frame is from the XYZ32F or MOTION_XYZ32F stream, the return value is Float32Array; - * for other cases, return value is Uint8Array. - */ - get data() { - if (this.typedArray) return this.typedArray; - - if (!this.arrayBuffer) { - this.arrayBuffer = this.cxxFrame.getData(); - this.typedArray = undefined; - } - - if (!this.arrayBuffer) return undefined; - - this.updateProfile(); - switch (this.format) { - case constants.format.FORMAT_Z16: - case constants.format.FORMAT_DISPARITY16: - case constants.format.FORMAT_Y16: - case constants.format.FORMAT_RAW16: - this.typedArray = new Uint16Array(this.arrayBuffer); - return this.typedArray; - case constants.format.FORMAT_YUYV: - case constants.format.FORMAT_UYVY: - case constants.format.FORMAT_RGB8: - case constants.format.FORMAT_BGR8: - case constants.format.FORMAT_RGBA8: - case constants.format.FORMAT_BGRA8: - case constants.format.FORMAT_Y8: - case constants.format.FORMAT_RAW8: - case constants.format.FORMAT_MOTION_RAW: - case constants.format.FORMAT_GPIO_RAW: - case constants.format.FORMAT_RAW10: - case constants.format.FORMAT_FG: - case constants.format.FORMAT_Y411: - case constants.format.FORMAT_ANY: - this.typedArray = new Uint8Array(this.arrayBuffer); - return this.typedArray; - case constants.format.FORMAT_XYZ32F: - case constants.format.FORMAT_MOTION_XYZ32F: - case constants.format.FORMAT_6DOF: - case constants.format.FORMAT_DISPARITY32: - this.typedArray = new Float32Array(this.arrayBuffer); - return this.typedArray; - } - } - - /** - * Get the frame buffer data - * There are 2 acceptable forms of syntax: - *
    
    -   *  Syntax 1. getData()
    -   *  Syntax 2. getData(ArrayBuffer)
    -   * 
    - * - * @param {ArrayBuffer} [buffer] The buffer that will be written to. - * @return {Float32Array|Uint16Array|Uint8Array|undefined} - * Returns a TypedArray or undefined for syntax 1, - * see {@link Frame#data}; - * if syntax 2 is used, return value is not used (undefined). - * - * @see [VideoFrame.dataByteLength]{@link VideoFrame#dataByteLength} to determine the buffer size - * in bytes. - */ - getData(buffer) { - const funcName = 'Frame.supportsFrameMetadata()'; - checkArgumentLength(0, 1, arguments.length, funcName); - if (arguments.length === 0) { - return this.data; - } else if (arguments.length === 1) { - checkArgumentType(arguments, 'ArrayBuffer', 0, funcName); - return this.cxxFrame.writeData(buffer); - } - } - - /** - * communicate to the library you intend to keep the frame alive for a while - * this will remove the frame from the regular count of the frame pool - * once this function is called, the SDK can no longer guarantee 0-allocations during frame - * cycling - * @return {undefined} - */ - keep() { - this.cxxFrame.keep(); - } - - static _internalCreateFrame(cxxFrame) { - if (!cxxFrame) return undefined; - if (cxxFrame.isPoseFrame()) return new PoseFrame(cxxFrame); - if (cxxFrame.isMotionFrame()) return new MotionFrame(cxxFrame); - if (cxxFrame.isDisparityFrame()) return new DisparityFrame(cxxFrame); - if (cxxFrame.isDepthFrame()) return new DepthFrame(cxxFrame); - if (cxxFrame.isVideoFrame()) return new VideoFrame(cxxFrame); - return new Frame(cxxFrame); - } -} - -/** - * This class resprents a video frame and is a subclass of Frame - * - * @property {Integer} width - The image width in pixels. - * @property {Integer} height - The image height in pixels. - * @property {Integer} dataByteLength - The length in bytes - * @property {Integer} strideInBytes - The stride of the frame. The unit is number of bytes. - * @property {Integer} bitsPerPixel - The number of bits per pixel - * @property {Integer} bytesPerPixel - The number of bytes per pixel - */ -class VideoFrame extends Frame { - constructor(frame) { - super(frame); - } - - /** - * Get image width in pixels - * @return {Integer} - */ - get width() { - return this.cxxFrame.getWidth(); - } - - /** - * Get image height in pixels - * @return {Integer} - */ - get height() { - return this.cxxFrame.getHeight(); - } - - /** - * Get the data length in bytes - * @return {Integer} - */ - get dataByteLength() { - return this.strideInBytes * this.height; - } - - /** - * Retrieve frame stride, the actual line width in bytes (not the logical image width) - * @return {Integer} - */ - get strideInBytes() { - return this.cxxFrame.getStrideInBytes(); - } - - /** - * Retrieve count of bits per pixel - * @return {Integer} - */ - get bitsPerPixel() { - return this.cxxFrame.getBitsPerPixel(); - } - - /** - * Retrieve bytes per pixel - * @return {Integer} - */ - get bytesPerPixel() { - return this.cxxFrame.getBitsPerPixel()/8; - } -} - -/** - * Class used to get 3D vertices and texture coordinates - */ -class Points extends Frame { - constructor(cxxFrame) { - super(cxxFrame); - } - - /** - * Get an array of 3D vertices. - * The coordinate system is: X right, Y up, Z away from the camera. Units: Meters - * - * @return {Float32Array|undefined} - */ - get vertices() { - if (this.verticesArray) return this.verticesArray; - - if (this.cxxFrame.canGetPoints()) { - const newLength = this.cxxFrame.getVerticesBufferLen(); - if (!this.verticesData || newLength !== this.verticesData.byteLength) { - this.verticesData = new ArrayBuffer(newLength); - } - if (this.cxxFrame.writeVertices(this.verticesData)) { - this.verticesArray = new Float32Array(this.verticesData); - return this.verticesArray; - } - } - return undefined; - } - - release() { - if (this.cxxFrame) this.cxxFrame.destroy(); - this.verticesArray = undefined; - this.verticesCoordArray = undefined; - } - - destroy() { - this.release(); - this.verticesData = undefined; - this.textureCoordData = undefined; - this.cxxFrame = undefined; - } - - /** - * Creates a ply file of the model with the given file name. - * @param {String} fileName name of the ply file - * @param {VideoFrame} texture texture frame - * @return {undefined} - */ - exportToPly(fileName, texture) { - const funcName = 'Points.exportToPly()'; - checkArgumentLength(2, 2, arguments.length, funcName); - checkArgumentType(arguments, 'string', 0, funcName); - checkArgumentType(arguments, VideoFrame, 1, funcName); - if (this.cxxFrame) { - this.cxxFrame.exportToPly(fileName, texture.cxxFrame); - } - } - - /** - * Get an array of texture coordinates per vertex - * Each coordinate represent a (u,v) pair within [0,1] range, to be mapped to texture image - * - * @return {Int32Array|undefined} - */ - get textureCoordinates() { - if (this.verticesCoordArray) return this.verticesCoordArray; - - if (this.cxxFrame.canGetPoints()) { - const newLength = this.cxxFrame.getTexCoordBufferLen(); - if (!this.textureCoordData || newLength !== this.textureCoordData.byteLength) { - this.textureCoordData = new ArrayBuffer(newLength); - } - if (this.cxxFrame.writeTextureCoordinates(this.textureCoordData)) { - this.verticesCoordArray = new Int32Array(this.textureCoordData); - return this.verticesCoordArray; - } - } - return undefined; - } - - /** - * Get number of vertices - * - * @return {Integer} - */ - get size() { - if (this.cxxFrame.canGetPoints()) { - return this.cxxFrame.getPointsCount(); - } - - throw new TypeError('Can\'t get size due to invalid frame type'); - } -} - -/** - * This class represents depth stream - */ -class DepthFrame extends VideoFrame { - constructor(cxxFrame) { - super(cxxFrame); - } - - /** - * Get the distance of a point from the camera - * @param {Integer} x x coordinate of the point - * @param {Integer} y y coordinate of the point - * @return {Float} - */ - getDistance(x, y) { - const funcName = 'DepthFrame.getDistance()'; - checkArgumentLength(2, 2, arguments.length, funcName); - checkArgumentType(arguments, 'number', 0, funcName); - checkArgumentType(arguments, 'number', 1, funcName); - return this.cxxFrame.getDistance(x, y); - } -} - -/** - * Disparity Frame - */ -class DisparityFrame extends DepthFrame { - constructor(cxxFrame) { - super(cxxFrame); - } - - /** - * Retrieve the stereoscopic baseline value. Applicable to stereo-based depth modules - * @return {Float} Stereoscopic baseline in millimeters - */ - get baseLine() { - return this.cxxFrame.getBaseLine(); - } -} - -/** - * 3D vector in Euclidean coordinate space - * @typedef {Object} Vector - * @property {Float32} x - value of x coordinate - * @property {Float32} y - value of y coordinate - * @property {Float32} z - value of z coordinate - * @see [MotionFrame.getMotionData()]{@link MotionFrame#getMotionData} - */ - -/** - * Quaternion used to represent rotation - * @typedef {Object} Quaternion - * @property {Float32} x - * @property {Float32} y - * @property {Float32} z - * @property {Float32} w - * @see [PoseFrame.getPoseData()]{@link PoseFrame#getPoseData} - */ - -/** - * This class resprents a motion frame and is a subclass of Frame - */ -class MotionFrame extends Frame { - constructor(frame) { - super(frame); - this._motion = {x: 0, y: 0, z: 0}; - } - - /** - * Get the motion data - * @return {Vector} the motion data on x, y and z coordinates - */ - get motionData() { - this.cxxFrame.getMotionData(this._motion); - return this._motion; - } -} - -/** - * PoseData - * @typedef {Object} PoseData - * @property {Vector} translation - X, Y, Z values of translation, in meters (relative to - * initial position) - * @property {Vector} velocity - X, Y, Z values of velocity, in meter/sec - * @property {Vector} acceleration - X, Y, Z values of acceleration, in meter/sec^2 - * @property {Quaternion} rotation - Qi, Qj, Qk, Qr components of rotation as represented - * in quaternion rotation (relative to initial position) - * @property {Vector} angularVelocity - X, Y, Z values of angular velocity, in radians/sec - * @property {Vector} angularAcceleration - X, Y, Z values of angular acceleration, in radians/sec^2 - * @property {Integer} trackerConfidence - pose data confidence 0 - Failed, 1 - Low, 2 - Medium, - * 3 - High - * @property {Integer} mapperConfidence - pose data confidence 0 - Failed, 1 - Low, 2 - Medium, - * 3 - High - * @see [PoseFrame.getPoseData()]{@link PoseFrame#getPoseData} - */ - -/** - * This class resprents a pose frame and is a subclass of Frame - */ -class PoseFrame extends Frame { - constructor(frame) { - super(frame); - this._pose = { - translation: {x: 0, y: 0, z: 0}, - velocity: {x: 0, y: 0, z: 0}, - acceleration: {x: 0, y: 0, z: 0}, - rotation: {x: 0, y: 0, z: 0, w: 0}, - angularVelocity: {x: 0, y: 0, z: 0}, - angularAcceleration: {x: 0, y: 0, z: 0}, - trackerConfidence: 0, - mapperConfidence: 0, - }; - } - - /** - * Get the pose data - * @return {PoseData|undefined} - */ - get poseData() { - return (this.cxxFrame.getPoseData(this._pose)) ? this._pose : undefined; - } -} - -/** - * Class containing a set of frames - * - * @property {Integer} size - count of frames. - * @property {DepthFrame|undefined} depthFrame - The depth frame in the frameset. - * @property {VideoFrame|undefined} colorFrame - The color frame in the frameset. - */ -class FrameSet { - constructor(cxxFrameSet) { - this.cxxFrameSet = cxxFrameSet || new RS2.RSFrameSet(); - this.cache = []; - this.cacheMetadata = []; - this.__update(); - } - - /** - * Count of frames - * - * @return {Integer} - */ - get size() { - return this.sizeValue; - } - - /** - * Get the depth frame - * - * @return {DepthFrame|undefined} - */ - get depthFrame() { - return this.getFrame(stream.STREAM_DEPTH, 0); - } - - /** - * Get the color frame - * - * @return {VideoFrame|undefined} - */ - get colorFrame() { - return this.getFrame(stream.STREAM_COLOR, 0); - } - - /** - * Get the infrared frame - * @param {Integer} streamIndex index of the expected infrared stream - * @return {VideoFrame|undefined} - */ - getInfraredFrame(streamIndex = 0) { - const funcName = 'FrameSet.getInfraredFrame()'; - checkArgumentLength(0, 1, arguments.length, funcName); - if (arguments.length === 1) { - checkArgumentType(arguments, 'integer', 0, funcName); - } - return this.getFrame(stream.STREAM_INFRARED, streamIndex); - } - - /** - * Get the frame at specified index - * - * @param {Integer} index the index of the expected frame (Note: this is not - * stream index) - * @return {DepthFrame|VideoFrame|Frame|undefined} - */ - at(index) { - const funcName = 'FrameSet.at()'; - checkArgumentLength(1, 1, arguments.length, funcName); - checkArgumentType(arguments, 'number', 0, funcName, 0, this.size); - return this.getFrame(this.cxxFrameSet.indexToStream(index), - this.cxxFrameSet.indexToStreamIndex(index)); - } - - /** - * Run the provided callback function with each Frame inside the FrameSet - * @param {FrameCallback} callback the callback function to process each frame - * @return {undefined} - */ - forEach(callback) { - const funcName = 'FrameSet.forEach()'; - checkArgumentLength(1, 1, arguments.length, funcName); - checkArgumentType(arguments, 'function', 0, funcName); - const size = this.size; - for (let i = 0; i < size; i++) { - callback(this.at(i)); - } - } - - __internalGetFrame(stream, streamIndex) { - let cxxFrame = this.cxxFrameSet.getFrame(stream, streamIndex); - return (cxxFrame ? Frame._internalCreateFrame(cxxFrame) : undefined); - } - - __internalFindFrameInCache(stream, streamIndex) { - if (stream === stream.STREAM_ANY) { - return (this.cacheMetadata.size ? 0 : undefined); - } - - for (const [i, data] of this.cacheMetadata.entries()) { - if (data.stream !== stream) { - continue; - } - if (!streamIndex || (streamIndex && streamIndex === data.streamIndex)) { - return i; - } - } - return undefined; - } - - __internalGetFrameCache(stream, streamIndex, callback) { - let idx = this.__internalFindFrameInCache(stream, streamIndex); - if (idx === undefined) { - let frame = callback(stream, streamIndex); - if (!frame) return undefined; - - this.cache.push(frame); - // the stream parameter may be stream.STREAM_ANY, but when we store the frame in - // cache, we shall store its actual stream type. - this.cacheMetadata.push({stream: frame.streamType, streamIndex: streamIndex}); - idx = this.cache.length - 1; - } else { - let frame = this.cache[idx]; - if (!frame.cxxFrame) { - frame.cxxFrame = new RS2.RSFrame(); - } - - // as cache metadata entries always use actual stream type, we use the actual - // stream types to easy native from processing stream.STREAM_ANY - if (! this.cxxFrameSet.replaceFrame( - this.cacheMetadata[idx].stream, streamIndex, frame.cxxFrame)) { - this.cache[idx] = undefined; - this.cacheMetadata[idx] = undefined; - } - } - return this.cache[idx]; - } - - /** - * Get the frame with specified stream - * - * @param {Integer|String} stream stream type of the frame - * @param {Integer} streamIndex index of the stream, 0 means the first - * matching stream - * @return {DepthFrame|VideoFrame|Frame|undefined} - */ - getFrame(stream, streamIndex = 0) { - const funcName = 'FrameSet.getFrame()'; - checkArgumentLength(1, 2, arguments.length, funcName); - const s = checkArgumentType(arguments, constants.stream, 0, funcName); - if (arguments.length === 2) { - checkArgumentType(arguments, 'integer', 1, funcName); - } - return this.__internalGetFrameCache(s, streamIndex, this.__internalGetFrame.bind(this)); - } - - __update() { - this.sizeValue = this.cxxFrameSet.getSize(); - } - - releaseCache() { - this.cache.forEach((f) => { - if (f && f.cxxFrame) { - f.release(); - } - }); - this.cache = []; - this.cacheMetadata = []; - } - - release() { - this.releaseCache(); - if (this.cxxFrameSet) this.cxxFrameSet.destroy(); - } - - /** - * Release resources associated with this object - * - * @return {undefined} - */ - destroy() { - this.release(); - this.cxxFrameSet = undefined; - } -} - -/** - * This class provides a simple way to retrieve frame data - */ -class Pipeline { - /** - * Construct a Pipeline object - * There are 2 acceptable syntax - * - *
    
    -   *  Syntax 1. new Pipeline()
    -   *  Syntax 2. new Pipeline(context)
    -   * 
    - * Syntax 1 uses the default context. - * Syntax 2 used the context created by application - * @param {Context} [context] - the {@link Context} that is being used by the pipeline - */ - constructor(context) { - const funcName = 'Pipeline.constructor()'; - checkArgumentLength(0, 1, arguments.length, funcName); - let ownCtx = true; - let ctx; - - if (arguments.length === 1) { - checkArgumentType(arguments, Context, 0, funcName); - ownCtx = false; - this.ctx = arguments[0]; - } - - if (ownCtx === true) { - this.ctx = new Context(); - // get existing sensors params - let sensores = this.ctx.querySensors(); - if (sensores.length>=2) { - let depthSensor = sensores[0]; - let colorSensor = sensores[1]; - let cfg = new Config(); - let depthProfiles = depthSensor - .getStreamProfiles() - .filter( (s) => s.streamType == stream.STREAM_DEPTH); - let depthProfile = depthProfiles - .find( (x) => x.width == 640 && x.height==480) || - depthProfiles[depthProfiles.length-1]; - let colorProfiles = colorSensor - .getStreamProfiles() - .filter( (s) => s.streamType == stream.STREAM_COLOR); - let colorProfile = colorProfiles - .find( (x) => x.width == 640 && x.height==480) || - colorProfiles[colorProfiles.length-1]; - console.log('depth: w: ' + depthProfile.width + - ', h: ' + depthProfile.height + - ', format: ' + depthProfile.format + - ', fps: ' + depthProfile.fps - ); - console.log('color: w: ' + colorProfile.width + - ', h: ' + colorProfile.height + - ', format: ' + colorProfile.format + - ', fps: ' + colorProfile.fps - ); - cfg.enableStream( - stream.STREAM_DEPTH, - -1, - depthProfile.width, - depthProfile.height, - depthProfile.format, - depthProfile.fps); - cfg.enableStream( - stream.STREAM_COLOR, - -1, - colorProfile.width, - colorProfile.height, - format.FORMAT_RGB8, - colorProfile.fps - ); - this.autoConfig = cfg; - } - } - - this.cxxPipeline = new RS2.RSPipeline(); - this.cxxPipeline.create(this.ctx.cxxCtx); - this.started = false; - this.frameSet = new FrameSet(); - internal.addObject(this); - } - - /** - * Destroy the resource associated with this pipeline - * - * @return {undefined} - */ - destroy() { - if (this.started === true) this.stop(); - - if (this.cxxPipeline) { - this.cxxPipeline.destroy(); - this.cxxPipeline = undefined; - } - - if (this.ownCtx && this.ctx) { - this.ctx.destroy(); - } - this.ctx = undefined; - - if (this.frameSet) { - this.frameSet.destroy(); - } - this.frameSet = undefined; - } - - /** - * Start streaming - * There are 2 acceptable syntax - * - *
    
    -   *  Syntax 1. start()
    -   *  Syntax 2. start(config)
    -   * 
    - * Syntax 1 uses the default configuration. - * Syntax 2 used the configured streams and or device of the config parameter - * - * @param {Config} [config] - the {@link Config} object to use for configuration - * @return {@link PipelineProfile} - */ - start() { - const funcName = 'Pipeline.start()'; - checkArgumentLength(0, 1, arguments.length, funcName); - if (this.started === true) return undefined; - - if (arguments.length === 0) { - this.started = true; - return new PipelineProfile(this.cxxPipeline.start()); - } else { - checkArgumentType(arguments, Config, 0, funcName); - this.started = true; - console.log('Pipeline started with config'); - return new PipelineProfile(this.cxxPipeline.startWithConfig(arguments[0].cxxConfig)); - } - } - - /** - * Stop streaming - * - * @return {undefined} - */ - stop() { - if (this.started === false) return; - - if (this.cxxPipeline ) { - this.cxxPipeline.stop(); - } - this.started = false; - - if (this.frameSet) this.frameSet.release(); - } - - /** - * Wait until a new set of frames becomes available. - * The returned frameset includes time-synchronized frames of each enabled stream in the pipeline. - * In case of different frame rates of the streams, the frames set include a matching frame of the - * slow stream, which may have been included in previous frames set. - * The method blocks the calling thread, and fetches the latest unread frames set. - * Device frames, which were produced while the function wasn't called, are dropped. - * To avoid frame drops, this method should be called as fast as the device frame rate. - * - * @param {Integer} timeout - max time to wait, in milliseconds, default to 5000 ms - * @return {FrameSet|undefined} a FrameSet object or Undefined - * @see See [Pipeline.latestFrame]{@link Pipeline#latestFrame} - */ - waitForFrames(timeout = 5000) { - const funcName = 'Pipeline.waitForFrames()'; - checkArgumentLength(0, 1, arguments.length, funcName); - checkArgumentType(arguments, 'number', 0, funcName); - this.frameSet.release(); - if (this.cxxPipeline.waitForFrames(this.frameSet.cxxFrameSet, timeout)) { - this.frameSet.__update(); - return this.frameSet; - } - return undefined; - } - - get latestFrame() { - return this.frameSet; - } - - /** - * Check if a new set of frames is available and retrieve the latest undelivered set. - * The frameset includes time-synchronized frames of each enabled stream in the pipeline. - * The method returns without blocking the calling thread, with status of new frames available - * or not. If available, it fetches the latest frames set. - * Device frames, which were produced while the function wasn't called, are dropped. - * To avoid frame drops, this method should be called as fast as the device frame rate. - * - * @return {FrameSet|undefined} - */ - pollForFrames() { - this.frameSet.release(); - if (this.cxxPipeline.pollForFrames(this.frameSet.cxxFrameSet)) { - this.frameSet.__update(); - return this.frameSet; - } - return undefined; - } - - /** - * Return the active device and streams profiles, used by the pipeline. - * The pipeline streams profiles are selected during {@link Pipeline.start}. The method returns a - * valid result only when the pipeline is active - - * between calls to {@link Pipeline.start} and {@link Pipeline.stop}. - * After {@link Pipeline.stop} is called, the pipeline doesn't own the device, thus, the pipeline - * selected device may change in - * subsequent activations. - * - * @return {PipelineProfile} the actual pipeline device and streams profile, which was - * successfully configured to the streaming device on start. - */ - getActiveProfile() { - if (this.started === false) return undefined; - - return new PipelineProfile(this.cxxPipeline.getActiveProfile()); - } -} - -/** - * The pipeline profile includes a device and a selection of active streams, with specific profile. - * The profile is a selection of the above under filters and conditions defined by the pipeline. - * Streams may belong to more than one sensor of the device. - */ -class PipelineProfile { - constructor(profile) { - this.cxxPipelineProfile = profile; - internal.addObject(this); - } - - /** - * Check if the object is valid - * @return {Boolean} - */ - get isValid() { - return (this.cxxPipelineProfile != null); - } - - /** - * Return the selected streams profiles, which are enabled in this profile. - * - * @return {StreamProfile[]} an array of StreamProfile - */ - getStreams() { - let profiles = this.cxxPipelineProfile.getStreams(); - if (!profiles) return undefined; - - const array = []; - profiles.forEach((profile) => { - array.push(StreamProfile._internalCreateStreamProfile(profile)); - }); - return array; - } - - /** - * Return the selected stream profile, which are enabled in this profile. - * @param {Integer|String} streamType the stream type of the desired profile, - * see {@link stream} for avaiable values - * @param {Integer} streamIndex stream index of the desired profile, -1 for any matching - * @return {StreamProfile} the first matching stream profile - */ - getStream(streamType, streamIndex = -1) { - const funcName = 'PipelineProfile.getStream()'; - checkArgumentLength(1, 2, arguments.length, funcName); - const s = checkArgumentType(arguments, constants.stream, 0, funcName); - checkArgumentType(arguments, 'number', 1, funcName); - let profiles = this.getStreams(); - if (!profiles) { - return undefined; - } - for (let i = 0; i < profiles.length; i++) { - if (profiles[i].streamType === s && - (streamIndex === -1 || (streamIndex === profiles[i].indexValue))) { - return profiles[i]; - } - } - return undefined; - } - - /** - * Retrieve the device used by the pipeline. - * The device class provides the application access to control camera additional settings - - * get device information, sensor options information, options value query and set, sensor - * specific extensions. - * Since the pipeline controls the device streams configuration, activation state and frames - * reading, calling the device API functions, which execute those operations, results in - * unexpected behavior. The pipeline streaming device is selected during {@link Pipeline.start}. - * Devices of profiles, which are not returned by - * {@link Pipeline.start} or {@link Pipeline.getActiveProfile}, are not guaranteed to be used by - * the pipeline. - * - * @return {Device} the pipeline selected device - */ - getDevice() { - return Device._internalCreateDevice(this.cxxPipelineProfile.getDevice()); - } - - /** - * Destroy the resource associated with this object - * - * @return {undefined} - */ - destroy() { - if (this.cxxPipelineProfile) { - this.cxxPipelineProfile.destroy(); - this.cxxPipelineProfile = undefined; - } - } -} - -/** - * The config allows pipeline users to request filters for the pipeline streams and device selection - * and configuration. - * This is an optional step in pipeline creation, as the pipeline resolves its streaming device - * internally. - * Config provides its users a way to set the filters and test if there is no conflict with the - * pipeline requirements from the device. It also allows the user to find a matching device for - * the config filters and the pipeline, in order to select a device explicitly, and modify its - * controls before streaming starts. - */ -class Config { - constructor() { - this.cxxConfig = new RS2.RSConfig(); - internal.addObject(this); - } - - /** - * Enable a device stream explicitly, with selected stream parameters. - * The method allows the application to request a stream with specific configuration. If no stream - * is explicitly enabled, the pipeline configures the device and its streams according to the - * attached computer vision modules and processing blocks requirements, or default configuration - * for the first available device. - * The application can configure any of the input stream parameters according to its requirement, - * or set to 0 for don't care value. The config accumulates the application calls for enable - * configuration methods, until the configuration is applied. Multiple enable stream calls for the - * same stream override each other, and the last call is maintained. - * Upon calling {@link Config.resolve}, the config checks for conflicts between the application - * configuration requests and the attached computer vision modules and processing blocks - * requirements, and fails if conflicts are found. - * Before {@link Config.resolve} is called, no conflict check is done. - * - * @param {Integer|String} stream stream type to be enabled - * @param {Integer} index stream index, used for multiple streams of the same type. -1 indicates - * any. - * @param {Integer} width stream image width - for images streams. 0 indicates any. - * @param {Integer} height stream image height - for images streams. 0 indicates any. - * @param {Integer|String} format stream data format - pixel format for images streams, of data - * type for other streams. format.FORMAT_ANY indicates any. - * @param {Integer} fps stream frames per second. 0 indicates any. - */ - enableStream(stream, index, width, height, format, fps) { - const funcName = 'Config.enableStream()'; - checkArgumentLength(6, 6, arguments.length, funcName); - const s = checkArgumentType(arguments, constants.stream, 0, funcName); - checkArgumentType(arguments, 'number', 1, funcName); - checkArgumentType(arguments, 'number', 2, funcName); - checkArgumentType(arguments, 'number', 3, funcName); - const f = checkArgumentType(arguments, constants.format, 4, funcName); - checkArgumentType(arguments, 'number', 5, funcName); - this.cxxConfig.enableStream(s, index, width, height, f, fps); - } - - /** - * Disable a device stream explicitly, to remove any requests on this stream profile. - */ - disableStream(stream) { - const funcName = 'Config.disableStream()'; - checkArgumentLength(1, 1, arguments.length, funcName); - const s = checkArgumentType(arguments, constants.stream, 0, funcName); - this.cxxConfig.disableStream(s); - } - - /** - * Enable all device streams explicitly. - */ - enableAllStreams() { - this.cxxConfig.enableAllStreams(); - } - - /** - * Disable all device streams explicitly. - */ - disableAllStreams() { - this.cxxConfig.disableAllStreams(); - } - - /** - * Select a specific device explicitly by its serial number, to be used by the pipeline. - * The conditions and behavior of this method are similar to those of {@link Config.enableStream}. - * This method is required if the application needs to set device or sensor settings prior to - * pipeline streaming, to enforce the pipeline to use the configured device. - * - * @param {String} serial device serial number, as returned by - * Device.getCameraInfo(camera_info.CAMERA_INFO_SERIAL_NUMBER). - */ - enableDevice(serial) { - const funcName = 'Config.enableDevice()'; - checkArgumentLength(1, 1, arguments.length, funcName); - checkArgumentType(arguments, 'string', 0, funcName); - this.cxxConfig.enableDevice(serial); - } - - /** - * Select a recorded device from a file, to be used by the pipeline through playback. - * The device available streams are as recorded to the file, and {@link Config.resolve} considers - * only this device and configuration as available. - * This request cannot be used if {@link Config.enableRecordToFile} is called for the current - * config, and vise versa - * - * @param {String} fileName the playback file of the device - * @param {Boolean} repeat whether to repeat the playback automatically - */ - enableDeviceFromFile(fileName, repeat = true) { - const funcName = 'Config.enableDeviceFromFile()'; - checkArgumentLength(1, 2, arguments.length, funcName); - checkArgumentType(arguments, 'string', 0, funcName); - checkArgumentType(arguments, 'boolean', 1, funcName); - checkFileExistence(fileName); - this.cxxConfig.enableDeviceFromFileRepeatOption(fileName, repeat); - } - - /** - * Requires that the resolved device would be recorded to file - * This request cannot be used if {@link Config.enableDeviceFromFile} is called for the current - * config, and vise versa as available. - * - * @param {String} fileName the desired file for the output record - */ - enableRecordToFile(fileName) { - const funcName = 'Config.enableRecordToFile()'; - checkArgumentLength(1, 1, arguments.length, funcName); - checkArgumentType(arguments, 'string', 0, funcName); - this.cxxConfig.enableRecordToFile(fileName); - } - - /** - * Resolve the configuration filters, to find a matching device and streams profiles. - * The method resolves the user configuration filters for the device and streams, and combines - * them with the requirements of the computer vision modules and processing blocks attached to the - * pipeline. If there are no conflicts of requests, - * it looks for an available device, which can satisfy all requests, and selects the first - * matching streams configuration. In the absence of any request, the config selects the first - * available device and the first color and depth streams configuration. - * The pipeline profile selection during {@link Pipeline.start} follows the same method. Thus, - * the selected profile is the same, if no change occurs to the available devices occurs. - * Resolving the pipeline configuration provides the application access to the pipeline selected - * device for advanced control. - * The returned configuration is not applied to the device, so the application doesn't own the - * device sensors. However, the application can call {@link Cofnig.enableDevice}, to enforce the - * device returned by this method is selected by pipeline start, and configure the device and - * sensors options or extensions before streaming starts. - * - * @param {Pipeline} pipeline the pipeline for which the selected filters are applied - * @return {PipelineProfile|undefined} a matching device and streams profile, which satisfies the - * filters and pipeline requests. - */ - resolve(pipeline) { - const funcName = 'Config.resolve()'; - checkArgumentLength(1, 1, arguments.length, funcName); - checkArgumentType(arguments, Pipeline, 0, funcName); - return new PipelineProfile(this.cxxConfig.resolve(arguments[0].cxxPipeline)); - } - - /** - * Check if the config can resolve the configuration filters, to find a matching device and - * streams profiles. The resolution conditions are as described in {@link Config.resolve}. - * - * @param {Pipeline} pipeline the pipeline for which the selected filters are applied - * @return {boolean} true if a valid profile selection exists, false if no selection can be found - * under the config filters and the available devices. - */ - canResolve(pipeline) { - const funcName = 'Config.canResolve()'; - checkArgumentLength(1, 1, arguments.length, funcName); - checkArgumentType(arguments, Pipeline, 0, funcName); - return this.cxxConfig.canResolve(arguments[0].cxxPipeline); - } - - /** - * Release resources associated with the object - */ - destroy() { - if (this.cxxConfig) { - this.cxxConfig.destroy(); - this.cxxConfig = null; - } - } -} - -/** - * Syncer class, which is used to group synchronized frames into coherent frame-sets. - */ -class Syncer { - constructor() { - this.cxxSyncer = new RS2.RSSyncer(); - this.frameSet = new FrameSet(); - } - - /* - * Wait until coherent set of frames becomes available - * @param {Number} timeout Max time in milliseconds to wait until an exception will be thrown - * @return {Frame[]|undefined} Set of coherent frames or undefined if no frames. - */ - waitForFrames(timeout = 5000) { - const funcName = 'Syncer.waitForFrames()'; - checkArgumentLength(0, 1, arguments.length, funcName); - checkArgumentType(arguments, 'number', 0, funcName); - this.frameSet.release(); - if (this.cxxSyncer.waitForFrames(this.frameSet.cxxFrameSet, timeout)) { - this.frameSet.__update(); - return this.frameSet; - } - return undefined; - } - - /** - * Check if a coherent set of frames is available, if yes return them - * @return {Frame[]|undefined} an array of frames if available and undefined if not. - */ - pollForFrames() { - this.frameSet.release(); - if (this.cxxSyncer.pollForFrames(this.frameSet.cxxFrameSet)) { - this.frameSet.__update(); - return this.frameSet; - } - return undefined; - } - - /** - * Release resources associated with the object - */ - destroy() { - if (this.cxxSyncer) { - this.cxxSyncer.destroy(); - this.cxxSyncer = undefined; - } - - if (this.frameset) { - this.frameSet.destroy(); - this.frameSet = undefined; - } - } -} - -/** - * Encapsulate the handling of 'device-changed' notification, when devices are conncted or - * disconnected. It can connect to the existing device(s) in system, and/or wait for the - * arrival/removal of devices. - */ -class DeviceHub { - /** - * @param {Context} context - a librealsense2 Context - */ - constructor(context) { - const funcName = 'DeviceHub.constructor()'; - checkArgumentLength(1, 1, arguments.length, funcName); - checkArgumentType(arguments, Context, 0, funcName); - this.context = context; - this.cxxHub = new RS2.RSDeviceHub(context.cxxCtx); - internal.addObject(this); - } - - /** - * If any device is connected return it, otherwise wait until next RealSense device connects. - * Calling this method multiple times will cycle through connected devices - * @return {Device|undefined} - */ - waitForDevice() { - let dev = this.cxxHub.waitForDevice(); - return (dev ? Device._internalCreateDevice(dev) : undefined); - } - - /** - * Check if a device is connected - * @return {Boolean} - */ - isConnected(device) { - const funcName = 'DeviceHub.isConnected()'; - checkArgumentLength(1, 1, arguments.length, funcName); - checkArgumentType(arguments, Device, 0, funcName); - return this.cxxHub.isConnected(device.cxxDev); - } - - /** - * Release resources associated with the object - */ - destroy() { - if (this.cxxHub) { - this.cxxHub.destroy(); - this.cxxHub = undefined; - } - } -} - -/** - * Base class of specific filter classes, see {@link DecimationFilter}. - * Don't create Filter objects directly from this class, use child classes, - */ -class Filter extends Options { - constructor(type) { - super(new RS2.RSFilter(type)); - internal.addObject(this); - } - - _internalGetInputType() { - return DepthFrame; - } - - _internalPrepareOutputFrame() { - if (!this.frame) { - this.frame = new DepthFrame(); - } - } - /** - * Apply the filter processing on the frame and return the processed frame - * @param {Frame} frame the depth frame to be processed - * @return {Frame} - */ - process(frame) { - const funcName = 'Filter.process()'; - checkArgumentLength(1, 1, arguments.length, funcName); - checkArgumentType(arguments, this._internalGetInputType(), 0, funcName); - this._internalPrepareOutputFrame(); - if (this.cxxObj && this.cxxObj.process(frame.cxxFrame, this.frame.cxxFrame)) { - this.frame.updateProfile(); - return this.frame; - } - return undefined; - } - - /** - * Release resources associated with the object - */ - destroy() { - if (this.cxxObj) { - this.cxxObj.destroy(); - this.cxxObj = null; - } - if (this.frame) { - this.frame.destroy(); - this.frame = undefined; - } - } -} - -/** - * Depth post-processing filter block. This block can apply decimation filter on depth frame. - */ -class DecimationFilter extends Filter { - constructor() { - super('decimation'); - } - // override base implementation - _internalGetInputType() { - return VideoFrame; - } - _internalPrepareOutputFrame() { - if (!this.frame) { - this.frame = new VideoFrame(); - } - } -} - -/** - * Depth post-processing filter block. This block can apply temporal filter on depth frame. - */ -class TemporalFilter extends Filter { - constructor() { - super('temporal'); - } -} - -/** - * Depth post-processing filter block. This block can apply spatial filter on depth frame. - */ -class SpatialFilter extends Filter { - constructor() { - super('spatial'); - } -} - -/** - * Depth post-processing filter block. This block replaces empty pixels with data from adjacent - * pixels based on the method selected. - */ -class HoleFillingFilter extends Filter { - constructor() { - super('hole-filling'); - } -} - -/** - * Post processing block that could transform disparity frame to depth frame - */ -class DisparityToDepthTransform extends Filter { - constructor() { - super('disparity-to-depth'); - } - - // override base implementation - _internalGetInputType() { - return DisparityFrame; - } -} - -/** - * Post processing block that could transform depth frame to disparity frame - */ -class DepthToDisparityTransform extends Filter { - constructor() { - super('depth-to-disparity'); - } - - // override base implementation - _internalPrepareOutputFrame() { - if (!this.frame) { - this.frame = new DisparityFrame(); - } - } -} - -/** - * util.preset_preference: The enum for preset preference values. - * @readonly - * @enum {String} - */ -const preset_preference = { - /** - * String literal of 'best-quality'.
    Prefers the best overall quality that is - * available in the camera.
    Equivalent to its uppercase counterpart. - */ - best_quality: 'best-quality', - /** - * String literal of 'largest-image'.
    Prefers the largest image dimension that is - * available in the camera.
    Equivalent to its uppercase counterpart. - */ - largest_image: 'largest-image', - /** - * String literal of 'highest-framerate'.
    Prefers the highest frame rate that is - * available in the camera.
    Equivalent to its uppercase counterpart. - */ - highest_framerate: 'highest-framerate', - - /** - * Prefers the best overall quality that is available in the camera
    Equivalent to its - * lowercase counterpart. - * @type {Integer} - */ - BEST_QUALITY: 0, - /** - * Prefers the largest image dimension that is available in the camera
    Equivalent to its - * lowercase counterpart. - * @type {Integer} - */ - LARGEST_IMAGE: 1, - /** - * Prefers the highest frame rate that is available in the camera
    Equivalent to its lowercase - * counterpart. - * @type {Integer} - */ - HIGHEST_FRAMERATE: 2, - - PRESET_BEGIN: 0, - PRESET_END: 3, -}; - -const util = {}; - -util.preset_preference = preset_preference; - -Object.defineProperty(util, '__stack', { - get: function() { - let orig = Error.prepareStackTrace; - Error.prepareStackTrace = function(_, stack) { - return stack; - }; - let err = new Error(); - // TODO(kenny-y): fix the jshint error - /* jshint ignore:start */ - Error.captureStackTrace(err, arguments.callee); // eslint-disable-line - /* jshint ignore:end */ - let stack = err.stack; - Error.prepareStackTrace = orig; - return stack; - }, -}); - -Object.defineProperty(util, '__line', { - get: function() { - // TODO(kenny-y): fix the jshint error - /* jshint ignore:start */ - return __stack[1].getLineNumber(); - /* jshint ignore:end */ - }, -}); - -Object.defineProperty(util, '__file', { - get: function() { - // TODO(kenny-y): fix the jshint error - /* jshint ignore:start */ - return __stack[1].getFileName().split('/').slice(-1)[0]; - /* jshint ignore:end */ - }, -}); - -function isString(s) { - return (typeof s === 'string'); -} - -function isNumber(s) { - return (typeof s === 'number'); -} - -function checkStringNumber(v, rangeStart, rangeEnd, convertFunc, typeErrMsg, rangeErrMsg) { - let r; - if (isString(v)) { - r = convertFunc(v); - } else if (isNumber(v)) { - r = parseInt(v); - } else { - throw new TypeError(typeErrMsg); - } - if (r < rangeStart || r >= rangeEnd || typeof r === 'undefined') { - throw new RangeError(rangeErrMsg); - } - return r; -} - -function checkArgumentLength(minLengh, maxLength, actualLength, funcName) { - if (actualLength >= minLengh && actualLength <= maxLength) { - return; - } - - if (minLengh === maxLength) { - throw new TypeError(funcName + ' expects ' + minLengh + ' arguments'); - } else { - throw new TypeError(funcName + ' expects ' + minLengh + '~' + maxLength + ' arguments'); - } -} - -function checkArgumentType(args, expectedType, argIndex, funcName, start, end) { - if (argIndex >= args.length) { - return undefined; - } - let arg = args[argIndex]; - let errMsgPrefix = 'argument ' + argIndex + ' of ' + funcName; - let wrongTypeErrMsgPrefix = errMsgPrefix + ' should be a/an '; - let unsupportedErrMsg = errMsgPrefix + ' is an unsupported type'; - let rangeErrMsg = errMsgPrefix + ' has an invalid value'; - - switch (expectedType) { - case 'number': - case 'string': - case 'object': - case 'boolean': - case 'function': - if (typeof arg !== expectedType) { - throw new TypeError(wrongTypeErrMsgPrefix + expectedType); - } - if (expectedType === 'number' && (start !== undefined) && (end !== undefined)) { - if (arg < start || arg > end) { - throw new TypeError(rangeErrMsg); - } - } - break; - case 'ArrayBuffer': - if (!(isArrayBuffer(arg))) { - throw new TypeError(wrongTypeErrMsgPrefix + expectedType); - } - break; - case 'integer': - if (!Number.isInteger(arg)) { - throw new TypeError(wrongTypeErrMsgPrefix + expectedType); - } - break; - default: - if (typeof expectedType === 'function') { - if (!(arg instanceof expectedType)) { - throw new TypeError(wrongTypeErrMsgPrefix + expectedType.name); - } - } else if (typeof expectedType === 'object') { - for (let mem in constants) { - if (constants[mem] === expectedType) { - return checkEnumObjectArgument(args, expectedType, argIndex, funcName, start, end); - } - } - throw new TypeError(unsupportedErrMsg); - } else { - throw new TypeError(unsupportedErrMsg); - } - break; - } -} - -function checkEnumObjectArgument(args, expectedType, argIndex, funcName, start, end) { - let rangeStart; - let rangeEnd; - let convertFunc; - let errMsgPrefix = 'argument ' + argIndex + ' of ' + funcName; - let wrongTypeErrMsgPrefix = errMsgPrefix + ' should be a/an '; - let unsupportedErrMsg = errMsgPrefix + ' is an unsupported type'; - let rangeErrMsg = errMsgPrefix + ' has an invalid value'; - let typeErrMsg; - - switch (expectedType) { - case constants.stream: - rangeStart = constants.stream.STREAM_ANY; - rangeEnd = constants.stream.STREAM_COUNT; - convertFunc = stream2Int; - typeErrMsg = wrongTypeErrMsgPrefix + 'stream'; - break; - case constants.format: - rangeStart = constants.format.FORMAT_ANY; - rangeEnd = constants.format.FORMAT_COUNT; - convertFunc = format2Int; - typeErrMsg = wrongTypeErrMsgPrefix + 'format'; - break; - case constants.option: - rangeStart = constants.option.OPTION_BACKLIGHT_COMPENSATION; - rangeEnd = constants.option.OPTION_COUNT; - convertFunc = option2Int; - typeErrMsg = wrongTypeErrMsgPrefix + 'option'; - break; - case constants.camera_info: - rangeStart = constants.camera_info.CAMERA_INFO_NAME; - rangeEnd = constants.camera_info.CAMERA_INFO_COUNT; - convertFunc = cameraInfo2Int; - typeErrMsg = wrongTypeErrMsgPrefix + 'camera_info'; - break; - case constants.recording_mode: - rangeStart = constants.recording_mode.RECORDING_MODE_BLANK_FRAMES; - rangeEnd = constants.recording_mode.RECORDING_MODE_COUNT; - convertFunc = recordingMode2Int; - typeErrMsg = wrongTypeErrMsgPrefix + 'recording_mode'; - break; - case constants.frame_metadata: - rangeStart = constants.frame_metadata.FRAME_METADATA_FRAME_COUNTER; - rangeEnd = constants.frame_metadata.FRAME_METADATA_COUNT; - convertFunc = frameMetadata2Int; - typeErrMsg = wrongTypeErrMsgPrefix + 'frame_metadata'; - break; - case constants.distortion: - rangeStart = constants.distortion.DISTORTION_NONE; - rangeEnd = constants.distortion.DISTORTION_COUNT; - convertFunc = distortion2Int; - typeErrMsg = wrongTypeErrMsgPrefix + 'distortion'; - break; - case constants.notification_category: - rangeStart = constants.notification_category.NOTIFICATION_CATEGORY_FRAMES_TIMEOUT; - rangeEnd = constants.notification_category.NOTIFICATION_CATEGORY_COUNT; - convertFunc = notificationCategory2Int; - typeErrMsg = wrongTypeErrMsgPrefix + 'notification_category'; - break; - case constants.timestamp_domain: - rangeStart = constants.timestamp_domain.TIMESTAMP_DOMAIN_HARDWARE_CLOCK; - rangeEnd = constants.timestamp_domain.TIMESTAMP_DOMAIN_COUNT; - convertFunc = timestampDomain2Int; - typeErrMsg = wrongTypeErrMsgPrefix + 'timestamp_domain'; - break; - case constants.playback_status: - rangeStart = constants.playback_status.PLAYBACK_STATUS_UNKNOWN; - rangeEnd = constants.playback_status.PLAYBACK_STATUS_COUNT; - convertFunc = playbackStatus2Int; - typeErrMsg = wrongTypeErrMsgPrefix + 'playback_status'; - break; - case constants.sr300_visual_preset: - rangeStart = constants.sr300_visual_preset.SR300_VISUAL_PRESET_SHORT_RANGE; - rangeEnd = constants.sr300_visual_preset.SR300_VISUAL_PRESET_COUNT; - convertFunc = sr300VisualPreset2Int; - typeErrMsg = wrongTypeErrMsgPrefix + 'sr300_visual_preset'; - break; - case constants.rs400_visual_preset: - rangeStart = constants.rs400_visual_preset.RS2_RS400_VISUAL_PRESET_CUSTOM; - rangeEnd = constants.rs400_visual_preset.RS400_VISUAL_PRESET_COUNT; - convertFunc = rs400VisualPreset2Int; - typeErrMsg = wrongTypeErrMsgPrefix + 'rs400_visual_preset'; - break; - case constants.log_severity: - rangeStart = constants.log_severity.LOG_SEVERITY_DEBUG; - rangeEnd = constants.log_severity.LOG_SEVERITY_COUNT; - convertFunc = logSeverity2Int; - typeErrMsg = wrongTypeErrMsgPrefix + 'log_severity'; - break; - default: - throw new TypeError(unsupportedErrMsg); - } - return checkStringNumber( - args[argIndex], rangeStart, rangeEnd, convertFunc, typeErrMsg, rangeErrMsg); -} - -function checkNumberRange(arg, start, end, argIndex, funcName) { - if (arg < start || arg > end) { - throw new TypeError('argument ' + argIndex + ' of ' + funcName + ' is invalid'); - } -} - -function checkDiscreteArgumentValue(args, argIndex, valueArray, funcName) { - if (valueArray.indexOf(args[argIndex]) === -1) { - throw new TypeError('argument ' + argIndex + ' of ' + funcName + ' is invalid'); - } -} - -function checkDiscreteArgumentLength(lenthArray, actualLength, funcName) { - if (lenthArray.indexOf(actualLength) === -1) { - throw new TypeError(funcName + ' expects ' + lenthArray.toString() + ' arguments'); - } -} - -function equalsToEither(arg, strConst, numConst) { - return (typeof arg === 'string' && arg === strConst) || - (typeof arg === 'number' && arg === numConst); -} - -function checkFileExistence(file) { - if (!fs.existsSync(file)) { - throw new TypeError('Can\'t open file: ' + file); - } -} - -/** - * Given a point in 3D space, compute the corresponding pixel coordinates in an image with no - * distortion or forward distortion coefficients produced by the same camera. - * @param {Intrinsics} intrinsics - The intrinsics of the image stream - * @param {Object} pointCoordinate - The 3D space coordinate of the point, linke {x: 0, y: 0, z:1}. - * @return {Object} like {x: 0, y:0}. - */ -util.projectPointToPixel = function(intrinsics, pointCoordinate) { - const funcName = 'util.projectPointToPixel'; - checkArgumentLength(2, 2, arguments.length, funcName); - checkArgumentType(arguments, 'object', 0, funcName); - checkArgumentType(arguments, 'object', 1, funcName); - if (equalsToEither(intrinsics.model, - distortion.distortion_inverse_brown_conrady, - distortion.DISTORTION_INVERSE_BROWN_CONRADY)) { - throw new TypeError('projectPointToPixel cannot project to an inverse-distorted image'); - } - - let x = pointCoordinate.x / pointCoordinate.z; - let y = pointCoordinate.y / pointCoordinate.z; - - if (equalsToEither(intrinsics.model, - distortion.distortion_modified_brown_conrady, - distortion.DISTORTION_MODIFIED_BROWN_CONRADY)) { - const r2 = x * x + y * y; - const f = 1 + intrinsics.coeffs[0] * r2 + intrinsics.coeffs[1] * r2 * r2 + - intrinsics.coeffs[4] * r2 * r2 * r2; - x *= f; - y *= f; - const dx = x + 2 * intrinsics.coeffs[2] * x * y + intrinsics.coeffs[3] * (r2 + 2 * x * x); - const dy = y + 2 * intrinsics.coeffs[3] * x * y + intrinsics.coeffs[2] * (r2 + 2 * y * y); - x = dx; - y = dy; - } - - if (equalsToEither(intrinsics.model, - distortion.distortion_ftheta, - distortion.DISTORTION_FTHETA)) { - const r = Math.sqrt(x * x + y * y); - const rd = (1.0 / intrinsics.coeffs[0] * Math.atan(2 * r * Math.tan( - intrinsics.coeffs[0] / 2.0))); - x *= rd / r; - y *= rd / r; - } - return {x: x * intrinsics.fx + intrinsics.ppx, y: y * intrinsics.fy + intrinsics.ppy}; -}; - -/** - * Given pixel coordinates and depth in an image with no distortion or inverse distortion - * coefficients, compute the corresponding point in 3D space relative to the same camera - * @param {Intrinsics} intrinsics - The intrinsics of the depth stream - * @param {Object} pixelCoordinate - The pixel coordinate of the point, linke {x: 0, y: 0}. - * @param {Number} depth - The depth value of the point - * @return {Object} like {x: 0, y:0, z:0}. - */ -util.deprojectPixelToPoint = function(intrinsics, pixelCoordinate, depth) { - const funcName = 'util.deprojectPixelToPoint'; - checkArgumentLength(3, 3, arguments.length, funcName); - checkArgumentType(arguments, 'object', 0, funcName); - checkArgumentType(arguments, 'object', 1, funcName); - checkArgumentType(arguments, 'number', 2, funcName); - if (equalsToEither(intrinsics.model, - distortion.distortion_modified_brown_conrady, - distortion.DISTORTION_MODIFIED_BROWN_CONRADY)) { - throw new TypeError('deprojectPixelToPoint cannot deproject from a forward-distorted image'); - } - - if (equalsToEither(intrinsics.model, - distortion.distortion_ftheta, - distortion.DISTORTION_FTHETA)) { - throw new TypeError('deprojectPixelToPoint cannot deproject to an ftheta image'); - } - - let x = (pixelCoordinate.x - intrinsics.ppx) / intrinsics.fx; - let y = (pixelCoordinate.y - intrinsics.ppy) / intrinsics.fy; - - if (equalsToEither(intrinsics.model, - distortion.distortion_inverse_brown_conrady, - distortion.DISTORTION_INVERSE_BROWN_CONRADY)) { - const r2 = x * x + y * y; - const f = 1 + intrinsics.coeffs[0] * r2 + intrinsics.coeffs[1] * r2 * r2 + - intrinsics.coeffs[4] * r2 * r2 * r2; - const ux = x * f + 2 * intrinsics.coeffs[2] * x * y + intrinsics.coeffs[3] * (r2 + 2 * x * x); - const uy = y * f + 2 * intrinsics.coeffs[3] * x * y + intrinsics.coeffs[2] * (r2 + 2 * y * y); - x = ux; - y = uy; - } - - return {x: depth * x, y: depth * y, z: depth}; -}; - -/** - * Transform 3D coordinates relative to one sensor to 3D coordinates relative to another viewpoint - * @param {ExtrinsicsObject} extrinsics - The exrinsics from the original stream to the target - * stream - * @param {Object} pointCoordinate - The 3D space coordinate of the original point, - * like {x: 0, y: 0, z:1}. - * @return {Object} The tranformed 3D coordinate, like {x:0, y:0, z:0}. - */ -util.transformPointToPoint = function(extrinsics, pointCoordinate) { - const funcName = 'util.transformPointToPoint'; - checkArgumentLength(2, 2, arguments.length, funcName); - checkArgumentType(arguments, 'object', 0, funcName); - checkArgumentType(arguments, 'object', 1, funcName); - const x = extrinsics.rotation[0] * pointCoordinate.x + - extrinsics.rotation[3] * pointCoordinate.y + - extrinsics.rotation[6] * pointCoordinate.z + - extrinsics.translation[0]; - const y = extrinsics.rotation[1] * pointCoordinate.x + - extrinsics.rotation[4] * pointCoordinate.y + - extrinsics.rotation[7] * pointCoordinate.z + - extrinsics.translation[1]; - const z = extrinsics.rotation[2] * pointCoordinate.x + - extrinsics.rotation[5] * pointCoordinate.y + - extrinsics.rotation[8] * pointCoordinate.z + - extrinsics.translation[2]; - return {x: x, y: y, z: z}; -}; - -/** - * Save the frame to a file asynchronously - * - * @param {string} path target file path - * @param {Frame} frame frame to be saved - * @param {string} fileFormat the target file format, currently only 'png' is supported - * @return {Promise} - */ -util.writeFrameToFileAsync = function(path, frame, fileFormat = 'png') { - const funcName = 'util.writeFrameToFileAsync'; - checkArgumentLength(3, 3, arguments.length, funcName); - checkArgumentType(arguments, 'string', 0, funcName); - checkArgumentType(arguments, Frame, 1, funcName); - checkArgumentType(arguments, 'string', 2, funcName); - if (fileFormat.toLowerCase() === 'png') { - let png = new PNG({ - width: frame.width, - height: frame.height, - inputColorType: 2, - inputHasAlpha: false}); - png.data = frame.getData(); - return new Promise((resolve, reject) => { - png.pack().pipe(fs.createWriteStream(path)).on('finish', () => { - resolve(); - }); - }); - } else { - throw new TypeError('util.writeFrameToFileAsync expects a string as the 3rd argument and only \'png\' is supported now.'); // eslint-disable-line - } -}; - -/** - * Field of view (FOV) info: - * @typedef {Object} FOVObject - * @property {Float32} h - horizontal field of view - * @property {Float32} v - vertical field of view - * @see [util.fov]{@link util#fov} - */ - -/** - * Get the field of view from an IntrinsicsObject - * @param {IntrinsicsObject} intrinsics the intrinsics to calculate field of view. - * @return {FOVObject} - */ -util.fov = function(intrinsics) { - const funcName = 'util.fov'; - checkArgumentLength(1, 1, arguments.length, funcName); - checkArgumentType(arguments, 'object', 0, funcName); - let ppx = intrinsics.ppx; - let ppy = intrinsics.ppy; - let width = intrinsics.width; - let height = intrinsics.height; - let fx = intrinsics.fx; - let fy = intrinsics.fy; - let h = (Math.atan(ppx + 0.5, fx) + Math.atan(width - ppx - 0.5, fx)) * 57.2957795; - let v = (Math.atan(ppy + 0.5, fy) + Math.atan(height - ppy - 0.5, fy)) * 57.2957795; - return {h: h, v: v}; -}; - -/** - * Save the frame to a file synchronously - * - * @param {string} path target file path - * @param {Frame} frame frame to be saved - * @param {string} fileFormat the target file format, currently only 'png' is supported - * @return {undefined} - */ -util.writeFrameToFile = function(path, frame, fileFormat = 'png') { - const funcName = 'util.writeFrameToFile'; - checkArgumentLength(3, 3, arguments.length, funcName); - checkArgumentType(arguments, 'string', 0, funcName); - checkArgumentType(arguments, Frame, 1, funcName); - checkArgumentType(arguments, 'string', 2, funcName); - if (fileFormat.toLowerCase() === 'png') { - const opt = { - width: frame.width, - height: frame.height, - inputColorType: 2, - inputHasAlpha: false}; - const png = new PNG(opt); - png.data = frame.getData(); - const buf = PNG.sync.write(png, opt); - fs.writeFileSync(path, buf); - } else { - throw new TypeError('util.writeFrameToFile expects a string as the 3rd argument and only \'png\' is supported now.'); // eslint-disable-line - } -}; - -/** - * Get all the frame metadata representation as a string - * - * @param {frame} frame frame to be saved - * @return {String} the string representation of all supported frame metadata. - */ -function frameMetadataContent(frame) { - const funcName = 'frameMetadataContent'; - checkArgumentLength(1, 1, arguments.length, funcName); - checkArgumentType(arguments, Frame, 0, funcName); - let content = 'Stream,' + stream.streamToString(frame.profile.streamType)+'\nMetadata Attribute,Value\n'; // eslint-disable-line - for (let i = 0; i < frame_metadata.FRAME_METADATA_COUNT; i++) { - if (frame.supportsFrameMetadata(i)) { - content += frame_metadata.frameMetadataToString(i) + ',' + frame.frameMetadata(i) + '\n'; - } - } - return content; -} - -/** - * Save the frame metadata string representation to a file asynchronously - * - * @param {string} path target file path - * @param {Frame} frame frame to extract metadata from - * @return {undefined} - */ -util.writeFrameMetadataToFileAsync = function(path, frame) { - const funcName = 'util.writeFrameMetadataToFileAsync'; - checkArgumentLength(2, 2, arguments.length, funcName); - checkArgumentType(arguments, 'string', 0, funcName); - checkArgumentType(arguments, Frame, 1, funcName); - return new Promise((resolve, reject) => { - const content = frameMetadataContent(frame); - fs.writeFile(path, content, (err) => { - if (err) { - reject(err); - } else { - resolve(); - } - }); - }); -}; - -/** - * Save the frame metadata string representation to a file asynchronously - * - * @param {String} path target file path - * @param {Frame} frame to extract metadata from - * @return {undefined} - */ -util.writeFrameMetadataToFile = function(path, frame) { - const funcName = 'util.writeFrameMetadataToFile'; - checkArgumentLength(2, 2, arguments.length, funcName); - checkArgumentType(arguments, 'string', 0, funcName); - checkArgumentType(arguments, Frame, 1, funcName); - const content = frameMetadataContent(frame); - const fd = fs.openSync(path, 'w'); - fs.writeSync(fd, content); - fs.closeSync(fd); -}; - -/** - * Enum for format values. - * @readonly - * @enum {String} - */ -const format = { - - /** - * String literal of 'any'.
    When passed to enable stream, librealsense will try - * to provide best suited format.
    Equivalent to its uppercase counterpart. - */ - format_any: 'any', - /** - * String literal of 'z16'.
    16-bit linear depth values. The depth is meters is - * equal to depth scale * pixel value.
    Equivalent to its uppercase counterpart. - */ - format_z16: 'z16', - /** - * String literal of 'disparity16'.
    16-bit linear disparity values. The depth in - * meters is equal to depth scale / pixel value.
    Equivalent to its uppercase counterpart. - */ - format_disparity16: 'disparity16', - /** - * String literal of 'xyz32f'.
    32-bit floating point 3D coordinates. - *
    Equivalent to its uppercase counterpart. - */ - format_xyz32f: 'xyz32f', - /** - * String literal of 'yuyv'.
    32-bit y0, u, y1, v data for every two pixels. - * Similar to YUV422 but packed in a different order - https://en.wikipedia.org/wiki/YUV - *
    Equivalent to its uppercase counterpart. - */ - format_yuyv: 'yuyv', - /** - * String literal of 'rgb8'.
    8-bit red, green and blue channels. - *
    Equivalent to its uppercase counterpart. - */ - format_rgb8: 'rgb8', - /** - * String literal of 'bgr8'.
    8-bit blue, green, and red channels -- suitable for - * OpenCV.
    Equivalent to its uppercase counterpart. - */ - format_bgr8: 'bgr8', - /** - * String literal of 'rgba8'.
    8-bit red, green and blue channels + constant - * alpha channel equal to FF.
    Equivalent to its uppercase counterpart. - */ - format_rgba8: 'rgba8', - /** - * String literal of 'bgra8'.
    8-bit blue, green, and red channels + constant - * alpha channel equal to FF.
    Equivalent to its uppercase counterpart. - */ - format_bgra8: 'bgra8', - /** - * String literal of 'y8'.
    8-bit per-pixel grayscale image. - *
    Equivalent to its uppercase counterpart. - */ - format_y8: 'y8', - /** - * String literal of 'y16'.
    16-bit per-pixel grayscale image. - *
    Equivalent to its uppercase counterpart. - */ - format_y16: 'y16', - /** - * String literal of 'raw10'.
    Four 10-bit luminance values encoded into - * a 5-byte macropixel.
    Equivalent to its uppercase counterpart. - */ - format_raw10: 'raw10', - /** - * String literal of 'raw16'.
    16-bit raw image.
    Equivalent to - * its uppercase counterpart. - */ - format_raw16: 'raw16', - /** - * String literal of 'raw8'.
    8-bit raw image.
    Equivalent to - * its uppercase counterpart. - */ - format_raw8: 'raw8', - /** - * String literal of 'uyvy'.
    Similar to the standard YUYV pixel - * format, but packed in a different order.
    Equivalent to its uppercase counterpart. - */ - format_uyvy: 'uyvy', - /** - * String literal of 'motion_raw'.
    Raw data from the motion sensor. - *
    Equivalent to its uppercase counterpart. - */ - format_motion_raw: 'motion-raw', - /** - * String literal of 'motion_xyz32f'.
    Motion data packed as 3 32-bit - * float values, for X, Y, and Z axis.
    Equivalent to its uppercase counterpart. - */ - format_motion_xyz32f: 'motion-xyz32f', - /** - * String literal of 'gpio-raw'.
    Raw data from the external sensors - * hooked to one of the GPIO's.
    Equivalent to its uppercase counterpart. - */ - format_gpio_raw: 'gpio-raw', - /** - * String literal of '6dof'.
    Pose data packed as floats array, containing - * translation vector, rotation quaternion and prediction velocities and accelerations vectors - *
    Equivalent to its uppercase counterpart. - */ - format_6dof: '6dof', - /** - * String literal of 'disparity32'.
    32-bit float-point disparity values. - * Depth->Disparity conversion : Disparity = Baseline*FocalLength/Depth. - *
    Equivalent to its uppercase counterpart. - */ - format_disparity32: 'disparity32', - /** - * String literal of 'mjpeg'. - *
    Bitstream encoding for video in which an image of each frame is encoded as JPEG-DIB. - */ - format_mjpeg: 'mjpeg', - /** - * String literal of 'y8i'.
    8-bit per pixel interleaved. 8-bit left, 8-bit right. - */ - format_y8i: 'y8i', - /** - * String literal of 'y12i'. - *
    12-bit per pixel interleaved. 12-bit left, 12-bit right. - * Each pixel is stored in a 24-bit word in little-endian order. - */ - format_y12i: 'y12i', - /** - * String literal of 'inzi'.
    multi-planar Depth 16bit + IR 10bit. - */ - format_inzi: 'inzi', - /** - * String literal of 'invi'.
    8-bit IR stream - */ - format_invi: 'invi', - /** - * String literal of 'w10'. - *
    Grey-scale image as a bit-packed array. 4 pixel data stream taking 5 bytes - */ - format_w10: 'w10', - /** - * String literal of 'FG'. - *
    16-bit per-pixel frame grabber format. - */ - format_FG: 'FG', - /** - * String literal of 'Y411'. - *
    12-bit per-pixel. 6 pixel data stream taking 4 bytes. - */ - format_Y411: 'Y411', - /** - * When passed to enable stream, librealsense will try to provide best suited - * format.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - FORMAT_ANY: RS2.RS2_FORMAT_ANY, - /** - * 16-bit linear depth values. The depth is meters is equal to depth - * scale * pixel value.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - FORMAT_Z16: RS2.RS2_FORMAT_Z16, - /** - * 16-bit linear disparity values. The depth in meters is equal to depth - * scale / pixel value.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - FORMAT_DISPARITY16: RS2.RS2_FORMAT_DISPARITY16, - /** - * 32-bit floating point 3D coordinates.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - FORMAT_XYZ32F: RS2.RS2_FORMAT_XYZ32F, - /** - * 32-bit y0, u, y1, v data for every two pixels. Similar to YUV422 but packed in a different - * order - https://en.wikipedia.org/wiki/YUV. - *
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - FORMAT_YUYV: RS2.RS2_FORMAT_YUYV, - /** - * 8-bit red, green and blue channels.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - FORMAT_RGB8: RS2.RS2_FORMAT_RGB8, - /** - * 8-bit blue, green, and red channels -- suitable for OpenCV.
    Equivalent to its lowercase - * counterpart. - * @type {Integer} - */ - FORMAT_BGR8: RS2.RS2_FORMAT_BGR8, - /** - * 8-bit red, green and blue channels + constant alpha channel equal to FF.
    Equivalent to - * its lowercase counterpart. - * @type {Integer} - */ - FORMAT_RGBA8: RS2.RS2_FORMAT_RGBA8, - /** - * 8-bit blue, green, and red channels + constant alpha channel equal to FF.
    Equivalent to - * its lowercase counterpart. - * @type {Integer} - */ - FORMAT_BGRA8: RS2.RS2_FORMAT_BGRA8, - /** - * 8-bit per-pixel grayscale image.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - FORMAT_Y8: RS2.RS2_FORMAT_Y8, - /** - * 16-bit per-pixel grayscale image.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - FORMAT_Y16: RS2.RS2_FORMAT_Y16, - /** - * Four 10-bit luminance values encoded into a 5-byte macropixel.
    Equivalent to its - * lowercase counterpart. - * @type {Integer} - */ - FORMAT_RAW10: RS2.RS2_FORMAT_RAW10, - /** - * 16-bit raw image.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - FORMAT_RAW16: RS2.RS2_FORMAT_RAW16, - /** - * 8-bit raw image.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - FORMAT_RAW8: RS2.RS2_FORMAT_RAW8, - /** - * Similar to the standard YUYV pixel format, but packed in a different order.
    Equivalent to - * its lowercase counterpart. - * @type {Integer} - */ - FORMAT_UYVY: RS2.RS2_FORMAT_UYVY, - /** - * Raw data from the motion sensor.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - FORMAT_MOTION_RAW: RS2.RS2_FORMAT_MOTION_RAW, - /** - * Motion data packed as 3 32-bit float values, for X, Y, and Z axis.
    Equivalent to its - * lowercase counterpart. - * @type {Integer} - */ - FORMAT_MOTION_XYZ32F: RS2.RS2_FORMAT_MOTION_XYZ32F, - /** - * Raw data from the external sensors hooked to one of the GPIO's.
    Equivalent to its - * lowercase counterpart. - * @type {Integer} - */ - FORMAT_GPIO_RAW: RS2.RS2_FORMAT_GPIO_RAW, - /** - * Pose data packed as floats array, containing translation vector, rotation quaternion - * and prediction velocities and accelerations vectors - *
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - FORMAT_6DOF: RS2.RS2_FORMAT_6DOF, - /** - * 32-bit float-point disparity values. Depth->Disparity conversion : - * Disparity = Baseline*FocalLength/Depth.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - FORMAT_DISPARITY32: RS2.RS2_FORMAT_DISPARITY32, - /** - * Bitstream encoding for video in which an image of each frame is encoded as JPEG-DIB. - * @type {Integer} - */ - FORMAT_MJPEG: RS2.RS2_FORMAT_MJPEG, - /** - * 8-bit per pixel interleaved. 8-bit left, 8-bit right. - * @type {Integer} - */ - FORMAT_Y8I: RS2.RS2_FORMAT_Y8I, - /** - * 12-bit per pixel interleaved. 12-bit left, 12-bit right. - * Each pixel is stored in a 24-bit word in little-endian order. - * @type {Integer} - */ - FORMAT_Y12I: RS2.RS2_FORMAT_Y12I, - /** - * multi-planar Depth 16bit + IR 10bit. - * @type {Integer} - */ - FORMAT_INZI: RS2.RS2_FORMAT_INZI, - /** - * 8-bit IR stream. - * @type {Integer} - */ - FORMAT_INVI: RS2.RS2_FORMAT_INVI, - /** - * Grey-scale image as a bit-packed array. 4 pixel data stream taking 5 bytes. - * @type {Integer} - */ - FORMAT_W10: RS2.RS2_FORMAT_W10, - /** - * 16-bit per-pixel frame grabber format. - * @type {Integer} - */ - FORMAT_FG: RS2.RS2_FORMAT_FG, - /** - * 12-bit per-pixel. 4 pixel data stream taking 6 bytes. - * @type {Integer} - */ - FORMAT_Y411: RS2.RS2_FORMAT_Y411, - /** - * Number of enumeration values. Not a valid input: intended to be used in for-loops. - *
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - FORMAT_COUNT: RS2.RS2_FORMAT_COUNT, - - /** - * Get the string representation out of the integer format type - * @param {Integer} format the format type - * @return {String} - */ - formatToString: function(format) { - const funcName = 'format.formatToString()'; - checkArgumentLength(1, 1, arguments.length, funcName); - const i = checkArgumentType(arguments, constants.format, 0, funcName); - switch (i) { - case this.FORMAT_ANY: - return this.format_any; - case this.FORMAT_Z16: - return this.format_z16; - case this.FORMAT_DISPARITY16: - return this.format_disparity16; - case this.FORMAT_XYZ32F: - return this.format_xyz32f; - case this.FORMAT_YUYV: - return this.format_yuyv; - case this.FORMAT_RGB8: - return this.format_rgb8; - case this.FORMAT_BGR8: - return this.format_bgr8; - case this.FORMAT_RGBA8: - return this.format_rgba8; - case this.FORMAT_BGRA8: - return this.format_bgra8; - case this.FORMAT_Y8: - return this.format_y8; - case this.FORMAT_Y16: - return this.format_y16; - case this.FORMAT_RAW10: - return this.format_raw10; - case this.FORMAT_RAW16: - return this.format_raw16; - case this.FORMAT_RAW8: - return this.format_raw8; - case this.FORMAT_UYVY: - return this.format_uyvy; - case this.FORMAT_MOTION_RAW: - return this.format_motion_raw; - case this.FORMAT_MOTION_XYZ32F: - return this.format_motion_xyz32f; - case this.FORMAT_GPIO_RAW: - return this.format_gpio_raw; - case this.FORMAT_6DOF: - return this.format_6dof; - case this.FORMAT_DISPARITY32: - return this.format_disparity32; - case this.RS2_FORMAT_MJPEG: - return this.format_mjpeg; - case this.RS2_FORMAT_Y8I: - return this.format_y8i; - case this.RS2_FORMAT_Y12I: - return this.format_y12i; - case this.RS2_FORMAT_INZI: - return this.format_inzi; - case this.RS2_FORMAT_INVI: - return this.format_invi; - case this.RS2_FORMAT_W10: - return this.format_w10; - case this.RS2_FORMAT_FG: - return this.format_FG; - case this.RS2_FORMAT_Y411: - return this.format_Y411; - } - }, -}; - - -/** - * Enum for stream values. - * @readonly - * @enum {String} - */ -const stream = { - /** - * String literal of 'any'.
    Any stream.
    Equivalent - * to its uppercase counterpart. - */ - stream_any: 'any', - /** - * String literal of 'depth'.
    Native stream of depth data - * produced by RealSense device .
    Equivalent to its uppercase counterpart. - */ - stream_depth: 'depth', - /** - * String literal of 'color'.
    Native stream of color data - * captured by RealSense device .
    Equivalent to its uppercase counterpart. - */ - stream_color: 'color', - /** - * String literal of 'infrared'.
    Native stream of infrared data - * captured by RealSense device .
    Equivalent to its uppercase counterpart. - */ - stream_infrared: 'infrared', - /** - * String literal of 'fisheye'.
    Native stream of fish-eye(wide) data - * captured from the dedicate motion camera .
    Equivalent to its uppercase counterpart. - */ - stream_fisheye: 'fisheye', - /** - * String literal of 'gyro'.
    Native stream of gyroscope motion - * data produced by RealSense device .
    Equivalent to its uppercase counterpart. - */ - stream_gyro: 'gyro', - /** - * String literal of 'accel'.
    Native stream of accelerometer motion - * data produced by RealSense device .
    Equivalent to its uppercase counterpart. - */ - stream_accel: 'accel', - /** - * String literal of 'gpio'.
    Signals from external device connected - * through GPIO .
    Equivalent to its uppercase counterpart. - */ - stream_gpio: 'gpio', - /** - * String literal of 'pose'.
    6 Degrees of Freedom pose data, calculated by - * RealSense device.
    Equivalent to its uppercase counterpart. - */ - stream_pose: 'pose', - /** - * String literal of 'confidence'.
    Confidence stream - *
    Equivalent to its uppercase counterpart. - */ - stream_confidence: 'confidence', - - /** - * Any stream.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - STREAM_ANY: RS2.RS2_STREAM_ANY, - /** - * Native stream of depth data produced by RealSense device.
    Equivalent to its - * lowercase counterpart. - * @type {Integer} - */ - STREAM_DEPTH: RS2.RS2_STREAM_DEPTH, - /** - * Native stream of color data captured by RealSense device.
    Equivalent to its - * lowercase counterpart. - * @type {Integer} - */ - STREAM_COLOR: RS2.RS2_STREAM_COLOR, - /** - * Native stream of infrared data captured by RealSense device.
    Equivalent to its - * lowercase counterpart. - * @type {Integer} - */ - STREAM_INFRARED: RS2.RS2_STREAM_INFRARED, - /** - * Native stream of fish-eye (wide) data captured from the dedicate motion camera. - *
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - STREAM_FISHEYE: RS2.RS2_STREAM_FISHEYE, - /** - * Native stream of gyroscope motion data produced by RealSense device.
    Equivalent to - * its lowercase counterpart. - * @type {Integer} - */ - STREAM_GYRO: RS2.RS2_STREAM_GYRO, - /** - * Native stream of accelerometer motion data produced by RealSense device.
    Equivalent to - * its lowercase counterpart. - * @type {Integer} - */ - STREAM_ACCEL: RS2.RS2_STREAM_ACCEL, - /** - * Signals from external device connected through GPIO.
    Equivalent to its - * lowercase counterpart. - * @type {Integer} - */ - STREAM_GPIO: RS2.RS2_STREAM_GPIO, - /** - * 6 Degrees of Freedom pose data, calculated by RealSense device.
    Equivalent to its - * lowercase counterpart. - * @type {Integer} - */ - STREAM_POSE: RS2.RS2_STREAM_POSE, - /** - * Confidence stream.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - STREAM_CONFIDENCE: RS2.RS2_STREAM_CONFIDENCE, - /** - * Number of enumeration values. Not a valid input: intended to be used in for-loops. - * @type {Integer} - */ - STREAM_COUNT: RS2.RS2_STREAM_COUNT, - - /** - * Get the string representation out of the integer stream type - * @param {Integer} stream the stream type - * @return {String} - */ - streamToString: function(stream) { - const funcName = 'stream.streamToString()'; - checkArgumentLength(1, 1, arguments.length, funcName); - const i = checkArgumentType(arguments, constants.stream, 0, funcName); - switch (i) { - case this.STREAM_ANY: - return this.stream_any; - case this.STREAM_DEPTH: - return this.stream_depth; - case this.STREAM_COLOR: - return this.stream_color; - case this.STREAM_INFRARED: - return this.stream_infrared; - case this.STREAM_FISHEYE: - return this.stream_fisheye; - case this.STREAM_GYRO: - return this.stream_gyro; - case this.STREAM_ACCEL: - return this.stream_accel; - case this.STREAM_GPIO: - return this.stream_gpio; - case this.STREAM_POSE: - return this.stream_pose; - case this.STREAM_CONFIDENCE: - return this.stream_confidence; - } - }, -}; - -/** - * Enum for recording options - * @readonly - * @enum {String} - * @see See [RecordingContext.constructor()]{@link RecordingContext} for usage - */ -const recording_mode = { - /** - * String literal of 'blank-frames'.
    Frame metadata will be recorded, - * but pixel data will be replaced with zeros to save space.
    Equivalent to its uppercase - * counterpart. - */ - recording_mode_blank_frames: 'blank-frames', - /** - * String literal of 'compressed'.
    Frames will be encoded using a proprietary - * lossy encoding, aiming at x5 compression at some CPU expense.
    Equivalent to its uppercase - * counterpart. - */ - recording_mode_compressed: 'compressed', - /** - * String literal of 'best-quality'.
    Frames will not be compressed, - * but rather stored as-is. This gives best quality and low CPU overhead, but you might run out - * of memory.
    Equivalent to its uppercase counterpart. - */ - recording_mode_best_quality: 'best-quality', - - /** - * Frame metadata will be recorded, but pixel data will be replaced with zeros to save space. - *
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - RECORDING_MODE_BLANK_FRAMES: RS2.RS2_RECORDING_MODE_BLANK_FRAMES, - /** - * Frames will be encoded using a proprietary lossy encoding, aiming at x5 compression at some - * CPU expense.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - RECORDING_MODE_COMPRESSED: RS2.RS2_RECORDING_MODE_COMPRESSED, - /** - * Frames will not be compressed, but rather stored as-is. This gives best quality and low CPU - * overhead, but you might run out of memory.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - RECORDING_MODE_BEST_QUALITY: RS2.RS2_RECORDING_MODE_BEST_QUALITY, - /** - * Number of enumeration values. Not a valid input: intended to be used in for-loops. - * @type {Integer} - */ - RECORDING_MODE_COUNT: RS2.RS2_RECORDING_MODE_COUNT, -}; - -/** - * Enum for option values. - * @readonly - * @enum {String} - * @see [Sensor.isOptionReadOnly()]{@link Sensor#isOptionReadOnly} - * @see [Sensor.getOption()]{@link Sensor#getOption} - * @see [Sensor.getOptionRange()]{@link Sensor#getOptionRange} - * @see [Sensor.setOption()]{@link Sensor#setOption} - * @see [Sensor.supportsOption()]{@link Sensor#supportsOption} - * @see [Sensor.getOptionDescription()]{@link Sensor#getOptionDescription} - * @see [Sensor.getOptionValueDescription()]{@link Sensor#getOptionValueDescription} - */ - -const option = { - /** - * String literal of 'backlight-compensation'.
    Enable / disable color - * backlight compensation.
    Equivalent to its uppercase counterpart. - */ - option_backlight_compensation: 'backlight-compensation', - /** - * String literal of 'brightness'.
    Color image brightness.
    Equivalent - * to its uppercase counterpart. - */ - option_brightness: 'brightness', - /** - * String literal of 'contrast'.
    Color image contrast.
    Equivalent - * to its uppercase counterpart. - */ - option_contrast: 'contrast', - /** - * String literal of 'exposure'.
    Controls exposure time of color camera - *. Setting any value will disable auto exposure.
    Equivalent to its uppercase counterpart. - */ - option_exposure: 'exposure', - /** - * String literal of 'gain'.
    Color image gain.
    Equivalent to its - * uppercase counterpart. - */ - option_gain: 'gain', - /** - * String literal of 'gamma'.
    Color image gamma setting.
    Equivalent - * to its uppercase counterpart. - */ - option_gamma: 'gamma', - /** - * String literal of 'hue'.
    Color image hue.
    Equivalent to its - * uppercase counterpart. - */ - option_hue: 'hue', - /** - * String literal of 'saturation'.
    Color image saturation setting. - *
    Equivalent to its uppercase counterpart. - */ - option_saturation: 'saturation', - /** - * String literal of 'sharpness'.
    Color image sharpness setting. - *
    Equivalent to its uppercase counterpart. - */ - option_sharpness: 'sharpness', - /** - * String literal of 'white-balance'.
    Controls white balance of color - * image. Setting any value will disable auto white balance.
    Equivalent to its uppercase - * counterpart. - */ - option_white_balance: 'white-balance', - /** - * String literal of 'enable-auto-exposure'.
    Enable / disable color - * image auto-exposure.
    Equivalent to its uppercase counterpart. - */ - option_enable_auto_exposure: 'enable-auto-exposure', - /** - * String literal of 'enable-auto-white-balance'.
    Enable / disable - * color image auto-white-balance.
    Equivalent to its uppercase counterpart. - */ - option_enable_auto_white_balance: 'enable-auto-white-balance', - /** - * String literal of 'visual-preset'.
    Provide access to several recommend - * sets of option presets for the depth camera .
    Equivalent to its uppercase counterpart. - */ - option_visual_preset: 'visual-preset', - /** - * String literal of 'laser-power'.
    Power of the F200 / SR300 projector - *, with 0 meaning projector off.
    Equivalent to its uppercase counterpart. - */ - option_laser_power: 'laser-power', - /** - * String literal of 'accuracy'.
    Set the number of patterns projected - * per frame. The higher the accuracy value the more patterns projected. Increasing the number - * of patterns help to achieve better accuracy. Note that this control is affecting the Depth FPS. - *
    Equivalent to its uppercase counterpart. - */ - option_accuracy: 'accuracy', - /** - * String literal of 'motion-range'.
    Motion vs. Range trade-off, with - * lower values allowing for better motion sensitivity and higher values allowing for better - * depth range.
    Equivalent to its uppercase counterpart. - */ - option_motion_range: 'motion-range', - /** - * String literal of 'filter-option'.
    Set the filter to apply to each - * depth frame. Each one of the filter is optimized per the application requirements. - *
    Equivalent to its uppercase counterpart. - */ - option_filter_option: 'filter-option', - /** - * String literal of 'confidence-threshold'.
    The confidence level threshold - * used by the Depth algorithm pipe to set whether a pixel will get a valid range or will - * be marked with invalid range.
    Equivalent to its uppercase counterpart. - */ - option_confidence_threshold: 'confidence-threshold', - /** - * String literal of 'emitter-enabled'.
    Laser Emitter enabled . - *
    Equivalent to its uppercase counterpart. - */ - option_emitter_enabled: 'emitter-enabled', - /** - * String literal of 'frames-queue-size'.
    Number of frames the user - * is allowed to keep per stream. Trying to hold-on to more frames will cause frame-drops. - *
    Equivalent to its uppercase counterpart. - */ - option_frames_queue_size: 'frames-queue-size', - /** - * String literal of 'total-frame-drops'.
    Total number of detected - * frame drops from all streams .
    Equivalent to its uppercase counterpart. - */ - option_total_frame_drops: 'total-frame-drops', - /** - * String literal of 'auto-exposure-mode'.
    Auto-Exposure modes: Static - *, Anti-Flicker and Hybrid .
    Equivalent to its uppercase counterpart. - */ - option_auto_exposure_mode: 'auto-exposure-mode', - /** - * String literal of 'power-line-frequency'.
    Power Line Frequency control - * for anti-flickering, Off/50Hz/60Hz/Auto.
    Equivalent to its uppercase counterpart. - */ - option_power_line_frequency: 'power-line-frequency', - /** - * String literal of 'asic-temperature'.
    Current Asic Temperature . - *
    Equivalent to its uppercase counterpart. - */ - option_asic_temperature: 'asic-temperature', - /** - * String literal of 'error-polling-enabled'.
    disable error handling - * .
    Equivalent to its uppercase counterpart. - */ - option_error_polling_enabled: 'error-polling-enabled', - /** - * String literal of 'projector-temperature'.
    Current Projector Temperature - * .
    Equivalent to its uppercase counterpart. - */ - option_projector_temperature: 'projector-temperature', - /** - * String literal of 'output-trigger-enabled'.
    Enable / disable trigger - * to be outputed from the camera to any external device on every depth frame. - *
    Equivalent to its uppercase counterpart. - */ - option_output_trigger_enabled: 'output-trigger-enabled', - /** - * String literal of 'motion-module-temperature'.
    Current Motion-Module - * Temperature .
    Equivalent to its uppercase counterpart. - */ - option_motion_module_temperature: 'motion-module-temperature', - /** - * String literal of 'depth-units'.
    Number of meters represented by - * a single depth unit .
    Equivalent to its uppercase counterpart. - */ - option_depth_units: 'depth-units', - /** - * String literal of 'enable-motion-correction'.
    Enable/Disable automatic - * correction of the motion data .
    Equivalent to its uppercase counterpart. - */ - option_enable_motion_correction: 'enable-motion-correction', - /** - * String literal of 'auto-exposure-priority'. - *
    Allows sensor to dynamically ajust the frame rate - * depending on lighting conditions
    Equivalent to its uppercase counterpart - */ - option_auto_exposure_priority: 'auto-exposure-priority', - - /** - * String literal of ''color-scheme'.
    Color scheme for data visualization - *
    Equivalent to its uppercase counterpart - */ - option_color_scheme: 'color-scheme', - - /** - * String literal of ''histogram-equalization-enabled'.
    Perform histogram - * equalization post-processing on the depth data
    Equivalent to its uppercase counterpart - */ - option_histogram_equalization_enabled: 'histogram-equalization-enabled', - - /** - * String literal of ''min-distance'.
    Minimal distance to the target - *
    Equivalent to its uppercase counterpart - */ - option_min_distance: 'min-distance', - - /** - * String literal of ''max-distance'.
    Maximum distance to the target - *
    Equivalent to its uppercase counterpart - */ - option_max_distance: 'max-distance', - /** - * String literal of 'texture-source'.
    Texture mapping stream unique ID - *
    Equivalent to its uppercase counterpart. - */ - option_texture_source: 'texture-source', - /** - * String literal of 'filter-magnitude'.
    The 2D-filter effect. The specific - * interpretation is given within the context of the filter - *
    Equivalent to its uppercase counterpart. - */ - option_filter_magnitude: 'filter-magnitude', - /** - * String literal of 'filter-smooth-alpha'.
    2D-filter parameter controls - * the weight/radius for smoothing. - *
    Equivalent to its uppercase counterpart. - */ - option_filter_smooth_alpha: 'filter-smooth-alpha', - /** - * String literal of 'filter-smooth-delta'.
    2D-filter range/validity threshold - *
    Equivalent to its uppercase counterpart. - */ - option_filter_smooth_delta: 'filter-smooth-delta', - /** - * String literal of 'holes-fill'.
    Enhance depth data post-processing - * with holes filling where appropriate - *
    Equivalent to its uppercase counterpart. - */ - option_holes_fill: 'holes-fill', - /** - * String literal of 'stereo-baseline'.
    The distance in mm between the first - * and the second imagers in stereo-based depth cameras - *
    Equivalent to its uppercase counterpart. - */ - option_stereo_baseline: 'stereo-baseline', - /** - * String literal of 'auto-exposure-converage-step'.
    Allows dynamically ajust - * the converge step value of the target exposure in Auto-Exposure algorithm - *
    Equivalent to its uppercase counterpart. - */ - option_auto_exposure_converge_step: 'auto-exposure-converge-step', - /** - * String literal of 'inter-cam-sync-mode'.
    Impose Inter-camera HW synchronization mode. - * Applicable for D400/Rolling Shutter SKUs - *
    Equivalent to its uppercase counterpart. - */ - option_inter_cam_sync_mode: 'inter-cam-sync-mode', - option_stream_filter: 'stream-filter', - option_stream_format_filter: 'stream-format-filter', - option_stream_index_filter: 'stream-index-filter', - option_emitter_on_off: 'emitter-on-off', - option_zero_order_point_x: 'zero-order-point-x', /* Deprecated */ - option_zero_order_point_y: 'zero-order-point-y', /* Deprecated */ - option_lld_temperature: 'lld-temperature', - option_mc_temperature: 'mc-temperature', - option_ma_temperature: 'ma-temperature', - option_apd_temperature: 'apd-temperature', - option_hardware_preset: 'hardware-preset', - option_global_time_enabled: 'global-time-enabled', - option_enable_mapping: 'enable-mapping', - option_enable_relocalization: 'enable-relocalization', - option_enable_pose_jumping: 'enable-pose-jumping', - option_enable_dynamic_calibration: 'enable-dynamic-calibration', - option_depth_offset: 'depth-offset', - option_led_power: 'led-power', - option_zero_order_enabled: 'zero-order-enabled', /* Deprecated */ - option_enable_map_preservation: 'enable-map-preservation', - /** - * Enable / disable color backlight compensatio.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - OPTION_BACKLIGHT_COMPENSATION: RS2.RS2_OPTION_BACKLIGHT_COMPENSATION, - /** - * Color image brightnes.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - OPTION_BRIGHTNESS: RS2.RS2_OPTION_BRIGHTNESS, - /** - * Color image contras.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - OPTION_CONTRAST: RS2.RS2_OPTION_CONTRAST, - /** - * Controls exposure time of color camera. Setting any value will disable auto exposur. - *
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - OPTION_EXPOSURE: RS2.RS2_OPTION_EXPOSURE, - /** - * Color image gai.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - OPTION_GAIN: RS2.RS2_OPTION_GAIN, - /** - * Color image gamma settin.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - OPTION_GAMMA: RS2.RS2_OPTION_GAMMA, - /** - * Color image hu.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - OPTION_HUE: RS2.RS2_OPTION_HUE, - /** - * Color image saturation settin.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - OPTION_SATURATION: RS2.RS2_OPTION_SATURATION, - /** - * Color image sharpness settin.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - OPTION_SHARPNESS: RS2.RS2_OPTION_SHARPNESS, - /** - * Controls white balance of color image. Setting any value will disable auto white balanc. - *
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - OPTION_WHITE_BALANCE: RS2.RS2_OPTION_WHITE_BALANCE, - /** - * Enable / disable color image auto-exposur.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - OPTION_ENABLE_AUTO_EXPOSURE: RS2.RS2_OPTION_ENABLE_AUTO_EXPOSURE, - /** - * Enable / disable color image auto-white-balanc.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - OPTION_ENABLE_AUTO_WHITE_BALANCE: RS2.RS2_OPTION_ENABLE_AUTO_WHITE_BALANCE, - /** - * Provide access to several recommend sets of option presets for the depth camera. - *
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - OPTION_VISUAL_PRESET: RS2.RS2_OPTION_VISUAL_PRESET, - /** - * Power of the F200 / SR300 projector, with 0 meaning projector of. - *
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - OPTION_LASER_POWER: RS2.RS2_OPTION_LASER_POWER, - /** - * Set the number of patterns projected per frame. The higher the accuracy value the more - * patterns projected. Increasing the number of patterns help to achieve better accuracy. Note - * that this control is affecting the Depth FPS.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - OPTION_ACCURACY: RS2.RS2_OPTION_ACCURACY, - /** - * Motion vs. Range trade-off, with lower values allowing for better motion sensitivity and - * higher values allowing for better depth rang.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - OPTION_MOTION_RANGE: RS2.RS2_OPTION_MOTION_RANGE, - /** - * Set the filter to apply to each depth frame. Each one of the filter is optimized per the - * application requirement.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - OPTION_FILTER_OPTION: RS2.RS2_OPTION_FILTER_OPTION, - /** - * The confidence level threshold used by the Depth algorithm pipe to set whether a pixel will - * get a valid range or will be marked with invalid rang.
    Equivalent to its lowercase - * counterpart. - * @type {Integer} - */ - OPTION_CONFIDENCE_THRESHOLD: RS2.RS2_OPTION_CONFIDENCE_THRESHOLD, - /** - * Laser Emitter enabled.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - OPTION_EMITTER_ENABLED: RS2.RS2_OPTION_EMITTER_ENABLED, - /** - * Number of frames the user is allowed to keep per stream. Trying to hold-on to more frames will - * cause frame-drops.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - OPTION_FRAMES_QUEUE_SIZE: RS2.RS2_OPTION_FRAMES_QUEUE_SIZE, - /** - * Total number of detected frame drops from all streams.
    Equivalent to its lowercase - * counterpart. - * @type {Integer} - */ - OPTION_TOTAL_FRAME_DROPS: RS2.RS2_OPTION_TOTAL_FRAME_DROPS, - /** - * Auto-Exposure modes: Static, Anti-Flicker and Hybrid.
    Equivalent to its lowercase - * counterpart. - * @type {Integer} - */ - OPTION_AUTO_EXPOSURE_MODE: RS2.RS2_OPTION_AUTO_EXPOSURE_MODE, - /** - * Power Line Frequency control for anti-flickering, Off/50Hz/60Hz/Auto.
    Equivalent to its - * lowercase counterpart. - * @type {Integer} - */ - OPTION_POWER_LINE_FREQUENCY: RS2.RS2_OPTION_POWER_LINE_FREQUENCY, - /** - * Current Asic Temperature.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - OPTION_ASIC_TEMPERATURE: RS2.RS2_OPTION_ASIC_TEMPERATURE, - /** - * disable error handling.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - OPTION_ERROR_POLLING_ENABLED: RS2.RS2_OPTION_ERROR_POLLING_ENABLED, - /** - * Current Projector Temperature.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - OPTION_PROJECTOR_TEMPERATURE: RS2.RS2_OPTION_PROJECTOR_TEMPERATURE, - /** - * Enable / disable trigger to be outputed from the camera to any external device on every depth - * frame.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - OPTION_OUTPUT_TRIGGER_ENABLED: RS2.RS2_OPTION_OUTPUT_TRIGGER_ENABLED, - /** - * Current Motion-Module Temperature.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - OPTION_MOTION_MODULE_TEMPERATURE: RS2.RS2_OPTION_MOTION_MODULE_TEMPERATURE, - /** - * Number of meters represented by a single depth unit.
    Equivalent to its lowercase - * counterpart. - * @type {Integer} - */ - OPTION_DEPTH_UNITS: RS2.RS2_OPTION_DEPTH_UNITS, - /** - * Enable/Disable automatic correction of the motion data.
    Equivalent to its lowercase - * counterpart. - * @type {Integer} - */ - OPTION_ENABLE_MOTION_CORRECTION: RS2.RS2_OPTION_ENABLE_MOTION_CORRECTION, - /** - * Allows sensor to dynamically ajust the frame rate depending on lighting conditions. - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - OPTION_AUTO_EXPOSURE_PRIORITY: RS2.RS2_OPTION_AUTO_EXPOSURE_PRIORITY, - - /** - * Color scheme for data visualization
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - OPTION_COLOR_SCHEME: RS2.RS2_OPTION_COLOR_SCHEME, - - /** - * Perform histogram equalization post-processing on the depth data. - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - OPTION_HISTOGRAM_EQUALIZATION_ENABLED: RS2.RS2_OPTION_HISTOGRAM_EQUALIZATION_ENABLED, - - /** - * Minimal distance to the target
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - OPTION_MIN_DISTANCE: RS2.RS2_OPTION_MIN_DISTANCE, - - /** - * Maximum distance to the target
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - OPTION_MAX_DISTANCE: RS2.RS2_OPTION_MAX_DISTANCE, - /** - * Texture mapping stream unique ID
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - OPTION_TEXTURE_SOURCE: RS2.RS2_OPTION_TEXTURE_SOURCE, - /** - * The 2D-filter effect. The specific interpretation is given within the context of the filter - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - OPTION_FILTER_MAGNITUDE: RS2.RS2_OPTION_FILTER_MAGNITUDE, - /** - * 2D-filter parameter controls the weight/radius for smoothing. - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - OPTION_FILTER_SMOOTH_ALPHA: RS2.RS2_OPTION_FILTER_SMOOTH_ALPHA, - /** - * 2D-filter range/validity threshold
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - OPTION_FILTER_SMOOTH_DELTA: RS2.RS2_OPTION_FILTER_SMOOTH_DELTA, - /** - * Enhance depth data post-processing with holes filling where appropriate - *
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - OPTION_HOLES_FILL: RS2.RS2_OPTION_HOLES_FILL, - /** - * The distance in mm between the first and the second imagers in stereo-based depth cameras - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - OPTION_STEREO_BASELINE: RS2.RS2_OPTION_STEREO_BASELINE, - /** - * Allows dynamically ajust the converge step value of the target exposure in Auto-Exposure - * algorithm - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - OPTION_AUTO_EXPOSURE_CONVERGE_STEP: RS2.RS2_OPTION_AUTO_EXPOSURE_CONVERGE_STEP, - /** - * Impose Inter-camera HW synchronization mode. - * Applicable for D400/Rolling Shutter SKUs - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - OPTION_INTER_CAM_SYNC_MODE: RS2.RS2_OPTION_INTER_CAM_SYNC_MODE, - OPTION_STREAM_FILTER: RS2.RS2_OPTION_STREAM_FILTER, - OPTION_STREAM_FORMAT_FILTER: RS2.RS2_OPTION_STREAM_FORMAT_FILTER, - OPTION_STREAM_INDEX_FILTER: RS2.RS2_OPTION_STREAM_INDEX_FILTER, - OPTION_EMITTER_ON_OFF: RS2.RS2_OPTION_EMITTER_ON_OFF, - OPTION_ZERO_ORDER_POINT_X: RS2.RS2_OPTION_ZERO_ORDER_POINT_X, - OPTION_ZERO_ORDER_POINT_Y: RS2.RS2_OPTION_ZERO_ORDER_POINT_Y, - OPTION_LLD_TEMPERATURE: RS2.RS2_OPTION_LLD_TEMPERATURE, - OPTION_MC_TEMPERATURE: RS2.RS2_OPTION_MC_TEMPERATURE, - OPTION_MA_TEMPERATURE: RS2.RS2_OPTION_MA_TEMPERATURE, - OPTION_HARDWARE_PRESET: RS2.RS2_OPTION_HARDWARE_PRESET, - OPTION_GLOBAL_TIME_ENABLED: RS2.RS2_OPTION_GLOBAL_TIME_ENABLED, - OPTION_APD_TEMPERATURE: RS2.RS2_OPTION_APD_TEMPERATURE, - OPTION_ENABLE_MAPPING: RS2.RS2_OPTION_ENABLE_MAPPING, - OPTION_ENABLE_RELOCALIZATION: RS2.RS2_OPTION_ENABLE_RELOCALIZATION, - OPTION_ENABLE_POSE_JUMPING: RS2.RS2_OPTION_ENABLE_POSE_JUMPING, - OPTION_ENABLE_DYNAMIC_CALIBRATION: RS2.RS2_OPTION_ENABLE_DYNAMIC_CALIBRATION, - OPTION_DEPTH_OFFSET: RS2.RS2_OPTION_DEPTH_OFFSET, - OPTION_LED_POWER: RS2.RS2_OPTION_LED_POWER, - OPTION_ZERO_ORDER_ENABLED: RS2.RS2_OPTION_ZERO_ORDER_ENABLED, - OPTION_ENABLE_MAP_PRESERVATION: RS2.RS2_OPTION_ENABLE_MAP_PRESERVATION, - OPTION_FREEFALL_DETECTION_ENABLED: RS2.RS2_OPTION_FREEFALL_DETECTION_ENABLED, - OPTION_DIGITAL_GAIN: RS2.RS2_OPTION_DIGITAL_GAIN, - /** - * Enable Laser On constantly (GS SKU Only) - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - OPTION_EMITTER_ALWAYS_ON: RS2.RS2_OPTION_EMITTER_ALWAYS_ON, - OPTION_THERMAL_COMPENSATION: RS2.RS2_OPTION_THERMAL_COMPENSATION, - OPTION_TRIGGER_CAMERA_ACCURACY_HEALTH: RS2.RS2_OPTION_TRIGGER_CAMERA_ACCURACY_HEALTH, - OPTION_RESET_CAMERA_ACCURACY_HEALTH: RS2.RS2_OPTION_RESET_CAMERA_ACCURACY_HEALTH, - OPTION_HOST_PERFORMANCE: RS2.RS2_OPTION_HOST_PERFORMANCE, - OPTION_HDR_ENABLED: RS2.RS2_OPTION_HDR_ENABLED, - OPTION_SEQUENCE_NAME: RS2.RS2_OPTION_SEQUENCE_NAME, - OPTION_SEQUENCE_SIZE: RS2.RS2_OPTION_SEQUENCE_SIZE, - OPTION_SEQUENCE_ID: RS2.RS2_OPTION_SEQUENCE_ID, - OPTION_HUMIDITY_TEMPERATURE: RS2.RS2_OPTION_HUMIDITY_TEMPERATURE, - OPTION_ENABLE_MAX_USABLE_RANGE: RS2.RS2_OPTION_ENABLE_MAX_USABLE_RANGE, - OPTION_ALTERNATE_IR: RS2.RS2_OPTION_ALTERNATE_IR, - OPTION_NOISE_ESTIMATION: RS2.RS2_OPTION_NOISE_ESTIMATION, - OPTION_ENABLE_IR_REFLECTIVITY: RS2.RS2_OPTION_ENABLE_IR_REFLECTIVITY, - OPTION_EMITTER_FREQUENCY: RS2.RS2_OPTION_EMITTER_FREQUENCY, - /** - * Set or get auto exposure limit in microsecond. - * @type {Integer} - */ - OPTION_AUTO_EXPOSURE_LIMIT: RS2.RS2_OPTION_AUTO_EXPOSURE_LIMIT, - /** - * Set or get auto gain limit. - * @type {Integer} - */ - OPTION_AUTO_GAIN_LIMIT: RS2.RS2_OPTION_AUTO_GAIN_LIMIT, - /** - * Set or get auto rx sensitivity. - * @type {Integer} - */ - OPTION_AUTO_RX_SENSITIVITY: RS2.RS2_OPTION_AUTO_RX_SENSITIVITY, - /** - * Number of enumeration values. Not a valid input: intended to be used in for-loops. - * @type {Integer} - */ - OPTION_COUNT: RS2.RS2_OPTION_COUNT, - - /** - * Get the string representation out of the integer option type - * @param {Integer} option the option type - * @return {String} - */ - optionToString: function(option) { - const funcName = 'option.optionToString()'; - checkArgumentLength(1, 1, arguments.length, funcName); - const i = checkArgumentType(arguments, constants.option, 0, funcName); - switch (i) { - case this.OPTION_BACKLIGHT_COMPENSATION: - return this.option_backlight_compensation; - case this.OPTION_BRIGHTNESS: - return this.option_brightness; - case this.OPTION_CONTRAST: - return this.option_contrast; - case this.OPTION_EXPOSURE: - return this.option_exposure; - case this.OPTION_GAIN: - return this.option_gain; - case this.OPTION_GAMMA: - return this.option_gamma; - case this.OPTION_HUE: - return this.option_hue; - case this.OPTION_SATURATION: - return this.option_saturation; - case this.OPTION_SHARPNESS: - return this.option_sharpness; - case this.OPTION_WHITE_BALANCE: - return this.option_white_balance; - case this.OPTION_ENABLE_AUTO_EXPOSURE: - return this.option_enable_auto_exposure; - case this.OPTION_ENABLE_AUTO_WHITE_BALANCE: - return this.option_enable_auto_white_balance; - case this.OPTION_VISUAL_PRESET: - return this.option_visual_preset; - case this.OPTION_LASER_POWER: - return this.option_laser_power; - case this.OPTION_ACCURACY: - return this.option_accuracy; - case this.OPTION_MOTION_RANGE: - return this.option_motion_range; - case this.OPTION_FILTER_OPTION: - return this.option_filter_option; - case this.OPTION_CONFIDENCE_THRESHOLD: - return this.option_confidence_threshold; - case this.OPTION_EMITTER_ENABLED: - return this.option_emitter_enabled; - case this.OPTION_FRAMES_QUEUE_SIZE: - return this.option_frames_queue_size; - case this.OPTION_TOTAL_FRAME_DROPS: - return this.option_total_frame_drops; - case this.OPTION_AUTO_EXPOSURE_MODE: - return this.option_auto_exposure_mode; - case this.OPTION_POWER_LINE_FREQUENCY: - return this.option_power_line_frequency; - case this.OPTION_ASIC_TEMPERATURE: - return this.option_asic_temperature; - case this.OPTION_ERROR_POLLING_ENABLED: - return this.option_error_polling_enabled; - case this.OPTION_PROJECTOR_TEMPERATURE: - return this.option_projector_temperature; - case this.OPTION_OUTPUT_TRIGGER_ENABLED: - return this.option_output_trigger_enabled; - case this.OPTION_MOTION_MODULE_TEMPERATURE: - return this.option_motion_module_temperature; - case this.OPTION_DEPTH_UNITS: - return this.option_depth_units; - case this.OPTION_ENABLE_MOTION_CORRECTION: - return this.option_enable_motion_correction; - case this.OPTION_AUTO_EXPOSURE_PRIORITY: - return this.option_auto_exposure_priority; - case this.OPTION_COLOR_SCHEME: - return this.option_color_scheme; - case this.OPTION_HISTOGRAM_EQUALIZATION_ENABLED: - return this.option_histogram_equalization_enabled; - case this.OPTION_MIN_DISTANCE: - return this.option_min_distance; - case this.OPTION_MAX_DISTANCE: - return this.option_max_distance; - case this.OPTION_TEXTURE_SOURCE: - return this.option_texture_source; - case this.OPTION_FILTER_MAGNITUDE: - return this.option_filter_magnitude; - case this.OPTION_FILTER_SMOOTH_ALPHA: - return this.option_filter_smooth_alpha; - case this.OPTION_FILTER_SMOOTH_DELTA: - return this.option_filter_smooth_delta; - case this.OPTION_HOLES_FILL: - return this.option_holes_fill; - case this.OPTION_STEREO_BASELINE: - return this.option_stereo_baseline; - case this.OPTION_AUTO_EXPOSURE_CONVERGE_STEP: - return this.option_auto_exposure_converge_step; - case this.OPTION_INTER_CAM_SYNC_MODE: - return this.option_inter_cam_sync_mode; - case this.OPTION_STREAM_FILTER: - return this.option_stream_filter; - case this.OPTION_STREAM_FORMAT_FILTER: - return this.option_stream_format_filter; - case this.OPTION_STREAM_INDEX_FILTER: - return this.option_stream_index_filter; - case this.OPTION_EMITTER_ON_OFF: - return this.option_emitter_on_off; - case this.OPTION_ZERO_ORDER_POINT_X: - return this.option_zero_order_point_x; - case this.OPTION_ZERO_ORDER_POINT_Y: - return this.option_zero_order_point_y; - case this.OPTION_LLD_TEMPERATURE: - return this.option_lld_temperature; - case this.OPTION_MC_TEMPERATURE: - return this.option_mc_temperature; - case this.OPTION_MA_TEMPERATURE: - return this.option_ma_temperature; - case this.OPTION_HARDWARE_PRESET: - return this.option_hardware_preset; - case this.OPTION_GLOBAL_TIME_ENABLED: - return this.option_global_time_enabled; - case this.OPTION_APD_TEMPERATURE: - return this.option_apd_temperature; - case this.OPTION_ENABLE_MAPPING: - return this.option_enable_mapping; - case this.OPTION_ENABLE_RELOCALIZATION: - return this.option_enable_relocalization; - case this.OPTION_ENABLE_POSE_JUMPING: - return this.option_enable_pose_jumping; - case this.OPTION_ENABLE_DYNAMIC_CALIBRATION: - return this.option_enable_dynamic_calibration; - case this.OPTION_DEPTH_OFFSET: - return this.option_depth_offset; - case this.OPTION_LED_POWER: - return this.option_led_power; - case this.OPTION_ZERO_ORDER_ENABLED: - return this.option_zero_order_enabled; - case this.OPTION_ENABLE_MAP_PRESERVATION: - return this.option_enable_map_preservation; - case this.OPTION_FREEFALL_DETECTION_ENABLED: - return this.option_freefall_detection_enabled; - case this.OPTION_DIGITAL_GAIN: - return this.option_digital_gain; - case this.OPTION_EMITTER_ALWAYS_ON: - return this.option_emitter_always_on; - case this.OPTION_THERMAL_COMPENSATION: - return this.option_thermal_compensation; - case this.OPTION_HUMIDITY_TEMPERATURE: - return this.option_humidity_temperature; - case this.OPTION_ENABLE_MAX_USABLE_RANGE: - return this.option_enable_max_usable_range; - case this.OPTION_ALTERNATE_IR: - return this.option_alternate_ir; - case this.OPTION_NOISE_ESTIMATION: - return this.option_noise_estimation; - case this.ENABLE_IR_REFLECTIVITY: - return this.option_enable_ir_reflectivity; - default: - throw new TypeError( - 'option.optionToString(option) expects a valid value as the 1st argument'); - } - }, -}; - -/** - * Enum for camera info types - * @readonly - * @enum {String} - * @see [Device.supportsCameraInfo()]{@link Device#supportsCameraInfo} - */ -const camera_info = { - /** - * String literal of 'name'.
    Device friendly name.
    Equivalent to its - * uppercase counterpart. - * - */ - camera_info_name: 'name', - /** - * String literal of 'serial-number'.
    Serial number.
    Equivalent to its - * uppercase counterpart. - * - */ - camera_info_serial_number: 'serial-number', - /** - * String literal of 'firmware-version'.
    Primary firmware version. - *
    Equivalent to its uppercase counterpart. - */ - camera_info_firmware_version: 'firmware-version', - /** - * String literal of 'recommended-firmware-version'.
    Latest firmware version - * available.
    Equivalent to its uppercase counterpart. - */ - camera_info_recommended_firmware_version: 'recommended-firmware-version', - /** - * String literal of 'port'.
    Unique identifier of the port the device is - * connected to (platform specific).
    Equivalent to its uppercase counterpart. - * - */ - camera_info_physical_port: 'physical-port', - /** - * String literal of 'debug-op-code'.
    If device supports firmware logging, - * this is the command to send to get logs from firmware.
    Equivalent to its uppercase - * counterpart. - */ - camera_info_debug_op_code: 'debug-op-code', - /** - * String literal of 'advanced-mode'.
    True iff the device is in advanced - * mode.
    Equivalent to its uppercase counterpart. - * - */ - camera_info_advanced_mode: 'advanced-mode', - /** - * String literal of 'product-id'.
    Product ID as reported in the USB - * descriptor.
    Equivalent to its uppercase counterpart. - * - */ - camera_info_product_id: 'product-id', - /** - * String literal of 'camera-locked'.
    True if EEPROM is locked. - *
    Equivalent to its uppercase counterpart. - */ - camera_info_camera_locked: 'camera-locked', - /** - * String literal of 'usb-type-descriptor'.
    Designated USB specification: - * USB2/USB3.
    Equivalent to its uppercase counterpart. - */ - camera_info_usb_type_descriptor: 'usb-type-descriptor', - /** - * Device friendly name.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - CAMERA_INFO_NAME: RS2.RS2_CAMERA_INFO_NAME, - /** - * Device serial number.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - CAMERA_INFO_SERIAL_NUMBER: RS2.RS2_CAMERA_INFO_SERIAL_NUMBER, - /** - * Primary firmware version.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - CAMERA_INFO_FIRMWARE_VERSION: RS2.RS2_CAMERA_INFO_FIRMWARE_VERSION, - /** - * Latest firmware version available.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - CAMERA_INFO_RECOMMENDED_FIRMWARE_VERSION: RS2.RS2_CAMERA_INFO_RECOMMENDED_FIRMWARE_VERSION, - /** - * Unique identifier of the port the device is connected to (platform specific).
    Equivalent to - * its lowercase counterpart. - * @type {Integer} - */ - CAMERA_INFO_PHYSICAL_PORT: RS2.RS2_CAMERA_INFO_PHYSICAL_PORT, - /** - * If device supports firmware logging, this is the command to send to get logs from firmware. - *
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - CAMERA_INFO_DEBUG_OP_CODE: RS2.RS2_CAMERA_INFO_DEBUG_OP_CODE, - /** - * True iff the device is in advanced mode.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - CAMERA_INFO_ADVANCED_MODE: RS2.RS2_CAMERA_INFO_ADVANCED_MODE, - /** - * Product ID as reported in the USB descriptor.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - CAMERA_INFO_PRODUCT_ID: RS2.RS2_CAMERA_INFO_PRODUCT_ID, - /** - * True if EEPROM is locked.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - CAMERA_INFO_CAMERA_LOCKED: RS2.RS2_CAMERA_INFO_CAMERA_LOCKED, - /** - * Designated USB specification: USB2/USB3.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - CAMERA_INFO_USB_TYPE_DESCRIPTOR: RS2.RS2_CAMERA_INFO_USB_TYPE_DESCRIPTOR, - /** - * Number of enumeration values. Not a valid input: intended to be used in for-loops. - * @type {Integer} - */ - CAMERA_INFO_COUNT: RS2.RS2_CAMERA_INFO_COUNT, - - /** - * Get the string representation out of the integer camera_info type - * @param {Integer} info the camera_info type - * @return {String} - */ - cameraInfoToString: function(info) { - const funcName = 'camera_info.cameraInfoToString()'; - checkArgumentLength(1, 1, arguments.length, funcName); - const i = checkArgumentType(arguments, constants.camera_info, 0, funcName); - switch (i) { - case this.CAMERA_INFO_NAME: - return this.camera_info_name; - case this.CAMERA_INFO_SERIAL_NUMBER: - return this.camera_info_serial_number; - case this.CAMERA_INFO_FIRMWARE_VERSION: - return this.camera_info_firmware_version; - case this.CAMERA_INFO_PHYSICAL_PORT: - return this.camera_info_physical_port; - case this.CAMERA_INFO_DEBUG_OP_CODE: - return this.camera_info_debug_op_code; - case this.CAMERA_INFO_ADVANCED_MODE: - return this.camera_info_advanced_mode; - case this.CAMERA_INFO_PRODUCT_ID: - return this.camera_info_product_id; - case this.CAMERA_INFO_CAMERA_LOCKED: - return this.camera_info_camera_locked; - case this.CAMERA_INFO_USB_TYPE_DESCRIPTOR: - return this.camera_info_usb_type_descriptor; - case this.CAMERA_INFO_RECOMMENDED_FIRMWARE_VERSION: - return this.camera_info_recommended_firmware_version; - } - }, -}; - -/** - * Enum for frame metadata types - * @readonly - * @enum {String} - * @see [Frame.supportsFrameMetadata()]{@link Frame#supportsFrameMetadata} - */ -const frame_metadata = { - /** - * String literal of 'frame-counter'.
    A sequential index managed - * per-stream. Integer value
    Equivalent to its uppercase counterpart - */ - frame_metadata_frame_counter: 'frame-counter', - /** - * String literal of 'frame-timestamp'.
    Timestamp set by device - * clock when data readout and transmit commence. usec
    Equivalent to its uppercase - * counterpart - */ - frame_metadata_frame_timestamp: 'frame-timestamp', - /** - * String literal of 'sensor-timestamp'.
    Timestamp of the middle - * of sensor's exposure calculated by device. usec
    Equivalent to its uppercase counterpart - */ - frame_metadata_sensor_timestamp: 'sensor-timestamp', - /** - * String literal of 'actual-exposure'.
    Sensor's exposure width. - * When Auto Exposure (AE) is on the value is controlled by firmware. usec
    Equivalent to - * its uppercase counterpart - */ - frame_metadata_actual_exposure: 'actual-exposure', - /** - * String literal of 'gain-level'.
    A relative value increasing - * which will increase the Sensor's gain factor. When AE is set On, the value is controlled by - * firmware. Integer value
    Equivalent to its uppercase counterpart - */ - frame_metadata_gain_level: 'gain-level', - /** - * String literal of 'auto-exposure'.
    Auto Exposure Mode - * indicator. Zero corresponds to AE switched off.
    Equivalent to its uppercase counterpart - */ - frame_metadata_auto_exposure: 'auto-exposure', - /** - * String literal of 'white-balance'.
    White Balance setting as a - * color temperature. Kelvin degrees
    Equivalent to its uppercase counterpart - */ - frame_metadata_white_balance: 'white-balance', - /** - * String literal of 'time-of-arrival'.
    Time of arrival in - * system clock
    Equivalent to its uppercase counterpart - */ - frame_metadata_time_of_arrival: 'time-of-arrival', - /** - * Temperature of the device, measured at the time of the frame capture. Celsius degrees - *
    Equivalent to its uppercase counterpart - */ - frame_metadata_temperature: 'temperature', - /** - * Timestamp get from uvc driver. usec - *
    Equivalent to its uppercase counterpart - */ - frame_metadata_backend_timestamp: 'backend-timestamp', - /** - * Actual fps - *
    Equivalent to its uppercase counterpart - */ - frame_metadata_actual_fps: 'actual-fps', - /** - * Laser power value 0-360. - *
    Equivalent to its uppercase counterpart - */ - frame_metadata_frame_laser_power: 'frame-laser-power', - /** - * Laser power mode. Zero corresponds to Laser power switched off and one for switched on. - *
    Equivalent to its uppercase counterpart - */ - frame_metadata_frame_laser_power_mode: 'frame-laser-power-mode', - /** - * Exposure priority. - *
    Equivalent to its uppercase counterpart - */ - frame_metadata_exposure_priority: 'exposure-priority', - /** - * Left region of interest for the auto exposure Algorithm. - *
    Equivalent to its uppercase counterpart - */ - frame_metadata_exposure_roi_left: 'exposure-roi-left', - /** - * Right region of interest for the auto exposure Algorithm. - *
    Equivalent to its uppercase counterpart - */ - frame_metadata_exposure_roi_right: 'exposure-roi-right', - /** - * Top region of interest for the auto exposure Algorithm. - *
    Equivalent to its uppercase counterpart - */ - frame_metadata_exposure_roi_top: 'exposure-roi-top', - /** - * Bottom region of interest for the auto exposure Algorithm. - *
    Equivalent to its uppercase counterpart - */ - frame_metadata_exposure_roi_bottom: 'exposure-roi-bottom', - /** - * Color image brightness. - *
    Equivalent to its uppercase counterpart - */ - frame_metadata_brightness: 'brightness', - /** - * Color image contrast. - *
    Equivalent to its uppercase counterpart - */ - frame_metadata_contrast: 'contrast', - /** - * Color image saturation. - *
    Equivalent to its uppercase counterpart - */ - frame_metadata_saturation: 'saturation', - /** - * Color image sharpness. - *
    Equivalent to its uppercase counterpart - */ - frame_metadata_sharpness: 'sharpness', - /** - * Auto white balance temperature Mode indicator. Zero corresponds to automatic mode switched off. - *
    Equivalent to its uppercase counterpart - */ - frame_metadata_auto_white_balance_temperature: 'auto-white-balance-temperature', - /** - * Color backlight compensation. Zero corresponds to switched off. - *
    Equivalent to its uppercase counterpart - */ - frame_metadata_backlight_compensation: 'backlight-compensation', - /** - * Color image hue. - *
    Equivalent to its uppercase counterpart - */ - frame_metadata_hue: 'hue', - /** - * Color image gamma. - *
    Equivalent to its uppercase counterpart - */ - frame_metadata_gamma: 'gamma', - /** - * Color image white balance. - *
    Equivalent to its uppercase counterpart - */ - frame_metadata_manual_white_balance: 'manual-white-balance', - /** - * Power Line Frequency for anti-flickering Off/50Hz/60Hz/Auto. - *
    Equivalent to its uppercase counterpart - */ - frame_metadata_power_line_frequency: 'power-line-frequency', - /** - * Color lowlight compensation. Zero corresponds to switched off. - *
    Equivalent to its uppercase counterpart - */ - frame_metadata_low_light_compensation: 'low-light-compensation', - /** - * A sequential index managed per-stream. Integer value
    Equivalent to its lowercase - * counterpart. - * @type {Integer} - */ - FRAME_METADATA_FRAME_COUNTER: RS2.RS2_FRAME_METADATA_FRAME_COUNTER, - /** - * Timestamp set by device clock when data readout and transmit commence. usec
    Equivalent - * to its lowercase counterpart. - * @type {Integer} - */ - FRAME_METADATA_FRAME_TIMESTAMP: RS2.RS2_FRAME_METADATA_FRAME_TIMESTAMP, - /** - * Timestamp of the middle of sensor's exposure calculated by device. usec
    Equivalent to - * its lowercase counterpart. - * @type {Integer} - */ - FRAME_METADATA_SENSOR_TIMESTAMP: RS2.RS2_FRAME_METADATA_SENSOR_TIMESTAMP, - /** - * Sensor's exposure width. When Auto Exposure (AE) is on the value is controlled by - * firmware. usec
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - FRAME_METADATA_ACTUAL_EXPOSURE: RS2.RS2_FRAME_METADATA_ACTUAL_EXPOSURE, - /** - * A relative value increasing which will increase the Sensor's gain factor. When AE is set - * On, the value is controlled by firmware. Integer value
    Equivalent to its lowercase - * counterpart. - * @type {Integer} - */ - FRAME_METADATA_GAIN_LEVEL: RS2.RS2_FRAME_METADATA_GAIN_LEVEL, - /** - * Auto Exposure Mode indicator. Zero corresponds to AE switched off.
    Equivalent to its - * lowercase counterpart. - * @type {Integer} - */ - FRAME_METADATA_AUTO_EXPOSURE: RS2.RS2_FRAME_METADATA_AUTO_EXPOSURE, - /** - * White Balance setting as a color temperature. Kelvin degrees
    Equivalent to its lowercase - * counterpart. - * @type {Integer} - */ - FRAME_METADATA_WHITE_BALANCE: RS2.RS2_FRAME_METADATA_WHITE_BALANCE, - /** - * Time of arrival in system clock
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - FRAME_METADATA_TIME_OF_ARRIVAL: RS2.RS2_FRAME_METADATA_TIME_OF_ARRIVAL, - /** - * Temperature of the device, measured at the time of the frame capture. Celsius degrees - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - FRAME_METADATA_TEMPERATURE: RS2.RS2_FRAME_METADATA_TEMPERATURE, - /** - * Timestamp get from uvc driver. usec - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - FRAME_METADATA_BACKEND_TIMESTAMP: RS2.RS2_FRAME_METADATA_BACKEND_TIMESTAMP, - /** - * Actual fps - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - FRAME_METADATA_ACTUAL_FPS: RS2.RS2_FRAME_METADATA_ACTUAL_FPS, - /** - * Laser power value 0-360. - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - FRAME_METADATA_FRAME_LASER_POWER: RS2.RS2_FRAME_METADATA_FRAME_LASER_POWER, - /** - * Laser power mode. Zero corresponds to Laser power switched off and one for switched on. - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - FRAME_METADATA_FRAME_LASER_POWER_MODE: RS2.RS2_FRAME_METADATA_FRAME_LASER_POWER_MODE, - /** - * Exposure priority. - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - FRAME_METADATA_EXPOSURE_PRIORITY: RS2.RS2_FRAME_METADATA_EXPOSURE_PRIORITY, - /** - * Left region of interest for the auto exposure Algorithm. - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - FRAME_METADATA_EXPOSURE_ROI_LEFT: RS2.RS2_FRAME_METADATA_EXPOSURE_ROI_LEFT, - /** - * Right region of interest for the auto exposure Algorithm. - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - FRAME_METADATA_EXPOSURE_ROI_RIGHT: RS2.RS2_FRAME_METADATA_EXPOSURE_ROI_RIGHT, - /** - * Top region of interest for the auto exposure Algorithm. - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - FRAME_METADATA_EXPOSURE_ROI_TOP: RS2.RS2_FRAME_METADATA_EXPOSURE_ROI_TOP, - /** - * Bottom region of interest for the auto exposure Algorithm. - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - FRAME_METADATA_EXPOSURE_ROI_BOTTOM: RS2.RS2_FRAME_METADATA_EXPOSURE_ROI_BOTTOM, - /** - * Color image brightness. - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - FRAME_METADATA_BRIGHTNESS: RS2.RS2_FRAME_METADATA_BRIGHTNESS, - /** - * Color image contrast. - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - FRAME_METADATA_CONTRAST: RS2.RS2_FRAME_METADATA_CONTRAST, - /** - * Color image saturation. - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - FRAME_METADATA_SATURATION: RS2.RS2_FRAME_METADATA_SATURATION, - /** - * Color image sharpness. - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - FRAME_METADATA_SHARPNESS: RS2.RS2_FRAME_METADATA_SHARPNESS, - /** - * Auto white balance temperature Mode indicator. Zero corresponds to automatic mode switched off. - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - FRAME_METADATA_AUTO_WHITE_BALANCE_TEMPERATURE: - RS2.RS2_FRAME_METADATA_AUTO_WHITE_BALANCE_TEMPERATURE, - /** - * Color backlight compensation. Zero corresponds to switched off. - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - FRAME_METADATA_BACKLIGHT_COMPENSATION: RS2.RS2_FRAME_METADATA_BACKLIGHT_COMPENSATION, - /** - * Color image hue. - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - FRAME_METADATA_HUE: RS2.RS2_FRAME_METADATA_HUE, - /** - * Color image gamma. - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - FRAME_METADATA_GAMMA: RS2.RS2_FRAME_METADATA_GAMMA, - /** - * Color image white balance. - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - FRAME_METADATA_MANUAL_WHITE_BALANCE: RS2.RS2_FRAME_METADATA_MANUAL_WHITE_BALANCE, - /** - * Power Line Frequency for anti-flickering Off/50Hz/60Hz/Auto. - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - FRAME_METADATA_POWER_LINE_FREQUENCY: RS2.RS2_FRAME_METADATA_POWER_LINE_FREQUENCY, - /** - * Color lowlight compensation. Zero corresponds to switched off. - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - FRAME_METADATA_LOW_LIGHT_COMPENSATION: RS2.RS2_FRAME_METADATA_LOW_LIGHT_COMPENSATION, - /** - * Emitter mode: 0 - all emitters disabled. - * 1- laser enabled. - * 2 - auto laser enabled (opt). - * 3 - LED enabled (opt). - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - RS2_FRAME_METADATA_FRAME_EMITTER_MODE: RS2.RS2_FRAME_METADATA_FRAME_EMITTER_MODE, - /** - * Led power value 0-360. - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - RS2_FRAME_METADATA_FRAME_LED_POWER: RS2.RS2_FRAME_METADATA_FRAME_LED_POWER, - /** - * The number of transmitted payload bytes, not including metadata - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - RS2_FRAME_METADATA_RAW_FRAME_SIZE: RS2.RS2_FRAME_METADATA_RAW_FRAME_SIZE, - /** - * GPIO input data - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - RS2_FRAME_METADATA_GPIO_INPUT_DATA: RS2.RS2_FRAME_METADATA_GPIO_INPUT_DATA, - /** - * Sub-preset name. Used in advanced scenarios, such as HDR - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - RS2_FRAME_METADATA_SEQUENCE_NAME: RS2.RS2_FRAME_METADATA_SEQUENCE_NAME, - /** - * Sub-preset sequence id - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - RS2_FRAME_METADATA_SEQUENCE_ID: RS2.RS2_FRAME_METADATA_SEQUENCE_ID, - /** - * Sub-preset sequence size in bytes - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - RS2_FRAME_METADATA_SEQUENCE_SIZE: RS2.RS2_FRAME_METADATA_SEQUENCE_SIZE, - /** - * Frame trigger type, used in MIPI SKU Metadata - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - RS2_FRAME_METADATA_TRIGGER: RS2.RS2_FRAME_METADATA_TRIGGER, - /** - * Preset id, used in MIPI SKU Metadata - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - RS2_FRAME_METADATA_PRESET: RS2.RS2_FRAME_METADATA_PRESET, - /** - * Frame input width in pixels, used in MIPI SKU Metadata as safety attribute - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - RS2_FRAME_METADATA_INPUT_WIDTH: RS2.RS2_FRAME_METADATA_INPUT_WIDTH, - /** - * Frame input height in pixels, used in MIPI SKU Metadata as safety attribute - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - RS2_FRAME_METADATA_INPUT_HEIGHT: RS2.RS2_FRAME_METADATA_INPUT_HEIGHT, - /** - * Sub-preset information, used in MIPI SKU - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - RS2_FRAME_METADATA_SUB_PRESET_INFO: RS2.RS2_FRAME_METADATA_SUB_PRESET_INFO, - /** - * FW-controlled frame counter to be using in Calibration scenarios. Used with MIPI SKU only - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - RS2_FRAME_METADATA_CALIB_INFO: RS2.RS2_FRAME_METADATA_CALIB_INFO, - /** - * CRC checksum of the Metadata, avalable for MIPI SKU only - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - RS2_FRAME_METADATA_CRC: RS2.RS2_FRAME_METADATA_CRC, - /** - * Number of enumeration values. Not a valid input: intended to be used in for-loops. - * @type {Integer} - */ - FRAME_METADATA_COUNT: RS2.RS2_FRAME_METADATA_COUNT, - - /** - * Get the string representation out of the integer frame metadata type - * @param {Integer} metadata the frame metadata type - * @return {String} - */ - frameMetadataToString: function(metadata) { - const funcName = 'frame_metadata.frameMetadataToString()'; - checkArgumentLength(1, 1, arguments.length, funcName); - const i = checkArgumentType(arguments, constants.frame_metadata, 0, funcName); - switch (i) { - case this.FRAME_METADATA_FRAME_COUNTER: - return this.frame_metadata_frame_counter; - case this.FRAME_METADATA_FRAME_TIMESTAMP: - return this.frame_metadata_frame_timestamp; - case this.FRAME_METADATA_SENSOR_TIMESTAMP: - return this.frame_metadata_sensor_timestamp; - case this.FRAME_METADATA_ACTUAL_EXPOSURE: - return this.frame_metadata_actual_exposure; - case this.FRAME_METADATA_GAIN_LEVEL: - return this.frame_metadata_gain_level; - case this.FRAME_METADATA_AUTO_EXPOSURE: - return this.frame_metadata_auto_exposure; - case this.FRAME_METADATA_WHITE_BALANCE: - return this.frame_metadata_white_balance; - case this.FRAME_METADATA_TIME_OF_ARRIVAL: - return this.frame_metadata_time_of_arrival; - case this.FRAME_METADATA_TEMPERATURE: - return this.frame_metadata_temperature; - case this.FRAME_METADATA_BACKEND_TIMESTAMP: - return this.frame_metadata_backend_timestamp; - case this.FRAME_METADATA_ACTUAL_FPS: - return this.frame_metadata_actual_fps; - case this.FRAME_METADATA_FRAME_LASER_POWER: - return this.frame_metadata_frame_laser_power; - case this.FRAME_METADATA_FRAME_LASER_POWER_MODE: - return this.frame_metadata_frame_laser_power_mode; - case this.FRAME_METADATA_EXPOSURE_PRIORITY: - return this.frame_metadata_exposure_priority; - case this.FRAME_METADATA_EXPOSURE_ROI_LEFT: - return this.frame_metadata_exposure_roi_left; - case this.FRAME_METADATA_EXPOSURE_ROI_RIGHT: - return this.frame_metadata_exposure_roi_right; - case this.FRAME_METADATA_EXPOSURE_ROI_TOP: - return this.frame_metadata_exposure_roi_top; - case this.FRAME_METADATA_EXPOSURE_ROI_BOTTOM: - return this.frame_metadata_exposure_roi_bottom; - case this.FRAME_METADATA_BRIGHTNESS: - return this.frame_metadata_brightness; - case this.FRAME_METADATA_CONTRAST: - return this.frame_metadata_contrast; - case this.FRAME_METADATA_SATURATION: - return this.frame_metadata_saturation; - case this.FRAME_METADATA_SHARPNESS: - return this.frame_metadata_sharpness; - case this.FRAME_METADATA_AUTO_WHITE_BALANCE_TEMPERATURE: - return this.frame_metadata_auto_white_balance_temperature; - case this.FRAME_METADATA_BACKLIGHT_COMPENSATION: - return this.frame_metadata_backlight_compensation; - case this.FRAME_METADATA_HUE: - return this.frame_metadata_hue; - case this.FRAME_METADATA_GAMMA: - return this.frame_metadata_gamma; - case this.FRAME_METADATA_MANUAL_WHITE_BALANCE: - return this.frame_metadata_manual_white_balance; - case this.FRAME_METADATA_POWER_LINE_FREQUENCY: - return this.frame_metadata_power_line_frequency; - case this.FRAME_METADATA_LOW_LIGHT_COMPENSATION: - return this.frame_metadata_low_light_compensation; - } - }, -}; - -/** - * Enum for distortion types - * @readonly - * @enum {String} - */ -const distortion = { - /** - * String literal of 'none'.
    Rectilinear images. No distortion compensation - * required.
    Equivalent to its uppercase counterpart. - */ - distortion_none: 'none', - /** - * String literal of 'modified-brown-conrady'.
    Equivalent to Brown-Conrady - * distortion, except that tangential distortion is applied to radially distorted points - *
    Equivalent to its uppercase counterpart. - */ - distortion_modified_brown_conrady: 'modified-brown-conrady', - /** - * String literal of 'inverse-brown-conrady'.
    Equivalent to Brown-Conrady - * distortion, except undistorts image instead of distorting it - *
    Equivalent to its uppercase counterpart. - */ - distortion_inverse_brown_conrady: 'inverse-brown-conrady', - /** - * String literal of 'ftheta'.
    F-Theta fish-eye distortion model - *
    Equivalent to its uppercase counterpart. - */ - distortion_ftheta: 'ftheta', - /** - * String literal of 'brown-conrady'.
    Unmodified Brown-Conrady distortion - * model
    Equivalent to its uppercase counterpart. - */ - distortion_brown_conrady: 'brown-conrady', - - /** Rectilinear images. No distortion compensation required.
    Equivalent to its lowercase - * counterpart - * @type {Integer} - */ - DISTORTION_NONE: RS2.RS2_DISTORTION_NONE, - /** Equivalent to Brown-Conrady distortion, except that tangential distortion is applied to - * radially distorted points
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - DISTORTION_MODIFIED_BROWN_CONRADY: RS2.RS2_DISTORTION_MODIFIED_BROWN_CONRADY, - /** Equivalent to Brown-Conrady distortion, except undistorts image instead of distorting it - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - DISTORTION_INVERSE_BROWN_CONRADY: RS2.RS2_DISTORTION_INVERSE_BROWN_CONRADY, - /** F-Theta fish-eye distortion model
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - DISTORTION_FTHETA: RS2.RS2_DISTORTION_FTHETA, - /** Unmodified Brown-Conrady distortion model
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - DISTORTION_BROWN_CONRADY: RS2.RS2_DISTORTION_BROWN_CONRADY, - /** - * Number of enumeration values. Not a valid input: intended to be used in for-loops. - * @type {Integer} - */ - DISTORTION_COUNT: RS2.RS2_DISTORTION_COUNT, - - /** - * Get the string representation out of the integer distortion type - * @param {Integer} distortionVal the distortion type - * @return {String} - */ - distortionToString: function(distortionVal) { - const funcName = 'distortion.distortionToString()'; - checkArgumentLength(1, 1, arguments.length, funcName); - const i = checkArgumentType(arguments, constants.distortion, 0, funcName); - switch (i) { - case this.DISTORTION_NONE: - return this.distortion_none; - case this.DISTORTION_MODIFIED_BROWN_CONRADY: - return this.distortion_modified_brown_conrady; - case this.DISTORTION_INVERSE_BROWN_CONRADY: - return this.distortion_inverse_brown_conrady; - case this.DISTORTION_FTHETA: - return this.distortion_ftheta; - case this.DISTORTION_BROWN_CONRADY: - return this.distortion_brown_conrady; - } - }, -}; - -/** - * Enum for notification severity - * @readonly - * @enum {String} - */ -const log_severity = { - /** - * String literal of 'debug'.
    Detailed information about ordinary operations. - *
    Equivalent to its uppercase counterpart. - */ - log_severity_debug: 'debug', - /** - * String literal of 'info'.
    Terse information about ordinary operations. - *
    Equivalent to its uppercase counterpart. - */ - log_severity_info: 'info', - /** - * String literal of 'warn'.
    Indication of possible failure. - *
    Equivalent to its uppercase counterpart. - */ - log_severity_warn: 'warn', - /** - * String literal of 'error'.
    Indication of definite failure. - *
    Equivalent to its uppercase counterpart. - */ - log_severity_error: 'error', - /** - * String literal of 'fatal'.
    Indication of unrecoverable failure. - *
    Equivalent to its uppercase counterpart. - */ - log_severity_fatal: 'fatal', - /** - * String literal of 'none'.
    No logging will occur. - *
    Equivalent to its uppercase counterpart. - */ - log_severity_none: 'none', - - /** - * Detailed information about ordinary operations.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - LOG_SEVERITY_DEBUG: RS2.RS2_LOG_SEVERITY_DEBUG, - /** - * Terse information about ordinary operations.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - LOG_SEVERITY_INFO: RS2.RS2_LOG_SEVERITY_INFO, - /** - * Indication of possible failure.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - LOG_SEVERITY_WARN: RS2.RS2_LOG_SEVERITY_WARN, - /** - * Indication of definite failure.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - LOG_SEVERITY_ERROR: RS2.RS2_LOG_SEVERITY_ERROR, - /** - * Indication of unrecoverable failure.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - LOG_SEVERITY_FATAL: RS2.RS2_LOG_SEVERITY_FATAL, - /** - * No logging will occur.
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - LOG_SEVERITY_NONE: RS2.RS2_LOG_SEVERITY_NONE, - /** - * Number of enumeration values. Not a valid input: intended to be used in for-loops. - * @type {Integer} - */ - LOG_SEVERITY_COUNT: RS2.RS2_LOG_SEVERITY_COUNT, - /** - * Get the string representation out of the integer log_severity type - * @param {Integer} severity the log_severity value - * @return {String} - */ - logSeverityToString: function(severity) { - const funcName = 'log_severity.logSeverityToString()'; - checkArgumentLength(1, 1, arguments.length, funcName); - const i = checkArgumentType(arguments, constants.log_severity, 0, funcName); - switch (i) { - case this.LOG_SEVERITY_DEBUG: - return this.log_severity_debug; - case this.LOG_SEVERITY_INFO: - return this.log_severity_info; - case this.LOG_SEVERITY_WARN: - return this.log_severity_warn; - case this.LOG_SEVERITY_ERROR: - return this.log_severity_error; - case this.LOG_SEVERITY_FATAL: - return this.log_severity_fatal; - case this.LOG_SEVERITY_NONE: - return this.log_severity_none; - } - }, -}; - -/** - * Enum for notification category - * @readonly - * @enum {String} - */ -const notification_category = { - /** - * String literal of 'frames-timeout'.
    Frames didn't arrived within 5 seconds - *
    Equivalent to its uppercase counterpart. - */ - notification_category_frames_timeout: 'frames-timeout', - /** - * String literal of 'frame-corrupted'.
    Received partial/incomplete frame - *
    Equivalent to its uppercase counterpart. - */ - notification_category_frame_corrupted: 'frame-corrupted', - /** - * String literal of 'hardware-error'.
    Error reported from the device - *
    Equivalent to its uppercase counterpart. - */ - notification_category_hardware_error: 'hardware-error', - /** - * String literal of 'hardware-event'.
    General hardware notification reported - * from the sensor
    Equivalent to its uppercase counterpart. - */ - notification_category_hardware_event: 'hardware-event', - /** - * String literal of 'unknown-error'.
    Received unknown error from the device - *
    Equivalent to its uppercase counterpart. - */ - notification_category_unknown_error: 'unknown-error', - /** - * String literal of 'firmware-update-recommended'.
    Current firmware version - * installed is not the latest available.
    Equivalent to its uppercase counterpart. - */ - notification_category_firmware_update_recommended: 'firmware-update-recommended', - /** - * Frames didn't arrived within 5 seconds
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - NOTIFICATION_CATEGORY_FRAMES_TIMEOUT: RS2.RS2_NOTIFICATION_CATEGORY_FRAMES_TIMEOUT, - /** - * Received partial/incomplete frame
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - NOTIFICATION_CATEGORY_FRAME_CORRUPTED: RS2.RS2_NOTIFICATION_CATEGORY_FRAME_CORRUPTED, - /** - * Error reported from the device
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - NOTIFICATION_CATEGORY_HARDWARE_ERROR: RS2.RS2_NOTIFICATION_CATEGORY_HARDWARE_ERROR, - /** - * General hardware notification reported from the sensor
    Equivalent to its lowercase - * counterpart - * @type {Integer} - */ - NOTIFICATION_CATEGORY_HARDWARE_EVENT: RS2.RS2_NOTIFICATION_CATEGORY_HARDWARE_EVENT, - /** - * Received unknown error from the device
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - NOTIFICATION_CATEGORY_UNKNOWN_ERROR: RS2.RS2_NOTIFICATION_CATEGORY_UNKNOWN_ERROR, - /** - * Current firmware version installed is not the latest available
    Equivalent to its lowercase - * counterpart - * @type {Integer} - */ - NOTIFICATION_CATEGORY_FIRMWARE_UPDATE_RECOMMENDED: - RS2.RS2_NOTIFICATION_CATEGORY_FIRMWARE_UPDATE_RECOMMENDED, - /** - * Number of enumeration values. Not a valid input: intended to be used in for-loops. - * @type {Integer} - */ - NOTIFICATION_CATEGORY_COUNT: RS2.RS2_NOTIFICATION_CATEGORY_COUNT, - /** - * Get the string representation out of the integer notification_category type - * @param {Integer} notification the notification_category type - * @return {String} - */ - notificationCategoryToString: function(notification) { - const funcName = 'notification_category.notificationCategoryToString()'; - checkArgumentLength(1, 1, arguments.length, funcName); - const i = checkArgumentType(arguments, constants.notification_category, 0, funcName); - switch (i) { - case this.NOTIFICATION_CATEGORY_FRAMES_TIMEOUT: - return this.notification_category_frames_timeout; - case this.NOTIFICATION_CATEGORY_FRAME_CORRUPTED: - return this.notification_category_frame_corrupted; - case this.NOTIFICATION_CATEGORY_HARDWARE_ERROR: - return this.notification_category_hardware_error; - case this.NOTIFICATION_CATEGORY_HARDWARE_EVENT: - return this.notification_category_hardware_event; - case this.NOTIFICATION_CATEGORY_UNKNOWN_ERROR: - return this.notification_category_unknown_error; - case this.NOTIFICATION_CATEGORY_FIRMWARE_UPDATE_RECOMMENDED: - return this.notification_category_firmware_update_recommended; - } - }, -}; - -/** - * Enum for timestamp domain. - * @readonly - * @enum {String} - */ -const timestamp_domain = { - /** - * String literal of 'hardware-clock'.
    Frame timestamp was measured in - * relation to the camera clock
    Equivalent to its uppercase counterpart. - */ - timestamp_domain_hardware_clock: 'hardware-clock', - /** - * String literal of 'system-time'.
    Frame timestamp was measured in relation - * to the OS system clock
    Equivalent to its uppercase counterpart. - */ - timestamp_domain_system_time: 'system-time', - - /** - * Frame timestamp was measured in relation to the camera clock
    Equivalent to its lowercase - * counterpart. - * @type {Integer} - */ - TIMESTAMP_DOMAIN_HARDWARE_CLOCK: RS2.RS2_TIMESTAMP_DOMAIN_HARDWARE_CLOCK, - /** - * Frame timestamp was measured in relation to the OS system clock
    Equivalent to its - * lowercase counterpart. - * @type {Integer} - */ - TIMESTAMP_DOMAIN_SYSTEM_TIME: RS2.RS2_TIMESTAMP_DOMAIN_SYSTEM_TIME, - /** - * Number of enumeration values. Not a valid input: intended to be used in for-loops. - * @type {Integer} - */ - TIMESTAMP_DOMAIN_COUNT: RS2.RS2_TIMESTAMP_DOMAIN_COUNT, - /** - * Get the string representation out of the integer timestamp_domain type - * @param {Integer} domainVal the timestamp_domain type - * @return {String} - */ - timestampDomainToString: function(domainVal) { - const funcName = 'timestamp_domain.timestampDomainToString()'; - checkArgumentLength(1, 1, arguments.length, funcName); - const i = checkArgumentType(arguments, constants.timestamp_domain, 0, funcName); - switch (i) { - case this.TIMESTAMP_DOMAIN_HARDWARE_CLOCK: - return this.timestamp_domain_hardware_clock; - case this.TIMESTAMP_DOMAIN_SYSTEM_TIME: - return this.timestamp_domain_system_time; - default: - throw new TypeError('timestamp_domain.timestampDomainToString() expects a valid value as the 1st argument'); // eslint-disable-line - } - }, -}; - -/** - * Enum for calibration target type. - * @readonly - * @enum {String} - */ -const calib_target_type = { - /** - * String literal of 'rect-gaussian-dot-vertices'. - *
    Target with rectangle vertices as - * the centers of gaussuian dots
    Equivalent to its uppercase counterpart. - */ - calib_target_rect_gaussian_dot_vertices: 'rect-gaussian-dot-vertices', - calib_target_roi_rect_gaussian_dot_vertices: 'roi-rect-gaussian-dot-vertices', - calib_target_pos_gaussian_dot_vertices: 'pos-gaussian-dot-vertices', - - /** - * Frame timestamp was measured in relation to the camera clock
    Equivalent to its lowercase - * counterpart. - * @type {Integer} - */ - CALIB_TARGET_RECT_GAUSSIAN_DOT_VERTICES: // linesplit due to ESLint 80-char max-len - RS2.RS2_CALIB_TARGET_RECT_GAUSSIAN_DOT_VERTICES, - CALIB_TARGET_ROI_RECT_GAUSSIAN_DOT_VERTICES: - RS2.RS2_CALIB_TARGET_ROI_RECT_GAUSSIAN_DOT_VERTICES, - CALIB_TARGET_POS_GAUSSIAN_DOT_VERTICES: - RS2.RS2_CALIB_TARGET_POS_GAUSSIAN_DOT_VERTICES, - /** - * Number of enumeration values. Not a valid input: intended to be used in for-loops. - * @type {Integer} - */ - CALIB_TARGET_COUNT: RS2.RS2_CALIB_TARGET_COUNT, - - calibTargetTypeToString: function(domainVal) { - const funcName = 'calib_target_type.calibTargetTypeToString()'; - checkArgumentLength(1, 1, arguments.length, funcName); - const i = checkArgumentType(arguments, constants.calib_target_type, 0, funcName); - switch (i) { - case this.CALIB_TARGET_RECT_GAUSSIAN_DOT_VERTICES: - return this.calib_target_rect_gaussian_dot_vertices; - case this.CALIB_TARGET_ROI_RECT_GAUSSIAN_DOT_VERTICES: - return this.calib_target_roi_rect_gaussian_dot_vertices; - case this.CALIB_TARGET_POS_GAUSSIAN_DOT_VERTICES: - return this.calib_target_pos_gaussian_dot_vertices; - default: - throw new TypeError('calib_target_type.calibTargetTypeToString() expects a valid value as the 1st argument'); // eslint-disable-line - } - }, -}; - -/** - * Enum for visual preset of SR300 devices: provides optimized settings (presets) for specific - * types of usage. - * @readonly - * @enum {String} - */ -const sr300_visual_preset = { - /** - * String literal of 'short-range'.
    Preset for short range. - *
    Equivalent to its uppercase counterpart - */ - sr300_visual_preset_short_range: 'short-range', - /** - * String literal of 'long-range'.
    Preset for long range. - *
    Equivalent to its uppercase counterpart - */ - sr300_visual_preset_long_range: 'long-range', - /** - * String literal of 'background-segmentation'.
    Preset for background - * segmentation. - *
    Equivalent to its uppercase counterpart - */ - sr300_visual_preset_background_segmentation: 'background-segmentation', - /** - * String literal of 'gesture-recognition'.
    Preset for gesture recognition. - *
    Equivalent to its uppercase counterpart - */ - sr300_visual_preset_gesture_recognition: 'gesture-recognition', - /** - * String literal of 'object-scanning'.
    Preset for object scanning. - *
    Equivalent to its uppercase counterpart - */ - sr300_visual_preset_object_scanning: 'object-scanning', - /** - * String literal of 'face-analytics'.
    Preset for face analytics. - *
    Equivalent to its uppercase counterpart - */ - sr300_visual_preset_face_analytics: 'face-analytics', - /** - * String literal of 'face-login'.
    Preset for face login. - *
    Equivalent to its uppercase counterpart - */ - sr300_visual_preset_face_login: 'face-login', - /** - * String literal of 'gr-cursor'.
    Preset for GR cursor. - *
    Equivalent to its uppercase counterpart - */ - sr300_visual_preset_gr_cursor: 'gr-cursor', - /** - * String literal of 'default'.
    Preset for default. - *
    Equivalent to its uppercase counterpart - */ - sr300_visual_preset_default: 'default', - /** - * String literal of 'mid-range'.
    Preset for mid-range. - *
    Equivalent to its uppercase counterpart - */ - sr300_visual_preset_mid_range: 'mid-range', - /** - * String literal of 'ir-only'.
    Preset for IR only. - *
    Equivalent to its uppercase counterpart - */ - sr300_visual_preset_ir_only: 'ir-only', - - /** - * Preset for short range - *
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - SR300_VISUAL_PRESET_SHORT_RANGE: RS2.RS2_SR300_VISUAL_PRESET_SHORT_RANGE, - /** - * Preset for long range - *
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - SR300_VISUAL_PRESET_LONG_RANGE: RS2.RS2_SR300_VISUAL_PRESET_LONG_RANGE, - /** - * Preset for background segmentation - *
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - SR300_VISUAL_PRESET_BACKGROUND_SEGMENTATION: RS2.RS2_SR300_VISUAL_PRESET_BACKGROUND_SEGMENTATION, - /** - * Preset for gesture recognition - *
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - SR300_VISUAL_PRESET_GESTURE_RECOGNITION: RS2.RS2_SR300_VISUAL_PRESET_GESTURE_RECOGNITION, - /** - * Preset for object scanning - *
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - SR300_VISUAL_PRESET_OBJECT_SCANNING: RS2.RS2_SR300_VISUAL_PRESET_OBJECT_SCANNING, - /** - * Preset for face analytics - *
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - SR300_VISUAL_PRESET_FACE_ANALYTICS: RS2.RS2_SR300_VISUAL_PRESET_FACE_ANALYTICS, - /** - * Preset for face login - *
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - SR300_VISUAL_PRESET_FACE_LOGIN: RS2.RS2_SR300_VISUAL_PRESET_FACE_LOGIN, - /** - * Preset for GR cursor - *
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - SR300_VISUAL_PRESET_GR_CURSOR: RS2.RS2_SR300_VISUAL_PRESET_GR_CURSOR, - /** - * Preset for default - *
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - SR300_VISUAL_PRESET_DEFAULT: RS2.RS2_SR300_VISUAL_PRESET_DEFAULT, - /** - * Preset for mid-range - *
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - SR300_VISUAL_PRESET_MID_RANGE: RS2.RS2_SR300_VISUAL_PRESET_MID_RANGE, - /** - * Preset for IR only - *
    Equivalent to its lowercase counterpart. - * @type {Integer} - */ - SR300_VISUAL_PRESET_IR_ONLY: RS2.RS2_SR300_VISUAL_PRESET_IR_ONLY, - /** - * Number of enumeration values. Not a valid input: intended to be used in for-loops. - * @type {Integer} - */ - SR300_VISUAL_PRESET_COUNT: RS2.RS2_SR300_VISUAL_PRESET_COUNT, - /** - * Get the string representation out of the integer sr300_visual_preset type - * @param {Integer} preset the sr300_visual_preset type - * @return {String} - */ - sr300VisualPresetToString: function(preset) { - const funcName = 'sr300_visual_preset.sr300VisualPresetToString()'; - checkArgumentLength(1, 1, arguments.length, funcName); - const i = checkArgumentType(arguments, constants.sr300_visual_preset, 0, funcName); - switch (i) { - case this.SR300_VISUAL_PRESET_SHORT_RANGE: - return this.sr300_visual_preset_short_range; - case this.SR300_VISUAL_PRESET_LONG_RANGE: - return this.sr300_visual_preset_long_range; - case this.SR300_VISUAL_PRESET_BACKGROUND_SEGMENTATION: - return this.sr300_visual_preset_background_segmentation; - case this.SR300_VISUAL_PRESET_GESTURE_RECOGNITION: - return this.sr300_visual_preset_gesture_recognition; - case this.SR300_VISUAL_PRESET_OBJECT_SCANNING: - return this.sr300_visual_preset_object_scanning; - case this.SR300_VISUAL_PRESET_FACE_ANALYTICS: - return this.sr300_visual_preset_face_analytics; - case this.SR300_VISUAL_PRESET_FACE_LOGIN: - return this.sr300_visual_preset_face_login; - case this.SR300_VISUAL_PRESET_GR_CURSOR: - return this.sr300_visual_preset_gr_cursor; - case this.SR300_VISUAL_PRESET_DEFAULT: - return this.sr300_visual_preset_default; - case this.SR300_VISUAL_PRESET_MID_RANGE: - return this.sr300_visual_preset_mid_range; - case this.SR300_VISUAL_PRESET_IR_ONLY: - return this.sr300_visual_preset_ir_only; - } - }, -}; - -/** - * Enum for visual preset of RS400 devices: provides optimized settings (presets) for specific - * types of usage. - * @readonly - * @enum {String} - */ -const rs400_visual_preset = { - /** - * String literal of 'custom'.
    Preset for custom. - *
    Equivalent to its uppercase counterpart - */ - rs400_visual_preset_custom: 'custom', - /** - * String literal of 'default'.
    Preset for default. - *
    Equivalent to its uppercase counterpart - */ - rs400_visual_preset_default: 'default', - /** - * String literal of 'hand'.
    Preset for hand. - *
    Equivalent to its uppercase counterpart - */ - rs400_visual_preset_hand: 'hand', - /** - * String literal of 'high-accuracy'.
    Preset for high-accuracy. - *
    Equivalent to its uppercase counterpart - */ - rs400_visual_preset_high_accuracy: 'high-accuracy', - /** - * String literal of 'high-density'.
    Preset for high-density. - *
    Equivalent to its uppercase counterpart - */ - rs400_visual_preset_high_density: 'high-density', - /** - * String literal of 'medium-density'.
    Preset for medium-density. - *
    Equivalent to its uppercase counterpart - */ - rs400_visual_preset_medium_density: 'medium-density', - /** - * String literal of 'remove-ir-pattern'.
    Preset for remove-ir-pattern. - *
    Equivalent to its uppercase counterpart - */ - rs400_visual_preset_remove_ir_pattern: 'remove-ir-pattern', - /** - * Preset for custom - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - RS400_VISUAL_PRESET_CUSTOM: RS2.RS2_RS400_VISUAL_PRESET_CUSTOM, - /** - * Preset for default - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - RS400_VISUAL_PRESET_DEFAULT: RS2.RS2_RS400_VISUAL_PRESET_DEFAULT, - /** - * Preset for hand - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - RS400_VISUAL_PRESET_HAND: RS2.RS2_RS400_VISUAL_PRESET_HAND, - /** - * Preset for high_accuracy - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - RS400_VISUAL_PRESET_HIGH_ACCURACY: RS2.RS2_RS400_VISUAL_PRESET_HIGH_ACCURACY, - /** - * Preset for high-density - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - RS400_VISUAL_PRESET_HIGH_DENSITY: RS2.RS2_RS400_VISUAL_PRESET_HIGH_DENSITY, - /** - * Preset for medium-density - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - RS400_VISUAL_PRESET_MEDIUM_DENSITY: RS2.RS2_RS400_VISUAL_PRESET_MEDIUM_DENSITY, - /** - * Preset for remove-ir-pattern - *
    Equivalent to its lowercase counterpart - * @type {Integer} - */ - RS400_VISUAL_PRESET_REMOVE_IR_PATTERN: RS2.RS2_RS400_VISUAL_PRESET_REMOVE_IR_PATTERN, - /** - * Number of enumeration values. Not a valid input: intended to be used in for-loops. - * @type {Integer} - */ - RS400_VISUAL_PRESET_COUNT: RS2.RS2_RS400_VISUAL_PRESET_COUNT, - /** - * Get the string representation out of the integer rs400_visual_preset type - * @param {Integer} preset the rs400_visual_preset type - * @return {String} - */ - rs400VisualPresetToString: function(preset) { - const funcName = 'rs400_visual_preset.rs400VisualPresetToString()'; - checkArgumentLength(1, 1, arguments.length, funcName); - const i = checkArgumentType(arguments, constants.rs400_visual_preset, 0, funcName); - switch (i) { - case this.RS400_VISUAL_PRESET_CUSTOM: - return this.rs400_visual_preset_custom; - case this.RS400_VISUAL_PRESET_DEFAULT: - return this.rs400_visual_preset_default; - case this.RS400_VISUAL_PRESET_HAND: - return this.rs400_visual_preset_hand; - case this.RS400_VISUAL_PRESET_HIGH_ACCURACY: - return this.rs400_visual_preset_high_accuracy; - case this.RS400_VISUAL_PRESET_HIGH_DENSITY: - return this.rs400_visual_preset_high_density; - case this.RS400_VISUAL_PRESET_MEDIUM_DENSITY: - return this.rs400_visual_preset_medium_density; - case this.RS400_VISUAL_PRESET_REMOVE_IR_PATTERN: - return this.rs400_visual_preset_remove_ir_pattern; - } - }, -}; - -const playback_status = { - /** - * String literal of 'unknown'.
    Unknown state - *
    Equivalent to its uppercase counterpart - */ - playback_status_unknown: 'unknown', - /** - * String literal of 'playing'.
    One or more sensors were - * started, playback is reading and raising data - *
    Equivalent to its uppercase counterpart - */ - playback_status_playing: 'playing', - /** - * String literal of 'paused'.
    One or more sensors were - * started, but playback paused reading and paused raising data - *
    Equivalent to its uppercase counterpart - */ - playback_status_paused: 'paused', - /** - * String literal of 'stopped'.
    All sensors were stopped, or playback has - * ended (all data was read). This is the initial playback status - *
    Equivalent to its uppercase counterpart - */ - playback_status_stopped: 'stopped', - /** - * Unknown state - */ - PLAYBACK_STATUS_UNKNOWN: RS2.RS2_PLAYBACK_STATUS_UNKNOWN, - /** - * One or more sensors were started, playback is reading and raising data - */ - PLAYBACK_STATUS_PLAYING: RS2.RS2_PLAYBACK_STATUS_PLAYING, - /** - * One or more sensors were started, but playback paused reading and paused raising dat - */ - PLAYBACK_STATUS_PAUSED: RS2.RS2_PLAYBACK_STATUS_PAUSED, - /** - * All sensors were stopped, or playback has ended (all data was read). This is the initial - * playback statu - */ - PLAYBACK_STATUS_STOPPED: RS2.RS2_PLAYBACK_STATUS_STOPPED, - /** - * Number of enumeration values. Not a valid input: intended to be used in for-loops. - * @type {Integer} - */ - PLAYBACK_STATUS_COUNT: RS2.RS2_PLAYBACK_STATUS_COUNT, - /** - * Get the string representation out of the integer playback_status type - * @param {Integer} status the playback_status type - * @return {String} - */ - playbackStatusToString: function(status) { - const funcName = 'playback_status.playbackStatusToString()'; - checkArgumentLength(1, 1, arguments.length, funcName); - const i = checkArgumentType(arguments, constants.playback_status, 0, funcName); - switch (i) { - case this.PLAYBACK_STATUS_UNKNOWN: - return this.playback_status_unknown; - case this.PLAYBACK_STATUS_PLAYING: - return this.playback_status_playing; - case this.PLAYBACK_STATUS_PAUSED: - return this.playback_status_paused; - case this.PLAYBACK_STATUS_STOPPED: - return this.playback_status_stopped; - default: - throw new TypeError('playback_status.playbackStatusToString() expects a valid value as the 1st argument'); // eslint-disable-line - } - }, -}; - -// e.g. str2Int('enable_motion_correction', 'option') -function str2Int(str, category) { - const name = 'RS2_' + category.toUpperCase() + '_' + str.toUpperCase().replace(/-/g, '_'); - return RS2[name]; -} - -function stream2Int(str) { - return str2Int(str, 'stream'); -} -function format2Int(str) { - return str2Int(str, 'format'); -} -function option2Int(str) { - return str2Int(str, 'option'); -} -function cameraInfo2Int(str) { - return str2Int(str, 'camera_info'); -} -function recordingMode2Int(str) { - return str2Int(str, 'recording_mode'); -} -function timestampDomain2Int(str) { - return str2Int(str, 'timestamp_domain'); -} -function notificationCategory2Int(str) { - return str2Int(str, 'notification_category'); -} -function logSeverity2Int(str) { - return str2Int(str, 'log_severity'); -} -function distortion2Int(str) { - return str2Int(str, 'distortion'); -} -function frameMetadata2Int(str) { - return str2Int(str, 'frame_metadata'); -} -function sr300VisualPreset2Int(str) { - return str2Int(str, 'sr300_visual_preset'); -} -function rs400VisualPreset2Int(str) { - return str2Int(str, 'rs400_visual_preset'); -} -function playbackStatus2Int(str) { - return str2Int(str, 'playback_status'); -} -function isArrayBuffer(value) { - return value && (value instanceof ArrayBuffer) && (value.byteLength !== undefined); -} - -const constants = { - stream: stream, - format: format, - option: option, - camera_info: camera_info, - recording_mode: recording_mode, - timestamp_domain: timestamp_domain, - notification_category: notification_category, - log_severity: log_severity, - distortion: distortion, - frame_metadata: frame_metadata, - sr300_visual_preset: sr300_visual_preset, - rs400_visual_preset: rs400_visual_preset, - playback_status: playback_status, -}; - -/** - * Cleanup resources - */ -function cleanup() { - internal.cleanup(); - RS2.globalCleanup(); -} - -/** - * Error Information returned from native SDK - * @typedef {Object} ErrorInfoObject - * @property {Boolean} recoverable - True if the error is a recoverable error - * @property {String} description - Detailed description of the error - * @property {String} nativeFunction - Native function that triggered the error - * @see [getError()]{@link getError} - */ - -/** - * Get the error info - * User could call this method to get the detailed error info if the previous - * API failed. - * @return {ErrorInfoObject|undefined} If there is no error, undefined is returned - */ -function getError() { - return RS2.getError(); -} - -module.exports = { - cleanup: cleanup, - getError: getError, - UnrecoverableError: UnrecoverableError, - - Context: Context, - Pipeline: Pipeline, - PipelineProfile: PipelineProfile, - Config: Config, - Colorizer: Colorizer, - Device: Device, - Tm2: Tm2, - DeviceList: DeviceList, - DeviceHub: DeviceHub, - Sensor: Sensor, - DepthSensor: DepthSensor, - ROISensor: ROISensor, - ColorSensor: ColorSensor, - MotionSensor: MotionSensor, - FisheyeSensor: FisheyeSensor, - StreamProfile: StreamProfile, - VideoStreamProfile: VideoStreamProfile, - MotionStreamProfile: MotionStreamProfile, - Frame: Frame, - FrameSet: FrameSet, - VideoFrame: VideoFrame, - DepthFrame: DepthFrame, - DisparityFrame: DisparityFrame, - MotionFrame: MotionFrame, - PoseFrame: PoseFrame, - Align: Align, - PointCloud: PointCloud, - Points: Points, - Syncer: Syncer, - RecorderDevice: RecorderDevice, - PlaybackDevice: PlaybackDevice, - DecimationFilter: DecimationFilter, - TemporalFilter: TemporalFilter, - SpatialFilter: SpatialFilter, - HoleFillingFilter: HoleFillingFilter, - DisparityToDepthTransform: DisparityToDepthTransform, - DepthToDisparityTransform: DepthToDisparityTransform, - - - stream: stream, - format: format, - option: option, - camera_info: camera_info, - recording_mode: recording_mode, - timestamp_domain: timestamp_domain, - notification_category: notification_category, - log_severity: log_severity, - distortion: distortion, - frame_metadata: frame_metadata, - sr300_visual_preset: sr300_visual_preset, - rs400_visual_preset: rs400_visual_preset, - playback_status: playback_status, - - util: util, - internal: internal, - - stringConstantToIntegerValue: str2Int, -}; - -internal.registerErrorCallback(); diff --git a/wrappers/nodejs/package-lock.json b/wrappers/nodejs/package-lock.json deleted file mode 100644 index fa4b8c4a8d..0000000000 --- a/wrappers/nodejs/package-lock.json +++ /dev/null @@ -1,228 +0,0 @@ -{ - "name": "node-librealsense", - "version": "0.2130.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@babel/parser": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", - "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "bindings": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.2.1.tgz", - "integrity": "sha1-FK1hE4EtLTfXLme0ystLtyZQXxE=" - }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "catharsis": { - "version": "0.8.11", - "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.11.tgz", - "integrity": "sha512-a+xUyMV7hD1BrDQA/3iPV7oc+6W26BgVJO05PGEoatMyIuPScQKsde6i3YorWX1qs+AZjnJ18NqdKoCtKiNh1g==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } - }, - "entities": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", - "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", - "dev": true - }, - "escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true - }, - "fs-compare": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/fs-compare/-/fs-compare-0.0.4.tgz", - "integrity": "sha1-FwdvkbhjxqDVOSIOc8DYjEZSPno=" - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" - }, - "js2xmlparser": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.1.tgz", - "integrity": "sha512-KrPTolcw6RocpYjdC7pL7v62e55q7qOMHvLX1UCLc5AAS8qeJ6nukarEJAF2KL2PZxlbGueEbINqZR2bDe/gUw==", - "dev": true, - "requires": { - "xmlcreate": "^2.0.3" - } - }, - "jsdoc": { - "version": "3.6.6", - "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.6.tgz", - "integrity": "sha512-znR99e1BHeyEkSvgDDpX0sTiTu+8aQyDl9DawrkOGZTTW8hv0deIFXx87114zJ7gRaDZKVQD/4tr1ifmJp9xhQ==", - "dev": true, - "requires": { - "@babel/parser": "^7.9.4", - "bluebird": "^3.7.2", - "catharsis": "^0.8.11", - "escape-string-regexp": "^2.0.0", - "js2xmlparser": "^4.0.1", - "klaw": "^3.0.0", - "markdown-it": "^10.0.0", - "markdown-it-anchor": "^5.2.7", - "marked": "^0.8.2", - "mkdirp": "^1.0.4", - "requizzle": "^0.2.3", - "strip-json-comments": "^3.1.0", - "taffydb": "2.6.2", - "underscore": "~1.10.2" - }, - "dependencies": { - "marked": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.8.2.tgz", - "integrity": "sha512-EGwzEeCcLniFX51DhTpmTom+dSA/MG/OBUDjnWtHbEnjAH180VzUeAw+oE4+Zv+CoYBWyRlYOTR0N8SO9R1PVw==", - "dev": true - } - } - }, - "jsonfile": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz", - "integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=", - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "klaw": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", - "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.9" - } - }, - "linkify-it": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", - "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", - "dev": true, - "requires": { - "uc.micro": "^1.0.1" - } - }, - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", - "dev": true - }, - "markdown-it": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", - "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "entities": "~2.0.0", - "linkify-it": "^2.0.0", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - } - }, - "markdown-it-anchor": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.3.0.tgz", - "integrity": "sha512-/V1MnLL/rgJ3jkMWo84UR+K+jF1cxNG1a+KwqeXqTIJ+jtA8aWSHuigx8lTzauiIjBDbwF3NcWQMotd0Dm39jA==", - "dev": true - }, - "marked": { - "version": "0.3.12", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.12.tgz", - "integrity": "sha512-k4NaW+vS7ytQn6MgJn3fYpQt20/mOgYM5Ft9BYMfQJDz2QT6yEeS9XJ8k2Nw8JTeWK/znPPW2n3UJGzyYEiMoA==", - "dev": true - }, - "mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - }, - "nan": { - "version": "2.14.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", - "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==" - }, - "pngjs": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.3.0.tgz", - "integrity": "sha1-H1cwwYnJSTO4G+2iqy+OKFUmOo8=" - }, - "requizzle": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", - "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "taffydb": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", - "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", - "dev": true - }, - "uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true - }, - "underscore": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz", - "integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg==", - "dev": true - }, - "xmlcreate": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.3.tgz", - "integrity": "sha512-HgS+X6zAztGa9zIK3Y3LXuJes33Lz9x+YyTxgrkIdabu2vqcGOWwdfCpf1hWLRrd553wd4QCDf6BBO6FfdsRiQ==", - "dev": true - } - } -} diff --git a/wrappers/nodejs/package.json b/wrappers/nodejs/package.json deleted file mode 100644 index eb1f00343a..0000000000 --- a/wrappers/nodejs/package.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "node-librealsense", - "version": "0.2130.0", - "description": "Node.js API for Intel® RealSense™ SDK 2.0", - "main": "index.js", - "directories": { - "test": "test" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/IntelRealSense/librealsense.git" - }, - "keywords": [ - "realsense", - "camera", - "depth camera" - ], - "scripts": { - "test": "mocha", - "doc": "node scripts/generate-doc.js", - "install": "node-gyp rebuild", - "postinstall": "node scripts/generate-doc.js" - }, - "author": "Kenny Yuan ", - "license": "Apache-2.0", - "dependencies": { - "bindings": "^1.2.1", - "fs-compare": "0.0.4", - "jsonfile": "^3.0.1", - "nan": "^2.14.1", - "pngjs": "^3.3.0" - }, - "devDependencies": { - "marked": "~0.3.9", - "jsdoc": "^3.6.6" - } -} diff --git a/wrappers/nodejs/scripts/generate-dist-package.js b/wrappers/nodejs/scripts/generate-dist-package.js deleted file mode 100644 index 65fd37007a..0000000000 --- a/wrappers/nodejs/scripts/generate-dist-package.js +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -// Purpose: pack librealsense dir & wrappers/nodejs dir into npm package - -const {exec} = require('child_process'); -const jf = require('jsonfile'); - -function genDistPackage() { - genPackageJson().then(() => { - callDistScript(); - }); -} - -function genPackageJson() { - return new Promise((resolve, reject) => { - exec('cp -f ./package.json scripts/npm_dist/package.json', (error, stdout, stderr) => { - if (error) { - console.log('fail to generate package.json, error:', error); - reject(error); - } - - let distPackage = require('../scripts/npm_dist/package.json'); - // Add a new key 'preinstall' - distPackage.scripts.preinstall = 'node scripts/npm_dist/build-librealsense.js'; - jf.writeFileSync('./scripts/npm_dist/package.json', distPackage, {spaces: 2}); - resolve(); - }); - }); -} - -function callDistScript() { - exec('./scripts/npm_dist/gen-dist.sh ', (error, stdout, stderr) => { - if (error) { - console.log('fail to generate dist package, error:', error); - throw error; - } - - if (stdout) { - process.stdout.write(stdout); - } - - if (stderr) { - process.stderr.write(stderr); - } - }); -} - -genDistPackage(); diff --git a/wrappers/nodejs/scripts/generate-doc.js b/wrappers/nodejs/scripts/generate-doc.js deleted file mode 100644 index 6dc48c26e7..0000000000 --- a/wrappers/nodejs/scripts/generate-doc.js +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -const {exec} = require('child_process'); -const {chdir} = require('process'); -const fsCompare = require('fs-compare'); - -chdir('doc'); - -fsCompare.ctime('../index.js', './index.html', function(err, diff) { - if (err) { - console.log(err); - throw err; - } else { - if (diff == 1) { - console.log('Doc: rebuild'); - genDoc(); - } else { - console.log('Doc: already up to date'); - } - } -}); - -function genDoc() { - exec('jsdoc ../index.js -t ./jsdoc-template -d .', (error, stdout, stderr) => { - if (error) { - throw error; - } - - if (stdout) process.stdout.write(stdout); - if (stderr) process.stderr.write(stderr); - }); -} diff --git a/wrappers/nodejs/scripts/npm_dist/.gitignore b/wrappers/nodejs/scripts/npm_dist/.gitignore deleted file mode 100644 index ec6d3cdd7f..0000000000 --- a/wrappers/nodejs/scripts/npm_dist/.gitignore +++ /dev/null @@ -1 +0,0 @@ -package.json diff --git a/wrappers/nodejs/scripts/npm_dist/README.md b/wrappers/nodejs/scripts/npm_dist/README.md deleted file mode 100644 index d8dfb6b866..0000000000 --- a/wrappers/nodejs/scripts/npm_dist/README.md +++ /dev/null @@ -1,107 +0,0 @@ -# Node.js API for Intel® RealSense™ Depth Cameras - -This module works with Intel® RealSense™ D400 series camera (and SR300 camera). It's part of the Intel® [librealsense](https://github.com/IntelRealSense/librealsense) open source project. - -# Sample Usage # - -``` -const rs2 = require('node-librealsense'); - -const colorizer = new rs2.Colorizer(); // This will make depth image pretty -const pipeline = new rs2.Pipeline(); // Main work pipeline of RealSense camera -pipeline.start(); // Start camera - -const frameset = pipeline.waitForFrames(); // Get a set of frames -const depth = frameset.depthFrame; // Get depth data -const depthRGB = colorizer.colorize(depth); // Make depth image pretty -const color = frameset.colorFrame; // Get RGB image - -// TODO: use frame buffer data -depthRGB.getData(); -color.getData(); - -// Before exiting, do cleanup. -rs2.cleanup(); -``` - -More examples can be found in [examples directory](https://github.com/IntelRealSense/librealsense/tree/development/wrappers/nodejs/examples) of the module. - -## 1. Install Prerequisites ## - -### Setup Windows 10 Build Environment ### - - 1. Install Python 2.7.xx, make sure "`Add python.exe to Path`" is checked during the installation. - - 1. Install Visual Studio 2015 or 2017. The `Visual Studio 2017 Community` version also works. - After installation, make sure `msbuild.exe` is in PATH, e.g "`C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin`" - - 1. Install CMake, make sure `CMake` is in system PATH (Choose "`Add CMake to the system PATH for all users`" or "`Add CMake to the system PATH for the current user`" during the installation). - -Note: The npm module `windows-build-tools` is not suffcient to build the native C++ librealsense. - -### Setup Ubuntu Linux 16.04 Build Environment ### - -``` -sudo apt install -y libusb-1.0-0-dev pkg-config libgtk-3-dev libglfw3-dev cmake -``` - -Please refer to [Linux installation doc](https://github.com/IntelRealSense/librealsense/blob/development/doc/installation.md) or [Windows installation doc](https://github.com/IntelRealSense/librealsense/blob/development/doc/installation_windows.md) for full document of C++ librealsense build environment setup. - -### Setup Mac OS Build Environment ### - -**Note:** OSX support for the full range of functionality offered by the SDK is not yet complete. - - 1. Install XCode 6.0+ via the AppStore. - - 2. Install the Homebrew package manager via terminal - [link](http://brew.sh/) - - 3. Install the following packages via brew: - * `brew install libusb pkg-config` - * `brew install homebrew/versions/glfw3` - * `brew install cmake` - -### Setup Necessary Global NPM Packages ### - -``` -npm install -g jsdoc -``` - -## 2. Instal node-librealsense Module ## - -``` -npm install --save node-librealsense -``` -It will take a while to build C++ librealsense library, and then the Node.js addon will be built. If both of them succeed, the node-librealsense module is ready to use. - -## 3. Run Examples ## - -When it's installed, you can run examples to see if it works fine. Plug in your Intel® RealSense™ camera and do the following: - -``` -cd node-librealsense/examples -npm install -node nodejs-capture.js -``` -### List of Examples ## - -1. `nodejs-align.js`: capture and then align RGB image frames to depth image frames, using depth info to remove background by a distance threshold. -1. `nodejs-capture.js`: display RGB image frames and colorized depth image frames that are captured in real time -1. `nodejs-save-to-disk.js`: capture a RGB image frame and a depth image frame, then save both of them to disk file (*.png) -1. `nodejs-pointcloud.js`: capture RGB image frames and depth image frames, and then use them to generate and visualize textured 3D pointcloud - -## 4. API Reference Document ## -Open `node-librealsense/doc/index.html` for full reference document. If it isn't there, run the following commands to generate it: - -``` -cd node-librealsense/ -npm run doc -``` - -## 5. Compatibility ## - -List of supported platforms - - Windows 10 + Node.js x64 & ia32 - supported - - Windows 8.1 + Node.js x64 & ia32 - theoretically supported. Not verified yet. - - Ubuntu 16.04 + Node.js x64 & ia32 - supported - - Node.js v8 - supported - - Node.js v6 LTS - You might need to [upgrade npm-bundled `node-gyp`](https://github.com/nodejs/node-gyp/wiki/Updating-npm%27s-bundled-node-gyp) to support Visual Studio 2017 (if you're using it) diff --git a/wrappers/nodejs/scripts/npm_dist/binding.gyp b/wrappers/nodejs/scripts/npm_dist/binding.gyp deleted file mode 100644 index 1f389bd185..0000000000 --- a/wrappers/nodejs/scripts/npm_dist/binding.gyp +++ /dev/null @@ -1,105 +0,0 @@ -{ - 'variables': { - }, - "targets": [ - { - "target_name": "node_librealsense", - "variables": { - }, - "sources": [ - "./src/addon.cpp", - ], - "include_dirs": [ - "./librealsense/include", - " /dev/null -pwd - -cd librealsense -mkdir -p build -cd build - -# Step 1 -cmake .. -DBUILD_EXAMPLES=false -DBUILD_UNIT_TESTS=false -DBUILD_WITH_OPENMP=false -DHWM_OVER_XU=false -G Xcode -if [ "$?" -gt 0 ] -then - echo 'Failed to configure librealsense' - exit 1 -fi - -#step 2 -xcodebuild -configuration Release -if [ "$?" -gt 0 ] -then - echo 'Failed to build librealsense' - exit 2 -fi - -cd ../.. - -popd > /dev/null diff --git a/wrappers/nodejs/scripts/npm_dist/build-dist.bat b/wrappers/nodejs/scripts/npm_dist/build-dist.bat deleted file mode 100644 index de6be516e6..0000000000 --- a/wrappers/nodejs/scripts/npm_dist/build-dist.bat +++ /dev/null @@ -1,33 +0,0 @@ -REM Copyright (c) 2017 Intel Corporation. All rights reserved. -REM Use of this source code is governed by an Apache 2.0 license -REM that can be found in the LICENSE file. - -@echo off -pushd . - -cd librealsense -md build -cd build - -REM Step 1 -IF /I "%1"=="x64" ( - cmake -DBUILD_UNIT_TESTS=0 -DBUILD_EXAMPLES=0 -DBUILD_GRAPHICAL_EXAMPLES=0 -DCMAKE_GENERATOR_PLATFORM=x64 .. > NUL -) else ( - cmake -DBUILD_UNIT_TESTS=0 -DBUILD_EXAMPLES=0 -DBUILD_GRAPHICAL_EXAMPLES=0 .. > NUL -) - -if errorlevel 1 ( - echo 'Failed to configure librealsense' - exit 1 -) - -REM Step 2 -msbuild librealsense2.sln /p:Configuration=Release /p:Platform=%2 /m:4 -if errorlevel 1 ( - echo 'Failed to build librealsense' - exit 2 -) - -cd ../.. - -popd diff --git a/wrappers/nodejs/scripts/npm_dist/build-dist.sh b/wrappers/nodejs/scripts/npm_dist/build-dist.sh deleted file mode 100755 index 133fc9ecdf..0000000000 --- a/wrappers/nodejs/scripts/npm_dist/build-dist.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/bash - -# Copyright (c) 2017 Intel Corporation. All rights reserved. -# Use of this source code is governed by an Apache 2.0 license -# that can be found in the LICENSE file. - -#sudo apt install -y libusb-1.0-0-dev pkg-config libgtk-3-dev libglfw3-dev cmake - -echo 'Buliding librealsense C++ API...' -pushd . > /dev/null -pwd - -cd librealsense -mkdir -p build -cd build - -# Step 1 -cmake -DBUILD_UNIT_TESTS=0 -DBUILD_EXAMPLES=0 -DBUILD_GRAPHICAL_EXAMPLES=0 .. -if [ "$?" -gt 0 ] -then - echo 'Failed to configure librealsense' - exit 1 -fi - -# Step 2 -CPU_NUM=`grep -c ^processor /proc/cpuinfo` -make -j $CPU_NUM -if [ "$?" -gt 0 ] -then - echo 'Failed to build librealsense' - exit 2 -fi - -cd ../.. - -popd > /dev/null diff --git a/wrappers/nodejs/scripts/npm_dist/build-librealsense.js b/wrappers/nodejs/scripts/npm_dist/build-librealsense.js deleted file mode 100644 index acbdcb53ba..0000000000 --- a/wrappers/nodejs/scripts/npm_dist/build-librealsense.js +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -// Purpose: build native librealsense - -const {spawn} = require('child_process'); -const os = require('os'); - -function buildNativeLib() { - console.log('Building librealsense C++ API. It takes time...'); - const type = os.type(); - if (type === 'Windows_NT') { - buildNativeLibWindows(); - } else if (type === 'Linux') { - buildNativeLibLinux(); - } else if (type === 'Darwin') { - buildNativeLibMac(); - } else { - throw new TypeError('Not supported build platform!'); - } -} - -function buildNativeLibMac() { - let child = spawn('./scripts/npm_dist/build-dist-mac.sh'); - child.stderr.on('data', (data) => { - console.error(`${data}`); - }); - child.stdout.on('data', (data) => { - console.log(`${data}`); - }); - child.on('close', (code) => { - if (code) { - throw new Error(`Failed to build librealsense, build-dist-mac.sh exited with code ${code}`); - } - }); -} - -function buildNativeLibLinux() { - let child = spawn('./scripts/npm_dist/build-dist.sh'); - child.stderr.on('data', (data) => { - console.error(`${data}`); - }); - child.stdout.on('data', (data) => { - console.log(`${data}`); - }); - child.on('close', (code) => { - if (code) { - throw new Error(`Failed to build librealsense, build-dist.sh exited with code ${code}`); - } - }); -} - -function buildNativeLibWindows() { - const cmakeGenPlatform = process.arch; - const msBuildPlatform = process.arch=='ia32'?'Win32':process.arch; - let child = spawn('cmd', ['/c', '.\\scripts\\npm_dist\\build-dist.bat', cmakeGenPlatform, - msBuildPlatform]); - child.stderr.on('data', (data) => { - console.error(`${data}`); - }); - child.stdout.on('data', (data) => { - console.log(`${data}`); - }); - child.on('close', (code) => { - if (code) { - throw new Error(`Failed to build librealsense, build-dist.bat exited with code ${code}`); - } - }); -} -buildNativeLib(); diff --git a/wrappers/nodejs/scripts/npm_dist/gen-dist.sh b/wrappers/nodejs/scripts/npm_dist/gen-dist.sh deleted file mode 100755 index 9cf6d3e681..0000000000 --- a/wrappers/nodejs/scripts/npm_dist/gen-dist.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash - -# Copyright (c) 2017 Intel Corporation. All rights reserved. -# Use of this source code is governed by an Apache 2.0 license -# that can be found in the LICENSE file. - -#Usage: gen-dist.sh xxxx.tar.gz - -WORKDIR=`mktemp -d` -RAWMODULEDIR="node-librealsense/" -MODULEDIR="$WORKDIR/$RAWMODULEDIR" -RSDIR="$MODULEDIR/librealsense" - -mkdir -p $RSDIR/wrappers -rsync -a ../.. $RSDIR --exclude wrappers --exclude doc --exclude unit-tests --exclude build --exclude .git -rsync -a . $MODULEDIR --exclude build --exclude dist --exclude node_modules - -cp -f ../CMakeLists.txt $RSDIR/wrappers/ -cp -f scripts/npm_dist/binding.gyp $MODULEDIR -cp -f scripts/npm_dist/package.json $MODULEDIR -cp -f scripts/npm_dist/README.md $MODULEDIR -git rev-parse --verify HEAD > $RSDIR/commit - -pushd . > /dev/null -cd $WORKDIR -FILENAME=`npm pack $RAWMODULEDIR` -TARFILENAME="$WORKDIR/$FILENAME" - -popd > /dev/null -mkdir -p dist -cp -f $TARFILENAME ./dist/ -rm -rf $WORKDIR - -echo "Generated ./dist/$FILENAME" -# SHOW INFO & DIR -if [ "$RS_SHOW_DIST_PACKAGE" == "1" ]; -then - gnome-open ./dist -fi diff --git a/wrappers/nodejs/src/addon.cpp b/wrappers/nodejs/src/addon.cpp deleted file mode 100644 index 9fe4e3f854..0000000000 --- a/wrappers/nodejs/src/addon.cpp +++ /dev/null @@ -1,5092 +0,0 @@ -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -class DictBase { - public: - explicit DictBase(v8::Local source) : v8obj_(source) {} - - DictBase() { - v8obj_ = v8::Object::New(v8::Isolate::GetCurrent()); - } - - ~DictBase() {} - - v8::Local GetMember(const char* name) const { - return v8obj_->Get(Nan::GetCurrentContext(), - Nan::New(name).ToLocalChecked()).ToLocalChecked(); - } - - v8::Local GetMember(const std::string& name) const { - return GetMember(name.c_str()); - } - - void SetMemberUndefined(const char* name) { - v8obj_->Set(Nan::GetCurrentContext(), - Nan::New(name).ToLocalChecked(), Nan::Undefined()); - } - - void DeleteMember(const char* name) { - v8obj_->Delete(Nan::GetCurrentContext(), Nan::New(name).ToLocalChecked()); - } - - void SetMember(const char* name, const char* value) { - v8obj_->Set(Nan::GetCurrentContext(), Nan::New(name).ToLocalChecked(), - Nan::New(value).ToLocalChecked()); - } - - void SetMember(const char* name, v8::Local value) { - v8obj_->Set(Nan::GetCurrentContext(), - Nan::New(name).ToLocalChecked(), value); - } - - void SetMember(const char* name, const std::string& value) { - v8obj_->Set(Nan::GetCurrentContext(), Nan::New(name).ToLocalChecked(), - Nan::New(value.c_str()).ToLocalChecked()); - } - - template - void SetMemberArray(const char* name, V value[len]) { - v8::Local array = Nan::New(len); - for (uint32_t i = 0; i < len; i++) { - array->Set(Nan::GetCurrentContext(), i, Nan::New(value[i])); - } - SetMember(name, array); - } - - template - void SetMemberT(const char* name, const T& value) { - v8obj_->Set(Nan::GetCurrentContext(), Nan::New(name).ToLocalChecked(), - Nan::New(value)); - } - - bool IsMemberPresent(const char* name) const { - v8::Local v = v8obj_->Get(Nan::GetCurrentContext(), - Nan::New(name).ToLocalChecked()).ToLocalChecked(); - return !(v->IsUndefined() || v->IsNull()); - } - - bool IsMemberPresent(const std::string& name) const { - return IsMemberPresent(name.c_str()); - } - - v8::Local GetObject() const { - return v8obj_; - } - - protected: - mutable v8::Local v8obj_; -}; - -class ErrorUtil { - public: - class ErrorInfo { - public: - ErrorInfo() : is_error_(false), recoverable_(false) {} - - ~ErrorInfo() {} - - void Update(bool is_error, bool recoverable, std::string description, - std::string function) { - is_error_ = is_error; - recoverable_ = recoverable; - description_ = description; - native_function_ = function; - } - - void Reset() { Update(false, false, "", ""); } - - // set value to js attributes only when this method is called - v8::Local GetJSObject() { - DictBase obj; - obj.SetMemberT("recoverable", recoverable_); - obj.SetMember("description", description_); - obj.SetMember("nativeFunction", native_function_); - return obj.GetObject(); - } - - private: - bool is_error_; - bool recoverable_; - std::string description_; - std::string native_function_; - - friend class ErrorUtil; - }; - - ~ErrorUtil() {} - - static void Init() { - if (!singleton_) singleton_ = new ErrorUtil(); - } - - static void UpdateJSErrorCallback( - const Nan::FunctionCallbackInfo& info) { - v8::Local context = info.GetIsolate()->GetCurrentContext(); - singleton_->js_error_container_.Reset( - info[0]->ToObject(context).ToLocalChecked()); - Nan::Utf8String value(info[1]->ToString(context).ToLocalChecked()); - singleton_->js_error_callback_name_ = std::string(*value); - } - - static void AnalyzeError(rs2_error* err) { - if (!err) return; - - auto function = std::string(rs2_get_failed_function(err)); - auto type = rs2_get_librealsense_exception_type(err); - auto msg = std::string(rs2_get_error_message(err)); - bool recoverable = false; - - if (type == RS2_EXCEPTION_TYPE_INVALID_VALUE || - type == RS2_EXCEPTION_TYPE_WRONG_API_CALL_SEQUENCE || - type == RS2_EXCEPTION_TYPE_NOT_IMPLEMENTED) { - recoverable = true; - } - - singleton_->MarkError(recoverable, msg, function); - } - - static void ResetError() { - singleton_->error_info_.Reset(); - } - - static v8::Local GetJSErrorObject() { - if (singleton_->error_info_.is_error_) - return singleton_->error_info_.GetJSObject(); - - return Nan::Undefined(); - } - - private: - // Save detailed error info to the js object - void MarkError(bool recoverable, std::string description, - std::string native_function) { - error_info_.Update(true, recoverable, description, native_function); - v8::Local args[1] = { GetJSErrorObject() }; - auto container = Nan::New(js_error_container_); - Nan::AsyncResource resource("js_error_callback_name_"); - resource.runInAsyncScope(container, js_error_callback_name_.c_str(), - 1, args); - // Nan::MakeCallback(container, , - // 1, args); - } - - static ErrorUtil* singleton_; - ErrorInfo error_info_; - Nan::Persistent js_error_container_; - std::string js_error_callback_name_; -}; - -ErrorUtil* ErrorUtil::singleton_ = nullptr; - -template -R GetNativeResult(F func, rs2_error** error, arguments... params) { - // reset the error pointer for each call. - *error = nullptr; - ErrorUtil::ResetError(); - R val = func(params...); - ErrorUtil::AnalyzeError(*error); - return val; -} - -template -void CallNativeFunc(F func, rs2_error** error, arguments... params) { - // reset the error pointer for each call. - *error = nullptr; - ErrorUtil::ResetError(); - func(params...); - ErrorUtil::AnalyzeError(*error); -} - -class MainThreadCallbackInfo { - public: - MainThreadCallbackInfo() : consumed_(false) { - pending_infos_.push_back(this); - } - virtual ~MainThreadCallbackInfo() { - pending_infos_.erase( - std::find(pending_infos_.begin(), pending_infos_.end(), this)); - } - virtual void Run() {} - virtual void Release() {} - void SetConsumed() { consumed_ = true; } - static bool InfoExist(MainThreadCallbackInfo* info) { - auto result = std::find(pending_infos_.begin(), pending_infos_.end(), info); - return (result != pending_infos_.end()); - } - static void ReleasePendingInfos() { - while (pending_infos_.size()) { delete *(pending_infos_.begin()); } - } - - protected: - static std::list pending_infos_; - bool consumed_; -}; - -std::list MainThreadCallbackInfo::pending_infos_; - -class MainThreadCallback { - public: - class LockGuard { - public: - LockGuard() { - MainThreadCallback::Lock(); - } - ~LockGuard() { - MainThreadCallback::Unlock(); - } - }; - static void Init() { - if (!singleton_) - singleton_ = new MainThreadCallback(); - } - static void Destroy() { - if (singleton_) { - delete singleton_; - singleton_ = nullptr; - MainThreadCallbackInfo::ReleasePendingInfos(); - } - } - ~MainThreadCallback() { - uv_close(reinterpret_cast(async_), - [](uv_handle_t* ptr) -> void { - free(ptr); - }); - uv_mutex_destroy(&mutex_); - } - static void NotifyMainThread(MainThreadCallbackInfo* info) { - if (singleton_) { - LockGuard guard; - if (singleton_->async_->data) { - MainThreadCallbackInfo* info = - reinterpret_cast(singleton_->async_->data); - info->Release(); - delete info; - } - singleton_->async_->data = static_cast(info); - uv_async_send(singleton_->async_); - } - } - - private: - MainThreadCallback() { - async_ = static_cast(malloc(sizeof(uv_async_t))); - async_->data = nullptr; - uv_async_init(uv_default_loop(), async_, AsyncProc); - uv_mutex_init(&mutex_); - } - static void Lock() { - if (singleton_) uv_mutex_lock(&(singleton_->mutex_)); - } - static void Unlock() { - if (singleton_) uv_mutex_unlock(&(singleton_->mutex_)); - } - static void AsyncProc(uv_async_t* async) { - MainThreadCallbackInfo* info = nullptr; - { - LockGuard guard; - if (!(async->data)) - return; - - info = reinterpret_cast(async->data); - async->data = nullptr; - } - info->Run(); - // As the above info->Run() enters js world and during that, any code - // such as cleanup() could be called to release everything. So this info - // may has been released, we need to check before releasing it. - if (MainThreadCallbackInfo::InfoExist(info)) delete info; - } - static MainThreadCallback* singleton_; - uv_async_t* async_; - uv_mutex_t mutex_; -}; - -MainThreadCallback* MainThreadCallback::singleton_ = nullptr; -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -class RSExtrinsics : public DictBase { - public: - explicit RSExtrinsics(rs2_extrinsics extrinsics) { - SetMemberArray("rotation", extrinsics.rotation); - SetMemberArray("translation", extrinsics.translation); - } -}; - - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -class RSIntrinsics : public DictBase { - public: - explicit RSIntrinsics(rs2_intrinsics intrinsics) { - SetMemberT("width", intrinsics.width); - SetMemberT("height", intrinsics.height); - SetMemberT("ppx", intrinsics.ppx); - SetMemberT("ppy", intrinsics.ppy); - SetMemberT("fx", intrinsics.fx); - SetMemberT("fy", intrinsics.fy); - SetMemberT("model", intrinsics.model); - SetMemberArray("coeffs", intrinsics.coeffs); - } -}; - -class RSMotionIntrinsics : public DictBase { - public: - explicit RSMotionIntrinsics(rs2_motion_device_intrinsic* intri) { - v8::Local data_array = Nan::New(3); - int32_t index = 0; - for (int32_t i = 0; i < 3; i++) { - for (int32_t j = 0; j < 4; j++) { - data_array->Set(Nan::GetCurrentContext(), - index++, Nan::New(intri->data[i][j])); - } - } - SetMember("data", data_array); - SetMemberArray("noiseVariances", - intri->noise_variances); - SetMemberArray("biasVariances", - intri->bias_variances); - } -}; - -class RSOptionRange : public DictBase { - public: - RSOptionRange(float min, float max, float step, float def) { - SetMemberT("minValue", min); - SetMemberT("maxValue", max); - SetMemberT("step", step); - SetMemberT("defaultValue", def); - } -}; - -class RSNotification : public DictBase { - public: - RSNotification(const std::string& des, rs2_time_t time, - rs2_log_severity severity, rs2_notification_category category, - const std::string& serialized_data) { - SetMember("descr", des); - SetMemberT("timestamp", time); - SetMemberT("severity", (int32_t)severity); - SetMemberT("category", (int32_t)category); - SetMember("serializedData", serialized_data); - } -}; - -class RSRegionOfInterest : public DictBase { - public: - RSRegionOfInterest(int32_t minx, int32_t miny, int32_t maxx, int32_t maxy) { - SetMemberT("minX", minx); - SetMemberT("minY", miny); - SetMemberT("maxX", maxx); - SetMemberT("maxY", maxy); - } -}; - -class RSStreamProfile : public Nan::ObjectWrap { - public: - static void Init(v8::Local exports) { - v8::Local tpl = Nan::New(New); - tpl->SetClassName(Nan::New("RSStreamProfile").ToLocalChecked()); - tpl->InstanceTemplate()->SetInternalFieldCount(1); - - Nan::SetPrototypeMethod(tpl, "destroy", Destroy); - Nan::SetPrototypeMethod(tpl, "stream", Stream); - Nan::SetPrototypeMethod(tpl, "format", Format); - Nan::SetPrototypeMethod(tpl, "fps", Fps); - Nan::SetPrototypeMethod(tpl, "index", Index); - Nan::SetPrototypeMethod(tpl, "uniqueID", UniqueID); - Nan::SetPrototypeMethod(tpl, "isDefault", IsDefault); - Nan::SetPrototypeMethod(tpl, "isVideoProfile", IsVideoProfile); - Nan::SetPrototypeMethod(tpl, "isMotionProfile", IsMotionProfile); - Nan::SetPrototypeMethod(tpl, "width", Width); - Nan::SetPrototypeMethod(tpl, "height", Height); - Nan::SetPrototypeMethod(tpl, "getExtrinsicsTo", GetExtrinsicsTo); - Nan::SetPrototypeMethod(tpl, "getVideoStreamIntrinsics", - GetVideoStreamIntrinsics); - Nan::SetPrototypeMethod(tpl, "getMotionIntrinsics", GetMotionIntrinsics); - - v8::Local context = exports->CreationContext(); - - constructor_.Reset(tpl->GetFunction(context).ToLocalChecked()); - exports->Set(context, Nan::New("RSStreamProfile").ToLocalChecked(), - tpl->GetFunction(context).ToLocalChecked()); - } - - static v8::Local NewInstance( - rs2_stream_profile* p, bool own = false) { - Nan::EscapableHandleScope scope; - - v8::Local cons = Nan::New(constructor_); - v8::Local context = Nan::GetCurrentContext(); - - v8::Local instance = - cons->NewInstance(context, 0, nullptr).ToLocalChecked(); - auto me = Nan::ObjectWrap::Unwrap(instance); - me->profile_ = p; - me->own_profile_ = own; - CallNativeFunc(rs2_get_stream_profile_data, &me->error_, p, &me->stream_, - &me->format_, &me->index_, &me->unique_id_, &me->fps_, &me->error_); - me->is_default_ = rs2_is_stream_profile_default(p, &me->error_); - if (GetNativeResult(rs2_stream_profile_is, &me->error_, p, - RS2_EXTENSION_VIDEO_PROFILE, &me->error_)) { - me->is_video_ = true; - CallNativeFunc(rs2_get_video_stream_resolution, &me->error_, p, - &me->width_, &me->height_, &me->error_); - } else if (GetNativeResult(rs2_stream_profile_is, &me->error_, p, - RS2_EXTENSION_MOTION_PROFILE, &me->error_)) { - me->is_motion_ = true; - } - - return scope.Escape(instance); - } - - private: - RSStreamProfile() : error_(nullptr), profile_(nullptr), index_(0), - unique_id_(0), fps_(0), format_(static_cast(0)), - stream_(static_cast(0)), is_video_(false), width_(0), - height_(0), is_default_(false), own_profile_(false), is_motion_(false) {} - - ~RSStreamProfile() { - DestroyMe(); - } - - void DestroyMe() { - if (error_) rs2_free_error(error_); - error_ = nullptr; - if (profile_ && own_profile_) rs2_delete_stream_profile(profile_); - profile_ = nullptr; - } - - static NAN_METHOD(Destroy) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) { - me->DestroyMe(); - } - info.GetReturnValue().Set(Nan::Undefined()); - } - - static void New(const Nan::FunctionCallbackInfo& info) { - if (info.IsConstructCall()) { - RSStreamProfile* obj = new RSStreamProfile(); - obj->Wrap(info.This()); - info.GetReturnValue().Set(info.This()); - } - } - - static NAN_METHOD(Stream) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) { - info.GetReturnValue().Set(Nan::New(me->stream_)); - return; - } - info.GetReturnValue().Set(Nan::Undefined()); - } - static NAN_METHOD(Format) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) { - info.GetReturnValue().Set(Nan::New(me->format_)); - return; - } - info.GetReturnValue().Set(Nan::Undefined()); - } - static NAN_METHOD(Fps) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) { - info.GetReturnValue().Set(Nan::New(me->fps_)); - return; - } - info.GetReturnValue().Set(Nan::Undefined()); - } - static NAN_METHOD(Index) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) { - info.GetReturnValue().Set(Nan::New(me->index_)); - return; - } - info.GetReturnValue().Set(Nan::Undefined()); - } - static NAN_METHOD(UniqueID) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) { - info.GetReturnValue().Set(Nan::New(me->unique_id_)); - return; - } - info.GetReturnValue().Set(Nan::Undefined()); - } - static NAN_METHOD(IsDefault) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) { - info.GetReturnValue().Set(Nan::New(me->is_default_)); - return; - } - info.GetReturnValue().Set(Nan::Undefined()); - } - static NAN_METHOD(IsVideoProfile) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) { - info.GetReturnValue().Set(Nan::New(me->is_video_)); - return; - } - info.GetReturnValue().Set(Nan::Undefined()); - } - - static NAN_METHOD(IsMotionProfile) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - info.GetReturnValue().Set(Nan::Undefined()); - if (!me) return; - - info.GetReturnValue().Set(Nan::New(me->is_motion_)); - } - - static NAN_METHOD(Width) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) { - info.GetReturnValue().Set(Nan::New(me->width_)); - return; - } - info.GetReturnValue().Set(Nan::Undefined()); - } - - static NAN_METHOD(Height) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) { - info.GetReturnValue().Set(Nan::New(me->height_)); - return; - } - info.GetReturnValue().Set(Nan::Undefined()); - } - - static NAN_METHOD(GetExtrinsicsTo) { - info.GetReturnValue().Set(Nan::Undefined()); - v8::Local context = info.GetIsolate()->GetCurrentContext(); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - auto to = Nan::ObjectWrap::Unwrap( - info[0]->ToObject(context).ToLocalChecked()); - if (!me || !to) return; - - rs2_extrinsics res; - CallNativeFunc(rs2_get_extrinsics, &me->error_, me->profile_, to->profile_, - &res, &me->error_); - if (me->error_) return; - - RSExtrinsics rsres(res); - info.GetReturnValue().Set(rsres.GetObject()); - } - - static NAN_METHOD(GetVideoStreamIntrinsics) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - rs2_intrinsics intr; - CallNativeFunc(rs2_get_video_stream_intrinsics, &me->error_, me->profile_, - &intr, &me->error_); - if (me->error_) return; - - RSIntrinsics res(intr); - info.GetReturnValue().Set(res.GetObject()); - } - - static NAN_METHOD(GetMotionIntrinsics) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - rs2_motion_device_intrinsic output; - CallNativeFunc(rs2_get_motion_intrinsics, &me->error_, me->profile_, - &output, &me->error_); - if (me->error_) return; - - RSMotionIntrinsics intrinsics(&output); - info.GetReturnValue().Set(intrinsics.GetObject()); - } - - private: - static Nan::Persistent constructor_; - - rs2_error* error_; - rs2_stream_profile* profile_; - int32_t index_; - int32_t unique_id_; - int32_t fps_; - rs2_format format_; - rs2_stream stream_; - bool is_video_; - int32_t width_; - int32_t height_; - bool is_default_; - bool own_profile_; - bool is_motion_; - - friend class RSSensor; -}; - -Nan::Persistent RSStreamProfile::constructor_; - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -// // -// 8888888b. .d8888b. 8888888888 // -// 888 Y88b d88P Y88b 888 // -// 888 888 Y88b. 888 // -// 888 d88P "Y888b. 8888888 888d888 8888b. 88888b.d88b. .d88b. // -// 8888888P" "Y88b. 888 888P" "88b 888 "888 "88b d8P Y8b // -// 888 T88b "888 888 888 .d888888 888 888 888 88888888 // -// 888 T88b Y88b d88P 888 888 888 888 888 888 888 Y8b. // -// 888 T88b "Y8888P" 888 888 "Y888888 888 888 888 "Y8888 // -// // -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -class RSFrame : public Nan::ObjectWrap { - public: - static void Init(v8::Local exports) { - v8::Local tpl = Nan::New(New); - tpl->SetClassName(Nan::New("RSFrame").ToLocalChecked()); - tpl->InstanceTemplate()->SetInternalFieldCount(1); - - Nan::SetPrototypeMethod(tpl, "destroy", Destroy); - Nan::SetPrototypeMethod(tpl, "getStreamProfile", GetStreamProfile); - Nan::SetPrototypeMethod(tpl, "getData", GetData); - Nan::SetPrototypeMethod(tpl, "writeData", WriteData); - Nan::SetPrototypeMethod(tpl, "getWidth", GetWidth); - Nan::SetPrototypeMethod(tpl, "getHeight", GetHeight); - Nan::SetPrototypeMethod(tpl, "getStrideInBytes", GetStrideInBytes); - Nan::SetPrototypeMethod(tpl, "getBitsPerPixel", GetBitsPerPixel); - Nan::SetPrototypeMethod(tpl, "getTimestamp", GetTimestamp); - Nan::SetPrototypeMethod(tpl, "getTimestampDomain", GetTimestampDomain); - Nan::SetPrototypeMethod(tpl, "getFrameNumber", GetFrameNumber); - Nan::SetPrototypeMethod(tpl, "getFrameMetadata", GetFrameMetadata); - Nan::SetPrototypeMethod(tpl, "supportsFrameMetadata", - SupportsFrameMetadata); - Nan::SetPrototypeMethod(tpl, "isVideoFrame", IsVideoFrame); - Nan::SetPrototypeMethod(tpl, "isDepthFrame", IsDepthFrame); - Nan::SetPrototypeMethod(tpl, "isDisparityFrame", IsDisparityFrame); - Nan::SetPrototypeMethod(tpl, "isMotionFrame", IsMotionFrame); - Nan::SetPrototypeMethod(tpl, "isPoseFrame", IsPoseFrame); - - // Points related APIs - Nan::SetPrototypeMethod(tpl, "canGetPoints", CanGetPoints); - Nan::SetPrototypeMethod(tpl, "getVertices", GetVertices); - Nan::SetPrototypeMethod(tpl, "getVerticesBufferLen", GetVerticesBufferLen); - Nan::SetPrototypeMethod(tpl, "getTexCoordBufferLen", GetTexCoordBufferLen); - Nan::SetPrototypeMethod(tpl, "writeVertices", WriteVertices); - Nan::SetPrototypeMethod(tpl, "getTextureCoordinates", - GetTextureCoordinates); - Nan::SetPrototypeMethod(tpl, "writeTextureCoordinates", - WriteTextureCoordinates); - Nan::SetPrototypeMethod(tpl, "getPointsCount", GetPointsCount); - Nan::SetPrototypeMethod(tpl, "exportToPly", ExportToPly); - Nan::SetPrototypeMethod(tpl, "isValid", IsValid); - Nan::SetPrototypeMethod(tpl, "getDistance", GetDistance); - Nan::SetPrototypeMethod(tpl, "getBaseLine", GetBaseLine); - Nan::SetPrototypeMethod(tpl, "keep", Keep); - Nan::SetPrototypeMethod(tpl, "getMotionData", GetMotionData); - Nan::SetPrototypeMethod(tpl, "getPoseData", GetPoseData); - - v8::Local context = exports->CreationContext(); - - constructor_.Reset(tpl->GetFunction(context).ToLocalChecked()); - exports->Set(context, Nan::New("RSFrame").ToLocalChecked(), - tpl->GetFunction(context).ToLocalChecked()); - } - - static v8::Local NewInstance(rs2_frame* frame) { - Nan::EscapableHandleScope scope; - - v8::Local cons = Nan::New(constructor_); - v8::Local context = Nan::GetCurrentContext(); - - v8::Local instance = - cons->NewInstance(context, 0, nullptr).ToLocalChecked(); - - auto me = Nan::ObjectWrap::Unwrap(instance); - me->frame_ = frame; - - return scope.Escape(instance); - } - - void Replace(rs2_frame* value) { - DestroyMe(); - frame_ = value; - // As the underlying frame changed, we must clean the js side's buffer - Nan::AsyncResource resource("_internalResetBuffer"); - resource.runInAsyncScope(handle(), "_internalResetBuffer", 0, nullptr); - // Nan::MakeCallback(handle(), "_internalResetBuffer", 0, nullptr); - } - - private: - RSFrame() : frame_(nullptr), error_(nullptr) {} - - ~RSFrame() { - DestroyMe(); - } - - void DestroyMe() { - if (error_) rs2_free_error(error_); - if (frame_) rs2_release_frame(frame_); - error_ = nullptr; - frame_ = nullptr; - } - - static void SetAFloatInVectorObject(v8::Local obj, uint32_t index, - float value) { - const char* names[4] = {"x", "y", "z", "w"}; - v8::Local name = Nan::New(names[index]).ToLocalChecked(); - Nan::Set(obj, name, Nan::New(value)); - } - - static void FillAFloatVector(v8::Local obj, - const rs2_vector& vec) { - SetAFloatInVectorObject(obj, 0, vec.x); - SetAFloatInVectorObject(obj, 1, vec.y); - SetAFloatInVectorObject(obj, 2, vec.z); - } - - static void FillAFloatQuaternion(v8::Local obj, - const rs2_quaternion& quaternion) { - SetAFloatInVectorObject(obj, 0, quaternion.x); - SetAFloatInVectorObject(obj, 1, quaternion.y); - SetAFloatInVectorObject(obj, 2, quaternion.z); - SetAFloatInVectorObject(obj, 3, quaternion.w); - } - - static void AssemblePoseData(v8::Local obj, - const rs2_pose& pose) { - auto translation_name = Nan::New("translation").ToLocalChecked(); - auto velocity_name = Nan::New("velocity").ToLocalChecked(); - auto acceleration_name = Nan::New("acceleration").ToLocalChecked(); - auto rotation_name = Nan::New("rotation").ToLocalChecked(); - auto angular_velocity_name = Nan::New("angularVelocity").ToLocalChecked(); - auto angular_acceleration_name = - Nan::New("angularAcceleration").ToLocalChecked(); - auto tracker_confidence_name = - Nan::New("trackerConfidence").ToLocalChecked(); - auto mapper_confidence_name = Nan::New("mapperConfidence").ToLocalChecked(); - - auto translation_obj = Nan::GetRealNamedProperty( - obj, translation_name).ToLocalChecked() - ->ToObject(Nan::GetCurrentContext()); - auto velocity_obj = Nan::GetRealNamedProperty( - obj, velocity_name).ToLocalChecked() - ->ToObject(Nan::GetCurrentContext()); - auto acceleration_obj = Nan::GetRealNamedProperty( - obj, acceleration_name).ToLocalChecked() - ->ToObject(Nan::GetCurrentContext()); - auto rotation_obj = Nan::GetRealNamedProperty( - obj, rotation_name).ToLocalChecked() - ->ToObject(Nan::GetCurrentContext()); - auto angular_velocity_obj = Nan::GetRealNamedProperty( - obj, angular_velocity_name).ToLocalChecked() - ->ToObject(Nan::GetCurrentContext()); - auto angular_acceleration_obj = Nan::GetRealNamedProperty( - obj, angular_acceleration_name).ToLocalChecked() - ->ToObject(Nan::GetCurrentContext()); - - FillAFloatVector(translation_obj.ToLocalChecked(), pose.translation); - FillAFloatVector(velocity_obj.ToLocalChecked(), pose.velocity); - FillAFloatVector(acceleration_obj.ToLocalChecked(), pose.acceleration); - FillAFloatQuaternion(rotation_obj.ToLocalChecked(), pose.rotation); - FillAFloatVector( - angular_velocity_obj.ToLocalChecked(), pose.angular_velocity); - FillAFloatVector( - angular_acceleration_obj.ToLocalChecked(), pose.angular_acceleration); - - Nan::Set(obj, tracker_confidence_name, Nan::New(pose.tracker_confidence)); - Nan::Set(obj, mapper_confidence_name, Nan::New(pose.mapper_confidence)); - } - - static void New(const Nan::FunctionCallbackInfo& info) { - if (info.IsConstructCall()) { - RSFrame* obj = new RSFrame(); - obj->Wrap(info.This()); - info.GetReturnValue().Set(info.This()); - } - } - - static NAN_METHOD(GetStreamProfile) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me || !me->frame_) return; - - rs2_stream stream; - rs2_format format; - int32_t index = 0; - int32_t unique_id = 0; - int32_t fps = 0; - const rs2_stream_profile* profile_org = - GetNativeResult(rs2_get_frame_stream_profile, - &me->error_, me->frame_, &me->error_); - CallNativeFunc(rs2_get_stream_profile_data, &me->error_, profile_org, - &stream, &format, &index, &unique_id, &fps, &me->error_); - if (me->error_) return; - - rs2_stream_profile* profile = GetNativeResult( - rs2_clone_stream_profile, &me->error_, profile_org, stream, index, - format, &me->error_); - if (!profile) return; - - info.GetReturnValue().Set(RSStreamProfile::NewInstance(profile, true)); - } - - static NAN_METHOD(GetData) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - auto buffer = GetNativeResult(rs2_get_frame_data, &me->error_, - me->frame_, &me->error_); - if (!buffer) return; - - const auto stride = GetNativeResult(rs2_get_frame_stride_in_bytes, - &me->error_, me->frame_, &me->error_); - const auto height = GetNativeResult(rs2_get_frame_height, &me->error_, - me->frame_, &me->error_); - const auto length = stride * height; - auto array_buffer = v8::ArrayBuffer::New( - v8::Isolate::GetCurrent(), - static_cast(const_cast(buffer)), length, - v8::ArrayBufferCreationMode::kExternalized); - info.GetReturnValue().Set(array_buffer); - } - - static NAN_METHOD(WriteData) { - info.GetReturnValue().Set(Nan::Undefined()); - auto array_buffer = v8::Local::Cast(info[0]); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - const auto buffer = GetNativeResult(rs2_get_frame_data, - &me->error_, me->frame_, &me->error_); - const auto stride = GetNativeResult(rs2_get_frame_stride_in_bytes, - &me->error_, me->frame_, &me->error_); - const auto height = GetNativeResult(rs2_get_frame_height, &me->error_, - me->frame_, &me->error_); - const size_t length = stride * height; - if (buffer && array_buffer->ByteLength() >= length) { - auto contents = array_buffer->GetContents(); - memcpy(contents.Data(), buffer, length); - } - } - - static NAN_METHOD(GetWidth) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - auto value = GetNativeResult(rs2_get_frame_width, &me->error_, - me->frame_, &me->error_); - info.GetReturnValue().Set(Nan::New(value)); - } - - static NAN_METHOD(GetHeight) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - auto value = GetNativeResult(rs2_get_frame_height, &me->error_, - me->frame_, &me->error_); - info.GetReturnValue().Set(Nan::New(value)); - } - - static NAN_METHOD(GetStrideInBytes) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - auto value = GetNativeResult(rs2_get_frame_stride_in_bytes, - &me->error_, me->frame_, &me->error_); - info.GetReturnValue().Set(Nan::New(value)); - } - - static NAN_METHOD(GetBitsPerPixel) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - auto value = GetNativeResult(rs2_get_frame_bits_per_pixel, &me->error_, - me->frame_, &me->error_); - info.GetReturnValue().Set(Nan::New(value)); - } - - static NAN_METHOD(GetTimestamp) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - auto value = GetNativeResult(rs2_get_frame_timestamp, &me->error_, - me->frame_, &me->error_); - info.GetReturnValue().Set(Nan::New(value)); - } - - static NAN_METHOD(GetTimestampDomain) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - auto value = GetNativeResult( - rs2_get_frame_timestamp_domain, &me->error_, me->frame_, &me->error_); - info.GetReturnValue().Set(Nan::New(value)); - } - - static NAN_METHOD(GetFrameNumber) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - uint32_t value = GetNativeResult(rs2_get_frame_number, - &me->error_, me->frame_, &me->error_); - info.GetReturnValue().Set(Nan::New(value)); - } - - static NAN_METHOD(IsVideoFrame) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - bool isVideo = false; - if (GetNativeResult(rs2_is_frame_extendable_to, &me->error_, - me->frame_, RS2_EXTENSION_VIDEO_FRAME, &me->error_)) - isVideo = true; - info.GetReturnValue().Set(Nan::New(isVideo)); - } - - static NAN_METHOD(IsDepthFrame) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - bool isDepth = false; - if (GetNativeResult(rs2_is_frame_extendable_to, &me->error_, - me->frame_, RS2_EXTENSION_DEPTH_FRAME, &me->error_)) - isDepth = true; - info.GetReturnValue().Set(Nan::New(isDepth)); - } - - static NAN_METHOD(IsDisparityFrame) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - info.GetReturnValue().Set(Nan::Undefined()); - if (!me) return; - - auto is_disparity = GetNativeResult(rs2_is_frame_extendable_to, - &me->error_, me->frame_, RS2_EXTENSION_DISPARITY_FRAME, &me->error_); - info.GetReturnValue().Set(Nan::New(is_disparity ? true : false)); - } - - static NAN_METHOD(IsMotionFrame) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - info.GetReturnValue().Set(Nan::Undefined()); - if (!me) return; - - auto val = GetNativeResult(rs2_is_frame_extendable_to, &me->error_, - me->frame_, RS2_EXTENSION_MOTION_FRAME, &me->error_); - info.GetReturnValue().Set(Nan::New(val ? true : false)); - } - - static NAN_METHOD(IsPoseFrame) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - info.GetReturnValue().Set(Nan::Undefined()); - if (!me) return; - - auto val = GetNativeResult(rs2_is_frame_extendable_to, &me->error_, - me->frame_, RS2_EXTENSION_POSE_FRAME, &me->error_); - info.GetReturnValue().Set(Nan::New(val ? true : false)); - } - - static NAN_METHOD(GetFrameMetadata) { - info.GetReturnValue().Set(Nan::New(false)); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - rs2_frame_metadata_value metadata = - (rs2_frame_metadata_value)(Nan::To(info[0]).FromJust()); - Nan::TypedArrayContents content(info[1]); - unsigned char* internal_data = *content; - if (!me || !internal_data) return; - - rs2_metadata_type output = GetNativeResult( - rs2_get_frame_metadata, &me->error_, me->frame_, metadata, &me->error_); - unsigned char* out_ptr = reinterpret_cast(&output); - uint32_t val = 1; - unsigned char* val_ptr = reinterpret_cast(&val); - - if (*val_ptr == 0) { - // big endian - memcpy(internal_data, out_ptr, 8); - } else { - // little endian - for (int32_t i=0; i < 8; i++) { - internal_data[i] = out_ptr[7-i]; - } - } - info.GetReturnValue().Set(Nan::New(true)); - } - - static NAN_METHOD(SupportsFrameMetadata) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - rs2_frame_metadata_value metadata = - (rs2_frame_metadata_value)(Nan::To(info[0]).FromJust()); - if (!me) return; - - int result = GetNativeResult(rs2_supports_frame_metadata, &me->error_, - me->frame_, metadata, &me->error_); - info.GetReturnValue().Set(Nan::New(result ? true : false)); - } - - static NAN_METHOD(Destroy) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) { - me->DestroyMe(); - } - info.GetReturnValue().Set(Nan::Undefined()); - } - - static NAN_METHOD(CanGetPoints) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - bool result = false; - if (GetNativeResult(rs2_is_frame_extendable_to, &me->error_, - me->frame_, RS2_EXTENSION_POINTS, &me->error_)) - result = true; - info.GetReturnValue().Set(Nan::New(result)); - } - - static NAN_METHOD(GetVertices) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - rs2_vertex* vertices = GetNativeResult(rs2_get_frame_vertices, - &me->error_, me->frame_, &me->error_); - size_t count = GetNativeResult(rs2_get_frame_points_count, - &me->error_, me->frame_, &me->error_); - if (!vertices || !count) return; - - uint32_t step = 3 * sizeof(float); - uint32_t len = count * step; - auto vertex_buf = static_cast(malloc(len)); - - for (size_t i = 0; i < count; i++) { - memcpy(vertex_buf+i*step, vertices[i].xyz, step); - } - auto array_buffer = v8::ArrayBuffer::New( - v8::Isolate::GetCurrent(), vertex_buf, len, - v8::ArrayBufferCreationMode::kInternalized); - - info.GetReturnValue().Set(v8::Float32Array::New(array_buffer, 0, 3*count)); - } - - static NAN_METHOD(GetVerticesBufferLen) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - const size_t count = GetNativeResult(rs2_get_frame_points_count, - &me->error_, me->frame_, &me->error_); - const uint32_t step = 3 * sizeof(float); - const uint32_t length = count * step; - info.GetReturnValue().Set(Nan::New(length)); - } - - static NAN_METHOD(GetTexCoordBufferLen) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - const size_t count = GetNativeResult(rs2_get_frame_points_count, - &me->error_, me->frame_, &me->error_); - const uint32_t step = 2 * sizeof(int); - const uint32_t length = count * step; - info.GetReturnValue().Set(Nan::New(length)); - } - - static NAN_METHOD(WriteVertices) { - info.GetReturnValue().Set(Nan::False()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - auto array_buffer = v8::Local::Cast(info[0]); - if (!me) return; - - const rs2_vertex* vertBuf = GetNativeResult( - rs2_get_frame_vertices, &me->error_, me->frame_, &me->error_); - const size_t count = GetNativeResult(rs2_get_frame_points_count, - &me->error_, me->frame_, &me->error_); - if (!vertBuf || !count) return; - - const uint32_t step = 3 * sizeof(float); - const uint32_t length = count * step; - if (array_buffer->ByteLength() < length) return; - - auto contents = array_buffer->GetContents(); - uint8_t* vertex_buf = static_cast(contents.Data()); - for (size_t i = 0; i < count; i++) { - memcpy(vertex_buf+i*step, vertBuf[i].xyz, step); - } - info.GetReturnValue().Set(Nan::True()); - } - - static NAN_METHOD(GetTextureCoordinates) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - rs2_pixel* coords = GetNativeResult( - rs2_get_frame_texture_coordinates, &me->error_, me->frame_, - &me->error_); - size_t count = GetNativeResult(rs2_get_frame_points_count, - &me->error_, me->frame_, &me->error_); - if (!coords || !count) return; - - uint32_t step = 2 * sizeof(int); - uint32_t len = count * step; - auto texcoord_buf = static_cast(malloc(len)); - - for (size_t i = 0; i < count; ++i) { - memcpy(texcoord_buf + i * step, coords[i].ij, step); - } - auto array_buffer = v8::ArrayBuffer::New( - v8::Isolate::GetCurrent(), texcoord_buf, len, - v8::ArrayBufferCreationMode::kInternalized); - - info.GetReturnValue().Set(v8::Int32Array::New(array_buffer, 0, 2*count)); - } - - static NAN_METHOD(WriteTextureCoordinates) { - info.GetReturnValue().Set(Nan::False()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - auto array_buffer = v8::Local::Cast(info[0]); - if (!me) return; - - const rs2_pixel* coords = - rs2_get_frame_texture_coordinates(me->frame_, &me->error_); - const size_t count = GetNativeResult(rs2_get_frame_points_count, - &me->error_, me->frame_, &me->error_); - if (!coords || !count) return; - - const uint32_t step = 2 * sizeof(int); - const uint32_t length = count * step; - if (array_buffer->ByteLength() < length) return; - - auto contents = array_buffer->GetContents(); - uint8_t* texcoord_buf = static_cast(contents.Data()); - for (size_t i = 0; i < count; ++i) { - memcpy(texcoord_buf + i * step, coords[i].ij, step); - } - info.GetReturnValue().Set(Nan::True()); - } - - static NAN_METHOD(GetPointsCount) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - int32_t count = GetNativeResult(rs2_get_frame_points_count, - &me->error_, me->frame_, &me->error_); - info.GetReturnValue().Set(Nan::New(count)); - } - - static NAN_METHOD(ExportToPly) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - // v8::String::Utf8Value str(info[0]); - Nan::Utf8String str(info[0]); - std::string file = std::string(*str); - v8::Local context = info.GetIsolate()->GetCurrentContext(); - auto texture = Nan::ObjectWrap::Unwrap( - info[1]->ToObject(context).ToLocalChecked()); - info.GetReturnValue().Set(Nan::Undefined()); - if (!me || !texture) return; - - rs2_frame* ptr = nullptr; - std::swap(texture->frame_, ptr); - CallNativeFunc(rs2_export_to_ply, &me->error_, me->frame_, file.c_str(), - ptr, &me->error_); - } - - static NAN_METHOD(IsValid) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) { - if (me->frame_) { - info.GetReturnValue().Set(Nan::True()); - return; - } - } - info.GetReturnValue().Set(Nan::False()); - } - - static NAN_METHOD(GetDistance) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - auto x = Nan::To(info[0]).FromJust(); - auto y = Nan::To(info[1]).FromJust(); - if (!me) return; - - auto val = GetNativeResult(rs2_depth_frame_get_distance, &me->error_, - me->frame_, x, y, &me->error_); - info.GetReturnValue().Set(Nan::New(val)); - } - - static NAN_METHOD(GetBaseLine) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - info.GetReturnValue().Set(Nan::Undefined()); - if (!me) return; - - auto val = GetNativeResult(rs2_depth_stereo_frame_get_baseline, - &me->error_, me->frame_, &me->error_); - info.GetReturnValue().Set(Nan::New(val)); - } - - static NAN_METHOD(Keep) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - info.GetReturnValue().Set(Nan::Undefined()); - if (!me || !me->frame_) return; - - rs2_keep_frame(me->frame_); - } - - static NAN_METHOD(GetMotionData) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - info.GetReturnValue().Set(Nan::Undefined()); - if (!me) return; - v8::Local context = info.GetIsolate()->GetCurrentContext(); - auto obj = info[0]->ToObject(context).ToLocalChecked(); - auto frame_data = static_cast(GetNativeResult( - rs2_get_frame_data, &me->error_, me->frame_, &me->error_)); - for (uint32_t i = 0; i < 3; i++) { - SetAFloatInVectorObject(obj, i, frame_data[i]); - } - } - - static NAN_METHOD(GetPoseData) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - info.GetReturnValue().Set(Nan::False()); - if (!me) return; - - rs2_pose pose_data; - CallNativeFunc(rs2_pose_frame_get_pose_data, &me->error_, me->frame_, - &pose_data, &me->error_); - if (me->error_) return; - v8::Local context = info.GetIsolate()->GetCurrentContext(); - AssemblePoseData(info[0]->ToObject(context).ToLocalChecked(), pose_data); - info.GetReturnValue().Set(Nan::True()); - } - - private: - static Nan::Persistent constructor_; - rs2_frame* frame_; - rs2_error* error_; - friend class RSColorizer; - friend class RSFilter; - friend class RSFrameQueue; - friend class RSPointCloud; - friend class RSSyncer; -}; - -Nan::Persistent RSFrame::constructor_; - - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -// -// 8888888888 .d88888b. // -// 888 d88P" "Y88b // -// 888 888 888 // -// 8888888 888d888 8888b. 88888b.d88b. .d88b. 888 888 // -// 888 888P" "88b 888 "888 "88b d8P Y8b 888 888 // -// 888 888 .d888888 888 888 888 88888888 888 Y8b 888 // -// 888 888 888 888 888 888 888 Y8b. Y88b.Y8b88P // -// 888 888 "Y888888 888 888 888 "Y8888 "Y888888" // -// // -// -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -// TODO(shaoting) remove this class if not used in future. -class RSFrameQueue : public Nan::ObjectWrap { - public: - static void Init(v8::Local exports) { - v8::Local tpl = Nan::New(New); - tpl->SetClassName(Nan::New("RSFrameQueue").ToLocalChecked()); - tpl->InstanceTemplate()->SetInternalFieldCount(1); - - Nan::SetPrototypeMethod(tpl, "create", Create); - Nan::SetPrototypeMethod(tpl, "destroy", Destroy); - Nan::SetPrototypeMethod(tpl, "waitForFrame", WaitForFrame); - Nan::SetPrototypeMethod(tpl, "pollForFrame", PollForFrame); - Nan::SetPrototypeMethod(tpl, "enqueueFrame", EnqueueFrame); - v8::Local context = exports->CreationContext(); - constructor_.Reset(tpl->GetFunction(context).ToLocalChecked()); - exports->Set(context, Nan::New("RSFrameQueue").ToLocalChecked(), - tpl->GetFunction(context).ToLocalChecked()); - } - - static v8::Local NewInstance() { - Nan::EscapableHandleScope scope; - - v8::Local cons = Nan::New(constructor_); - v8::Local context = Nan::GetCurrentContext(); - - v8::Local instance = - cons->NewInstance(context, 0, nullptr).ToLocalChecked(); - - return scope.Escape(instance); - } - - private: - RSFrameQueue() : frame_queue_(nullptr), error_(nullptr) {} - - ~RSFrameQueue() { - DestroyMe(); - } - - void DestroyMe() { - if (error_) rs2_free_error(error_); - error_ = nullptr; - if (frame_queue_) rs2_delete_frame_queue(frame_queue_); - frame_queue_ = nullptr; - } - - static void New(const Nan::FunctionCallbackInfo& info) { - if (info.IsConstructCall()) { - RSFrameQueue* obj = new RSFrameQueue(); - obj->Wrap(info.This()); - info.GetReturnValue().Set(info.This()); - } - } - - static NAN_METHOD(WaitForFrame) { - info.GetReturnValue().Set(Nan::Undefined()); - int32_t timeout = Nan::To(info[0]).FromJust(); // in ms - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - auto frame = GetNativeResult(rs2_wait_for_frame, &me->error_, - me->frame_queue_, timeout, &me->error_); - if (!frame) return; - - info.GetReturnValue().Set(RSFrame::NewInstance(frame)); - } - - static NAN_METHOD(Create) { - info.GetReturnValue().Set(Nan::Undefined()); - int32_t capacity = Nan::To(info[0]).FromJust(); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - me->frame_queue_ = GetNativeResult(rs2_create_frame_queue, - &me->error_, capacity, &me->error_); - } - - static NAN_METHOD(Destroy) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) { - me->DestroyMe(); - } - info.GetReturnValue().Set(Nan::Undefined()); - } - - static NAN_METHOD(PollForFrame) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - rs2_frame* frame = nullptr; - auto res = GetNativeResult(rs2_poll_for_frame, &me->error_, - me->frame_queue_, &frame, &me->error_); - if (!res) return; - - info.GetReturnValue().Set(RSFrame::NewInstance(frame)); - } - - static NAN_METHOD(EnqueueFrame) { - v8::Local context = info.GetIsolate()->GetCurrentContext(); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - auto frame = Nan::ObjectWrap::Unwrap( - info[0]->ToObject(context).ToLocalChecked()); - - if (me && frame) { - rs2_enqueue_frame(frame->frame_, me->frame_queue_); - frame->frame_ = nullptr; - } - info.GetReturnValue().Set(Nan::Undefined()); - } - - private: - static Nan::Persistent constructor_; - rs2_frame_queue* frame_queue_; - rs2_error* error_; - friend class RSDevice; -}; - -Nan::Persistent RSFrameQueue::constructor_; - -class RSDevice; -class RSSensor; -class FrameCallbackInfo : public MainThreadCallbackInfo { - public: - FrameCallbackInfo(rs2_frame* frame, void* data) : - frame_(frame), sensor_(static_cast(data)) {} - virtual ~FrameCallbackInfo() { if (!consumed_) Release(); } - virtual void Run(); - virtual void Release() { - if (frame_) { - rs2_release_frame(frame_); - frame_ = nullptr; - } - } - - private: - rs2_frame* frame_; - RSSensor* sensor_; -}; - -class NotificationCallbackInfo : public MainThreadCallbackInfo { - public: - NotificationCallbackInfo(const char* desc, - rs2_time_t time, - rs2_log_severity severity, - rs2_notification_category category, - std::string serialized_data, - RSSensor* s) : - desc_(desc), time_(time), severity_(severity), - category_(category), serialized_data_(serialized_data), - sensor_(s) {} - virtual ~NotificationCallbackInfo() {} - virtual void Run(); - - private: - std::string desc_; - rs2_time_t time_; - rs2_log_severity severity_; - rs2_notification_category category_; - std::string serialized_data_; - RSSensor* sensor_; - rs2_error* error_; -}; - -class NotificationCallback : public rs2_notifications_callback { - public: - explicit NotificationCallback(RSSensor* s) : error_(nullptr), sensor_(s) {} - void on_notification(rs2_notification* notification) override { - if (notification) { - const char* desc = GetNativeResult( - rs2_get_notification_description, &error_, notification, &error_); - rs2_time_t time = GetNativeResult( - rs2_get_notification_timestamp, &error_, notification, &error_); - rs2_log_severity severity = GetNativeResult( - rs2_get_notification_severity, &error_, notification, &error_); - rs2_notification_category category = - GetNativeResult( - rs2_get_notification_category, &error_, notification, &error_); - std::string serialized_data = GetNativeResult( - rs2_get_notification_serialized_data, &error_, notification, &error_); - MainThreadCallback::NotifyMainThread(new NotificationCallbackInfo(desc, - time, severity, category, serialized_data, sensor_)); - } - } - void release() override { delete this; } - rs2_error* error_; - RSSensor* sensor_; -}; - -class FrameCallbackForFrameQueue : public rs2_frame_callback { - public: - explicit FrameCallbackForFrameQueue(rs2_frame_queue* queue) - : frame_queue_(queue) {} - void on_frame(rs2_frame* frame) override { - if (frame && frame_queue_) - rs2_enqueue_frame(frame, frame_queue_); - } - void release() override { delete this; } - rs2_frame_queue* frame_queue_; -}; - -class FrameCallbackForProc : public rs2_frame_callback { - public: - explicit FrameCallbackForProc(void* data) : callback_data_(data) {} - void on_frame(rs2_frame* frame) override { - MainThreadCallback::NotifyMainThread( - new FrameCallbackInfo(frame, callback_data_)); - } - void release() override { delete this; } - void* callback_data_; -}; - -class FrameCallbackForProcessingBlock : public rs2_frame_callback { - public: - explicit FrameCallbackForProcessingBlock(rs2_processing_block* block_ptr) : - block_(block_ptr), error_(nullptr) {} - virtual ~FrameCallbackForProcessingBlock() { - if (error_) rs2_free_error(error_); - } - void on_frame(rs2_frame* frame) override { - rs2_process_frame(block_, frame, &error_); - } - void release() override { delete this; } - rs2_processing_block* block_; - rs2_error* error_; -}; - -class PlaybackStatusCallbackInfo : public MainThreadCallbackInfo { - public: - PlaybackStatusCallbackInfo(rs2_playback_status status, RSDevice* dev) : - status_(status), dev_(dev), error_(nullptr) {} - virtual ~PlaybackStatusCallbackInfo() {} - virtual void Run(); - - private: - rs2_playback_status status_; - RSDevice* dev_; - rs2_error* error_; -}; - -class PlaybackStatusCallback : public rs2_playback_status_changed_callback { - public: - explicit PlaybackStatusCallback(RSDevice* dev) : error_(nullptr), dev_(dev) {} - void on_playback_status_changed(rs2_playback_status status) override { - MainThreadCallback::NotifyMainThread(new PlaybackStatusCallbackInfo(status, - dev_)); - } - void release() override { delete this; } - - private: - rs2_error* error_; - RSDevice* dev_; -}; - -class StreamProfileExtrator { - public: - explicit StreamProfileExtrator(const rs2_stream_profile* profile) { - rs2_get_stream_profile_data(profile, &stream_, &format_, &index_, - &unique_id_, &fps_, &error_); - } - ~StreamProfileExtrator() {} - rs2_stream stream_; - rs2_format format_; - int32_t fps_; - int32_t index_; - int32_t unique_id_; - rs2_error* error_; -}; - -class RSFrameSet : public Nan::ObjectWrap { - public: - static void Init(v8::Local exports) { - v8::Local tpl = Nan::New(New); - tpl->SetClassName(Nan::New("RSFrameSet").ToLocalChecked()); - tpl->InstanceTemplate()->SetInternalFieldCount(1); - - Nan::SetPrototypeMethod(tpl, "destroy", Destroy); - Nan::SetPrototypeMethod(tpl, "getSize", GetSize); - Nan::SetPrototypeMethod(tpl, "getFrame", GetFrame); - Nan::SetPrototypeMethod(tpl, "replaceFrame", ReplaceFrame); - Nan::SetPrototypeMethod(tpl, "indexToStream", IndexToStream); - Nan::SetPrototypeMethod(tpl, "indexToStreamIndex", IndexToStreamIndex); - v8::Local context = exports->CreationContext(); - constructor_.Reset(tpl->GetFunction(context).ToLocalChecked()); - exports->Set(context, Nan::New("RSFrameSet").ToLocalChecked(), - tpl->GetFunction(context).ToLocalChecked()); - } - - static v8::Local NewInstance(rs2_frame* frame) { - Nan::EscapableHandleScope scope; - - v8::Local cons = Nan::New(constructor_); - v8::Local context = Nan::GetCurrentContext(); - - v8::Local instance = - cons->NewInstance(context, 0, nullptr).ToLocalChecked(); - auto me = Nan::ObjectWrap::Unwrap(instance); - me->SetFrame(frame); - - return scope.Escape(instance); - } - - rs2_frame* GetFrames() { - return frames_; - } - - void Replace(rs2_frame* frame) { - DestroyMe(); - SetFrame(frame); - } - - private: - RSFrameSet() { - error_ = nullptr; - frames_ = nullptr; - } - - ~RSFrameSet() { - DestroyMe(); - } - - void SetFrame(rs2_frame* frame) { - if (!frame || (!GetNativeResult(rs2_is_frame_extendable_to, &error_, - frame, RS2_EXTENSION_COMPOSITE_FRAME, &error_))) return; - - frames_ = frame; - frame_count_ = GetNativeResult(rs2_embedded_frames_count, &error_, - frame, &error_); - } - - void DestroyMe() { - if (error_) rs2_free_error(error_); - error_ = nullptr; - if (frames_) rs2_release_frame(frames_); - frames_ = nullptr; - } - - static NAN_METHOD(Destroy) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) { - me->DestroyMe(); - } - info.GetReturnValue().Set(Nan::Undefined()); - } - - static void New(const Nan::FunctionCallbackInfo& info) { - if (info.IsConstructCall()) { - RSFrameSet* obj = new RSFrameSet(); - obj->Wrap(info.This()); - info.GetReturnValue().Set(info.This()); - } - } - - static NAN_METHOD(GetSize) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me && me->frames_) { - info.GetReturnValue().Set(Nan::New(me->frame_count_)); - return; - } - info.GetReturnValue().Set(Nan::New(0)); - } - - static NAN_METHOD(GetFrame) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me || !me->frames_) return; - - rs2_stream stream = - static_cast(Nan::To(info[0]).FromJust()); - auto stream_index = Nan::To(info[1]).FromJust(); - // if RS2_STREAM_ANY is used, we return the first frame. - if (stream == RS2_STREAM_ANY && me->frame_count_) { - rs2_frame* frame = GetNativeResult(rs2_extract_frame, - &me->error_, me->frames_, 0, &me->error_); - if (!frame) return; - - info.GetReturnValue().Set(RSFrame::NewInstance(frame)); - return; - } - - for (uint32_t i=0; i < me->frame_count_; i++) { - rs2_frame* frame = GetNativeResult(rs2_extract_frame, - &me->error_, me->frames_, i, &me->error_); - if (!frame) continue; - - const rs2_stream_profile* profile = - GetNativeResult( - rs2_get_frame_stream_profile, &me->error_, frame, &me->error_); - if (profile) { - StreamProfileExtrator extrator(profile); - if (extrator.stream_ == stream && (!stream_index || - (stream_index && stream_index == extrator.index_))) { - info.GetReturnValue().Set(RSFrame::NewInstance(frame)); - return; - } - } - rs2_release_frame(frame); - } - } - - static NAN_METHOD(ReplaceFrame) { - info.GetReturnValue().Set(Nan::False()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - rs2_stream stream = - static_cast(Nan::To(info[0]).FromJust()); - auto stream_index = Nan::To(info[1]).FromJust(); - auto target_frame = Nan::ObjectWrap::Unwrap( - Nan::To(info[2]).ToLocalChecked()); - - if (!me || !me->frames_) return; - - for (uint32_t i = 0; i < me->frame_count_; i++) { - rs2_frame* frame = GetNativeResult(rs2_extract_frame, - &me->error_, me->frames_, i, &me->error_); - if (!frame) continue; - - const rs2_stream_profile* profile = - GetNativeResult( - rs2_get_frame_stream_profile, &me->error_, frame, &me->error_); - if (profile) { - StreamProfileExtrator extrator(profile); - if (extrator.stream_ == stream && (!stream_index || - (stream_index && stream_index == extrator.index_))) { - target_frame->Replace(frame); - info.GetReturnValue().Set(Nan::True()); - return; - } - } - rs2_release_frame(frame); - } - } - - static NAN_METHOD(IndexToStream) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me || !me->frames_) return; - - int32_t index = Nan::To(info[0]).FromJust(); - rs2_frame* frame = GetNativeResult(rs2_extract_frame, - &me->error_, me->frames_, index, &me->error_); - if (!frame) return; - - const rs2_stream_profile* profile = - GetNativeResult(rs2_get_frame_stream_profile, - &me->error_, frame, &me->error_); - if (!profile) { - rs2_release_frame(frame); - return; - } - - rs2_stream stream = RS2_STREAM_ANY; - rs2_format format = RS2_FORMAT_ANY; - int32_t fps = 0; - int32_t idx = 0; - int32_t unique_id = 0; - CallNativeFunc(rs2_get_stream_profile_data, &me->error_, profile, &stream, - &format, &idx, &unique_id, &fps, &me->error_); - rs2_release_frame(frame); - if (me->error_) return; - - info.GetReturnValue().Set(Nan::New(stream)); - } - - static NAN_METHOD(IndexToStreamIndex) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - info.GetReturnValue().Set(Nan::Undefined()); - if (!me || !me->frames_) return; - - int32_t index = Nan::To(info[0]).FromJust(); - rs2_frame* frame = GetNativeResult(rs2_extract_frame, - &me->error_, me->frames_, index, &me->error_); - if (!frame) return; - - const rs2_stream_profile* profile = - GetNativeResult(rs2_get_frame_stream_profile, - &me->error_, frame, &me->error_); - if (!profile) { - rs2_release_frame(frame); - return; - } - rs2_stream stream = RS2_STREAM_ANY; - rs2_format format = RS2_FORMAT_ANY; - int32_t fps = 0; - int32_t idx = 0; - int32_t unique_id = 0; - CallNativeFunc(rs2_get_stream_profile_data, &me->error_, profile, &stream, - &format, &idx, &unique_id, &fps, &me->error_); - rs2_release_frame(frame); - if (me->error_) return; - - info.GetReturnValue().Set(Nan::New(idx)); - } - - private: - static Nan::Persistent constructor_; - rs2_frame* frames_; - uint32_t frame_count_; - rs2_error* error_; -}; - -Nan::Persistent RSFrameSet::constructor_; - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -// -// .d8888b. // -// d88P Y88b // -// Y88b. // -// "Y888b. 888 888 88888b. .d8888b .d88b. 888d888 // -// "Y88b. 888 888 888 "88b d88P" d8P Y8b 888P" // -// "888 888 888 888 888 888 88888888 888 // -// Y88b d88P Y88b 888 888 888 Y88b. Y8b. 888 // -// "Y8888P" "Y88888 888 888 "Y8888P "Y8888 888 // -// 888 // -// Y8b d88P // -// "Y88P" // -// -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -class RSSyncer : public Nan::ObjectWrap { - public: - static void Init(v8::Local exports) { - v8::Local tpl = Nan::New(New); - tpl->SetClassName(Nan::New("RSSyncer").ToLocalChecked()); - tpl->InstanceTemplate()->SetInternalFieldCount(1); - - Nan::SetPrototypeMethod(tpl, "destroy", Destroy); - Nan::SetPrototypeMethod(tpl, "waitForFrames", WaitForFrames); - Nan::SetPrototypeMethod(tpl, "pollForFrames", PollForFrames); - - v8::Local context = exports->CreationContext(); - constructor_.Reset(tpl->GetFunction(context).ToLocalChecked()); - exports->Set(context, Nan::New("RSSyncer").ToLocalChecked(), - tpl->GetFunction(context).ToLocalChecked()); - } - - static v8::Local NewInstance() { - Nan::EscapableHandleScope scope; - - v8::Local cons = Nan::New(constructor_); - v8::Local context = Nan::GetCurrentContext(); - - v8::Local instance = - cons->NewInstance(context, 0, nullptr).ToLocalChecked(); - - return scope.Escape(instance); - } - - private: - RSSyncer() : syncer_(nullptr), frame_queue_(nullptr), error_(nullptr) {} - - ~RSSyncer() { - DestroyMe(); - } - - void DestroyMe() { - if (error_) rs2_free_error(error_); - error_ = nullptr; - if (syncer_) rs2_delete_processing_block(syncer_); - syncer_ = nullptr; - if (frame_queue_) rs2_delete_frame_queue(frame_queue_); - frame_queue_ = nullptr; - } - - static void New(const Nan::FunctionCallbackInfo& info) { - if (info.IsConstructCall()) { - RSSyncer* obj = new RSSyncer(); - obj->syncer_ = GetNativeResult( - rs2_create_sync_processing_block, &obj->error_, &obj->error_); - obj->frame_queue_ = GetNativeResult( - rs2_create_frame_queue, &obj->error_, 1, &obj->error_); - auto callback = new FrameCallbackForFrameQueue(obj->frame_queue_); - CallNativeFunc(rs2_start_processing, &obj->error_, obj->syncer_, callback, - &obj->error_); - obj->Wrap(info.This()); - info.GetReturnValue().Set(info.This()); - } - } - - static NAN_METHOD(WaitForFrames) { - info.GetReturnValue().Set(Nan::False()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - auto frameset = Nan::ObjectWrap::Unwrap( - Nan::To(info[0]).ToLocalChecked()); - auto timeout = Nan::To(info[1]).FromJust(); - if (!me || !frameset) return; - - rs2_frame* frames = GetNativeResult(rs2_wait_for_frame, - &me->error_, me->frame_queue_, timeout, &me->error_); - if (!frames) return; - - frameset->Replace(frames); - info.GetReturnValue().Set(Nan::True()); - } - - static NAN_METHOD(Destroy) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) { - me->DestroyMe(); - } - info.GetReturnValue().Set(Nan::Undefined()); - } - - static NAN_METHOD(PollForFrames) { - info.GetReturnValue().Set(Nan::False()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - auto frameset = Nan::ObjectWrap::Unwrap( - Nan::To(info[0]).ToLocalChecked()); - if (!me || !frameset) return; - - rs2_frame* frame_ref = nullptr; - auto res = GetNativeResult(rs2_poll_for_frame, &me->error_, - me->frame_queue_, &frame_ref, &me->error_); - if (!res) return; - - frameset->Replace(frame_ref); - info.GetReturnValue().Set(Nan::True()); - } - - private: - static Nan::Persistent constructor_; - rs2_processing_block* syncer_; - rs2_frame_queue* frame_queue_; - rs2_error* error_; - friend class RSSensor; -}; - -Nan::Persistent RSSyncer::constructor_; - -class Options { - public: - Options() : error_(nullptr) {} - - virtual ~Options() { - if (error_) rs2_free_error(error_); - } - - virtual rs2_options* GetOptionsPointer() = 0; - - void SupportsOptionInternal( - const Nan::FunctionCallbackInfo& info) { - int32_t option = Nan::To(info[0]).FromJust(); - auto on = GetNativeResult(rs2_supports_option, &error_, - GetOptionsPointer(), static_cast(option), &error_); - info.GetReturnValue().Set(Nan::New(on ? true : false)); - return; - } - - void GetOptionInternal(const Nan::FunctionCallbackInfo& info) { - int32_t option = Nan::To(info[0]).FromJust(); - auto value = GetNativeResult(rs2_get_option, &error_, - GetOptionsPointer(), static_cast(option), &error_); - info.GetReturnValue().Set(Nan::New(value)); - } - - void GetOptionDescriptionInternal( - const Nan::FunctionCallbackInfo& info) { - int32_t option = Nan::To(info[0]).FromJust(); - auto desc = GetNativeResult(rs2_get_option_description, - &error_, GetOptionsPointer(), static_cast(option), &error_); - if (desc) - info.GetReturnValue().Set(Nan::New(desc).ToLocalChecked()); - else - info.GetReturnValue().Set(Nan::Undefined()); - } - - void GetOptionValueDescriptionInternal( - const Nan::FunctionCallbackInfo& info) { - int32_t option = Nan::To(info[0]).FromJust(); - auto val = Nan::To(info[1]).FromJust(); - auto desc = GetNativeResult(rs2_get_option_value_description, - &error_, GetOptionsPointer(), static_cast(option), - val, &error_); - if (desc) - info.GetReturnValue().Set(Nan::New(desc).ToLocalChecked()); - else - info.GetReturnValue().Set(Nan::Undefined()); - } - - void SetOptionInternal(const Nan::FunctionCallbackInfo& info) { - int32_t option = Nan::To(info[0]).FromJust(); - auto val = Nan::To(info[1]).FromJust(); - CallNativeFunc(rs2_set_option, &error_, GetOptionsPointer(), - static_cast(option), val, &error_); - info.GetReturnValue().Set(Nan::Undefined()); - } - - void GetOptionRangeInternal( - const Nan::FunctionCallbackInfo& info) { - int32_t option = Nan::To(info[0]).FromJust(); - float min = 0; - float max = 0; - float step = 0; - float def = 0; - CallNativeFunc(rs2_get_option_range, &error_, GetOptionsPointer(), - static_cast(option), &min, &max, &step, &def, &error_); - info.GetReturnValue().Set(RSOptionRange(min, max, step, def).GetObject()); - } - - void IsOptionReadonlyInternal( - const Nan::FunctionCallbackInfo& info) { - int32_t option = Nan::To(info[0]).FromJust(); - auto val = GetNativeResult(rs2_is_option_read_only, &error_, - GetOptionsPointer(), static_cast(option), &error_); - info.GetReturnValue().Set(Nan::New((val) ? true : false)); - } - - private: - rs2_error* error_; -}; - -class RSSensor : public Nan::ObjectWrap, Options { - public: - static void Init(v8::Local exports) { - v8::Local tpl = Nan::New(New); - tpl->SetClassName(Nan::New("RSSensor").ToLocalChecked()); - tpl->InstanceTemplate()->SetInternalFieldCount(1); - - Nan::SetPrototypeMethod(tpl, "destroy", Destroy); - Nan::SetPrototypeMethod(tpl, "openStream", OpenStream); - Nan::SetPrototypeMethod(tpl, "openMultipleStream", OpenMultipleStream); - Nan::SetPrototypeMethod(tpl, "getCameraInfo", GetCameraInfo); - Nan::SetPrototypeMethod(tpl, "startWithSyncer", StartWithSyncer); - Nan::SetPrototypeMethod(tpl, "startWithCallback", StartWithCallback); - Nan::SetPrototypeMethod(tpl, "supportsOption", SupportsOption); - Nan::SetPrototypeMethod(tpl, "getOption", GetOption); - Nan::SetPrototypeMethod(tpl, "setOption", SetOption); - Nan::SetPrototypeMethod(tpl, "getOptionRange", GetOptionRange); - Nan::SetPrototypeMethod(tpl, "isOptionReadonly", IsOptionReadonly); - Nan::SetPrototypeMethod(tpl, "getOptionDescription", GetOptionDescription); - Nan::SetPrototypeMethod(tpl, "getOptionValueDescription", - GetOptionValueDescription); - Nan::SetPrototypeMethod(tpl, "stop", Stop); - Nan::SetPrototypeMethod(tpl, "supportsCameraInfo", SupportsCameraInfo); - Nan::SetPrototypeMethod(tpl, "getStreamProfiles", GetStreamProfiles); - Nan::SetPrototypeMethod(tpl, "close", Close); - Nan::SetPrototypeMethod(tpl, "setNotificationCallback", - SetNotificationCallback); - Nan::SetPrototypeMethod(tpl, "setRegionOfInterest", SetRegionOfInterest); - Nan::SetPrototypeMethod(tpl, "getRegionOfInterest", GetRegionOfInterest); - Nan::SetPrototypeMethod(tpl, "getDepthScale", GetDepthScale); - Nan::SetPrototypeMethod(tpl, "isROISensor", IsROISensor); - Nan::SetPrototypeMethod(tpl, "is", Is); - - v8::Local context = exports->CreationContext(); - constructor_.Reset(tpl->GetFunction(context).ToLocalChecked()); - exports->Set(context, Nan::New("RSSensor").ToLocalChecked(), - tpl->GetFunction(context).ToLocalChecked()); - } - - static v8::Local NewInstance(rs2_sensor* sensor) { - Nan::EscapableHandleScope scope; - - v8::Local cons = Nan::New(constructor_); - v8::Local context = Nan::GetCurrentContext(); - - v8::Local instance = - cons->NewInstance(context, 0, nullptr).ToLocalChecked(); - - auto me = Nan::ObjectWrap::Unwrap(instance); - me->sensor_ = sensor; - return scope.Escape(instance); - } - - rs2_options* GetOptionsPointer() override { - // TODO(shaoting) find better way to avoid the reinterpret_cast which was - // caused the inheritance relation was hidden - return reinterpret_cast(sensor_); - } - - void ReplaceFrame(rs2_frame* raw_frame) { - // clear old frame first. - frame_->Replace(nullptr); - video_frame_->Replace(nullptr); - depth_frame_->Replace(nullptr); - disparity_frame_->Replace(nullptr); - motion_frame_->Replace(nullptr); - pose_frame_->Replace(nullptr); - - if (GetNativeResult(rs2_is_frame_extendable_to, &error_, - raw_frame, RS2_EXTENSION_DISPARITY_FRAME, &error_)) { - disparity_frame_->Replace(raw_frame); - } else if (GetNativeResult(rs2_is_frame_extendable_to, &error_, - raw_frame, RS2_EXTENSION_DEPTH_FRAME, &error_)) { - depth_frame_->Replace(raw_frame); - } else if (GetNativeResult(rs2_is_frame_extendable_to, &error_, - raw_frame, RS2_EXTENSION_VIDEO_FRAME, &error_)) { - video_frame_->Replace(raw_frame); - } else if (GetNativeResult(rs2_is_frame_extendable_to, &error_, - raw_frame, RS2_EXTENSION_MOTION_FRAME, &error_)) { - motion_frame_->Replace(raw_frame); - } else if (GetNativeResult(rs2_is_frame_extendable_to, &error_, - raw_frame, RS2_EXTENSION_POSE_FRAME, &error_)) { - pose_frame_->Replace(raw_frame); - } else { - frame_->Replace(raw_frame); - } - } - - private: - RSSensor() : sensor_(nullptr), error_(nullptr), profile_list_(nullptr), - frame_(nullptr), video_frame_(nullptr), depth_frame_(nullptr), - disparity_frame_(nullptr), motion_frame_(nullptr), pose_frame_(nullptr) {} - - ~RSSensor() { - DestroyMe(); - } - - void RegisterNotificationCallbackMethod(); - - void DestroyMe() { - if (error_) rs2_free_error(error_); - error_ = nullptr; - if (sensor_) rs2_delete_sensor(sensor_); - sensor_ = nullptr; - if (profile_list_) rs2_delete_stream_profiles_list(profile_list_); - profile_list_ = nullptr; - } - - static void New(const Nan::FunctionCallbackInfo& info) { - if (info.IsConstructCall()) { - RSSensor* obj = new RSSensor(); - obj->Wrap(info.This()); - info.GetReturnValue().Set(info.This()); - } - } - - static NAN_METHOD(SupportsOption) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) return me->SupportsOptionInternal(info); - - info.GetReturnValue().Set(Nan::False()); - } - - static NAN_METHOD(GetOption) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) return me->GetOptionInternal(info); - - info.GetReturnValue().Set(Nan::Undefined()); - } - - static NAN_METHOD(GetOptionDescription) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) return me->GetOptionDescriptionInternal(info); - - info.GetReturnValue().Set(Nan::Undefined()); - } - - static NAN_METHOD(GetOptionValueDescription) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) return me->GetOptionValueDescriptionInternal(info); - - info.GetReturnValue().Set(Nan::Undefined()); - } - - static NAN_METHOD(SetOption) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) return me->SetOptionInternal(info); - - info.GetReturnValue().Set(Nan::Undefined()); - } - - static NAN_METHOD(GetOptionRange) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) return me->GetOptionRangeInternal(info); - - info.GetReturnValue().Set(Nan::Undefined()); - } - - static NAN_METHOD(IsOptionReadonly) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) return me->IsOptionReadonlyInternal(info); - - info.GetReturnValue().Set(Nan::False()); - } - - static NAN_METHOD(GetCameraInfo) { - info.GetReturnValue().Set(Nan::Undefined()); - int32_t camera_info = Nan::To(info[0]).FromJust(); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - auto value = GetNativeResult(rs2_get_sensor_info, - &me->error_, me->sensor_, static_cast(camera_info), - &me->error_); - if (me->error_) return; - - info.GetReturnValue().Set(Nan::New(value).ToLocalChecked()); - } - - static NAN_METHOD(StartWithSyncer) { - info.GetReturnValue().Set(Nan::Undefined()); - auto syncer = Nan::ObjectWrap::Unwrap( - Nan::To(info[0]).ToLocalChecked()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me || !syncer) return; - - CallNativeFunc(rs2_start_cpp, &me->error_, me->sensor_, - new FrameCallbackForProcessingBlock(syncer->syncer_), &me->error_); - } - - static NAN_METHOD(StartWithCallback) { - auto frame = Nan::ObjectWrap::Unwrap( - Nan::To(info[1]).ToLocalChecked()); - auto depth_frame = Nan::ObjectWrap::Unwrap( - Nan::To(info[2]).ToLocalChecked()); - auto video_frame = Nan::ObjectWrap::Unwrap( - Nan::To(info[3]).ToLocalChecked()); - auto disparity_frame = Nan::ObjectWrap::Unwrap( - Nan::To(info[4]).ToLocalChecked()); - auto motion_frame = Nan::ObjectWrap::Unwrap( - Nan::To(info[5]).ToLocalChecked()); - auto pose_frame = Nan::ObjectWrap::Unwrap( - Nan::To(info[6]).ToLocalChecked()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me && frame && depth_frame && video_frame && disparity_frame && - motion_frame && pose_frame) { - me->frame_ = frame; - me->depth_frame_ = depth_frame; - me->video_frame_ = video_frame; - me->disparity_frame_ = disparity_frame; - me->motion_frame_ = motion_frame; - me->pose_frame_ = pose_frame; - Nan::Utf8String str(info[0]); - me->frame_callback_name_ = std::string(*str); - CallNativeFunc(rs2_start_cpp, &me->error_, me->sensor_, - new FrameCallbackForProc(me), &me->error_); - } - info.GetReturnValue().Set(Nan::Undefined()); - } - - static NAN_METHOD(Destroy) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) { - me->DestroyMe(); - } - info.GetReturnValue().Set(Nan::Undefined()); - } - - static NAN_METHOD(OpenStream) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - auto profile = Nan::ObjectWrap::Unwrap( - Nan::To(info[0]).ToLocalChecked()); - if (!me || !profile) return; - - CallNativeFunc(rs2_open, &me->error_, me->sensor_, profile->profile_, - &me->error_); - } - - static NAN_METHOD(OpenMultipleStream) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - auto array = v8::Local::Cast(info[0]); - uint32_t len = array->Length(); - std::vector profs; - v8::Local context = info.GetIsolate()->GetCurrentContext(); - for (uint32_t i=0; i < len; i++) { - auto profile = Nan::ObjectWrap::Unwrap( - Nan::To( - array->Get(context, i).ToLocalChecked()).ToLocalChecked()); - profs.push_back(profile->profile_); - } - CallNativeFunc(rs2_open_multiple, &me->error_, me->sensor_, profs.data(), - len, &me->error_); - } - - static NAN_METHOD(Stop) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - CallNativeFunc(rs2_stop, &me->error_, me->sensor_, &me->error_); - } - - static NAN_METHOD(GetStreamProfiles) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - rs2_stream_profile_list* list = me->profile_list_; - if (!list) { - list = GetNativeResult(rs2_get_stream_profiles, - &me->error_, me->sensor_, &me->error_); - me->profile_list_ = list; - } - if (!list) return; - - int32_t size = GetNativeResult(rs2_get_stream_profiles_count, - &me->error_, list, &me->error_); - - v8::Local context = info.GetIsolate()->GetCurrentContext(); - v8::Local array = Nan::New(size); - for (int32_t i = 0; i < size; i++) { - rs2_stream_profile* profile = const_cast( - rs2_get_stream_profile(list, i, &me->error_)); - array->Set(context, i, RSStreamProfile::NewInstance(profile)); - } - info.GetReturnValue().Set(array); - } - - static NAN_METHOD(SupportsCameraInfo) { - info.GetReturnValue().Set(Nan::False()); - int32_t camera_info = Nan::To(info[0]).FromJust(); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - int32_t on = GetNativeResult(rs2_supports_sensor_info, &me->error_, - me->sensor_, (rs2_camera_info)camera_info, &me->error_); - info.GetReturnValue().Set(Nan::New(on ? true : false)); - } - - static NAN_METHOD(Close) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - CallNativeFunc(rs2_close, &me->error_, me->sensor_, &me->error_); - } - - static NAN_METHOD(SetNotificationCallback) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - Nan::Utf8String value(Nan::To(info[0]).ToLocalChecked()); - me->notification_callback_name_ = std::string(*value); - me->RegisterNotificationCallbackMethod(); - } - - static NAN_METHOD(SetRegionOfInterest) { - info.GetReturnValue().Set(Nan::Undefined()); - int32_t minx = Nan::To(info[0]).FromJust(); - int32_t miny = Nan::To(info[1]).FromJust(); - int32_t maxx = Nan::To(info[2]).FromJust(); - int32_t maxy = Nan::To(info[3]).FromJust(); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - CallNativeFunc(rs2_set_region_of_interest, &me->error_, me->sensor_, minx, - miny, maxx, maxy, &me->error_); - } - - static NAN_METHOD(GetRegionOfInterest) { - info.GetReturnValue().Set(Nan::Undefined()); - int32_t minx = 0; - int32_t miny = 0; - int32_t maxx = 0; - int32_t maxy = 0; - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - CallNativeFunc(rs2_get_region_of_interest, &me->error_, me->sensor_, &minx, - &miny, &maxx, &maxy, &me->error_); - if (me->error_) return; - info.GetReturnValue().Set( - RSRegionOfInterest(minx, miny, maxx, maxy).GetObject()); - } - - static NAN_METHOD(GetDepthScale) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - auto scale = GetNativeResult(rs2_get_depth_scale, &me->error_, - me->sensor_, &me->error_); - if (me->error_) return; - - info.GetReturnValue().Set(Nan::New(scale)); - } - - static NAN_METHOD(Is) { - info.GetReturnValue().Set(Nan::Undefined()); - int32_t stype = Nan::To(info[0]).FromJust(); - - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - bool is_ok = GetNativeResult(rs2_is_sensor_extendable_to, - &me->error_, me->sensor_, - static_cast(stype), &me->error_); - if (me->error_) return; - - info.GetReturnValue().Set(Nan::New(is_ok)); - } - - static NAN_METHOD(IsROISensor) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - bool is_roi = GetNativeResult(rs2_is_sensor_extendable_to, &me->error_, - me->sensor_, RS2_EXTENSION_ROI, &me->error_); - if (me->error_) return; - - info.GetReturnValue().Set(Nan::New(is_roi)); - } - - private: - static Nan::Persistent constructor_; - rs2_sensor* sensor_; - rs2_error* error_; - rs2_stream_profile_list* profile_list_; - std::string frame_callback_name_; - std::string notification_callback_name_; - RSFrame* frame_; - RSFrame* video_frame_; - RSFrame* depth_frame_; - RSFrame* disparity_frame_; - RSFrame* motion_frame_; - RSFrame* pose_frame_; - friend class RSContext; - friend class DevicesChangedCallbackInfo; - friend class FrameCallbackInfo; - friend class NotificationCallbackInfo; -}; - -Nan::Persistent RSSensor::constructor_; - -void RSSensor::RegisterNotificationCallbackMethod() { - CallNativeFunc(rs2_set_notifications_callback_cpp, &error_, sensor_, - new NotificationCallback(this), &error_); -} - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -// -// 8888888b. .d8888b. 8888888b. d8b // -// 888 Y88b d88P Y88b 888 "Y88b Y8P // -// 888 888 Y88b. 888 888 // -// 888 d88P "Y888b. 888 888 .d88b. 888 888 888 .d8888b .d88b. // -// 8888888P" "Y88b. 888 888 d8P Y8b 888 888 888 d88P" d8P Y8b // -// 888 T88b "888 888 888 88888888 Y88 88P 888 888 88888888 // -// 888 T88b Y88b d88P 888 .d88P Y8b. Y8bd8P 888 Y88b. Y8b. // -// 888 T88b "Y8888P" 8888888P" "Y8888 Y88P 888 "Y8888P "Y8888 // -// -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -class RSDevice : public Nan::ObjectWrap { - public: - enum DeviceType { - kNormalDevice = 0, - kRecorderDevice, - kPlaybackDevice, - }; - static void Init(v8::Local exports) { - v8::Local tpl = Nan::New(New); - tpl->SetClassName(Nan::New("RSDevice").ToLocalChecked()); - tpl->InstanceTemplate()->SetInternalFieldCount(1); - - Nan::SetPrototypeMethod(tpl, "destroy", Destroy); - Nan::SetPrototypeMethod(tpl, "getCameraInfo", GetCameraInfo); - Nan::SetPrototypeMethod(tpl, "supportsCameraInfo", SupportsCameraInfo); - Nan::SetPrototypeMethod(tpl, "reset", Reset); - Nan::SetPrototypeMethod(tpl, "querySensors", QuerySensors); - Nan::SetPrototypeMethod(tpl, "triggerErrorForTest", TriggerErrorForTest); - Nan::SetPrototypeMethod(tpl, "spawnRecorderDevice", SpawnRecorderDevice); - - // Methods for record or playback - Nan::SetPrototypeMethod(tpl, "pauseRecord", PauseRecord); - Nan::SetPrototypeMethod(tpl, "resumeRecord", ResumeRecord); - Nan::SetPrototypeMethod(tpl, "getFileName", GetFileName); - Nan::SetPrototypeMethod(tpl, "pausePlayback", PausePlayback); - Nan::SetPrototypeMethod(tpl, "resumePlayback", ResumePlayback); - Nan::SetPrototypeMethod(tpl, "stopPlayback", StopPlayback); - Nan::SetPrototypeMethod(tpl, "getPosition", GetPosition); - Nan::SetPrototypeMethod(tpl, "getDuration", GetDuration); - Nan::SetPrototypeMethod(tpl, "seek", Seek); - Nan::SetPrototypeMethod(tpl, "isRealTime", IsRealTime); - Nan::SetPrototypeMethod(tpl, "setIsRealTime", SetIsRealTime); - Nan::SetPrototypeMethod(tpl, "setPlaybackSpeed", SetPlaybackSpeed); - Nan::SetPrototypeMethod(tpl, "getCurrentStatus", GetCurrentStatus); - Nan::SetPrototypeMethod(tpl, "setStatusChangedCallbackMethodName", - SetStatusChangedCallbackMethodName); - Nan::SetPrototypeMethod(tpl, "isTm2", IsTm2); - Nan::SetPrototypeMethod(tpl, "isPlayback", IsPlayback); - Nan::SetPrototypeMethod(tpl, "isRecorder", IsRecorder); - - // methods of tm2 device - Nan::SetPrototypeMethod(tpl, "enableLoopback", EnableLoopback); - Nan::SetPrototypeMethod(tpl, "disableLoopback", DisableLoopback); - Nan::SetPrototypeMethod(tpl, "isLoopbackEnabled", IsLoopbackEnabled); - - v8::Local context = exports->CreationContext(); - constructor_.Reset(tpl->GetFunction(context).ToLocalChecked()); - exports->Set(context, Nan::New("RSDevice").ToLocalChecked(), - tpl->GetFunction(context).ToLocalChecked()); - } - - static v8::Local NewInstance(rs2_device* dev, - DeviceType type = kNormalDevice) { - Nan::EscapableHandleScope scope; - - v8::Local cons = Nan::New(constructor_); - v8::Local context = Nan::GetCurrentContext(); - - v8::Local instance = - cons->NewInstance(context, 0, nullptr).ToLocalChecked(); - - auto me = Nan::ObjectWrap::Unwrap(instance); - me->dev_ = dev; - me->type_ = type; - - return scope.Escape(instance); - } - - private: - explicit RSDevice(DeviceType type = kNormalDevice) : dev_(nullptr), - error_(nullptr), type_(type) {} - - ~RSDevice() { - DestroyMe(); - } - - void DestroyMe() { - if (error_) rs2_free_error(error_); - error_ = nullptr; - if (dev_) rs2_delete_device(dev_); - dev_ = nullptr; - } - - static void New(const Nan::FunctionCallbackInfo& info) { - if (info.IsConstructCall()) { - RSDevice* obj = new RSDevice(); - obj->Wrap(info.This()); - info.GetReturnValue().Set(info.This()); - } - } - - static NAN_METHOD(GetCameraInfo) { - info.GetReturnValue().Set(Nan::Undefined()); - int32_t camera_info = Nan::To(info[0]).FromJust(); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - auto value = GetNativeResult(rs2_get_device_info, - &me->error_, me->dev_, static_cast(camera_info), - &me->error_); - if (me->error_) return; - - info.GetReturnValue().Set(Nan::New(value).ToLocalChecked()); - } - - static NAN_METHOD(Destroy) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) { - me->DestroyMe(); - } - info.GetReturnValue().Set(Nan::Undefined()); - } - - - static NAN_METHOD(SupportsCameraInfo) { - info.GetReturnValue().Set(Nan::False()); - int32_t camera_info = Nan::To(info[0]).FromJust(); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - int32_t on = GetNativeResult(rs2_supports_device_info, &me->error_, - me->dev_, (rs2_camera_info)camera_info, &me->error_); - if (me->error_) return; - info.GetReturnValue().Set(Nan::New(on ? true : false)); - } - - static NAN_METHOD(Reset) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - CallNativeFunc(rs2_hardware_reset, &me->error_, me->dev_, &me->error_); - } - - static NAN_METHOD(QuerySensors) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - std::shared_ptr list( - GetNativeResult(rs2_query_sensors, &me->error_, - me->dev_, &me->error_), rs2_delete_sensor_list); - if (!list) return; - - auto size = GetNativeResult(rs2_get_sensors_count, &me->error_, - list.get(), &me->error_); - if (!size) return; - - v8::Local array = Nan::New(); - v8::Local context = info.GetIsolate()->GetCurrentContext(); - for (int32_t i = 0; i < size; i++) { - rs2_sensor* sensor = GetNativeResult(rs2_create_sensor, - &me->error_, list.get(), i, &me->error_); - array->Set(context, i, RSSensor::NewInstance(sensor)); - } - info.GetReturnValue().Set(array); - } - - static NAN_METHOD(TriggerErrorForTest) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - uint8_t raw_data[24] = {0}; - raw_data[0] = 0x14; - raw_data[2] = 0xab; - raw_data[3] = 0xcd; - raw_data[4] = 0x4d; - raw_data[8] = 4; - CallNativeFunc(rs2_send_and_receive_raw_data, &me->error_, me->dev_, - static_cast(raw_data), 24, &me->error_); - } - - static NAN_METHOD(SpawnRecorderDevice) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - info.GetReturnValue().Set(Nan::Undefined()); - if (!me) return; - - Nan::Utf8String file(Nan::To(info[0]).ToLocalChecked()); - auto dev = GetNativeResult(rs2_create_record_device, - &me->error_, me->dev_, *file, &me->error_); - if (me->error_) return; - - auto obj = RSDevice::NewInstance(dev, kRecorderDevice); - info.GetReturnValue().Set(obj); - } - - static NAN_METHOD(PauseRecord) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - CallNativeFunc(rs2_record_device_pause, &me->error_, me->dev_, - &me->error_); - } - - static NAN_METHOD(ResumeRecord) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - CallNativeFunc(rs2_record_device_resume, &me->error_, me->dev_, - &me->error_); - } - - static NAN_METHOD(GetFileName) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - info.GetReturnValue().Set(Nan::Undefined()); - if (!me) return; - - const char* file = nullptr; - if (me->IsPlaybackInternal()) { - file = GetNativeResult(rs2_playback_device_get_file_path, - &me->error_, me->dev_, &me->error_); - } else if (me->IsRecorderInternal()) { - file = GetNativeResult(rs2_record_device_filename, - &me->error_, me->dev_, &me->error_); - } else { - return; - } - if (me->error_) return; - - info.GetReturnValue().Set(Nan::New(file).ToLocalChecked()); - } - - static NAN_METHOD(PausePlayback) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - CallNativeFunc(rs2_playback_device_pause, &me->error_, me->dev_, - &me->error_); - } - - static NAN_METHOD(ResumePlayback) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - CallNativeFunc(rs2_playback_device_resume, &me->error_, me->dev_, - &me->error_); - } - - static NAN_METHOD(StopPlayback) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - CallNativeFunc(rs2_playback_device_stop, &me->error_, me->dev_, - &me->error_); - } - - static NAN_METHOD(GetPosition) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - info.GetReturnValue().Set(Nan::Undefined()); - if (!me) return; - - auto pos = static_cast(GetNativeResult( - rs2_playback_get_position, &me->error_, me->dev_, &me->error_)/1000000); - info.GetReturnValue().Set(Nan::New(pos)); - } - - static NAN_METHOD(GetDuration) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - info.GetReturnValue().Set(Nan::Undefined()); - if (!me) return; - - auto duration = static_cast( - GetNativeResult(rs2_playback_get_duration, &me->error_, - me->dev_, &me->error_)/1000000); - info.GetReturnValue().Set(Nan::New(duration)); - } - - static NAN_METHOD(Seek) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - info.GetReturnValue().Set(Nan::Undefined()); - if (!me) return; - - uint64_t time = Nan::To(info[0]).FromJust(); - CallNativeFunc(rs2_playback_seek, &me->error_, me->dev_, time*1000000, - &me->error_); - } - - static NAN_METHOD(IsRealTime) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - info.GetReturnValue().Set(Nan::Undefined()); - if (!me) return; - - auto val = GetNativeResult(rs2_playback_device_is_real_time, - &me->error_, me->dev_, &me->error_); - if (me->error_) return; - - info.GetReturnValue().Set(val ? Nan::True() : Nan::False()); - } - - static NAN_METHOD(SetIsRealTime) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - info.GetReturnValue().Set(Nan::Undefined()); - if (!me) return; - - auto val = Nan::To(info[0]).FromJust(); - CallNativeFunc(rs2_playback_device_set_real_time, &me->error_, - me->dev_, val, &me->error_); - } - - static NAN_METHOD(SetPlaybackSpeed) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - info.GetReturnValue().Set(Nan::Undefined()); - if (!me) return; - - auto speed = Nan::To(info[0]).FromJust(); - CallNativeFunc(rs2_playback_device_set_playback_speed, &me->error_, - me->dev_, speed, &me->error_); - } - - static NAN_METHOD(IsPlayback) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - info.GetReturnValue().Set(Nan::Undefined()); - if (!me) return; - - auto val = me->IsPlaybackInternal(); - info.GetReturnValue().Set(val ? Nan::True() : Nan::False()); - } - - static NAN_METHOD(IsRecorder) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - info.GetReturnValue().Set(Nan::Undefined()); - if (!me) return; - - auto val = me->IsRecorderInternal(); - info.GetReturnValue().Set(val ? Nan::True() : Nan::False()); - } - - static NAN_METHOD(GetCurrentStatus) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - info.GetReturnValue().Set(Nan::Undefined()); - if (!me) return; - - auto status = GetNativeResult( - rs2_playback_device_get_current_status, &me->error_, - me->dev_, &me->error_); - if (me->error_) return; - - info.GetReturnValue().Set(Nan::New(status)); - } - - static NAN_METHOD(SetStatusChangedCallbackMethodName) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - info.GetReturnValue().Set(Nan::Undefined()); - if (!me) return; - - Nan::Utf8String method(Nan::To(info[0]).ToLocalChecked()); - me->status_changed_callback_method_name_ = std::string(*method); - CallNativeFunc(rs2_playback_device_set_status_changed_callback, &me->error_, - me->dev_, new PlaybackStatusCallback(me), &me->error_); - } - - static NAN_METHOD(IsTm2) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - info.GetReturnValue().Set(Nan::Undefined()); - if (!me) return; - - auto val = GetNativeResult(rs2_is_device_extendable_to, &me->error_, - me->dev_, RS2_EXTENSION_TM2, &me->error_); - info.GetReturnValue().Set(val ? Nan::True() : Nan::False()); - } - - static NAN_METHOD(EnableLoopback) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - info.GetReturnValue().Set(Nan::Undefined()); - if (!me) return; - - Nan::Utf8String file(Nan::To(info[0]).ToLocalChecked()); - CallNativeFunc(rs2_loopback_enable, &me->error_, me->dev_, *file, - &me->error_); - } - - static NAN_METHOD(DisableLoopback) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - info.GetReturnValue().Set(Nan::Undefined()); - if (!me) return; - - CallNativeFunc(rs2_loopback_disable, &me->error_, me->dev_, - &me->error_); - } - - static NAN_METHOD(IsLoopbackEnabled) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - info.GetReturnValue().Set(Nan::Undefined()); - if (!me) return; - - auto val = GetNativeResult(rs2_loopback_is_enabled, &me->error_, - me->dev_, &me->error_); - info.GetReturnValue().Set(val ? Nan::True() : Nan::False()); - } - - private: - bool IsPlaybackInternal() { - auto val = GetNativeResult(rs2_is_device_extendable_to, &error_, dev_, - RS2_EXTENSION_PLAYBACK, &error_); - - return (error_ || !val) ? false : true; - } - - bool IsRecorderInternal() { - auto val = GetNativeResult(rs2_is_device_extendable_to, &error_, dev_, - RS2_EXTENSION_RECORD, &error_); - - return (error_ || !val) ? false : true; - } - static Nan::Persistent constructor_; - rs2_device* dev_; - rs2_error* error_; - DeviceType type_; - std::string status_changed_callback_method_name_; - friend class RSContext; - friend class DevicesChangedCallbackInfo; - friend class FrameCallbackInfo; - friend class RSPipeline; - friend class RSDeviceList; - friend class RSDeviceHub; - friend class PlaybackStatusCallbackInfo; -}; - -Nan::Persistent RSDevice::constructor_; - -void FrameCallbackInfo::Run() { - SetConsumed(); - Nan::HandleScope scope; - // save the rs2_frame to the sensor - sensor_->ReplaceFrame(frame_); - - Nan::AsyncResource resource("frame_callback_name_"); - resource.runInAsyncScope( - sensor_->handle(), sensor_->frame_callback_name_.c_str(), 0, nullptr); - // Nan::MakeCallback( - // sensor_->handle(), sensor_->frame_callback_name_.c_str(), - // 0, nullptr); -} - -void NotificationCallbackInfo::Run() { - SetConsumed(); - Nan::HandleScope scope; - v8::Local args[1] = { - RSNotification( - desc_, time_, severity_, category_, serialized_data_).GetObject() - }; - - Nan::AsyncResource resource("notification_callback_name_"); - resource.runInAsyncScope( - sensor_->handle(), sensor_->notification_callback_name_.c_str(), 1, args); - // Nan::MakeCallback(sensor_->handle(), - // sensor_->notification_callback_name_.c_str(), 1, args); -} - -void PlaybackStatusCallbackInfo::Run() { - SetConsumed(); - Nan::HandleScope scope; - v8::Local args[1] = { Nan::New(status_) }; - Nan::AsyncResource resource("status_changed_callback_method_name_"); - resource.runInAsyncScope( - dev_->handle(), dev_->status_changed_callback_method_name_.c_str(), - 1, args); - // Nan::MakeCallback(dev_->handle(), - // dev_->status_changed_callback_method_name_.c_str(), 1, args); -} - -class RSPointCloud : public Nan::ObjectWrap, Options { - public: - static void Init(v8::Local exports) { - v8::Local tpl = Nan::New(New); - tpl->SetClassName(Nan::New("RSPointCloud").ToLocalChecked()); - tpl->InstanceTemplate()->SetInternalFieldCount(1); - - Nan::SetPrototypeMethod(tpl, "destroy", Destroy); - Nan::SetPrototypeMethod(tpl, "calculate", Calculate); - Nan::SetPrototypeMethod(tpl, "mapTo", MapTo); - - // options API - Nan::SetPrototypeMethod(tpl, "supportsOption", SupportsOption); - Nan::SetPrototypeMethod(tpl, "getOption", GetOption); - Nan::SetPrototypeMethod(tpl, "setOption", SetOption); - Nan::SetPrototypeMethod(tpl, "getOptionRange", GetOptionRange); - Nan::SetPrototypeMethod(tpl, "isOptionReadonly", IsOptionReadonly); - Nan::SetPrototypeMethod(tpl, "getOptionDescription", GetOptionDescription); - Nan::SetPrototypeMethod(tpl, "getOptionValueDescription", - GetOptionValueDescription); - - v8::Local context = exports->CreationContext(); - constructor_.Reset(tpl->GetFunction(context).ToLocalChecked()); - exports->Set(context, Nan::New("RSPointCloud").ToLocalChecked(), - tpl->GetFunction(context).ToLocalChecked()); - } - - rs2_options* GetOptionsPointer() override { - // we have to reinterpret_cast as they are unrelated types to compiler - return reinterpret_cast(processing_block_); - } - - private: - RSPointCloud() : processing_block_(nullptr), error_(nullptr) { - frame_queue_ = rs2_create_frame_queue(1, &error_); - } - - ~RSPointCloud() { - DestroyMe(); - } - - void DestroyMe() { - if (error_) rs2_free_error(error_); - error_ = nullptr; - if (processing_block_) rs2_delete_processing_block(processing_block_); - processing_block_ = nullptr; - if (frame_queue_) rs2_delete_frame_queue(frame_queue_); - frame_queue_ = nullptr; - } - - static NAN_METHOD(Destroy) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) { - me->DestroyMe(); - } - info.GetReturnValue().Set(Nan::Undefined()); - } - - static void New(const Nan::FunctionCallbackInfo& info) { - if (info.IsConstructCall()) { - RSPointCloud* obj = new RSPointCloud(); - obj->processing_block_ = GetNativeResult( - rs2_create_pointcloud, &obj->error_, &obj->error_); - auto callback = new FrameCallbackForFrameQueue(obj->frame_queue_); - CallNativeFunc(rs2_start_processing, &obj->error_, obj->processing_block_, - callback, &obj->error_); - - obj->Wrap(info.This()); - info.GetReturnValue().Set(info.This()); - } - } - - static NAN_METHOD(Calculate) { - info.GetReturnValue().Set(Nan::False()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - auto frame = Nan::ObjectWrap::Unwrap( - Nan::To(info[0]).ToLocalChecked()); - auto target_frame = Nan::ObjectWrap::Unwrap( - Nan::To(info[1]).ToLocalChecked()); - if (!me || !frame || !frame->frame_ || !target_frame) return; - - // rs2_process_frame will release the input frame, so we need to addref - CallNativeFunc(rs2_frame_add_ref, &me->error_, frame->frame_, &me->error_); - if (me->error_) return; - - CallNativeFunc(rs2_process_frame, &me->error_, me->processing_block_, - frame->frame_, &me->error_); - if (me->error_) return; - - auto new_frame = GetNativeResult(rs2_wait_for_frame, - &me->error_, me->frame_queue_, 5000, &me->error_); - if (!new_frame) return; - - target_frame->Replace(new_frame); - info.GetReturnValue().Set(Nan::True()); - } - - static NAN_METHOD(MapTo) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - auto frame = Nan::ObjectWrap::Unwrap( - Nan::To(info[0]).ToLocalChecked()); - info.GetReturnValue().Set(Nan::Undefined()); - if (!me || !frame) return; - - const rs2_stream_profile* profile = - GetNativeResult(rs2_get_frame_stream_profile, - &me->error_, frame->frame_, &me->error_); - if (!profile) return; - - StreamProfileExtrator extrator(profile); - CallNativeFunc(rs2_set_option, &me->error_, - reinterpret_cast(me->processing_block_), - RS2_OPTION_STREAM_FILTER, - static_cast(extrator.stream_), - &me->error_); - - CallNativeFunc(rs2_set_option, &me->error_, - reinterpret_cast(me->processing_block_), - RS2_OPTION_STREAM_FORMAT_FILTER, - static_cast(extrator.format_), - &me->error_); - - CallNativeFunc(rs2_set_option, &me->error_, - reinterpret_cast(me->processing_block_), - RS2_OPTION_STREAM_INDEX_FILTER, - static_cast(extrator.index_), - &me->error_); - - if (extrator.stream_ == RS2_STREAM_DEPTH) return; - - // rs2_process_frame will release the input frame, so we need to addref - CallNativeFunc(rs2_frame_add_ref, &me->error_, frame->frame_, &me->error_); - if (me->error_) return; - - CallNativeFunc(rs2_process_frame, &me->error_, me->processing_block_, - frame->frame_, &me->error_); - } - - static NAN_METHOD(SupportsOption) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) return me->SupportsOptionInternal(info); - - info.GetReturnValue().Set(Nan::False()); - } - - static NAN_METHOD(GetOption) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) return me->GetOptionInternal(info); - - info.GetReturnValue().Set(Nan::Undefined()); - } - - static NAN_METHOD(GetOptionDescription) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) return me->GetOptionDescriptionInternal(info); - - info.GetReturnValue().Set(Nan::Undefined()); - } - - static NAN_METHOD(GetOptionValueDescription) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) return me->GetOptionValueDescriptionInternal(info); - - info.GetReturnValue().Set(Nan::Undefined()); - } - - static NAN_METHOD(SetOption) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) return me->SetOptionInternal(info); - - info.GetReturnValue().Set(Nan::Undefined()); - } - - static NAN_METHOD(GetOptionRange) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) return me->GetOptionRangeInternal(info); - - info.GetReturnValue().Set(Nan::Undefined()); - } - - static NAN_METHOD(IsOptionReadonly) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) return me->IsOptionReadonlyInternal(info); - - info.GetReturnValue().Set(Nan::False()); - } - - private: - static Nan::Persistent constructor_; - - rs2_processing_block* processing_block_; - rs2_frame_queue* frame_queue_; - rs2_error* error_; -}; - -Nan::Persistent RSPointCloud::constructor_; - -class RSDeviceList : public Nan::ObjectWrap { - public: - static void Init(v8::Local exports) { - v8::Local tpl = Nan::New(New); - tpl->SetClassName(Nan::New("RSDeviceList").ToLocalChecked()); - tpl->InstanceTemplate()->SetInternalFieldCount(1); - - Nan::SetPrototypeMethod(tpl, "destroy", Destroy); - Nan::SetPrototypeMethod(tpl, "contains", Contains); - Nan::SetPrototypeMethod(tpl, "size", Size); - Nan::SetPrototypeMethod(tpl, "getDevice", GetDevice); - - v8::Local context = exports->CreationContext(); - constructor_.Reset(tpl->GetFunction(context).ToLocalChecked()); - exports->Set(context, Nan::New("RSDeviceList").ToLocalChecked(), - tpl->GetFunction(context).ToLocalChecked()); - } - - static v8::Local NewInstance(rs2_device_list* list) { - Nan::EscapableHandleScope scope; - v8::Local cons = Nan::New(constructor_); - v8::Local context = Nan::GetCurrentContext(); - v8::Local instance = - cons->NewInstance(context, 0, nullptr).ToLocalChecked(); - auto me = Nan::ObjectWrap::Unwrap(instance); - me->list_ = list; - return scope.Escape(instance); - } - - private: - RSDeviceList() : error_(nullptr), list_(nullptr) {} - - ~RSDeviceList() { - DestroyMe(); - } - - void DestroyMe() { - if (error_) rs2_free_error(error_); - error_ = nullptr; - if (list_) rs2_delete_device_list(list_); - list_ = nullptr; - } - - static void New(const Nan::FunctionCallbackInfo& info) { - if (info.IsConstructCall()) { - RSDeviceList* obj = new RSDeviceList(); - obj->Wrap(info.This()); - info.GetReturnValue().Set(info.This()); - } - } - - static NAN_METHOD(Destroy) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) me->DestroyMe(); - - info.GetReturnValue().Set(Nan::Undefined()); - } - - static NAN_METHOD(Contains) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - auto dev = Nan::ObjectWrap::Unwrap( - Nan::To(info[0]).ToLocalChecked()); - if (!me && dev) return; - - bool contains = GetNativeResult(rs2_device_list_contains, &me->error_, - me->list_, dev->dev_, &me->error_); - if (me->error_) return; - - info.GetReturnValue().Set(Nan::New(contains)); - } - - static NAN_METHOD(Size) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - auto cnt = GetNativeResult(rs2_get_device_count, &me->error_, - me->list_, &me->error_); - if (me->error_) return; - - info.GetReturnValue().Set(Nan::New(cnt)); - } - - static NAN_METHOD(GetDevice) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - auto index = Nan::To(info[0]).FromJust(); - if (!me) return; - - auto dev = GetNativeResult(rs2_create_device, &me->error_, - me->list_, index, &me->error_); - if (!dev) return; - - info.GetReturnValue().Set(RSDevice::NewInstance(dev)); - } - - private: - static Nan::Persistent constructor_; - rs2_error* error_; - rs2_device_list* list_; -}; - -Nan::Persistent RSDeviceList::constructor_; - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -// -// .d8888b. 888 888 // -// d88P Y88b 888 888 // -// 888 888 888 888 // -// 888 .d88b. 88888b. 888888 .d88b. 888 888 888888 // -// 888 d88""88b 888 "88b 888 d8P Y8b `Y8bd8P' 888 // -// 888 888 888 888 888 888 888 88888888 X88K 888 // -// Y88b d88P Y88..88P 888 888 Y88b. Y8b. .d8""8b. Y88b. // -// "Y8888P" "Y88P" 888 888 "Y888 "Y8888 888 888 "Y888 // -// -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -class RSContext : public Nan::ObjectWrap { - public: - enum ContextType { - kNormal = 0, - kRecording, - kPlayback, - }; - static void Init(v8::Local exports) { - v8::Local tpl = Nan::New(New); - tpl->SetClassName(Nan::New("RSContext").ToLocalChecked()); - tpl->InstanceTemplate()->SetInternalFieldCount(1); - - Nan::SetPrototypeMethod(tpl, "destroy", Destroy); - Nan::SetPrototypeMethod(tpl, "create", Create); - Nan::SetPrototypeMethod(tpl, "queryDevices", QueryDevices); - Nan::SetPrototypeMethod(tpl, "setDevicesChangedCallback", - SetDevicesChangedCallback); - Nan::SetPrototypeMethod(tpl, "loadDeviceFile", LoadDeviceFile); - Nan::SetPrototypeMethod(tpl, "unloadDeviceFile", UnloadDeviceFile); - Nan::SetPrototypeMethod(tpl, "createDeviceFromSensor", - CreateDeviceFromSensor); - - v8::Local context = exports->CreationContext(); - constructor_.Reset(tpl->GetFunction(context).ToLocalChecked()); - exports->Set(context, Nan::New("RSContext").ToLocalChecked(), - tpl->GetFunction(context).ToLocalChecked()); - } - - static v8::Local NewInstance(rs2_context* ctx_ptr = nullptr) { - Nan::EscapableHandleScope scope; - - v8::Local cons = Nan::New(constructor_); - v8::Local context = Nan::GetCurrentContext(); - - v8::Local instance = - cons->NewInstance(context, 0, nullptr).ToLocalChecked(); - - // If ctx_ptr is provided, no need to call create. - if (ctx_ptr) { - auto me = Nan::ObjectWrap::Unwrap(instance); - me->ctx_ = ctx_ptr; - } - return scope.Escape(instance); - } - - private: - explicit RSContext(ContextType type = kNormal) : ctx_(nullptr), - error_(nullptr), type_(type), mode_(RS2_RECORDING_MODE_BLANK_FRAMES) {} - - ~RSContext() { - DestroyMe(); - } - - void RegisterDevicesChangedCallbackMethod(); - - void DestroyMe() { - if (error_) rs2_free_error(error_); - error_ = nullptr; - if (ctx_) rs2_delete_context(ctx_); - ctx_ = nullptr; - } - - static void New(const Nan::FunctionCallbackInfo& info) { - if (!info.IsConstructCall()) return; - - ContextType type = kNormal; - if (info.Length()) { - Nan::Utf8String type_str(Nan::To(info[0]).ToLocalChecked()); - std::string std_type_str(*type_str); - if (!std_type_str.compare("recording")) - type = kRecording; - else if (!std_type_str.compare("playback")) - type = kPlayback; - } - RSContext* obj = new RSContext(type); - if (type == kRecording || type == kPlayback) { - Nan::Utf8String file(Nan::To(info[1]).ToLocalChecked()); - Nan::Utf8String section(Nan::To(info[2]).ToLocalChecked()); - obj->file_name_ = std::string(*file); - obj->section_ = std::string(*section); - } - if (type == kRecording) - obj->mode_ = - static_cast(Nan::To(info[3]).FromJust()); - obj->Wrap(info.This()); - info.GetReturnValue().Set(info.This()); - } - - static NAN_METHOD(Create) { - MainThreadCallback::Init(); - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - switch (me->type_) { - case kRecording: - me->ctx_ = GetNativeResult(rs2_create_recording_context, - &me->error_, RS2_API_VERSION, me->file_name_.c_str(), - me->section_.c_str(), me->mode_, &me->error_); - break; - case kPlayback: - me->ctx_ = GetNativeResult(rs2_create_mock_context, - &me->error_, RS2_API_VERSION, me->file_name_.c_str(), - me->section_.c_str(), &me->error_); - break; - default: - me->ctx_ = GetNativeResult(rs2_create_context, - &me->error_, RS2_API_VERSION, &me->error_); - break; - } - } - - static NAN_METHOD(Destroy) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) { - me->DestroyMe(); - } - info.GetReturnValue().Set(Nan::Undefined()); - } - - static NAN_METHOD(SetDevicesChangedCallback) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) { - Nan::Utf8String value(Nan::To(info[0]).ToLocalChecked()); - me->device_changed_callback_name_ = std::string(*value); - me->RegisterDevicesChangedCallbackMethod(); - } - info.GetReturnValue().Set(Nan::Undefined()); - } - - static NAN_METHOD(LoadDeviceFile) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - Nan::Utf8String value(Nan::To(info[0]).ToLocalChecked()); - auto dev = GetNativeResult(rs2_context_add_device, &me->error_, - me->ctx_, *value, &me->error_); - if (!dev) return; - - auto jsobj = RSDevice::NewInstance(dev, RSDevice::kPlaybackDevice); - info.GetReturnValue().Set(jsobj); - } - - static NAN_METHOD(UnloadDeviceFile) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - info.GetReturnValue().Set(Nan::Undefined()); - if (!me) return; - - Nan::Utf8String value(Nan::To(info[0]).ToLocalChecked()); - CallNativeFunc(rs2_context_remove_device, &me->error_, me->ctx_, *value, - &me->error_); - } - - static NAN_METHOD(CreateDeviceFromSensor) { - info.GetReturnValue().Set(Nan::Undefined()); - auto sensor = Nan::ObjectWrap::Unwrap( - Nan::To(info[0]).ToLocalChecked()); - if (!sensor) return; - - rs2_error* error = nullptr; - auto dev = GetNativeResult(rs2_create_device_from_sensor, - &error, sensor->sensor_, &error); - if (!dev) return; - - auto jsobj = RSDevice::NewInstance(dev); - info.GetReturnValue().Set(jsobj); - } - - static NAN_METHOD(QueryDevices) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - auto dev_list = GetNativeResult(rs2_query_devices, - &me->error_, me->ctx_, &me->error_); - if (!dev_list) return; - - auto jsobj = RSDeviceList::NewInstance(dev_list); - info.GetReturnValue().Set(jsobj); - } - - private: - static Nan::Persistent constructor_; - - rs2_context* ctx_; - rs2_error* error_; - std::string device_changed_callback_name_; - ContextType type_; - std::string file_name_; - std::string section_; - rs2_recording_mode mode_; - friend class DevicesChangedCallbackInfo; - friend class RSPipeline; - friend class RSDeviceHub; -}; - -Nan::Persistent RSContext::constructor_; - -class DevicesChangedCallbackInfo : public MainThreadCallbackInfo { - public: - DevicesChangedCallbackInfo(rs2_device_list* r, - rs2_device_list* a, RSContext* ctx) : - removed_(r), added_(a), ctx_(ctx) {} - virtual ~DevicesChangedCallbackInfo() { if (!consumed_) Release(); } - virtual void Run() { - SetConsumed(); - Nan::HandleScope scope; - v8::Local rmlist; - v8::Local addlist; - if (removed_) - rmlist = RSDeviceList::NewInstance(removed_); - else - rmlist = Nan::Undefined(); - - if (added_) - addlist = RSDeviceList::NewInstance(added_); - else - addlist = Nan::Undefined(); - - v8::Local args[2] = {rmlist, addlist}; - - Nan::AsyncResource resource("device_changed_callback_name_"); - resource.runInAsyncScope( - ctx_->handle(), ctx_->device_changed_callback_name_.c_str(), - 2, args); - // Nan::MakeCallback(ctx_->handle(), - // ctx_->device_changed_callback_name_.c_str(), 2, args); - } - virtual void Release() { - if (removed_) { - rs2_delete_device_list(removed_); - removed_ = nullptr; - } - - if (added_) { - rs2_delete_device_list(added_); - added_ = nullptr; - } - } - - private: - rs2_device_list* removed_; - rs2_device_list* added_; - RSContext* ctx_; -}; - -class DevicesChangedCallback : public rs2_devices_changed_callback { - public: - explicit DevicesChangedCallback(RSContext* context) : ctx_(context) {} - virtual void on_devices_changed( - rs2_device_list* removed, rs2_device_list* added) { - MainThreadCallback::NotifyMainThread( - new DevicesChangedCallbackInfo(removed, added, ctx_)); - } - - virtual void release() { - delete this; - } - - virtual ~DevicesChangedCallback() {} - RSContext* ctx_; -}; - -void RSContext::RegisterDevicesChangedCallbackMethod() { - CallNativeFunc(rs2_set_devices_changed_callback_cpp, &error_, ctx_, - new DevicesChangedCallback(this), &error_); -} - -class RSDeviceHub : public Nan::ObjectWrap { - public: - static void Init(v8::Local exports) { - v8::Local tpl = Nan::New(New); - tpl->SetClassName(Nan::New("RSDeviceHub").ToLocalChecked()); - tpl->InstanceTemplate()->SetInternalFieldCount(1); - - Nan::SetPrototypeMethod(tpl, "waitForDevice", WaitForDevice); - Nan::SetPrototypeMethod(tpl, "isConnected", IsConnected); - Nan::SetPrototypeMethod(tpl, "destroy", Destroy); - - v8::Local context = exports->CreationContext(); - constructor_.Reset(tpl->GetFunction(context).ToLocalChecked()); - exports->Set(context, Nan::New("RSDeviceHub").ToLocalChecked(), - tpl->GetFunction(context).ToLocalChecked()); - } - - static v8::Local NewInstance() { - Nan::EscapableHandleScope scope; - - v8::Local cons = Nan::New(constructor_); - v8::Local context = Nan::GetCurrentContext(); - - v8::Local instance = - cons->NewInstance(context, 0, nullptr).ToLocalChecked(); - - return scope.Escape(instance); - } - - private: - RSDeviceHub() : hub_(nullptr), ctx_(nullptr), error_(nullptr) {} - - ~RSDeviceHub() { - DestroyMe(); - } - - void DestroyMe() { - if (error_) rs2_free_error(error_); - error_ = nullptr; - - if (hub_) rs2_delete_device_hub(hub_); - hub_ = nullptr; - ctx_ = nullptr; - } - - static NAN_METHOD(Destroy) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) me->DestroyMe(); - info.GetReturnValue().Set(Nan::Undefined()); - } - - static void New(const Nan::FunctionCallbackInfo& info) { - if (info.IsConstructCall()) { - RSDeviceHub* obj = new RSDeviceHub(); - RSContext* ctx = Nan::ObjectWrap::Unwrap( - Nan::To(info[0]).ToLocalChecked()); - obj->ctx_ = ctx->ctx_; - obj->hub_ = GetNativeResult(rs2_create_device_hub, - &obj->error_, obj->ctx_, &obj->error_); - obj->Wrap(info.This()); - info.GetReturnValue().Set(info.This()); - } - } - - static NAN_METHOD(WaitForDevice) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - auto dev = GetNativeResult(rs2_device_hub_wait_for_device, - &me->error_, me->hub_, &me->error_); - if (!dev) return; - - info.GetReturnValue().Set(RSDevice::NewInstance(dev)); - } - - static NAN_METHOD(IsConnected) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - auto dev = Nan::ObjectWrap::Unwrap( - Nan::To(info[0]).ToLocalChecked()); - if (!me || !dev) return; - - auto res = GetNativeResult(rs2_device_hub_is_device_connected, - &me->error_, me->hub_, dev->dev_, &me->error_); - if (me->error_) return; - - info.GetReturnValue().Set(Nan::New(res ? true : false)); - } - - private: - static Nan::Persistent constructor_; - - rs2_device_hub* hub_; - rs2_context* ctx_; - rs2_error* error_; -}; - -Nan::Persistent RSDeviceHub::constructor_; - -class RSPipelineProfile : public Nan::ObjectWrap { - public: - static void Init(v8::Local exports) { - v8::Local tpl = Nan::New(New); - tpl->SetClassName(Nan::New("RSPipelineProfile").ToLocalChecked()); - tpl->InstanceTemplate()->SetInternalFieldCount(1); - - Nan::SetPrototypeMethod(tpl, "getStreams", GetStreams); - Nan::SetPrototypeMethod(tpl, "getDevice", GetDevice); - Nan::SetPrototypeMethod(tpl, "destroy", Destroy); - - v8::Local context = exports->CreationContext(); - constructor_.Reset(tpl->GetFunction(context).ToLocalChecked()); - exports->Set(context, Nan::New("RSPipelineProfile").ToLocalChecked(), - tpl->GetFunction(context).ToLocalChecked()); - } - - static v8::Local NewInstance(rs2_pipeline_profile* profile) { - Nan::EscapableHandleScope scope; - - v8::Local cons = Nan::New(constructor_); - v8::Local context = Nan::GetCurrentContext(); - - v8::Local instance = - cons->NewInstance(context, 0, nullptr).ToLocalChecked(); - - auto me = Nan::ObjectWrap::Unwrap(instance); - me->pipeline_profile_ = profile; - return scope.Escape(instance); - } - - private: - RSPipelineProfile() : pipeline_profile_(nullptr), error_(nullptr) {} - - ~RSPipelineProfile() { - DestroyMe(); - } - - void DestroyMe() { - if (error_) rs2_free_error(error_); - error_ = nullptr; - - if (pipeline_profile_) rs2_delete_pipeline_profile(pipeline_profile_); - pipeline_profile_ = nullptr; - } - - static NAN_METHOD(Destroy) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) me->DestroyMe(); - info.GetReturnValue().Set(Nan::Undefined()); - } - - static void New(const Nan::FunctionCallbackInfo& info) { - if (info.IsConstructCall()) { - RSPipelineProfile* obj = new RSPipelineProfile(); - obj->Wrap(info.This()); - info.GetReturnValue().Set(info.This()); - } - } - - static NAN_METHOD(GetStreams) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - rs2_stream_profile_list* list = GetNativeResult( - rs2_pipeline_profile_get_streams, &me->error_, me->pipeline_profile_, - &me->error_); - if (!list) return; - - int32_t size = GetNativeResult(rs2_get_stream_profiles_count, - &me->error_, list, &me->error_); - if (me->error_) return; - - v8::Local array = Nan::New(size); - v8::Local context = info.GetIsolate()->GetCurrentContext(); - for (int32_t i = 0; i < size; i++) { - rs2_stream_profile* profile = const_cast( - GetNativeResult(rs2_get_stream_profile, - &me->error_, list, i, &me->error_)); - array->Set(context, i, RSStreamProfile::NewInstance(profile)); - } - info.GetReturnValue().Set(array); - } - - static NAN_METHOD(GetDevice) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - rs2_device* dev = GetNativeResult( - rs2_pipeline_profile_get_device, &me->error_, me->pipeline_profile_, - &me->error_); - if (!dev) return; - - info.GetReturnValue().Set(RSDevice::NewInstance(dev)); - } - - private: - static Nan::Persistent constructor_; - - rs2_pipeline_profile* pipeline_profile_; - rs2_error* error_; -}; - -Nan::Persistent RSPipelineProfile::constructor_; - -class RSPipeline; -class RSConfig : public Nan::ObjectWrap { - public: - static void Init(v8::Local exports) { - v8::Local tpl = Nan::New(New); - tpl->SetClassName(Nan::New("RSConfig").ToLocalChecked()); - tpl->InstanceTemplate()->SetInternalFieldCount(1); - - Nan::SetPrototypeMethod(tpl, "destroy", Destroy); - Nan::SetPrototypeMethod(tpl, "enableStream", EnableStream); - Nan::SetPrototypeMethod(tpl, "enableAllStreams", EnableAllStreams); - Nan::SetPrototypeMethod(tpl, "enableDevice", EnableDevice); - Nan::SetPrototypeMethod(tpl, "enableDeviceFromFile", EnableDeviceFromFile); - Nan::SetPrototypeMethod(tpl, "enableRecordToFile", EnableRecordToFile); - Nan::SetPrototypeMethod(tpl, "disableStream", DisableStream); - Nan::SetPrototypeMethod(tpl, "disableAllStreams", DisableAllStreams); - Nan::SetPrototypeMethod(tpl, "resolve", Resolve); - Nan::SetPrototypeMethod(tpl, "canResolve", CanResolve); - Nan::SetPrototypeMethod(tpl, "enableDeviceFromFileRepeatOption", - EnableDeviceFromFileRepeatOption); - - v8::Local context = exports->CreationContext(); - constructor_.Reset(tpl->GetFunction(context).ToLocalChecked()); - exports->Set(context, Nan::New("RSConfig").ToLocalChecked(), - tpl->GetFunction(context).ToLocalChecked()); - } - - static v8::Local NewInstance() { - Nan::EscapableHandleScope scope; - - v8::Local cons = Nan::New(constructor_); - v8::Local context = Nan::GetCurrentContext(); - - v8::Local instance = - cons->NewInstance(context, 0, nullptr).ToLocalChecked(); - - return scope.Escape(instance); - } - - private: - RSConfig() : config_(nullptr), error_(nullptr) {} - - ~RSConfig() { - DestroyMe(); - } - - void DestroyMe() { - if (error_) rs2_free_error(error_); - error_ = nullptr; - if (config_) rs2_delete_config(config_); - config_ = nullptr; - } - - static NAN_METHOD(Destroy) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) me->DestroyMe(); - info.GetReturnValue().Set(Nan::Undefined()); - } - - static void New(const Nan::FunctionCallbackInfo& info) { - if (info.IsConstructCall()) { - RSConfig* obj = new RSConfig(); - obj->config_ = rs2_create_config(&obj->error_); - obj->Wrap(info.This()); - info.GetReturnValue().Set(info.This()); - } - } - - // TODO(halton): added all the overloads - static NAN_METHOD(EnableStream) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - auto stream = Nan::To(info[0]).FromJust(); - auto index = Nan::To(info[1]).FromJust(); - auto width = Nan::To(info[2]).FromJust(); - auto height = Nan::To(info[3]).FromJust(); - auto format = Nan::To(info[4]).FromJust(); - auto framerate = Nan::To(info[5]).FromJust(); - if (!me || !me->config_) return; - - CallNativeFunc(rs2_config_enable_stream, &me->error_, me->config_, - (rs2_stream)stream, - index, - width, - height, - (rs2_format)format, - framerate, - &me->error_); - } - - static NAN_METHOD(EnableAllStreams) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - CallNativeFunc(rs2_config_enable_all_stream, &me->error_, me->config_, - &me->error_); - } - - static NAN_METHOD(EnableDevice) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - Nan::Utf8String value(Nan::To(info[0]).ToLocalChecked()); - CallNativeFunc(rs2_config_enable_device, &me->error_, me->config_, *value, - &me->error_); - } - - static NAN_METHOD(EnableDeviceFromFile) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - Nan::Utf8String value(Nan::To(info[0]).ToLocalChecked()); - CallNativeFunc(rs2_config_enable_device_from_file, &me->error_, me->config_, - *value, &me->error_); - } - - static NAN_METHOD(EnableDeviceFromFileRepeatOption) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - auto repeat = Nan::To(info[1]).FromJust(); - Nan::Utf8String value(Nan::To(info[0]).ToLocalChecked()); - CallNativeFunc(rs2_config_enable_device_from_file_repeat_option, - &me->error_, me->config_, *value, repeat, &me->error_); - } - - static NAN_METHOD(EnableRecordToFile) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - Nan::Utf8String value(Nan::To(info[0]).ToLocalChecked()); - CallNativeFunc(rs2_config_enable_record_to_file, &me->error_, me->config_, - *value, &me->error_); - } - - static NAN_METHOD(DisableStream) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - auto stream = Nan::To(info[0]).FromJust(); - CallNativeFunc(rs2_config_disable_stream, &me->error_, me->config_, - (rs2_stream)stream, &me->error_); - } - - static NAN_METHOD(DisableAllStreams) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - CallNativeFunc(rs2_config_disable_all_streams, &me->error_, me->config_, - &me->error_); - } - static NAN_METHOD(Resolve); - static NAN_METHOD(CanResolve); - - private: - static Nan::Persistent constructor_; - friend class RSPipeline; - - rs2_config* config_; - rs2_error* error_; -}; - -Nan::Persistent RSConfig::constructor_; - -class RSPipeline : public Nan::ObjectWrap { - public: - static void Init(v8::Local exports) { - v8::Local tpl = Nan::New(New); - tpl->SetClassName(Nan::New("RSPipeline").ToLocalChecked()); - tpl->InstanceTemplate()->SetInternalFieldCount(1); - - Nan::SetPrototypeMethod(tpl, "start", Start); - Nan::SetPrototypeMethod(tpl, "startWithConfig", StartWithConfig); - Nan::SetPrototypeMethod(tpl, "stop", Stop); - Nan::SetPrototypeMethod(tpl, "waitForFrames", WaitForFrames); - Nan::SetPrototypeMethod(tpl, "pollForFrames", PollForFrames); - Nan::SetPrototypeMethod(tpl, "getActiveProfile", GetActiveProfile); - Nan::SetPrototypeMethod(tpl, "create", Create); - Nan::SetPrototypeMethod(tpl, "destroy", Destroy); - - v8::Local context = exports->CreationContext(); - constructor_.Reset(tpl->GetFunction(context).ToLocalChecked()); - exports->Set(context, Nan::New("RSPipeline").ToLocalChecked(), - tpl->GetFunction(context).ToLocalChecked()); - } - - static v8::Local NewInstance() { - Nan::EscapableHandleScope scope; - - v8::Local cons = Nan::New(constructor_); - v8::Local context = Nan::GetCurrentContext(); - - v8::Local instance = - cons->NewInstance(context, 0, nullptr).ToLocalChecked(); - return scope.Escape(instance); - } - - private: - friend class RSConfig; - - RSPipeline() : pipeline_(nullptr), error_(nullptr) {} - - ~RSPipeline() { - DestroyMe(); - } - - void DestroyMe() { - if (error_) rs2_free_error(error_); - error_ = nullptr; - if (pipeline_) rs2_delete_pipeline(pipeline_); - pipeline_ = nullptr; - } - - static NAN_METHOD(Destroy) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) me->DestroyMe(); - info.GetReturnValue().Set(Nan::Undefined()); - } - - static void New(const Nan::FunctionCallbackInfo& info) { - if (info.IsConstructCall()) { - RSPipeline* obj = new RSPipeline(); - obj->Wrap(info.This()); - info.GetReturnValue().Set(info.This()); - } - } - - static NAN_METHOD(Create) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - auto rsctx = Nan::ObjectWrap::Unwrap( - Nan::To(info[0]).ToLocalChecked()); - if (!me || !rsctx) return; - - me->pipeline_ = GetNativeResult(rs2_create_pipeline, - &me->error_, rsctx->ctx_, &me->error_); - } - - static NAN_METHOD(StartWithConfig) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me || !me->pipeline_) return; - - RSConfig* config = Nan::ObjectWrap::Unwrap( - Nan::To(info[0]).ToLocalChecked()); - rs2_pipeline_profile* prof = GetNativeResult( - rs2_pipeline_start_with_config, &me->error_, me->pipeline_, - config->config_, &me->error_); - if (!prof) return; - - info.GetReturnValue().Set(RSPipelineProfile::NewInstance(prof)); - } - - static NAN_METHOD(Start) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me || !me->pipeline_) return; - - rs2_pipeline_profile* prof = GetNativeResult( - rs2_pipeline_start, &me->error_, me->pipeline_, &me->error_); - if (!prof) return; - - info.GetReturnValue().Set(RSPipelineProfile::NewInstance(prof)); - } - - static NAN_METHOD(Stop) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me || !me->pipeline_) return; - - CallNativeFunc(rs2_pipeline_stop, &me->error_, me->pipeline_, &me->error_); - } - - static NAN_METHOD(WaitForFrames) { - info.GetReturnValue().Set(Nan::False()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - auto frameset = Nan::ObjectWrap::Unwrap( - Nan::To(info[0]).ToLocalChecked()); - if (!me || !frameset) return; - - auto timeout = Nan::To(info[1]).FromJust(); - rs2_frame* frames = GetNativeResult( - rs2_pipeline_wait_for_frames, &me->error_, me->pipeline_, timeout, - &me->error_); - if (!frames) return; - - frameset->Replace(frames); - info.GetReturnValue().Set(Nan::True()); - } - - static NAN_METHOD(PollForFrames) { - info.GetReturnValue().Set(Nan::False()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - auto frameset = Nan::ObjectWrap::Unwrap( - Nan::To(info[0]).ToLocalChecked()); - if (!me || !frameset) return; - - rs2_frame* frames = nullptr; - auto res = GetNativeResult(rs2_pipeline_poll_for_frames, &me->error_, - me->pipeline_, &frames, &me->error_); - if (!res) return; - - frameset->Replace(frames); - info.GetReturnValue().Set(Nan::True()); - } - - static NAN_METHOD(GetActiveProfile) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - rs2_pipeline_profile* prof = GetNativeResult( - rs2_pipeline_get_active_profile, &me->error_, me->pipeline_, - &me->error_); - if (!prof) return; - - info.GetReturnValue().Set(RSPipelineProfile::NewInstance(prof)); - } - - private: - static Nan::Persistent constructor_; - - rs2_pipeline* pipeline_; - rs2_error* error_; -}; - -Nan::Persistent RSPipeline::constructor_; - -NAN_METHOD(RSConfig::Resolve) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - RSPipeline* pipe = Nan::ObjectWrap::Unwrap( - Nan::To(info[0]).ToLocalChecked()); - auto pipeline_profile = GetNativeResult( - rs2_config_resolve, &me->error_, me->config_, pipe->pipeline_, - &me->error_); - if (!pipeline_profile) return; - - info.GetReturnValue().Set(RSPipelineProfile::NewInstance(pipeline_profile)); -} - -NAN_METHOD(RSConfig::CanResolve) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - RSPipeline* pipe = Nan::ObjectWrap::Unwrap( - Nan::To(info[0]).ToLocalChecked()); - auto can_resolve = GetNativeResult(rs2_config_can_resolve, &me->error_, - me->config_, pipe->pipeline_, &me->error_); - if (me->error_) return; - - info.GetReturnValue().Set(Nan::New(can_resolve ? true : false)); -} - -class RSColorizer : public Nan::ObjectWrap, Options { - public: - static void Init(v8::Local exports) { - v8::Local tpl = Nan::New(New); - tpl->SetClassName(Nan::New("RSColorizer").ToLocalChecked()); - tpl->InstanceTemplate()->SetInternalFieldCount(1); - - Nan::SetPrototypeMethod(tpl, "destroy", Destroy); - Nan::SetPrototypeMethod(tpl, "create", Create); - Nan::SetPrototypeMethod(tpl, "colorize", Colorize); - Nan::SetPrototypeMethod(tpl, "supportsOption", SupportsOption); - Nan::SetPrototypeMethod(tpl, "getOption", GetOption); - Nan::SetPrototypeMethod(tpl, "setOption", SetOption); - Nan::SetPrototypeMethod(tpl, "getOptionRange", GetOptionRange); - Nan::SetPrototypeMethod(tpl, "isOptionReadonly", IsOptionReadonly); - Nan::SetPrototypeMethod(tpl, "getOptionDescription", GetOptionDescription); - Nan::SetPrototypeMethod(tpl, "getOptionValueDescription", - GetOptionValueDescription); - - v8::Local context = exports->CreationContext(); - constructor_.Reset(tpl->GetFunction(context).ToLocalChecked()); - exports->Set(context, Nan::New("RSColorizer").ToLocalChecked(), - tpl->GetFunction(context).ToLocalChecked()); - } - - static v8::Local NewInstance() { - Nan::EscapableHandleScope scope; - - v8::Local cons = Nan::New(constructor_); - v8::Local context = Nan::GetCurrentContext(); - - v8::Local instance = - cons->NewInstance(context, 0, nullptr).ToLocalChecked(); - - return scope.Escape(instance); - } - - rs2_options* GetOptionsPointer() override { - // TODO(shaoting) find better way to avoid the reinterpret_cast which was - // caused the inheritance relation was hidden - return reinterpret_cast(colorizer_); - } - - private: - RSColorizer() : colorizer_(nullptr), frame_queue_(nullptr), error_(nullptr) {} - - ~RSColorizer() { - DestroyMe(); - } - - void DestroyMe() { - if (error_) rs2_free_error(error_); - error_ = nullptr; - if (colorizer_) rs2_delete_processing_block(colorizer_); - colorizer_ = nullptr; - if (frame_queue_) rs2_delete_frame_queue(frame_queue_); - frame_queue_ = nullptr; - } - - static NAN_METHOD(Destroy) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) { - me->DestroyMe(); - } - info.GetReturnValue().Set(Nan::Undefined()); - } - - static void New(const Nan::FunctionCallbackInfo& info) { - if (info.IsConstructCall()) { - RSColorizer* obj = new RSColorizer(); - obj->Wrap(info.This()); - info.GetReturnValue().Set(info.This()); - } - } - - static NAN_METHOD(Create) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - me->colorizer_ = GetNativeResult( - rs2_create_colorizer, &me->error_, &me->error_); - if (!me->colorizer_) return; - - me->frame_queue_ = GetNativeResult( - rs2_create_frame_queue, &me->error_, 1, &me->error_); - if (!me->frame_queue_) return; - - auto callback = new FrameCallbackForFrameQueue(me->frame_queue_); - CallNativeFunc(rs2_start_processing, &me->error_, me->colorizer_, callback, - &me->error_); - } - - static NAN_METHOD(Colorize) { - info.GetReturnValue().Set(Nan::False()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - RSFrame* depth = Nan::ObjectWrap::Unwrap( - Nan::To(info[0]).ToLocalChecked()); - RSFrame* target = Nan::ObjectWrap::Unwrap( - Nan::To(info[1]).ToLocalChecked()); - if (!me || !depth || !depth->frame_ || !target) return; - - // rs2_process_frame will release the input frame, so we need to addref - CallNativeFunc(rs2_frame_add_ref, &me->error_, depth->frame_, &me->error_); - if (me->error_) return; - - CallNativeFunc(rs2_process_frame, &me->error_, me->colorizer_, - depth->frame_, &me->error_); - if (me->error_) return; - - rs2_frame* result = GetNativeResult(rs2_wait_for_frame, - &me->error_, me->frame_queue_, 5000, &me->error_); - target->DestroyMe(); - if (!result) return; - - target->Replace(result); - info.GetReturnValue().Set(Nan::True()); - } - - static NAN_METHOD(SupportsOption) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) return me->SupportsOptionInternal(info); - - info.GetReturnValue().Set(Nan::False()); - } - - static NAN_METHOD(GetOption) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) return me->GetOptionInternal(info); - - info.GetReturnValue().Set(Nan::Undefined()); - } - - static NAN_METHOD(GetOptionDescription) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) return me->GetOptionDescriptionInternal(info); - - info.GetReturnValue().Set(Nan::Undefined()); - } - - static NAN_METHOD(GetOptionValueDescription) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) return me->GetOptionValueDescriptionInternal(info); - - info.GetReturnValue().Set(Nan::Undefined()); - } - - static NAN_METHOD(SetOption) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) return me->SetOptionInternal(info); - - info.GetReturnValue().Set(Nan::Undefined()); - } - - static NAN_METHOD(GetOptionRange) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) return me->GetOptionRangeInternal(info); - - info.GetReturnValue().Set(Nan::Undefined()); - } - - static NAN_METHOD(IsOptionReadonly) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) return me->IsOptionReadonlyInternal(info); - - info.GetReturnValue().Set(Nan::False()); - } - - private: - static Nan::Persistent constructor_; - - rs2_processing_block* colorizer_; - rs2_frame_queue* frame_queue_; - rs2_error* error_; -}; - -Nan::Persistent RSColorizer::constructor_; - -class RSAlign : public Nan::ObjectWrap { - public: - static void Init(v8::Local exports) { - v8::Local tpl = Nan::New(New); - tpl->SetClassName(Nan::New("RSAlign").ToLocalChecked()); - tpl->InstanceTemplate()->SetInternalFieldCount(1); - - Nan::SetPrototypeMethod(tpl, "destroy", Destroy); - Nan::SetPrototypeMethod(tpl, "waitForFrames", WaitForFrames); - Nan::SetPrototypeMethod(tpl, "process", Process); - - v8::Local context = exports->CreationContext(); - constructor_.Reset(tpl->GetFunction(context).ToLocalChecked()); - exports->Set(context, Nan::New("RSAlign").ToLocalChecked(), - tpl->GetFunction(context).ToLocalChecked()); - } - - private: - RSAlign() : align_(nullptr), frame_queue_(nullptr), error_(nullptr) {} - - ~RSAlign() { - DestroyMe(); - } - - void DestroyMe() { - if (error_) rs2_free_error(error_); - error_ = nullptr; - if (align_) rs2_delete_processing_block(align_); - align_ = nullptr; - if (frame_queue_) rs2_delete_frame_queue(frame_queue_); - frame_queue_ = nullptr; - } - - static NAN_METHOD(Destroy) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) me->DestroyMe(); - - info.GetReturnValue().Set(Nan::Undefined()); - } - - static void New(const Nan::FunctionCallbackInfo& info) { - if (!info.IsConstructCall()) return; - - RSAlign* obj = new RSAlign(); - auto stream = static_cast(Nan::To(info[0]).FromJust()); - obj->align_ = GetNativeResult(rs2_create_align, - &obj->error_, stream, &obj->error_); - if (!obj->align_) return; - - obj->frame_queue_ = GetNativeResult( - rs2_create_frame_queue, &obj->error_, 1, &obj->error_); - if (!obj->frame_queue_) return; - - auto callback = new FrameCallbackForFrameQueue(obj->frame_queue_); - CallNativeFunc(rs2_start_processing, &obj->error_, obj->align_, callback, - &obj->error_); - - obj->Wrap(info.This()); - info.GetReturnValue().Set(info.This()); - } - - static NAN_METHOD(WaitForFrames) { - info.GetReturnValue().Set(Nan::Undefined()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (!me) return; - - rs2_frame* result = GetNativeResult(rs2_wait_for_frame, - &me->error_, me->frame_queue_, 5000, &me->error_); - if (!result) return; - - info.GetReturnValue().Set(RSFrameSet::NewInstance(result)); - } - - static NAN_METHOD(Process) { - info.GetReturnValue().Set(Nan::False()); - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - auto frameset = Nan::ObjectWrap::Unwrap( - Nan::To(info[0]).ToLocalChecked()); - auto target_fs = Nan::ObjectWrap::Unwrap( - Nan::To(info[1]).ToLocalChecked()); - if (!me || !frameset || !target_fs) return; - - // rs2_process_frame will release the input frame, so we need to addref - CallNativeFunc(rs2_frame_add_ref, &me->error_, frameset->GetFrames(), - &me->error_); - if (me->error_) return; - - CallNativeFunc(rs2_process_frame, &me->error_, me->align_, - frameset->GetFrames(), &me->error_); - if (me->error_) return; - - rs2_frame* frame = nullptr; - auto ret_code = GetNativeResult(rs2_poll_for_frame, &me->error_, - me->frame_queue_, &frame, &me->error_); - if (!ret_code) return; - - target_fs->Replace(frame); - info.GetReturnValue().Set(Nan::True()); - } - - private: - static Nan::Persistent constructor_; - - rs2_processing_block* align_; - rs2_frame_queue* frame_queue_; - rs2_error* error_; - friend class RSPipeline; -}; - -Nan::Persistent RSAlign::constructor_; - -class RSFilter : public Nan::ObjectWrap, Options { - public: - enum FilterType { - kFilterDecimation = 0, - kFilterTemporal, - kFilterSpatial, - kFilterHoleFilling, - kFilterDisparity2Depth, - kFilterDepth2Disparity - }; - static void Init(v8::Local exports) { - v8::Local tpl = Nan::New(New); - tpl->SetClassName(Nan::New("RSFilter").ToLocalChecked()); - tpl->InstanceTemplate()->SetInternalFieldCount(1); - - Nan::SetPrototypeMethod(tpl, "destroy", Destroy); - Nan::SetPrototypeMethod(tpl, "process", Process); - Nan::SetPrototypeMethod(tpl, "supportsOption", SupportsOption); - Nan::SetPrototypeMethod(tpl, "getOption", GetOption); - Nan::SetPrototypeMethod(tpl, "setOption", SetOption); - Nan::SetPrototypeMethod(tpl, "getOptionRange", GetOptionRange); - Nan::SetPrototypeMethod(tpl, "isOptionReadonly", IsOptionReadonly); - Nan::SetPrototypeMethod(tpl, "getOptionDescription", GetOptionDescription); - Nan::SetPrototypeMethod(tpl, "getOptionValueDescription", - GetOptionValueDescription); - - v8::Local context = exports->CreationContext(); - constructor_.Reset(tpl->GetFunction(context).ToLocalChecked()); - exports->Set(context, Nan::New("RSFilter").ToLocalChecked(), - tpl->GetFunction(context).ToLocalChecked()); - } - - rs2_options* GetOptionsPointer() override { - return reinterpret_cast(block_); - } - - private: - RSFilter() : block_(nullptr), frame_queue_(nullptr), error_(nullptr), - type_(kFilterDecimation) {} - - ~RSFilter() { - DestroyMe(); - } - - void DestroyMe() { - if (error_) rs2_free_error(error_); - error_ = nullptr; - if (block_) rs2_delete_processing_block(block_); - block_ = nullptr; - if (frame_queue_) rs2_delete_frame_queue(frame_queue_); - frame_queue_ = nullptr; - } - - static NAN_METHOD(Destroy) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) me->DestroyMe(); - - info.GetReturnValue().Set(Nan::Undefined()); - } - - static void New(const Nan::FunctionCallbackInfo& info) { - if (!info.IsConstructCall()) return; - - Nan::Utf8String type_str(Nan::To(info[0]).ToLocalChecked()); - std::string type = std::string(*type_str); - RSFilter* obj = new RSFilter(); - if (!(type.compare("decimation"))) { - obj->type_ = kFilterDecimation; - obj->block_ = GetNativeResult( - rs2_create_decimation_filter_block, &obj->error_, &obj->error_); - } else if (!(type.compare("temporal"))) { - obj->type_ = kFilterTemporal; - obj->block_ = GetNativeResult( - rs2_create_temporal_filter_block, &obj->error_, &obj->error_); - } else if (!(type.compare("spatial"))) { - obj->type_ = kFilterSpatial; - obj->block_ = GetNativeResult( - rs2_create_spatial_filter_block, &obj->error_, &obj->error_); - } else if (!(type.compare("hole-filling"))) { - obj->type_ = kFilterHoleFilling; - obj->block_ = GetNativeResult( - rs2_create_hole_filling_filter_block, &obj->error_, &obj->error_); - } else if (!(type.compare("disparity-to-depth"))) { - obj->type_ = kFilterDisparity2Depth; - obj->block_ = GetNativeResult( - rs2_create_disparity_transform_block, &obj->error_, 0, &obj->error_); - } else if (!(type.compare("depth-to-disparity"))) { - obj->type_ = kFilterDepth2Disparity; - obj->block_ = GetNativeResult( - rs2_create_disparity_transform_block, &obj->error_, 1, &obj->error_); - } - if (!obj->block_) return; - - obj->frame_queue_ = GetNativeResult( - rs2_create_frame_queue, &obj->error_, 1, &obj->error_); - if (!obj->frame_queue_) return; - - auto callback = new FrameCallbackForFrameQueue(obj->frame_queue_); - CallNativeFunc(rs2_start_processing, &obj->error_, obj->block_, callback, - &obj->error_); - if (obj->error_) return; - - obj->Wrap(info.This()); - info.GetReturnValue().Set(info.This()); - } - - static NAN_METHOD(Process) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - auto input_frame = Nan::ObjectWrap::Unwrap( - Nan::To(info[0]).ToLocalChecked()); - auto out_frame = Nan::ObjectWrap::Unwrap( - Nan::To(info[1]).ToLocalChecked()); - info.GetReturnValue().Set(Nan::False()); - if (!me || !input_frame || !out_frame) return; - - // rs2_process_frame will release the input frame, so we need to addref - CallNativeFunc(rs2_frame_add_ref, &me->error_, input_frame->frame_, - &me->error_); - if (me->error_) return; - - CallNativeFunc(rs2_process_frame, &me->error_, me->block_, - input_frame->frame_, &me->error_); - if (me->error_) return; - - rs2_frame* frame = nullptr; - auto ret_code = GetNativeResult(rs2_poll_for_frame, &me->error_, - me->frame_queue_, &frame, &me->error_); - if (!ret_code) return; - - out_frame->Replace(frame); - info.GetReturnValue().Set(Nan::True()); - } - - static NAN_METHOD(SupportsOption) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) return me->SupportsOptionInternal(info); - - info.GetReturnValue().Set(Nan::False()); - } - - static NAN_METHOD(GetOption) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) return me->GetOptionInternal(info); - - info.GetReturnValue().Set(Nan::Undefined()); - } - - static NAN_METHOD(GetOptionDescription) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) return me->GetOptionDescriptionInternal(info); - - info.GetReturnValue().Set(Nan::Undefined()); - } - - static NAN_METHOD(GetOptionValueDescription) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) return me->GetOptionValueDescriptionInternal(info); - - info.GetReturnValue().Set(Nan::Undefined()); - } - - static NAN_METHOD(SetOption) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) return me->SetOptionInternal(info); - - info.GetReturnValue().Set(Nan::Undefined()); - } - - static NAN_METHOD(GetOptionRange) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) return me->GetOptionRangeInternal(info); - - info.GetReturnValue().Set(Nan::Undefined()); - } - - static NAN_METHOD(IsOptionReadonly) { - auto me = Nan::ObjectWrap::Unwrap(info.Holder()); - if (me) return me->IsOptionReadonlyInternal(info); - - info.GetReturnValue().Set(Nan::False()); - } - - private: - static Nan::Persistent constructor_; - - rs2_processing_block* block_; - rs2_frame_queue* frame_queue_; - rs2_error* error_; - FilterType type_; -}; - -Nan::Persistent RSFilter::constructor_; - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -// -// 888b d888 888 888 // -// 8888b d8888 888 888 // -// 88888b.d88888 888 888 // -// 888Y88888P888 .d88b. .d88888 888 888 888 .d88b. // -// 888 Y888P 888 d88""88b d88" 888 888 888 888 d8P Y8b // -// 888 Y8P 888 888 888 888 888 888 888 888 88888888 // -// 888 " 888 Y88..88P Y88b 888 Y88b 888 888 Y8b. // -// 888 888 "Y88P" "Y88888 "Y88888 888 "Y8888 // -// -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -NAN_METHOD(GlobalCleanup) { - MainThreadCallback::Destroy(); - ErrorUtil::ResetError(); - info.GetReturnValue().Set(Nan::Undefined()); -} - -NAN_METHOD(GetTime) { - rs2_error* e = nullptr; - auto time = rs2_get_time(&e); - info.GetReturnValue().Set(Nan::New(time)); -} - -NAN_METHOD(RegisterErrorCallback) { - ErrorUtil::Init(); - ErrorUtil::UpdateJSErrorCallback(info); -} - -NAN_METHOD(GetError) { - info.GetReturnValue().Set(ErrorUtil::GetJSErrorObject()); -} - -#define _FORCE_SET_ENUM(name) \ - Nan::DefineOwnProperty(exports, \ - Nan::New(#name).ToLocalChecked(), \ - Nan::New(static_cast((name))), \ - static_cast(v8::ReadOnly | v8::DontDelete)); - -void InitModule(v8::Local exports) { - v8::Local context = exports->CreationContext(); - - exports->Set(context, Nan::New("globalCleanup").ToLocalChecked(), - Nan::New(GlobalCleanup) - ->GetFunction(context).ToLocalChecked()); - exports->Set(context, Nan::New("getTime").ToLocalChecked(), - Nan::New(GetTime) - ->GetFunction(context).ToLocalChecked()); - exports->Set(context, Nan::New("registerErrorCallback").ToLocalChecked(), - Nan::New(RegisterErrorCallback) - ->GetFunction(context).ToLocalChecked()); - exports->Set(context, Nan::New("getError").ToLocalChecked(), - Nan::New(GetError) - ->GetFunction(context).ToLocalChecked()); - // rs2_error* error = nullptr; - // rs2_log_to_console(RS2_LOG_SEVERITY_DEBUG, &error); - - RSContext::Init(exports); - RSPointCloud::Init(exports); - RSPipelineProfile::Init(exports); - RSConfig::Init(exports); - RSPipeline::Init(exports); - RSFrameSet::Init(exports); - RSSensor::Init(exports); - RSDevice::Init(exports); - RSDeviceList::Init(exports); - RSDeviceHub::Init(exports); - RSStreamProfile::Init(exports); - RSColorizer::Init(exports); - RSFrameQueue::Init(exports); - RSFrame::Init(exports); - RSSyncer::Init(exports); - RSAlign::Init(exports); - RSFilter::Init(exports); - - // rs2_exception_type - _FORCE_SET_ENUM(RS2_EXCEPTION_TYPE_UNKNOWN); - _FORCE_SET_ENUM(RS2_EXCEPTION_TYPE_CAMERA_DISCONNECTED); - _FORCE_SET_ENUM(RS2_EXCEPTION_TYPE_BACKEND); - _FORCE_SET_ENUM(RS2_EXCEPTION_TYPE_INVALID_VALUE); - _FORCE_SET_ENUM(RS2_EXCEPTION_TYPE_WRONG_API_CALL_SEQUENCE); - _FORCE_SET_ENUM(RS2_EXCEPTION_TYPE_NOT_IMPLEMENTED); - _FORCE_SET_ENUM(RS2_EXCEPTION_TYPE_DEVICE_IN_RECOVERY_MODE); - _FORCE_SET_ENUM(RS2_EXCEPTION_TYPE_IO); - _FORCE_SET_ENUM(RS2_EXCEPTION_TYPE_COUNT); - - // rs2_stream - _FORCE_SET_ENUM(RS2_STREAM_ANY); - _FORCE_SET_ENUM(RS2_STREAM_DEPTH); - _FORCE_SET_ENUM(RS2_STREAM_COLOR); - _FORCE_SET_ENUM(RS2_STREAM_INFRARED); - _FORCE_SET_ENUM(RS2_STREAM_FISHEYE); - _FORCE_SET_ENUM(RS2_STREAM_GYRO); - _FORCE_SET_ENUM(RS2_STREAM_ACCEL); - _FORCE_SET_ENUM(RS2_STREAM_GPIO); - _FORCE_SET_ENUM(RS2_STREAM_POSE); - _FORCE_SET_ENUM(RS2_STREAM_CONFIDENCE); - _FORCE_SET_ENUM(RS2_STREAM_COUNT); - - // rs2_format - _FORCE_SET_ENUM(RS2_FORMAT_ANY); - _FORCE_SET_ENUM(RS2_FORMAT_Z16); - _FORCE_SET_ENUM(RS2_FORMAT_DISPARITY16); - _FORCE_SET_ENUM(RS2_FORMAT_XYZ32F); - _FORCE_SET_ENUM(RS2_FORMAT_YUYV); - _FORCE_SET_ENUM(RS2_FORMAT_RGB8); - _FORCE_SET_ENUM(RS2_FORMAT_BGR8); - _FORCE_SET_ENUM(RS2_FORMAT_RGBA8); - _FORCE_SET_ENUM(RS2_FORMAT_BGRA8); - _FORCE_SET_ENUM(RS2_FORMAT_Y8); - _FORCE_SET_ENUM(RS2_FORMAT_Y16); - _FORCE_SET_ENUM(RS2_FORMAT_RAW10); - _FORCE_SET_ENUM(RS2_FORMAT_RAW16); - _FORCE_SET_ENUM(RS2_FORMAT_RAW8); - _FORCE_SET_ENUM(RS2_FORMAT_UYVY); - _FORCE_SET_ENUM(RS2_FORMAT_MOTION_RAW); - _FORCE_SET_ENUM(RS2_FORMAT_MOTION_XYZ32F); - _FORCE_SET_ENUM(RS2_FORMAT_GPIO_RAW); - _FORCE_SET_ENUM(RS2_FORMAT_6DOF); - _FORCE_SET_ENUM(RS2_FORMAT_DISPARITY32); - _FORCE_SET_ENUM(RS2_FORMAT_Y10BPACK); - _FORCE_SET_ENUM(RS2_FORMAT_DISTANCE); - _FORCE_SET_ENUM(RS2_FORMAT_MJPEG); - _FORCE_SET_ENUM(RS2_FORMAT_Y8I); - _FORCE_SET_ENUM(RS2_FORMAT_Y12I); - _FORCE_SET_ENUM(RS2_FORMAT_INZI); - _FORCE_SET_ENUM(RS2_FORMAT_INVI); - _FORCE_SET_ENUM(RS2_FORMAT_W10); - _FORCE_SET_ENUM(RS2_FORMAT_Z16H); - _FORCE_SET_ENUM(RS2_FORMAT_FG); - _FORCE_SET_ENUM(RS2_FORMAT_Y411); - _FORCE_SET_ENUM(RS2_FORMAT_Y16I); - _FORCE_SET_ENUM(RS2_FORMAT_COUNT); - - // rs2_frame_metadata_value - _FORCE_SET_ENUM(RS2_FRAME_METADATA_FRAME_COUNTER); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_FRAME_TIMESTAMP); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_SENSOR_TIMESTAMP); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_ACTUAL_EXPOSURE); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_GAIN_LEVEL); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_AUTO_EXPOSURE); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_WHITE_BALANCE); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_TIME_OF_ARRIVAL); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_TEMPERATURE); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_BACKEND_TIMESTAMP); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_ACTUAL_FPS); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_FRAME_LASER_POWER); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_FRAME_LASER_POWER_MODE); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_EXPOSURE_PRIORITY); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_EXPOSURE_ROI_LEFT); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_EXPOSURE_ROI_RIGHT); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_EXPOSURE_ROI_TOP); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_EXPOSURE_ROI_BOTTOM); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_BRIGHTNESS); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_CONTRAST); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_SATURATION); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_SHARPNESS); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_AUTO_WHITE_BALANCE_TEMPERATURE); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_BACKLIGHT_COMPENSATION); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_HUE); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_GAMMA); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_MANUAL_WHITE_BALANCE); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_POWER_LINE_FREQUENCY); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_LOW_LIGHT_COMPENSATION); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_FRAME_EMITTER_MODE); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_FRAME_LED_POWER); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_RAW_FRAME_SIZE); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_GPIO_INPUT_DATA); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_SEQUENCE_NAME); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_SEQUENCE_ID); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_SEQUENCE_SIZE); - // mipi metadata_values - _FORCE_SET_ENUM(RS2_FRAME_METADATA_TRIGGER); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_PRESET); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_INPUT_WIDTH); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_INPUT_HEIGHT); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_SUB_PRESET_INFO); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_CALIB_INFO); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_CRC); - _FORCE_SET_ENUM(RS2_FRAME_METADATA_COUNT); - - // rs2_distortion - _FORCE_SET_ENUM(RS2_DISTORTION_NONE); - _FORCE_SET_ENUM(RS2_DISTORTION_MODIFIED_BROWN_CONRADY); - _FORCE_SET_ENUM(RS2_DISTORTION_INVERSE_BROWN_CONRADY); - _FORCE_SET_ENUM(RS2_DISTORTION_FTHETA); - _FORCE_SET_ENUM(RS2_DISTORTION_BROWN_CONRADY); - _FORCE_SET_ENUM(RS2_DISTORTION_KANNALA_BRANDT4); - _FORCE_SET_ENUM(RS2_DISTORTION_COUNT); - - // rs2_option - _FORCE_SET_ENUM(RS2_OPTION_BACKLIGHT_COMPENSATION); - _FORCE_SET_ENUM(RS2_OPTION_BRIGHTNESS); - _FORCE_SET_ENUM(RS2_OPTION_CONTRAST); - _FORCE_SET_ENUM(RS2_OPTION_EXPOSURE); - _FORCE_SET_ENUM(RS2_OPTION_GAIN); - _FORCE_SET_ENUM(RS2_OPTION_GAMMA); - _FORCE_SET_ENUM(RS2_OPTION_HUE); - _FORCE_SET_ENUM(RS2_OPTION_SATURATION); - _FORCE_SET_ENUM(RS2_OPTION_SHARPNESS); - _FORCE_SET_ENUM(RS2_OPTION_WHITE_BALANCE); - _FORCE_SET_ENUM(RS2_OPTION_ENABLE_AUTO_EXPOSURE); - _FORCE_SET_ENUM(RS2_OPTION_ENABLE_AUTO_WHITE_BALANCE); - _FORCE_SET_ENUM(RS2_OPTION_VISUAL_PRESET); - _FORCE_SET_ENUM(RS2_OPTION_LASER_POWER); - _FORCE_SET_ENUM(RS2_OPTION_ACCURACY); - _FORCE_SET_ENUM(RS2_OPTION_MOTION_RANGE); - _FORCE_SET_ENUM(RS2_OPTION_FILTER_OPTION); - _FORCE_SET_ENUM(RS2_OPTION_CONFIDENCE_THRESHOLD); - _FORCE_SET_ENUM(RS2_OPTION_EMITTER_ENABLED); - _FORCE_SET_ENUM(RS2_OPTION_FRAMES_QUEUE_SIZE); - _FORCE_SET_ENUM(RS2_OPTION_TOTAL_FRAME_DROPS); - _FORCE_SET_ENUM(RS2_OPTION_AUTO_EXPOSURE_MODE); - _FORCE_SET_ENUM(RS2_OPTION_POWER_LINE_FREQUENCY); - _FORCE_SET_ENUM(RS2_OPTION_ASIC_TEMPERATURE); - _FORCE_SET_ENUM(RS2_OPTION_ERROR_POLLING_ENABLED); - _FORCE_SET_ENUM(RS2_OPTION_PROJECTOR_TEMPERATURE); - _FORCE_SET_ENUM(RS2_OPTION_OUTPUT_TRIGGER_ENABLED); - _FORCE_SET_ENUM(RS2_OPTION_MOTION_MODULE_TEMPERATURE); - _FORCE_SET_ENUM(RS2_OPTION_DEPTH_UNITS); - _FORCE_SET_ENUM(RS2_OPTION_ENABLE_MOTION_CORRECTION); - _FORCE_SET_ENUM(RS2_OPTION_AUTO_EXPOSURE_PRIORITY); - _FORCE_SET_ENUM(RS2_OPTION_COLOR_SCHEME); - _FORCE_SET_ENUM(RS2_OPTION_HISTOGRAM_EQUALIZATION_ENABLED); - _FORCE_SET_ENUM(RS2_OPTION_MIN_DISTANCE); - _FORCE_SET_ENUM(RS2_OPTION_MAX_DISTANCE); - _FORCE_SET_ENUM(RS2_OPTION_TEXTURE_SOURCE); - _FORCE_SET_ENUM(RS2_OPTION_FILTER_MAGNITUDE); - _FORCE_SET_ENUM(RS2_OPTION_FILTER_SMOOTH_ALPHA); - _FORCE_SET_ENUM(RS2_OPTION_FILTER_SMOOTH_DELTA); - _FORCE_SET_ENUM(RS2_OPTION_HOLES_FILL); - _FORCE_SET_ENUM(RS2_OPTION_STEREO_BASELINE); - _FORCE_SET_ENUM(RS2_OPTION_AUTO_EXPOSURE_CONVERGE_STEP); - _FORCE_SET_ENUM(RS2_OPTION_INTER_CAM_SYNC_MODE); - _FORCE_SET_ENUM(RS2_OPTION_STREAM_FILTER); - _FORCE_SET_ENUM(RS2_OPTION_STREAM_FORMAT_FILTER); - _FORCE_SET_ENUM(RS2_OPTION_STREAM_INDEX_FILTER); - _FORCE_SET_ENUM(RS2_OPTION_EMITTER_ON_OFF); - _FORCE_SET_ENUM(RS2_OPTION_ZERO_ORDER_POINT_X); // Deprecated - _FORCE_SET_ENUM(RS2_OPTION_ZERO_ORDER_POINT_Y); // Deprecated - _FORCE_SET_ENUM(RS2_OPTION_LLD_TEMPERATURE); - _FORCE_SET_ENUM(RS2_OPTION_MC_TEMPERATURE); - _FORCE_SET_ENUM(RS2_OPTION_MA_TEMPERATURE); - _FORCE_SET_ENUM(RS2_OPTION_HARDWARE_PRESET); - _FORCE_SET_ENUM(RS2_OPTION_GLOBAL_TIME_ENABLED); - _FORCE_SET_ENUM(RS2_OPTION_APD_TEMPERATURE); - _FORCE_SET_ENUM(RS2_OPTION_ENABLE_MAPPING); - _FORCE_SET_ENUM(RS2_OPTION_ENABLE_RELOCALIZATION); - _FORCE_SET_ENUM(RS2_OPTION_ENABLE_POSE_JUMPING); - _FORCE_SET_ENUM(RS2_OPTION_ENABLE_DYNAMIC_CALIBRATION); - _FORCE_SET_ENUM(RS2_OPTION_DEPTH_OFFSET); - _FORCE_SET_ENUM(RS2_OPTION_LED_POWER); - _FORCE_SET_ENUM(RS2_OPTION_ZERO_ORDER_ENABLED); // Deprecated - _FORCE_SET_ENUM(RS2_OPTION_ENABLE_MAP_PRESERVATION); - _FORCE_SET_ENUM(RS2_OPTION_FREEFALL_DETECTION_ENABLED); - _FORCE_SET_ENUM(RS2_OPTION_AVALANCHE_PHOTO_DIODE); - _FORCE_SET_ENUM(RS2_OPTION_POST_PROCESSING_SHARPENING); - _FORCE_SET_ENUM(RS2_OPTION_PRE_PROCESSING_SHARPENING); - _FORCE_SET_ENUM(RS2_OPTION_NOISE_FILTERING); - _FORCE_SET_ENUM(RS2_OPTION_INVALIDATION_BYPASS); - _FORCE_SET_ENUM(RS2_OPTION_AMBIENT_LIGHT); - _FORCE_SET_ENUM(RS2_OPTION_DIGITAL_GAIN); - _FORCE_SET_ENUM(RS2_OPTION_SENSOR_MODE); - _FORCE_SET_ENUM(RS2_OPTION_EMITTER_ALWAYS_ON); - _FORCE_SET_ENUM(RS2_OPTION_THERMAL_COMPENSATION); - _FORCE_SET_ENUM(RS2_OPTION_TRIGGER_CAMERA_ACCURACY_HEALTH); - _FORCE_SET_ENUM(RS2_OPTION_RESET_CAMERA_ACCURACY_HEALTH); - _FORCE_SET_ENUM(RS2_OPTION_HOST_PERFORMANCE); - _FORCE_SET_ENUM(RS2_OPTION_HDR_ENABLED); - _FORCE_SET_ENUM(RS2_OPTION_SEQUENCE_NAME); - _FORCE_SET_ENUM(RS2_OPTION_SEQUENCE_SIZE); - _FORCE_SET_ENUM(RS2_OPTION_SEQUENCE_ID); - _FORCE_SET_ENUM(RS2_OPTION_HUMIDITY_TEMPERATURE); - _FORCE_SET_ENUM(RS2_OPTION_ENABLE_MAX_USABLE_RANGE); - _FORCE_SET_ENUM(RS2_OPTION_ALTERNATE_IR); - _FORCE_SET_ENUM(RS2_OPTION_NOISE_ESTIMATION); - _FORCE_SET_ENUM(RS2_OPTION_ENABLE_IR_REFLECTIVITY); - _FORCE_SET_ENUM(RS2_OPTION_AUTO_EXPOSURE_LIMIT); - _FORCE_SET_ENUM(RS2_OPTION_AUTO_GAIN_LIMIT); - _FORCE_SET_ENUM(RS2_OPTION_AUTO_RX_SENSITIVITY); - _FORCE_SET_ENUM(RS2_OPTION_TRANSMITTER_FREQUENCY); - _FORCE_SET_ENUM(RS2_OPTION_VERTICAL_BINNING); - _FORCE_SET_ENUM(RS2_OPTION_RECEIVER_SENSITIVITY); - _FORCE_SET_ENUM(RS2_OPTION_AUTO_EXPOSURE_LIMIT_TOGGLE); - _FORCE_SET_ENUM(RS2_OPTION_AUTO_GAIN_LIMIT_TOGGLE); - _FORCE_SET_ENUM(RS2_OPTION_EMITTER_FREQUENCY); - _FORCE_SET_ENUM(RS2_OPTION_COUNT); - - // rs2_camera_info - _FORCE_SET_ENUM(RS2_CAMERA_INFO_NAME); - _FORCE_SET_ENUM(RS2_CAMERA_INFO_SERIAL_NUMBER); - _FORCE_SET_ENUM(RS2_CAMERA_INFO_FIRMWARE_VERSION); - _FORCE_SET_ENUM(RS2_CAMERA_INFO_RECOMMENDED_FIRMWARE_VERSION); - _FORCE_SET_ENUM(RS2_CAMERA_INFO_PHYSICAL_PORT); - _FORCE_SET_ENUM(RS2_CAMERA_INFO_DEBUG_OP_CODE); - _FORCE_SET_ENUM(RS2_CAMERA_INFO_ADVANCED_MODE); - _FORCE_SET_ENUM(RS2_CAMERA_INFO_PRODUCT_ID); - _FORCE_SET_ENUM(RS2_CAMERA_INFO_CAMERA_LOCKED); - _FORCE_SET_ENUM(RS2_CAMERA_INFO_USB_TYPE_DESCRIPTOR); - _FORCE_SET_ENUM(RS2_CAMERA_INFO_PRODUCT_LINE); - _FORCE_SET_ENUM(RS2_CAMERA_INFO_ASIC_SERIAL_NUMBER); - _FORCE_SET_ENUM(RS2_CAMERA_INFO_FIRMWARE_UPDATE_ID); - _FORCE_SET_ENUM(RS2_CAMERA_INFO_IP_ADDRESS); - _FORCE_SET_ENUM(RS2_CAMERA_INFO_COUNT); - - - // rs2_log_severity - _FORCE_SET_ENUM(RS2_LOG_SEVERITY_DEBUG); - _FORCE_SET_ENUM(RS2_LOG_SEVERITY_INFO); - _FORCE_SET_ENUM(RS2_LOG_SEVERITY_WARN); - _FORCE_SET_ENUM(RS2_LOG_SEVERITY_ERROR); - _FORCE_SET_ENUM(RS2_LOG_SEVERITY_FATAL); - _FORCE_SET_ENUM(RS2_LOG_SEVERITY_NONE); - _FORCE_SET_ENUM(RS2_LOG_SEVERITY_COUNT); - _FORCE_SET_ENUM(RS2_LOG_SEVERITY_ALL); - - // rs2_notification_category - _FORCE_SET_ENUM(RS2_NOTIFICATION_CATEGORY_FRAMES_TIMEOUT); - _FORCE_SET_ENUM(RS2_NOTIFICATION_CATEGORY_FRAME_CORRUPTED); - _FORCE_SET_ENUM(RS2_NOTIFICATION_CATEGORY_HARDWARE_ERROR); - _FORCE_SET_ENUM(RS2_NOTIFICATION_CATEGORY_HARDWARE_EVENT); - _FORCE_SET_ENUM(RS2_NOTIFICATION_CATEGORY_UNKNOWN_ERROR); - _FORCE_SET_ENUM(RS2_NOTIFICATION_CATEGORY_FIRMWARE_UPDATE_RECOMMENDED); - _FORCE_SET_ENUM(RS2_NOTIFICATION_CATEGORY_POSE_RELOCALIZATION); - _FORCE_SET_ENUM(RS2_NOTIFICATION_CATEGORY_COUNT); - - // rs2_timestamp_domain - _FORCE_SET_ENUM(RS2_TIMESTAMP_DOMAIN_HARDWARE_CLOCK); - _FORCE_SET_ENUM(RS2_TIMESTAMP_DOMAIN_SYSTEM_TIME); - _FORCE_SET_ENUM(RS2_TIMESTAMP_DOMAIN_GLOBAL_TIME); - _FORCE_SET_ENUM(RS2_TIMESTAMP_DOMAIN_COUNT); - - // rs2_calib_target_type - _FORCE_SET_ENUM(RS2_CALIB_TARGET_RECT_GAUSSIAN_DOT_VERTICES); - _FORCE_SET_ENUM(RS2_CALIB_TARGET_ROI_RECT_GAUSSIAN_DOT_VERTICES); - _FORCE_SET_ENUM(RS2_CALIB_TARGET_POS_GAUSSIAN_DOT_VERTICES); - _FORCE_SET_ENUM(RS2_CALIB_TARGET_COUNT); - - // rs2_recording_mode - _FORCE_SET_ENUM(RS2_RECORDING_MODE_BLANK_FRAMES); - _FORCE_SET_ENUM(RS2_RECORDING_MODE_COMPRESSED); - _FORCE_SET_ENUM(RS2_RECORDING_MODE_BEST_QUALITY); - _FORCE_SET_ENUM(RS2_RECORDING_MODE_COUNT); - - // rs2_sr300_visual_preset - _FORCE_SET_ENUM(RS2_SR300_VISUAL_PRESET_SHORT_RANGE); - _FORCE_SET_ENUM(RS2_SR300_VISUAL_PRESET_LONG_RANGE); - _FORCE_SET_ENUM(RS2_SR300_VISUAL_PRESET_BACKGROUND_SEGMENTATION); - _FORCE_SET_ENUM(RS2_SR300_VISUAL_PRESET_GESTURE_RECOGNITION); - _FORCE_SET_ENUM(RS2_SR300_VISUAL_PRESET_OBJECT_SCANNING); - _FORCE_SET_ENUM(RS2_SR300_VISUAL_PRESET_FACE_ANALYTICS); - _FORCE_SET_ENUM(RS2_SR300_VISUAL_PRESET_FACE_LOGIN); - _FORCE_SET_ENUM(RS2_SR300_VISUAL_PRESET_GR_CURSOR); - _FORCE_SET_ENUM(RS2_SR300_VISUAL_PRESET_DEFAULT); - _FORCE_SET_ENUM(RS2_SR300_VISUAL_PRESET_MID_RANGE); - _FORCE_SET_ENUM(RS2_SR300_VISUAL_PRESET_IR_ONLY); - _FORCE_SET_ENUM(RS2_SR300_VISUAL_PRESET_COUNT); - - // rs2_rs400_visual_preset - _FORCE_SET_ENUM(RS2_RS400_VISUAL_PRESET_CUSTOM); - _FORCE_SET_ENUM(RS2_RS400_VISUAL_PRESET_DEFAULT); - _FORCE_SET_ENUM(RS2_RS400_VISUAL_PRESET_HAND); - _FORCE_SET_ENUM(RS2_RS400_VISUAL_PRESET_HIGH_ACCURACY); - _FORCE_SET_ENUM(RS2_RS400_VISUAL_PRESET_HIGH_DENSITY); - _FORCE_SET_ENUM(RS2_RS400_VISUAL_PRESET_MEDIUM_DENSITY); - _FORCE_SET_ENUM(RS2_RS400_VISUAL_PRESET_REMOVE_IR_PATTERN); - _FORCE_SET_ENUM(RS2_RS400_VISUAL_PRESET_COUNT); - - // rs2_playback_status - _FORCE_SET_ENUM(RS2_PLAYBACK_STATUS_UNKNOWN); - _FORCE_SET_ENUM(RS2_PLAYBACK_STATUS_PLAYING); - _FORCE_SET_ENUM(RS2_PLAYBACK_STATUS_PAUSED); - _FORCE_SET_ENUM(RS2_PLAYBACK_STATUS_STOPPED); - _FORCE_SET_ENUM(RS2_PLAYBACK_STATUS_COUNT); - - - // rs2_extension - _FORCE_SET_ENUM(RS2_EXTENSION_UNKNOWN); - _FORCE_SET_ENUM(RS2_EXTENSION_DEBUG); - _FORCE_SET_ENUM(RS2_EXTENSION_INFO); - _FORCE_SET_ENUM(RS2_EXTENSION_MOTION); - _FORCE_SET_ENUM(RS2_EXTENSION_OPTIONS); - _FORCE_SET_ENUM(RS2_EXTENSION_VIDEO); - _FORCE_SET_ENUM(RS2_EXTENSION_ROI); - _FORCE_SET_ENUM(RS2_EXTENSION_DEPTH_SENSOR); - _FORCE_SET_ENUM(RS2_EXTENSION_VIDEO_FRAME); - _FORCE_SET_ENUM(RS2_EXTENSION_MOTION_FRAME); - _FORCE_SET_ENUM(RS2_EXTENSION_COMPOSITE_FRAME); - _FORCE_SET_ENUM(RS2_EXTENSION_POINTS); - _FORCE_SET_ENUM(RS2_EXTENSION_DEPTH_FRAME); - _FORCE_SET_ENUM(RS2_EXTENSION_ADVANCED_MODE); - _FORCE_SET_ENUM(RS2_EXTENSION_RECORD); - _FORCE_SET_ENUM(RS2_EXTENSION_VIDEO_PROFILE); - _FORCE_SET_ENUM(RS2_EXTENSION_PLAYBACK); - _FORCE_SET_ENUM(RS2_EXTENSION_DEPTH_STEREO_SENSOR); - _FORCE_SET_ENUM(RS2_EXTENSION_DISPARITY_FRAME); - _FORCE_SET_ENUM(RS2_EXTENSION_MOTION_PROFILE); - _FORCE_SET_ENUM(RS2_EXTENSION_POSE_FRAME); - _FORCE_SET_ENUM(RS2_EXTENSION_POSE_PROFILE); - _FORCE_SET_ENUM(RS2_EXTENSION_TM2); - _FORCE_SET_ENUM(RS2_EXTENSION_SOFTWARE_DEVICE); - _FORCE_SET_ENUM(RS2_EXTENSION_SOFTWARE_SENSOR); - _FORCE_SET_ENUM(RS2_EXTENSION_DECIMATION_FILTER); - _FORCE_SET_ENUM(RS2_EXTENSION_THRESHOLD_FILTER); - _FORCE_SET_ENUM(RS2_EXTENSION_DISPARITY_FILTER); - _FORCE_SET_ENUM(RS2_EXTENSION_SPATIAL_FILTER); - _FORCE_SET_ENUM(RS2_EXTENSION_TEMPORAL_FILTER); - _FORCE_SET_ENUM(RS2_EXTENSION_HOLE_FILLING_FILTER); - _FORCE_SET_ENUM(RS2_EXTENSION_ZERO_ORDER_FILTER); - _FORCE_SET_ENUM(RS2_EXTENSION_RECOMMENDED_FILTERS); - _FORCE_SET_ENUM(RS2_EXTENSION_POSE); - _FORCE_SET_ENUM(RS2_EXTENSION_POSE_SENSOR); - _FORCE_SET_ENUM(RS2_EXTENSION_WHEEL_ODOMETER); - _FORCE_SET_ENUM(RS2_EXTENSION_GLOBAL_TIMER); - _FORCE_SET_ENUM(RS2_EXTENSION_UPDATABLE); - _FORCE_SET_ENUM(RS2_EXTENSION_UPDATE_DEVICE); - _FORCE_SET_ENUM(RS2_EXTENSION_L500_DEPTH_SENSOR); - _FORCE_SET_ENUM(RS2_EXTENSION_TM2_SENSOR); - _FORCE_SET_ENUM(RS2_EXTENSION_AUTO_CALIBRATED_DEVICE); - _FORCE_SET_ENUM(RS2_EXTENSION_COLOR_SENSOR); - _FORCE_SET_ENUM(RS2_EXTENSION_MOTION_SENSOR); - _FORCE_SET_ENUM(RS2_EXTENSION_FISHEYE_SENSOR); - _FORCE_SET_ENUM(RS2_EXTENSION_DEPTH_HUFFMAN_DECODER); - _FORCE_SET_ENUM(RS2_EXTENSION_SERIALIZABLE); - _FORCE_SET_ENUM(RS2_EXTENSION_FW_LOGGER); - _FORCE_SET_ENUM(RS2_EXTENSION_AUTO_CALIBRATION_FILTER); - _FORCE_SET_ENUM(RS2_EXTENSION_DEVICE_CALIBRATION); - _FORCE_SET_ENUM(RS2_EXTENSION_CALIBRATED_SENSOR); - _FORCE_SET_ENUM(RS2_EXTENSION_HDR_MERGE); - _FORCE_SET_ENUM(RS2_EXTENSION_SEQUENCE_ID_FILTER); - _FORCE_SET_ENUM(RS2_EXTENSION_MAX_USABLE_RANGE_SENSOR); - _FORCE_SET_ENUM(RS2_EXTENSION_DEBUG_STREAM_SENSOR); - _FORCE_SET_ENUM(RS2_EXTENSION_CALIBRATION_CHANGE_DEVICE); - _FORCE_SET_ENUM(RS2_EXTENSION_COUNT); - - - // rs2_ambient_light - _FORCE_SET_ENUM(RS2_AMBIENT_LIGHT_NO_AMBIENT) - _FORCE_SET_ENUM(RS2_AMBIENT_LIGHT_LOW_AMBIENT) - - - // rs2_calibration_type - _FORCE_SET_ENUM(RS2_CALIBRATION_AUTO_DEPTH_TO_RGB) - _FORCE_SET_ENUM(RS2_CALIBRATION_MANUAL_DEPTH_TO_RGB) - _FORCE_SET_ENUM(RS2_CALIBRATION_THERMAL) - _FORCE_SET_ENUM(RS2_CALIBRATION_TYPE_COUNT) - - - // rs2_calibration_status - _FORCE_SET_ENUM(RS2_CALIBRATION_TRIGGERED) - _FORCE_SET_ENUM(RS2_CALIBRATION_SPECIAL_FRAME) - _FORCE_SET_ENUM(RS2_CALIBRATION_STARTED) - _FORCE_SET_ENUM(RS2_CALIBRATION_NOT_NEEDED) - _FORCE_SET_ENUM(RS2_CALIBRATION_SUCCESSFUL) - _FORCE_SET_ENUM(RS2_CALIBRATION_RETRY) - _FORCE_SET_ENUM(RS2_CALIBRATION_FAILED) - _FORCE_SET_ENUM(RS2_CALIBRATION_SCENE_INVALID) - _FORCE_SET_ENUM(RS2_CALIBRATION_BAD_RESULT) - _FORCE_SET_ENUM(RS2_CALIBRATION_BAD_CONDITIONS) - _FORCE_SET_ENUM(RS2_CALIBRATION_STATUS_FIRST) - _FORCE_SET_ENUM(RS2_CALIBRATION_STATUS_LAST) - _FORCE_SET_ENUM(RS2_CALIBRATION_STATUS_COUNT) - - - // rs2_dsm_correction_model - _FORCE_SET_ENUM(RS2_DSM_CORRECTION_NONE) - _FORCE_SET_ENUM(RS2_DSM_CORRECTION_AOT) - _FORCE_SET_ENUM(RS2_DSM_CORRECTION_TOA) - _FORCE_SET_ENUM(RS2_DSM_CORRECTION_COUNT) - - - // rs2_host_perf_mode - _FORCE_SET_ENUM(RS2_HOST_PERF_DEFAULT) - _FORCE_SET_ENUM(RS2_HOST_PERF_LOW) - _FORCE_SET_ENUM(RS2_HOST_PERF_HIGH) - _FORCE_SET_ENUM(RS2_HOST_PERF_COUNT) - - // rs2_emitter_frequency - _FORCE_SET_ENUM(RS2_EMITTER_FREQUENCY_57_KHZ) - _FORCE_SET_ENUM(RS2_EMITTER_FREQUENCY_91_KHZ) - _FORCE_SET_ENUM(RS2_EMITTER_FREQUENCY_COUNT) - - // rs2_l500_visual_preset - _FORCE_SET_ENUM(RS2_L500_VISUAL_PRESET_CUSTOM) - _FORCE_SET_ENUM(RS2_L500_VISUAL_PRESET_DEFAULT) - _FORCE_SET_ENUM(RS2_L500_VISUAL_PRESET_NO_AMBIENT) - _FORCE_SET_ENUM(RS2_L500_VISUAL_PRESET_LOW_AMBIENT) - _FORCE_SET_ENUM(RS2_L500_VISUAL_PRESET_MAX_RANGE) - _FORCE_SET_ENUM(RS2_L500_VISUAL_PRESET_SHORT_RANGE) - _FORCE_SET_ENUM(RS2_L500_VISUAL_PRESET_AUTOMATIC) - _FORCE_SET_ENUM(RS2_L500_VISUAL_PRESET_COUNT) - - - // rs2_matchers - _FORCE_SET_ENUM(RS2_MATCHER_DI) - _FORCE_SET_ENUM(RS2_MATCHER_DI_C) - _FORCE_SET_ENUM(RS2_MATCHER_DLR_C) - _FORCE_SET_ENUM(RS2_MATCHER_DLR) - _FORCE_SET_ENUM(RS2_MATCHER_DIC) - _FORCE_SET_ENUM(RS2_MATCHER_DIC_C) - _FORCE_SET_ENUM(RS2_MATCHER_DEFAULT) - _FORCE_SET_ENUM(RS2_MATCHER_COUNT) - - - // rs2_sensor_mode - _FORCE_SET_ENUM(RS2_SENSOR_MODE_VGA) - _FORCE_SET_ENUM(RS2_SENSOR_MODE_XGA) - _FORCE_SET_ENUM(RS2_SENSOR_MODE_QVGA) - _FORCE_SET_ENUM(RS2_SENSOR_MODE_COUNT) - - - // rs2_digital_gain - _FORCE_SET_ENUM(RS2_DIGITAL_GAIN_AUTO) - _FORCE_SET_ENUM(RS2_DIGITAL_GAIN_HIGH) - _FORCE_SET_ENUM(RS2_DIGITAL_GAIN_LOW) -} - -NODE_MODULE(node_librealsense, InitModule); diff --git a/wrappers/nodejs/test/README.md b/wrappers/nodejs/test/README.md deleted file mode 100644 index aceb61f48c..0000000000 --- a/wrappers/nodejs/test/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# Nodejs Wrapper Tests - -# Installing node-librealsense # -There are two ways to get node-librealsense module before testing: **install from npm** and **build from source**, both used **mocha** (`npm install mocha`) as test framework. - -## Install From Npm -Used for feature validation in released node-librealsense module which updates bi-weekly. -Execute `npm i` under `/path/to/wrappers/nodejs/test` to download and install latest module from [npm](https://www.npmjs.com/package/node-librealsense). - -## Build From Source -Used for checking latest features in development branch which hasn't been released on npm. -Execute `npm list node-librealsense` to check if you had installed node-librealsense before, if yes, remove it by using `npm remove node-librealsense` - -# Running the Tests # -Use mocha to run test cases, for example: -Execute `mocha *.js` for all test cases under `/path/to/wrappers/nodejs/test` -or -Execute `mocha test-colorizer.js` for single test case diff --git a/wrappers/nodejs/test/package.json b/wrappers/nodejs/test/package.json deleted file mode 100644 index e0245d97b8..0000000000 --- a/wrappers/nodejs/test/package.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "node-librealsense2-tests", - "version": "0.0.1", - "description": "", - "author": "", - "license": "Apache-2.0", - "dependencies": { - "node-librealsense": "^0.282.1" - } -} diff --git a/wrappers/nodejs/test/test-align.js b/wrappers/nodejs/test/test-align.js deleted file mode 100644 index 22d20f1842..0000000000 --- a/wrappers/nodejs/test/test-align.js +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -/* global describe, it, before, after */ -const assert = require('assert'); -let rs2; -let pipeline; -try { - rs2 = require('node-librealsense'); -} catch (e) { - rs2 = require('../index.js'); -} - -let frameset; -describe('Align test', function() { - before(function() { - pipeline = new rs2.Pipeline(); - pipeline.start(); - while (frameset === undefined) { - const f = pipeline.waitForFrames(); - if (f.size > 1) { - frameset = f; - } - } - }); - - after(function() { - pipeline.destroy(); - rs2.cleanup(); - }); - - it('Testing constructor - 0 argument', () => { - assert.throws(() => { - new rs2.Align(); - }); - }); - - it('Testing constructor - invalid argument', () => { - assert.throws(() => { - new rs2.Align('dummy'); - }); - }); - - it('Testing constructor - valid argument', () => { - for (let i in rs2.stream) { - if (rs2.stream[i] && - i.toUpperCase() !== 'STREAM_COUNT' && // skip counter - i !== 'streamToString' // skip method - ) { - assert.doesNotThrow(() => { // jshint ignore:line - new rs2.Align(rs2.stream[i]); - }); - } - } - }); - - it('Testing process - 0 argument', () => { - const align = new rs2.Align(rs2.stream.STREAM_COLOR); - assert.throws(() => { - align.process(); - }); - }); - - it('Testing process - invalid argument', () => { - const align = new rs2.Align(rs2.stream.STREAM_COLOR); - assert.throws(() => { - align.process('dummy'); - }); - }); - - it('Testing process - valid argument', () => { - const align = new rs2.Align(rs2.stream.STREAM_COLOR); - assert.doesNotThrow(() => { - align.process(frameset); - }); - }); -}); diff --git a/wrappers/nodejs/test/test-colorizer.js b/wrappers/nodejs/test/test-colorizer.js deleted file mode 100644 index 871e444024..0000000000 --- a/wrappers/nodejs/test/test-colorizer.js +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. -'use strict'; - -/* global describe, it, before, after */ -const assert = require('assert'); -let rs2; -try { - rs2 = require('node-librealsense'); -} catch (e) { - rs2 = require('../index.js'); -} - -let ctx; -describe('Colorizer test', function() { - before(function() { - ctx = new rs2.Context(); - const devices = ctx.queryDevices().devices; - assert(devices.length > 0); // Device must be connected - }); - - after(function() { - rs2.cleanup(); - }); - - it('Testing constructor - 0 option', () => { - assert.doesNotThrow(() => { - new rs2.Colorizer(); - }); - }); - - it('Testing constructor - 1 option', () => { - assert.doesNotThrow(() => { - new rs2.Colorizer(1); - }); - }); - - it('Testing method destroy', () => { - let colorizer; - assert.doesNotThrow(() => { - colorizer= new rs2.Colorizer(); - colorizer.destroy(); - }); - assert.equal(colorizer.cxxColorizer, undefined); - assert.equal(colorizer.depthRGB, undefined); - }); - - it('Testing method colorize', () => { - let pipeline; - let colorizer; - assert.doesNotThrow(() => { - pipeline = new rs2.Pipeline(); - colorizer = new rs2.Colorizer(); - pipeline.start(); - }); - let endTest = false; - let n = 0; - while (!endTest) { - const frameSet = pipeline.waitForFrames(); - n++; - console.log(`retring left ...${10 - n} times`); - if (frameSet !== undefined && - frameSet.colorFrame !== undefined && - frameSet.depthFrame !== undefined) { - const depthf = frameSet.depthFrame; - const colorf = frameSet.colorFrame; - assert(depthf instanceof rs2.DepthFrame); - assert(colorf instanceof rs2.VideoFrame); - let videoFrame; - let videoFrameNull; - assert.doesNotThrow(() => { // jshint ignore:line - videoFrame = colorizer.colorize(depthf); - }); - assert(videoFrame instanceof rs2.VideoFrame); - assert.throws(() => { // jshint ignore:line - videoFrameNull = colorizer.colorize(); - }); - assert(videoFrameNull === undefined); - colorizer.destroy(); - if (colorf) colorf.destroy(); - if (depthf) depthf.destroy(); - endTest = true; - if (videoFrame) videoFrame.destroy(); - } - if (n >= 10) { - assert(false, 'could not get colorFrame or depthFrame, try to reset camera'); - } - } - pipeline.destroy(); - }).timeout(4000); -}); diff --git a/wrappers/nodejs/test/test-config.js b/wrappers/nodejs/test/test-config.js deleted file mode 100644 index 33de2f2ef2..0000000000 --- a/wrappers/nodejs/test/test-config.js +++ /dev/null @@ -1,322 +0,0 @@ -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -/* global describe, it, beforeEach, afterEach */ -const assert = require('assert'); -const fs = require('fs'); -let rs2; -try { - rs2 = require('node-librealsense'); -} catch (e) { - rs2 = require('../index.js'); -} - -let fileName = 'record.bag'; -let config; -let pipeline; -let serial; -describe('Config test', function() { - beforeEach(function() { - pipeline = new rs2.Pipeline(); - config = new rs2.Config(); - const ctx = new rs2.Context(); - const devices = ctx.queryDevices().devices; - assert(devices.length > 0); // Device must be connected - const dev = devices[0]; - serial = dev.getCameraInfo(rs2.camera_info.CAMERA_INFO_SERIAL_NUMBER); - }); - - afterEach(function() { - pipeline.destroy(); - rs2.cleanup(); - if (fs.existsSync(fileName)) { - fs.unlinkSync(fileName); - } - }); - - function startRecording(file, cnt) { - return new Promise((resolve, reject) => { - setTimeout(() => { - let ctx = new rs2.Context(); - let dev = ctx.queryDevices().devices[0]; - let recorder = new rs2.RecorderDevice(file, dev); - let sensors = recorder.querySensors(); - let sensor = sensors[0]; - let profiles = sensor.getStreamProfiles(); - assert.equal(recorder.fileName, file); - for (let i = 0; i < profiles.length; i++) { - if (profiles[i].streamType === rs2.stream.STREAM_DEPTH && - profiles[i].fps === 30 && - profiles[i].width === 640 && - profiles[i].height === 480 && - profiles[i].format === rs2.format.FORMAT_Z16) { - sensor.open(profiles[i]); - } - } - let counter = 0; - sensor.start((frame) => { - counter++; - if (counter === cnt) { - recorder.reset(); - resolve(); - } - }); - }, 2000); - }); - } - - it('Testing method canResolve - 0 argument', () => { - assert.throws(() => { - config.canResolve(); - }); - }); - - it('Testing method canResolve - 2 argument', () => { - assert.throws(() => { - config.canResolve(pipeline, pipeline); - }); - }); - - it('Testing method canResolve - invalid argument', () => { - assert.throws(() => { - config.canResolve('dummy'); - }); - }); - - it('Testing method canResolve - valid argument', () => { - let rtn; - assert.doesNotThrow(() => { - rtn = config.canResolve(pipeline); - }); - assert.equal(typeof rtn, 'boolean'); - }); - - it('Testing method disableAllStreams - 0 argument', () => { - assert.doesNotThrow(() => { - config.disableAllStreams(); - }); - }); - - it('Testing method disableAllStreams - 1 argument', () => { - assert.doesNotThrow(() => { - config.disableAllStreams(1); - }); - }); - - it('Testing method disableStream - 0 argument', () => { - assert.throws(() => { - config.disableStream(); - }); - }); - - it('Testing method disableStream - invalid argument', () => { - assert.throws(() => { - config.disableStream('dummy'); - }); - }); - - it('Testing method disableStream - valid argument', () => { - for (let i in rs2.stream) { - if (rs2.stream[i] && - i.toUpperCase() !== 'STREAM_COUNT' && // skip counter - i !== 'streamToString' // skip method - ) { - assert.doesNotThrow(() => { // jshint ignore:line - config.disableStream(rs2.stream[i]); - }); - } - } - }); - - it('Testing method enableDevice - 0 argument', () => { - assert.throws(() => { - config.enableDevice(); - }); - }); - - it('Testing method enableDevice - invalid argument', () => { - assert.doesNotThrow(() => { - config.enableDevice('dummy'); - }); - }); - - it('Testing method enableDevice - valid argument', () => { - assert.doesNotThrow(() => { - config.enableDevice(serial); - }); - }); - - it('Testing method enableStream - 0 argument', () => { - assert.throws(() => { - config.enableStream(); - }); - }); - - it('Testing method enableStream - invalid argument', () => { - assert.throws(() => { - config.enableStream('dummy', 1, 1, 1, 1, 1); - }); - }); - - it('Testing method enableStream - valid argument', () => { - // eslint-disable-next-line guard-for-in - for (let i in rs2.stream) { - for (let j in rs2.format) { - if (rs2.stream[i] && - i.toUpperCase() !== 'STREAM_COUNT' && // skip counter - i !== 'streamToString' && // skip method - rs2.format[j] && - j.toUpperCase() !== 'FORMAT_COUNT' && // skip counter - j !== 'formatToString' // skip method - ) { - assert.doesNotThrow(() => { // jshint ignore:line - config.enableStream(rs2.stream[i], 1, 1, 1, rs2.format[j], 1); - }); - } - } - } - }); - - it('Testing method resolve - 0 argument', () => { - assert.throws(() => { - config.resolve(); - }); - }); - - it('Testing method resolve - invalid argument', () => { - assert.throws(() => { - config.resolve('dummy'); - }); - }); - - it('Testing method resolve - valid argument', () => { - let pp; - assert.doesNotThrow(() => { - pp = config.resolve(pipeline); - }); - assert(pp instanceof rs2.PipelineProfile); - }); - - it('Testing method enableAllStreams - 0 argument', () => { - assert.doesNotThrow(() => { - config.enableAllStreams(); - }); - }); - - it('Testing method enableAllStreams - 1 argument', () => { - assert.doesNotThrow(() => { - config.enableAllStreams(1); - }); - }); - - it('Testing method enableDeviceFromFile - 0 argument', () => { - assert.throws(() => { - config.enableDeviceFromFile(); - }); - }); - - it('Testing method enableDeviceFromFile - 2 argument', () => { - assert.throws(() => { - config.enableDeviceFromFile(1, 1); - }); - }); - - it('Testing method enableDeviceFromFile - argument with number', () => { - assert.throws(() => { - config.enableDeviceFromFile(1); - }); - }); - - it('Testing method enableDeviceFromFile - with file', () => { - return new Promise((resolve, reject) => { - startRecording(fileName, 10).then(() => { - assert.doesNotThrow(() => { - config.enableDeviceFromFile(fileName); - }); - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method enableDeviceFromFile - with invalid argument', () => { - assert.throws(() => { - config.enableDeviceFromFile('dummy'); - }); - }); - - it('Testing method enableDeviceFromFile - after enableRecordToFile', () => { - assert.doesNotThrow(() => { - config.enableRecordToFile(fileName); - pipeline.start(config); - }); - assert.throws(() => { - config.enableDeviceFromFile(fileName); - }); - }); - - it('Testing method enableRecordToFile - 0 argument', () => { - assert.throws(() => { - config.enableRecordToFile(); - }); - }); - - it('Testing method enableRecordToFile - two arguments', () => { - assert.throws(() => { - config.enableRecordToFile(fileName, fileName); - }); - }); - - it('Testing method enableRecordToFile - argument with number', () => { - assert.throws(() => { - config.enableRecordToFile(1); - }); - }); - - it('Testing method enableRecordToFile - without pipeline.start', () => { - assert.doesNotThrow(() => { - config.enableRecordToFile(fileName); - }); - assert.equal(fs.existsSync(fileName), false); - }); - - it('Testing method enableRecordToFile - value result', () => { - assert.doesNotThrow(() => { - config.enableRecordToFile(fileName); - pipeline.start(config); - }); - assert.equal(fs.existsSync(fileName), true); - assert.doesNotThrow(() => { - let frameSet = pipeline.waitForFrames(); - assert(frameSet instanceof rs2.FrameSet); - }); - }).timeout(10000); - - it('Testing method enableRecordToFile - then enableDeviceFromFile', () => { - assert.doesNotThrow(() => { - config.enableRecordToFile(fileName); - pipeline.start(config); - let frameSet = pipeline.waitForFrames(); - assert(frameSet instanceof rs2.FrameSet); - }); - assert.equal(fs.existsSync(fileName), true); - assert.throws(() => { - config.enableDeviceFromFile(fileName); - }); - }); - - it('Testing method enableRecordToFile - fileName has been exist', () => { - fs.closeSync(fs.openSync(fileName, 'w')); - assert.doesNotThrow(() => { - config.enableRecordToFile(fileName); - pipeline.start(config); - }); - assert.doesNotThrow(() => { - let frameSet = pipeline.waitForFrames(); - assert(frameSet instanceof rs2.FrameSet); - }); - assert.equal(fs.existsSync(fileName), true); - }); -}); diff --git a/wrappers/nodejs/test/test-context.js b/wrappers/nodejs/test/test-context.js deleted file mode 100644 index 7f6759530e..0000000000 --- a/wrappers/nodejs/test/test-context.js +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -/* global describe, it, before, after */ -const assert = require('assert'); -const EventEmitter = require('events'); -const fs = require('fs'); -let librealsense2; -try { - librealsense2 = require('node-librealsense'); -} catch (e) { - librealsense2 = require('../index.js'); -} - -describe('Context test', function() { - before(function() { - const ctx = new librealsense2.Context(); - const devices = ctx.queryDevices().devices; - assert(devices.length > 0); // Device must be connected - }); - - after(function() { - librealsense2.cleanup(); - }); - - function startRecording(file, cnt, callback) { - return new Promise((resolve, reject) => { - setTimeout(() => { - let ctx = new librealsense2.Context(); - let dev = ctx.queryDevices().devices[0]; - let recorder = new librealsense2.RecorderDevice(file, dev); - let sensors = recorder.querySensors(); - let sensor = sensors[0]; - let profiles = sensor.getStreamProfiles(); - assert.equal(recorder.fileName, file); - for (let i = 0; i < profiles.length; i++) { - if (profiles[i].streamType === librealsense2.stream.STREAM_DEPTH && - profiles[i].fps === 30 && - profiles[i].width === 640 && - profiles[i].height === 480 && - profiles[i].format === librealsense2.format.FORMAT_Z16) { - sensor.open(profiles[i]); - } - } - let counter = 0; - sensor.start((frame) => { - if (callback) { - callback(recorder, counter); - } - counter++; - if (counter === cnt) { - recorder.reset(); - librealsense2.cleanup(); - resolve(); - } - }); - }, 2000); - }); - } - - it('testing constructor', () => { - assert.doesNotThrow(() => { - new librealsense2.Context(); - }); - assert.throws(() => { - new librealsense2.Context(123); - }); - assert.throws(() => { - new librealsense2.Context('dummy'); - }); - const context = new librealsense2.Context(); - assert.equal(typeof context, 'object'); - }); - - it('testing member - events', () => { - const context = new librealsense2.Context(); - assert(context._events instanceof EventEmitter); - }); - - it('testing constructor - new Context, should get Context', () => { - let context; - assert.doesNotThrow(() => { - context = new librealsense2.Context(); - }); - assert(context instanceof librealsense2.Context); - }); - - it('testing constructor - new Context, invalid 1 option', () => { - assert.throws(() => { - new librealsense2.Context(1); - }); - }); - - it('testing method - destroy, call 1 time', () => { - assert.doesNotThrow(() => { - const context = new librealsense2.Context(); - context.destroy(); - }); - assert.doesNotThrow(() => { - const context = new librealsense2.Context(); - context.destroy(123); - }); - }); - - it('testing method - destroy, call 2 times', () => { - assert.doesNotThrow(() => { - const context = new librealsense2.Context(); - context.destroy(); - context.destroy(); - }); - }); - - it('testing method - queryDevices, should get array', () => { - const context = new librealsense2.Context(); - assert.doesNotThrow(() => { - context.queryDevices(); - }); - const obj = context.queryDevices().devices; - assert.equal(Object.prototype.toString.call(obj), '[object Array]'); - assert.equal(obj[0] instanceof librealsense2.Device, true); - }); - - it('testing method - queryDevices, should be instance of Device', () => { - const context = new librealsense2.Context(); - assert.doesNotThrow(() => { - context.queryDevices(); - }); - const obj = context.queryDevices().devices; - assert.equal(obj[0] instanceof librealsense2.Device, true); - }); - - it('testing method - querySensors, should get array', () => { - const context = new librealsense2.Context(); - assert.doesNotThrow(() => { - context.querySensors(); - }); - const obj = context.querySensors(); - assert.equal(Object.prototype.toString.call(obj), '[object Array]'); - assert.equal(obj[0] instanceof librealsense2.Sensor, true); - }); - - it('testing method - querySensors, should be instance of Sensor', () => { - const context = new librealsense2.Context(); - assert.doesNotThrow(() => { - context.querySensors(); - }); - const obj = context.querySensors(); - assert.equal(obj[0] instanceof librealsense2.Sensor, true); - }); - - it('testing method - setDevicesChangedCallback', () => { - const context = new librealsense2.Context(); - assert.throws(() => { - context.setDevicesChangedCallback(); - }); - }); - - it('testing method - loadDevice, return playbackDevice', () => { - return new Promise((resolve, reject) => { - startRecording('record.bag', 10, null).then(() => { - const context = new librealsense2.Context(); - let pbd; - assert.doesNotThrow(() => { - pbd = context.loadDevice('record.bag'); - }); - assert(pbd instanceof librealsense2.Device); - fs.unlinkSync('record.bag'); - resolve(); - }); - }); - }).timeout(5000); - - it('testing method - getSensorParent', () => { - const context = new librealsense2.Context(); - const devices = context.queryDevices().devices; - const sensors = devices[0].querySensors(); - context.getSensorParent(sensors[0]); - }); -}); diff --git a/wrappers/nodejs/test/test-depthframe.js b/wrappers/nodejs/test/test-depthframe.js deleted file mode 100644 index 0a4f4cbee0..0000000000 --- a/wrappers/nodejs/test/test-depthframe.js +++ /dev/null @@ -1,195 +0,0 @@ -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -/* global describe, it, before, after */ -const assert = require('assert'); -let rs2; -try { - rs2 = require('node-librealsense'); -} catch (e) { - rs2 = require('../index.js'); -} - -let frame; -let pipeline; -describe('DepthFrame test', function() { - before(function() { - pipeline = new rs2.Pipeline(); - pipeline.start(); - while (!frame) { - const frameset = pipeline.waitForFrames(); - frame = frameset.at(0); - } - }); - - after(function() { - pipeline.destroy(); - rs2.cleanup(); - }); - - it('Testing constructor', () => { - assert.doesNotThrow(() => { - new rs2.DepthFrame(); - }); - }); - - it('Testing property isValid', () => { - assert.equal(typeof frame.isValid, 'boolean'); - }); - - it('Testing property data', () => { - assert(Object.prototype.toString.call(frame.data), '[object Uint16Array]' || - Object.prototype.toString.call(frame.data), '[object Uint8Array]' - ); - }); - - it('Testing property width', () => { - assert.equal(typeof frame.width, 'number'); - }); - - it('Testing property height', () => { - assert.equal(typeof frame.height, 'number'); - }); - - it('Testing property frameNumber', () => { - assert.equal(typeof frame.frameNumber, 'number'); - }); - - it('Testing property timestamp', () => { - assert.equal(typeof frame.timestamp, 'number'); - }); - - it('Testing property streamType', () => { - assert.equal(typeof frame.streamType, 'number'); - }); - - it('Testing property dataByteLength', () => { - assert.equal(typeof frame.dataByteLength, 'number'); - }); - - it('Testing property strideInBytes', () => { - assert.equal(typeof frame.strideInBytes, 'number'); - }); - - it('Testing property bitsPerPixel', () => { - assert.equal(typeof frame.bitsPerPixel, 'number'); - }); - - it('Testing property bytesPerPixel', () => { - assert.equal(typeof frame.bytesPerPixel, 'number'); - assert.equal(frame.bytesPerPixel, frame.bitsPerPixel/8); - }); - - it('Testing property timestampDomain', () => { - assert.equal(typeof frame.timestampDomain, 'number'); - }); - - it('Testing method frameMetadata - 0 argument', () => { - assert.throws(() => { - frame.frameMetadata(); - }); - }); - - it('Testing method frameMetadata - invalid argument', () => { - assert.throws(() => { - frame.frameMetadata('dummy'); - }); - }); - - it('Testing method frameMetadata - valid argument', () => { - for (let i in rs2.frame_metadata) { - if (rs2.frame_metadata[i] && - i.toUpperCase() !== 'FRAME_METADATA_COUNT' && // skip counter - i !== 'frameMetadataToString' // skip method - ) { - if (frame.supportsFrameMetadata(rs2.frame_metadata[i])) { - assert.doesNotThrow(() => { // jshint ignore:line - frame.frameMetadata(rs2.frame_metadata[i]); - }); - assert.equal(Object.prototype.toString.call( - frame.frameMetadata(rs2.frame_metadata[i]) - ), '[object Uint8Array]'); - } else { - assert.throws(() => { // jshint ignore:line - frame.frameMetadata(rs2.frame_metadata[i]); - }); - } - } - } - }); - - it('Testing method getData - 0 argument', () => { - assert.doesNotThrow(() => { - frame.getData(); - }); - assert( - Object.prototype.toString.call(frame.getData()), '[object Uint16Array]' || - Object.prototype.toString.call(frame.getData()), '[object Uint8Array]' || - Object.prototype.toString.call(frame.getData()), '[object Buffer]' - ); - }); - - it('Testing method getData - buffer argument', () => { - const len = frame.dataByteLength; - let buf = new ArrayBuffer(len); - assert.doesNotThrow(() => { - frame.getData(buf); - }); - assert( - Object.prototype.toString.call(buf), '[object Uint16Array]' || - Object.prototype.toString.call(buf), '[object Uint8Array]' || - Object.prototype.toString.call(buf), '[object Buffer]' - ); - }); - - it('Testing method getData - 2 argument', () => { - assert.throws(() => { - frame.getData(1, 2); - }); - }); - - it('Testing method getData - invalid argument', () => { - assert.throws(() => { - frame.getData('dummy'); - }); - }); - - it('Testing method supportsFrameMetadata - invalid argument', () => { - assert.throws(() => { - frame.supportsFrameMetadata('dummy'); - }); - }); - - it('Testing method supportsFrameMetadata - valid argument', () => { - for (let i in rs2.frame_metadata) { - if (rs2.frame_metadata[i] && - i.toUpperCase() !== 'FRAME_METADATA_COUNT' && // skip counter - i !== 'frameMetadataToString' // skip method - ) { - assert.doesNotThrow(() => { // jshint ignore:line - frame.supportsFrameMetadata(rs2.frame_metadata[i]); - }); - assert.equal(Object.prototype.toString.call( - frame.supportsFrameMetadata(rs2.frame_metadata[i]) - ), '[object Boolean]'); - } - } - }); - - it('Testing method getDistance - valid argument', () => { - let d; - assert.doesNotThrow(() => { - d = frame.getDistance(1, 2); - }); - assert.equal(typeof d, 'number'); - }); - - it('Testing method destroy', () => { - assert.doesNotThrow(() => { - frame.destroy(); - }); - }); -}); diff --git a/wrappers/nodejs/test/test-depthsensor.js b/wrappers/nodejs/test/test-depthsensor.js deleted file mode 100644 index 79f82bac59..0000000000 --- a/wrappers/nodejs/test/test-depthsensor.js +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -/* global describe, it, before, after */ -const assert = require('assert'); -let rs2; -try { - rs2 = require('node-librealsense'); -} catch (e) { - rs2 = require('../index.js'); -} - -let ctx; -let depthSensor; -let pipeline; -describe('Device test', function() { - before(function() { - ctx = new rs2.Context(); - const devices = ctx.queryDevices().devices; - assert(devices.length > 0); // Device must be connected - const dev = devices[0]; - pipeline = new rs2.Pipeline(); - pipeline.start(); - while (!depthSensor) { - const sensors = dev.querySensors(); - for (let i = 0; i < sensors.length; i++) { - if (sensors[i] instanceof rs2.DepthSensor) { - depthSensor = sensors[i]; - } - } - } - }); - - after(function() { - pipeline.destroy(); - rs2.cleanup(); - }); - - it('Testing constructor', () => { - assert.doesNotThrow(() => { - new rs2.DepthFrame(); - }); - }); - - it('Testing member depthScale - without argument', () => { - let v; - assert.doesNotThrow(() => { - v = depthSensor.depthScale; - }); - assert(typeof v !== undefined); - }); -}); diff --git a/wrappers/nodejs/test/test-device.js b/wrappers/nodejs/test/test-device.js deleted file mode 100644 index 15920d5550..0000000000 --- a/wrappers/nodejs/test/test-device.js +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -/* global describe, it, beforeEach, afterEach */ -const assert = require('assert'); -let rs2; -try { - rs2 = require('node-librealsense'); -} catch (e) { - rs2 = require('../index.js'); -} - -let ctx; -let dev; -describe('Device test', function() { - beforeEach(function() { - ctx = new rs2.Context(); - const devices = ctx.queryDevices().devices; - assert(devices.length > 0); // Device must be connected - dev = devices[0]; - }); - - afterEach(function() { - rs2.cleanup(); - }); - - it('Testing constructor', () => { - assert.doesNotThrow(() => { - new rs2.Device(dev); - }); - }); - - it('Testing member - first', () => { - assert(dev.first instanceof rs2.Sensor); - }); - - it('Testing member - isValid', () => { - assert.equal(typeof dev.isValid, 'boolean'); - }); - - it('Testing method destroy', () => { - assert.doesNotThrow(() => { - dev.destroy(); - }); - }); - - it('Testing method getCameraInfo - without argument', () => { - assert.doesNotThrow(() => { - dev.getCameraInfo(); - }); - }); - - it('Testing method getCameraInfo - return value', () => { - let rtn = dev.getCameraInfo(); - assert.equal(typeof rtn.name, 'string'); - assert.equal(typeof rtn.serialNumber, 'string'); - assert.equal(typeof rtn.firmwareVersion, 'string'); - assert.equal(typeof rtn.physicalPort, 'string'); - assert.equal(typeof rtn.debugOpCode, 'string'); - assert.equal(typeof rtn.advancedMode, 'string'); - assert.equal(typeof rtn.productId, 'string'); - // assert.equal(typeof rtn.cameraLocked, 'boolean'); // skip cameraLocked checking - }); - - it('Testing method getCameraInfo - with argument', () => { - for (let i in rs2.camera_info) { - if (rs2.camera_info[i] && - i.toUpperCase() !== 'CAMERA_INFO_LOCATION' && // location is not ready - i.toUpperCase() !== 'CAMERA_INFO_COUNT' && // skip counter - i.toUpperCase() !== 'CAMERA_INFO_CAMERA_LOCKED' && - i !== 'cameraInfoToString' // skip method - ) { - assert.doesNotThrow(() => { // jshint ignore:line - dev.getCameraInfo(rs2.camera_info[i]); - }); - } - } - }); - - it('Testing method getCameraInfo - with invalid argument', () => { - assert.throws(() => { - dev.getCameraInfo('dummy'); - }); - }); - - it('Testing method querySensors - return value', () => { - assert.doesNotThrow(() => { - dev.querySensors(); - }); - assert.equal(Object.prototype.toString.call(dev.querySensors()), '[object Array]'); - dev.querySensors().forEach((i) => { - assert(dev.querySensors()[0] instanceof rs2.Sensor); - }); - }); - - it('Testing method reset', () => { - assert.doesNotThrow(() => { - dev.reset(); - }); - assert.equal(typeof dev.reset(), 'undefined'); - }); - - it('Testing method supportsCameraInfo - without argument', () => { - assert.throws(() => { - dev.supportsCameraInfo(); - }); - }); - - // BUG-7430 - it('Testing method supportsCameraInfo - return value', () => { - let rtn = dev.supportsCameraInfo('serial-number'); - assert.equal(typeof rtn, 'boolean'); - }); - - it('Testing method supportsCameraInfo - with invalid argument', () => { - assert.throws(() => { - dev.supportsCameraInfo('dummy'); - }); - }); - - it('Testing method supportsCameraInfo - with argument', () => { - for (let i in rs2.camera_info) { - if (rs2.camera_info[i] && - i.toUpperCase() !== 'CAMERA_INFO_LOCATION' && // BUG-7429 - i.toUpperCase() !== 'CAMERA_INFO_COUNT' && // skip counter - i !== 'cameraInfoToString' // skip method - ) { - assert.doesNotThrow(() => { // jshint ignore:line - dev.supportsCameraInfo(rs2.camera_info[i]); - }); - } - } - }); -}); diff --git a/wrappers/nodejs/test/test-devicehub.js b/wrappers/nodejs/test/test-devicehub.js deleted file mode 100644 index 6287c60e71..0000000000 --- a/wrappers/nodejs/test/test-devicehub.js +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -/* global describe, it, beforeEach, afterEach */ -const assert = require('assert'); -let rs2; -try { - rs2 = require('node-librealsense'); -} catch (e) { - rs2 = require('../index.js'); -} - -let ctx; -let devh; -describe('DeviceHub test', function() { - beforeEach(function() { - ctx = new rs2.Context(); - devh = new rs2.DeviceHub(ctx); - }); - - afterEach(function() { - rs2.cleanup(); - }); - - it('Testing constructor', () => { - assert.doesNotThrow(() => { - new rs2.DeviceHub(ctx); - }); - }); - - it('Testing method destroy', () => { - assert.notEqual(devh.cxxHub, undefined); - assert.doesNotThrow(() => { - devh.destroy(); - }); - assert.equal(devh.cxxHub, undefined); - }); - - it('Testing method isConnected', () => { - let devs = ctx.queryDevices().devices; - devs.forEach((dev) => { - assert.doesNotThrow(() => { - devh.isConnected(dev); - }); - assert(devh.isConnected(dev)); - }); - }); - - it('Testing method isConnected - without argument', () => { - assert.throws(() => { - devh.isConnected(); - }); - }); - - it('Testing method isConnected - with invalid argument', () => { - assert.throws(() => { - devh.isConnected('dummy'); - }); - }); - - it('Testing method waitForDevice', () => { - assert.doesNotThrow(() => { - devh.waitForDevice(); - }); - }); - - it('Testing method waitForDevice - return value', () => { - let dev = devh.waitForDevice(); - if (dev) { - assert(dev instanceof rs2.Device); - } else { - assert.equal(dev, undefined); - } - }); - - it('Testing method waitForDevice - with invalid argument', () => { - let dev = devh.waitForDevice('dummy'); - assert(dev instanceof rs2.Device); - }); - - it('Testing method waitForDevice - call multiple times', () => { - let dev; - assert.doesNotThrow(() => { - dev = devh.waitForDevice(); - dev = devh.waitForDevice(); - }); - if (dev) { - assert(dev instanceof rs2.Device); - } else { - assert.equal(dev, undefined); - } - }); -}); diff --git a/wrappers/nodejs/test/test-devicelist.js b/wrappers/nodejs/test/test-devicelist.js deleted file mode 100644 index b30c780778..0000000000 --- a/wrappers/nodejs/test/test-devicelist.js +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright (c) 2018 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -/* global describe, it, beforeEach, afterEach */ -const assert = require('assert'); -let rs2; -try { - rs2 = require('node-librealsense'); -} catch (e) { - rs2 = require('../index.js'); -} - -let ctx; -let devl; -describe('DeviceList test', function() { - beforeEach(function() { - ctx = new rs2.Context(); - devl = ctx.queryDevices(); - }); - - afterEach(function() { - rs2.cleanup(); - }); - - it('Testing constructor', () => { - assert.doesNotThrow(() => { - new rs2.DeviceList(devl); - }); - }); - - it('Testing member devices', () => { - if (devl.size === 0 || devl.size === undefined) { - assert.equal(devl.devices, undefined); - } - let output = devl.devices; - for (let i=0; i < devl.size; i++) { - assert(output[i] instanceof rs2.Device); - } - }); - - it('Testing member size', () => { - assert.equal(typeof devl.size, 'number'); - }); - - it('Testing member back', () => { - let dev = devl.devices; - assert(dev.length > 0); // Device must be connected - let device = devl.getDevice(dev.length -1); - let SN = device.getCameraInfo().serialNumber; - assert.doesNotThrow(() => { - if (devl.size > 0) { - let res = devl.back; - assert(devl.back instanceof rs2.Device); - assert.equal(typeof res, 'object'); - assert.equal(res.getCameraInfo().serialNumber, SN); - } - }); - }); - - it('Testing member front', () => { - let dev = devl.devices; - assert(dev.length > 0); // Device must be connected - let device = devl.getDevice(0); - let SN = device.getCameraInfo().serialNumber; - assert.doesNotThrow(() => { - if (devl.size > 0) { - let res = devl.front; - assert(devl.front instanceof rs2.Device); - assert.equal(typeof res, 'object'); - assert.equal(res.getCameraInfo().serialNumber, SN); - } - }); - }); - - it('Testing method destroy', () => { - assert.notEqual(devl.cxxList, undefined); - assert.doesNotThrow(() => { - devl.destroy(); - }); - assert.equal(devl.cxxList, undefined); - }); - - it('Testing method getDevice - without argument', () => { - assert.throws(() => { - devl.getDevice(); - }); - }); - - it('Testing method getDevice - return value', () => { - for (let i = 0; i < devl.size; i++) { - let dev = devl.getDevice(i); - if (dev) { - assert(dev instanceof rs2.Device); - } else { - assert.equal(dev, undefined); - } - } - }); - - it('Testing method getDevice - with argument', () => { - for (let i = 0; i < devl.size; i++) { - assert.doesNotThrow(() => { // jshint ignore:line - devl.getDevice(i); - }); - } - }); - - it('Testing method getDevice - with invalid argument', () => { - assert.throws(() => { - devl.getDevice('dummy'); - }); - }); - - it('Testing method contains - without argument', () => { - assert.throws(() => { - devl.contains(); - }); - }); - - it('Testing method contains - return value', () => { - for (let i = 0; i < devl.size; i++) { - let dev = devl.getDevice(i); - assert.equal(typeof devl.contains(dev), 'boolean'); - } - }); - - it('Testing method contains - with argument', () => { - for (let i = 0; i < devl.size; i++) { - assert.doesNotThrow(() => { // jshint ignore:line - let dev = devl.getDevice(i); - devl.contains(dev); - }); - } - }); - - it('Testing method contains - with invalid argument', () => { - assert.throws(() => { - devl.contains('dummy'); - }); - }); -}); diff --git a/wrappers/nodejs/test/test-frame.js b/wrappers/nodejs/test/test-frame.js deleted file mode 100644 index 436591dd6b..0000000000 --- a/wrappers/nodejs/test/test-frame.js +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -/* global describe, it, before, after */ -const assert = require('assert'); -let rs2; -try { - rs2 = require('node-librealsense'); -} catch (e) { - rs2 = require('../index.js'); -} - -let frame; -let pipeline; -describe('Frame test', function() { - before(function() { - pipeline = new rs2.Pipeline(); - pipeline.start(); - while (!frame) { - const frameset = pipeline.waitForFrames(); - frame = frameset.at(0); - } - }); - - after(function() { - pipeline.destroy(); - rs2.cleanup(); - }); - - it('Testing constructor', () => { - assert.doesNotThrow(() => { - new rs2.Frame(); - }); - }); - - it('Testing property isValid', () => { - assert.equal(typeof frame.isValid, 'boolean'); - }); - - it('Testing property data', () => { - assert(Object.prototype.toString.call(frame.data), '[object Uint16Array]' || - Object.prototype.toString.call(frame.data), '[object Uint8Array]' - ); - }); - - it('Testing property width', () => { - assert.equal(typeof frame.width, 'number'); - }); - - it('Testing property height', () => { - assert.equal(typeof frame.height, 'number'); - }); - - it('Testing property frameNumber', () => { - assert.equal(typeof frame.frameNumber, 'number'); - }); - - it('Testing property timestamp', () => { - assert.equal(typeof frame.timestamp, 'number'); - }); - - it('Testing property streamType', () => { - assert.equal(typeof frame.streamType, 'number'); - }); - - it('Testing property dataByteLength', () => { - assert.equal(typeof frame.dataByteLength, 'number'); - }); - - it('Testing property strideInBytes', () => { - assert.equal(typeof frame.strideInBytes, 'number'); - }); - - it('Testing property bitsPerPixel', () => { - assert.equal(typeof frame.bitsPerPixel, 'number'); - }); - - it('Testing property timestampDomain', () => { - assert.equal(typeof frame.timestampDomain, 'number'); - }); - - it('Testing method frameMetadata - 0 argument', () => { - assert.throws(() => { - frame.frameMetadata(); - }); - }); - - it('Testing method frameMetadata - invalid argument', () => { - assert.throws(() => { - frame.frameMetadata('dummy'); - }); - }); - - it('Testing method frameMetadata - valid argument', () => { - for (let i in rs2.frame_metadata) { - if (rs2.frame_metadata[i] && - i.toUpperCase() !== 'FRAME_METADATA_COUNT' && // skip counter - i !== 'frameMetadataToString' // skip method - ) { - if (frame.supportsFrameMetadata(rs2.frame_metadata[i])) { - assert.doesNotThrow(() => { // jshint ignore:line - frame.frameMetadata(rs2.frame_metadata[i]); - }); - assert.equal(Object.prototype.toString.call( - frame.frameMetadata(rs2.frame_metadata[i]) - ), '[object Uint8Array]'); - } else { - assert.throws(() => { // jshint ignore:line - frame.frameMetadata(rs2.frame_metadata[i]); - }); - } - } - } - }); - - it('Testing method getData - 0 argument', () => { - assert.doesNotThrow(() => { - frame.getData(); - }); - assert( - Object.prototype.toString.call(frame.getData()), '[object Uint16Array]' || - Object.prototype.toString.call(frame.getData()), '[object Uint8Array]' || - Object.prototype.toString.call(frame.getData()), '[object Buffer]' - ); - }); - - it('Testing method getData - buffer argument', () => { - const len = frame.dataByteLength; - let buf = new ArrayBuffer(len); - assert.doesNotThrow(() => { - frame.getData(buf); - }); - assert( - Object.prototype.toString.call(buf), '[object Uint16Array]' || - Object.prototype.toString.call(buf), '[object Uint8Array]' || - Object.prototype.toString.call(buf), '[object Buffer]' - ); - }); - - it('Testing method getData - 2 argument', () => { - assert.throws(() => { - frame.getData(1, 2); - }); - }); - - it('Testing method getData - invalid argument', () => { - assert.throws(() => { - frame.getData('dummy'); - }); - }); - - it('Testing method supportsFrameMetadata - invalid argument', () => { - assert.throws(() => { - frame.supportsFrameMetadata('dummy'); - }); - }); - - it('Testing method supportsFrameMetadata - valid argument', () => { - for (let i in rs2.frame_metadata) { - if (rs2.frame_metadata[i] && - i.toUpperCase() !== 'FRAME_METADATA_COUNT' && // skip counter - i !== 'frameMetadataToString' // skip method - ) { - assert.doesNotThrow(() => { // jshint ignore:line - frame.supportsFrameMetadata(rs2.frame_metadata[i]); - }); - assert.equal(Object.prototype.toString.call( - frame.supportsFrameMetadata(rs2.frame_metadata[i]) - ), '[object Boolean]'); - } - } - }); - - it('Testing method destroy', () => { - assert.doesNotThrow(() => { - frame.destroy(); - }); - }); -}); diff --git a/wrappers/nodejs/test/test-frameset.js b/wrappers/nodejs/test/test-frameset.js deleted file mode 100644 index 629695d5de..0000000000 --- a/wrappers/nodejs/test/test-frameset.js +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright (c) 2018 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -/* global describe, it, before, after */ -const assert = require('assert'); -let rs2; -try { - rs2 = require('node-librealsense'); -} catch (e) { - rs2 = require('../index.js'); -} - -let frameset; -let pipeline; -describe('FrameSet test', function() { - before(function() { - pipeline = new rs2.Pipeline(); - pipeline.start(); - while (frameset === undefined) { - const f = pipeline.waitForFrames(); - if (f.size > 1) { - frameset = f; - } - } - }); - - after(function() { - pipeline.destroy(); - rs2.cleanup(); - }); - - it('Testing constructor', () => { - assert.doesNotThrow(() => { - new rs2.FrameSet(); - }); - }); - - it('Testing member size', () => { - assert.equal(typeof frameset.size, 'number'); - }); - - it('Testing member depthFrame', () => { - assert(frameset.depthFrame instanceof rs2.DepthFrame); - }); - - it('Testing member colorFrame', () => { - assert(frameset.colorFrame instanceof rs2.VideoFrame); - }); - - it('Testing method at - 0 argument', () => { - assert.throws(() => { - frameset.at(); - }); - }); - - it('Testing method at - invalid argument', () => { - const len = frameset.size; - let f; - assert.throws(() => { - f = frameset.at(len + 1); - }); - assert.equal(f, undefined); - }); - - it('Testing method at - valid argument', () => { - const len = frameset.size; - for (let i = 0; i < len; i++) { - let f; - assert.doesNotThrow(() => { // jshint ignore:line - f = frameset.at(i); - }); - assert(f instanceof rs2.DepthFrame || f instanceof rs2.VideoFrame); - } - }); - - it('Testing method getFrame - 0 argument', () => { - assert.throws(() => { - frameset.getFrame(); - }); - }); - - it('Testing method getFrame - invalid argument', () => { - assert.throws(() => { - frameset.getFrame('dummy'); - }); - }); - - it('Testing method getFrame - valid argument', () => { - for (let i in rs2.stream) { - if (rs2.stream[i] && - i.toUpperCase() !== 'STREAM_COUNT' && // skip counter - i !== 'streamToString' // skip method - ) { - assert.doesNotThrow(() => { // jshint ignore:line - frameset.getFrame(rs2.stream[i]); - }); - assert.doesNotThrow(() => { // jshint ignore:line - frameset.getFrame(rs2.stream[i]); - }); - } - } - }); - - it('Testing method getFrame - stream_depth', () => { - let d = frameset.getFrame(rs2.stream['stream_depth']); // jshint ignore:line - assert(d instanceof rs2.DepthFrame); - let D = frameset.getFrame(rs2.stream['STREAM_DEPTH']); // jshint ignore:line - assert(D instanceof rs2.DepthFrame); - }); - - it('Testing method getFrame - stream_color', () => { - let d = frameset.getFrame(rs2.stream['stream_color']); // jshint ignore:line - assert(d instanceof rs2.VideoFrame); - let D = frameset.getFrame(rs2.stream['STREAM_COLOR']); // jshint ignore:line - assert(D instanceof rs2.VideoFrame); - }); - - it('Testing method forEach', () => { - let counter = 0; - function callback(frame) { - counter++; - assert.equal(frame instanceof rs2.Frame, true); - } - frameset.forEach(callback); - assert.equal(counter, frameset.size); - }); -}); diff --git a/wrappers/nodejs/test/test-functional-online.js b/wrappers/nodejs/test/test-functional-online.js deleted file mode 100644 index fba2bb99c2..0000000000 --- a/wrappers/nodejs/test/test-functional-online.js +++ /dev/null @@ -1,661 +0,0 @@ -// Copyright (c) 2018 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -/* global describe, it, before, after */ -const assert = require('assert'); -const fs = require('fs'); -let rs2; -try { - rs2 = require('node-librealsense'); -} catch (e) { - rs2 = require('../index.js'); -} - -describe('Disparity transform tests', function() { - let ctx; - let pipe; - let depth2Disparity; - let disparith2Depth; - before(function() { - ctx = new rs2.Context(); - pipe = new rs2.Pipeline(ctx); - depth2Disparity = new rs2.DepthToDisparityTransform(); - disparith2Depth = new rs2.DisparityToDepthTransform(); - }); - - after(function() { - rs2.cleanup(); - }); - - it('depth frame <=> disparity frame using transform', () => { - pipe.start(); - const frames = pipe.waitForFrames(); - assert.equal(frames.size > 0, true); - frames.forEach((frame) => { - if (frame instanceof rs2.DepthFrame) { - let output = depth2Disparity.process(frame); - assert.equal(output instanceof rs2.DisparityFrame, true); - assert.equal(typeof output.baseLine, 'number'); - - let dout = disparith2Depth.process(output); - assert.equal(dout instanceof rs2.DepthFrame, true); - } - }); - pipe.stop(); - }); -}); - -describe('Points and Pointcloud test', function() { - it('Points.exportToPly', () => { - const pc = new rs2.PointCloud(); - const pipe = new rs2.Pipeline(); - const file = 'points.ply'; - pipe.start(); - const frameset = pipe.waitForFrames(); - const points = pc.calculate(frameset.depthFrame); - points.exportToPly(file, frameset.colorFrame); - assert.equal(fs.existsSync(file), true); - fs.unlinkSync(file); - pipe.stop(); - rs2.cleanup(); - }); - it('Pointcloud options API test', () => { - const pc = new rs2.PointCloud(); - for (let i = rs2.option.OPTION_BACKLIGHT_COMPENSATION; i < rs2.option.OPTION_COUNT; i++) { - if (pc.supportsOption(i)) { - assert.equal(typeof pc.getOption(i), 'number'); - } - } - rs2.cleanup(); - }); -}); - -describe('enum value test', function() { - it('sr300_visual_preset test', () => { - const obj = rs2.sr300_visual_preset; - const numberAttrs = [ - 'SR300_VISUAL_PRESET_SHORT_RANGE', - 'SR300_VISUAL_PRESET_LONG_RANGE', - 'SR300_VISUAL_PRESET_BACKGROUND_SEGMENTATION', - 'SR300_VISUAL_PRESET_GESTURE_RECOGNITION', - 'SR300_VISUAL_PRESET_OBJECT_SCANNING', - 'SR300_VISUAL_PRESET_FACE_ANALYTICS', - 'SR300_VISUAL_PRESET_FACE_LOGIN', - 'SR300_VISUAL_PRESET_GR_CURSOR', - 'SR300_VISUAL_PRESET_DEFAULT', - 'SR300_VISUAL_PRESET_MID_RANGE', - 'SR300_VISUAL_PRESET_IR_ONLY', - 'SR300_VISUAL_PRESET_COUNT', - ]; - const strAttrs = [ - 'sr300_visual_preset_short_range', - 'sr300_visual_preset_long_range', - 'sr300_visual_preset_background_segmentation', - 'sr300_visual_preset_gesture_recognition', - 'sr300_visual_preset_object_scanning', - 'sr300_visual_preset_face_analytics', - 'sr300_visual_preset_face_login', - 'sr300_visual_preset_gr_cursor', - 'sr300_visual_preset_default', - 'sr300_visual_preset_mid_range', - 'sr300_visual_preset_ir_only', - ]; - numberAttrs.forEach((attr) => { - assert.equal(typeof obj[attr], 'number'); - }); - strAttrs.forEach((attr) => { - assert.equal(typeof obj[attr], 'string'); - }); - for (let i = 0; i < obj.SR300_VISUAL_PRESET_COUNT; i++) { - assert.equal(typeof obj.sr300VisualPresetToString(i), 'string'); - } - }); - - it('rs400_visual_preset test', () => { - const obj = rs2.rs400_visual_preset; - const numberAttrs = [ - 'RS400_VISUAL_PRESET_CUSTOM', - 'RS400_VISUAL_PRESET_DEFAULT', - 'RS400_VISUAL_PRESET_HAND', - 'RS400_VISUAL_PRESET_HIGH_ACCURACY', - 'RS400_VISUAL_PRESET_HIGH_DENSITY', - 'RS400_VISUAL_PRESET_MEDIUM_DENSITY', - 'RS400_VISUAL_PRESET_REMOVE_IR_PATTERN', - 'RS400_VISUAL_PRESET_COUNT', - ]; - const strAttrs = [ - 'rs400_visual_preset_custom', - 'rs400_visual_preset_default', - 'rs400_visual_preset_hand', - 'rs400_visual_preset_high_accuracy', - 'rs400_visual_preset_high_density', - 'rs400_visual_preset_medium_density', - 'rs400_visual_preset_remove_ir_pattern', - ]; - numberAttrs.forEach((attr) => { - assert.equal(typeof obj[attr], 'number'); - }); - strAttrs.forEach((attr) => { - assert.equal(typeof obj[attr], 'string'); - }); - for (let i = 0; i < obj.RS400_VISUAL_PRESET_COUNT; i++) { - assert.equal(typeof obj.rs400VisualPresetToString(i), 'string'); - } - }); - - it('format test', () => { - const obj = rs2.format; - const numberAttrs = [ - 'FORMAT_ANY', - 'FORMAT_Z16', - 'FORMAT_DISPARITY16', - 'FORMAT_XYZ32F', - 'FORMAT_YUYV', - 'FORMAT_RGB8', - 'FORMAT_BGR8', - 'FORMAT_RGBA8', - 'FORMAT_BGRA8', - 'FORMAT_Y8', - 'FORMAT_Y16', - 'FORMAT_RAW10', - 'FORMAT_RAW16', - 'FORMAT_RAW8', - 'FORMAT_UYVY', - 'FORMAT_MOTION_RAW', - 'FORMAT_MOTION_XYZ32F', - 'FORMAT_GPIO_RAW', - 'FORMAT_6DOF', - 'FORMAT_DISPARITY32', - 'FORMAT_COUNT', - ]; - const strAttrs = [ - 'format_any', - 'format_z16', - 'format_disparity16', - 'format_xyz32f', - 'format_yuyv', - 'format_rgb8', - 'format_bgr8', - 'format_rgba8', - 'format_bgra8', - 'format_y8', - 'format_y16', - 'format_raw10', - 'format_raw16', - 'format_raw8', - 'format_uyvy', - 'format_motion_raw', - 'format_motion_xyz32f', - 'format_gpio_raw', - 'format_6dof', - 'format_disparity32', - ]; - numberAttrs.forEach((attr) => { - assert.equal(typeof obj[attr], 'number'); - }); - strAttrs.forEach((attr) => { - assert.equal(typeof obj[attr], 'string'); - }); - for (let i = 0; i < obj.FORMAT_COUNT; i++) { - assert.equal(typeof obj.formatToString(i), 'string'); - } - }); - it('notification_category test', () => { - const obj = rs2.notification_category; - const numberAttrs = [ - 'NOTIFICATION_CATEGORY_FRAMES_TIMEOUT', - 'NOTIFICATION_CATEGORY_FRAME_CORRUPTED', - 'NOTIFICATION_CATEGORY_HARDWARE_ERROR', - 'NOTIFICATION_CATEGORY_HARDWARE_EVENT', - 'NOTIFICATION_CATEGORY_UNKNOWN_ERROR', - 'NOTIFICATION_CATEGORY_FIRMWARE_UPDATE_RECOMMENDED', - ]; - const strAttrs = [ - 'notification_category_frames_timeout', - 'notification_category_frame_corrupted', - 'notification_category_hardware_error', - 'notification_category_hardware_event', - 'notification_category_unknown_error', - 'notification_category_firmware_update_recommended', - ]; - numberAttrs.forEach((attr) => { - assert.equal(typeof obj[attr], 'number'); - }); - strAttrs.forEach((attr) => { - assert.equal(typeof obj[attr], 'string'); - }); - for (let i = 0; i < obj.NOTIFICATION_CATEGORY_COUNT; i++) { - assert.equal(typeof obj.notificationCategoryToString(i), 'string'); - } - }); - it('frame_metadata test', () => { - const obj = rs2.frame_metadata; - const numberAttrs = [ - 'FRAME_METADATA_FRAME_COUNTER', - 'FRAME_METADATA_FRAME_TIMESTAMP', - 'FRAME_METADATA_SENSOR_TIMESTAMP', - 'FRAME_METADATA_ACTUAL_EXPOSURE', - 'FRAME_METADATA_GAIN_LEVEL', - 'FRAME_METADATA_AUTO_EXPOSURE', - 'FRAME_METADATA_WHITE_BALANCE', - 'FRAME_METADATA_TIME_OF_ARRIVAL', - 'FRAME_METADATA_TEMPERATURE', - 'FRAME_METADATA_FRAME_LASER_POWER', - 'FRAME_METADATA_FRAME_LASER_POWER_MODE', - 'FRAME_METADATA_EXPOSURE_PRIORITY', - 'FRAME_METADATA_EXPOSURE_ROI_LEFT', - 'FRAME_METADATA_EXPOSURE_ROI_RIGHT', - 'FRAME_METADATA_EXPOSURE_ROI_TOP', - 'FRAME_METADATA_EXPOSURE_ROI_BOTTOM', - 'FRAME_METADATA_BRIGHTNESS', - 'FRAME_METADATA_CONTRAST', - 'FRAME_METADATA_SATURATION', - 'FRAME_METADATA_SHARPNESS', - 'FRAME_METADATA_AUTO_WHITE_BALANCE_TEMPERATURE', - 'FRAME_METADATA_BACKLIGHT_COMPENSATION', - 'FRAME_METADATA_HUE', - 'FRAME_METADATA_GAMMA', - 'FRAME_METADATA_MANUAL_WHITE_BALANCE', - 'FRAME_METADATA_POWER_LINE_FREQUENCY', - 'FRAME_METADATA_LOW_LIGHT_COMPENSATION', - ]; - const strAttrs = [ - 'frame_metadata_frame_counter', - 'frame_metadata_frame_timestamp', - 'frame_metadata_sensor_timestamp', - 'frame_metadata_actual_exposure', - 'frame_metadata_gain_level', - 'frame_metadata_auto_exposure', - 'frame_metadata_white_balance', - 'frame_metadata_time_of_arrival', - 'frame_metadata_temperature', - 'frame_metadata_frame_laser_power', - 'frame_metadata_frame_laser_power_mode', - 'frame_metadata_exposure_priority', - 'frame_metadata_exposure_roi_left', - 'frame_metadata_exposure_roi_right', - 'frame_metadata_exposure_roi_top', - 'frame_metadata_exposure_roi_bottom', - 'frame_metadata_brightness', - 'frame_metadata_contrast', - 'frame_metadata_saturation', - 'frame_metadata_sharpness', - 'frame_metadata_auto_white_balance_temperature', - 'frame_metadata_backlight_compensation', - 'frame_metadata_hue', - 'frame_metadata_gamma', - 'frame_metadata_manual_white_balance', - 'frame_metadata_power_line_frequency', - 'frame_metadata_low_light_compensation', - ]; - numberAttrs.forEach((attr) => { - assert.equal(typeof obj[attr], 'number'); - }); - strAttrs.forEach((attr) => { - assert.equal(typeof obj[attr], 'string'); - }); - for (let i = 0; i < obj.FRAME_METADATA_COUNT; i++) { - assert.equal(typeof obj.frameMetadataToString(i), 'string'); - } - }); - it('stream test', () => { - const obj = rs2.stream; - const numberAttrs = [ - 'STREAM_ANY', - 'STREAM_DEPTH', - 'STREAM_COLOR', - 'STREAM_INFRARED', - 'STREAM_FISHEYE', - 'STREAM_GYRO', - 'STREAM_ACCEL', - 'STREAM_GPIO', - 'STREAM_POSE', - 'STREAM_CONFIDENCE', - ]; - const strAttrs = [ - 'stream_any', - 'stream_depth', - 'stream_color', - 'stream_infrared', - 'stream_fisheye', - 'stream_gyro', - 'stream_accel', - 'stream_gpio', - 'stream_pose', - 'stream_confidence', - ]; - numberAttrs.forEach((attr) => { - assert.equal(typeof obj[attr], 'number'); - }); - strAttrs.forEach((attr) => { - assert.equal(typeof obj[attr], 'string'); - }); - for (let i = 0; i < obj.STREAM_COUNT; i++) { - assert.equal(typeof obj.streamToString(i), 'string'); - } - }); - it('camera_info test', () => { - const obj = rs2.camera_info; - const numberAttrs = [ - 'CAMERA_INFO_NAME', - 'CAMERA_INFO_SERIAL_NUMBER', - 'CAMERA_INFO_FIRMWARE_VERSION', - 'CAMERA_INFO_RECOMMENDED_FIRMWARE_VERSION', - 'CAMERA_INFO_PHYSICAL_PORT', - 'CAMERA_INFO_DEBUG_OP_CODE', - 'CAMERA_INFO_ADVANCED_MODE', - 'CAMERA_INFO_PRODUCT_ID', - 'CAMERA_INFO_CAMERA_LOCKED', - 'CAMERA_INFO_USB_TYPE_DESCRIPTOR', - ]; - const strAttrs = [ - 'camera_info_name', - 'camera_info_serial_number', - 'camera_info_firmware_version', - 'camera_info_recommended_firmware_version', - 'camera_info_physical_port', - 'camera_info_debug_op_code', - 'camera_info_advanced_mode', - 'camera_info_product_id', - 'camera_info_camera_locked', - 'camera_info_usb_type_descriptor', - ]; - numberAttrs.forEach((attr) => { - assert.equal(typeof obj[attr], 'number'); - }); - strAttrs.forEach((attr) => { - assert.equal(typeof obj[attr], 'string'); - }); - for (let i = 0; i < obj.CAMERA_INFO_COUNT; i++) { - assert.equal(typeof obj.cameraInfoToString(i), 'string'); - } - let ctx = new rs2.Context(); - let dev = ctx.queryDevices().devices[0]; - - for (let i = obj.CAMERA_INFO_NAME; i < obj.CAMERA_INFO_COUNT; i++) { - let info = dev.getCameraInfo(i); - assert.equal((info === undefined) || (typeof info === 'string'), true); - } - rs2.cleanup(); - }); - it('option test', () => { - const obj = rs2.option; - const numberAttrs = [ - 'OPTION_BACKLIGHT_COMPENSATION', - 'OPTION_BRIGHTNESS', - 'OPTION_CONTRAST', - 'OPTION_EXPOSURE', - 'OPTION_GAIN', - 'OPTION_GAMMA', - 'OPTION_HUE', - 'OPTION_SATURATION', - 'OPTION_SHARPNESS', - 'OPTION_WHITE_BALANCE', - 'OPTION_ENABLE_AUTO_EXPOSURE', - 'OPTION_ENABLE_AUTO_WHITE_BALANCE', - 'OPTION_VISUAL_PRESET', - 'OPTION_LASER_POWER', - 'OPTION_ACCURACY', - 'OPTION_MOTION_RANGE', - 'OPTION_FILTER_OPTION', - 'OPTION_CONFIDENCE_THRESHOLD', - 'OPTION_EMITTER_ENABLED', - 'OPTION_FRAMES_QUEUE_SIZE', - 'OPTION_TOTAL_FRAME_DROPS', - 'OPTION_AUTO_EXPOSURE_MODE', - 'OPTION_POWER_LINE_FREQUENCY', - 'OPTION_ASIC_TEMPERATURE', - 'OPTION_ERROR_POLLING_ENABLED', - 'OPTION_PROJECTOR_TEMPERATURE', - 'OPTION_OUTPUT_TRIGGER_ENABLED', - 'OPTION_MOTION_MODULE_TEMPERATURE', - 'OPTION_DEPTH_UNITS', - 'OPTION_ENABLE_MOTION_CORRECTION', - 'OPTION_AUTO_EXPOSURE_PRIORITY', - 'OPTION_COLOR_SCHEME', - 'OPTION_HISTOGRAM_EQUALIZATION_ENABLED', - 'OPTION_MIN_DISTANCE', - 'OPTION_MAX_DISTANCE', - 'OPTION_TEXTURE_SOURCE', - 'OPTION_FILTER_MAGNITUDE', - 'OPTION_FILTER_SMOOTH_ALPHA', - 'OPTION_FILTER_SMOOTH_DELTA', - 'OPTION_HOLES_FILL', - 'OPTION_STEREO_BASELINE', - 'OPTION_AUTO_EXPOSURE_CONVERGE_STEP', - 'OPTION_INTER_CAM_SYNC_MODE', - ]; - const strAttrs = [ - 'option_backlight_compensation', - 'option_brightness', - 'option_contrast', - 'option_exposure', - 'option_gain', - 'option_gamma', - 'option_hue', - 'option_saturation', - 'option_sharpness', - 'option_white_balance', - 'option_enable_auto_exposure', - 'option_enable_auto_white_balance', - 'option_visual_preset', - 'option_laser_power', - 'option_accuracy', - 'option_motion_range', - 'option_filter_option', - 'option_confidence_threshold', - 'option_emitter_enabled', - 'option_frames_queue_size', - 'option_total_frame_drops', - 'option_auto_exposure_mode', - 'option_power_line_frequency', - 'option_asic_temperature', - 'option_error_polling_enabled', - 'option_projector_temperature', - 'option_output_trigger_enabled', - 'option_motion_module_temperature', - 'option_depth_units', - 'option_enable_motion_correction', - 'option_auto_exposure_priority', - 'option_color_scheme', - 'option_histogram_equalization_enabled', - 'option_min_distance', - 'option_max_distance', - 'option_texture_source', - 'option_filter_magnitude', - 'option_filter_smooth_alpha', - 'option_filter_smooth_delta', - 'option_holes_fill', - 'option_stereo_baseline', - 'option_auto_exposure_converge_step', - 'option_inter_cam_sync_mode', - ]; - numberAttrs.forEach((attr) => { - assert.equal(typeof obj[attr], 'number'); - }); - strAttrs.forEach((attr) => { - assert.equal(typeof obj[attr], 'string'); - }); - for (let i = 0; i < obj.OPTION_COUNT; i++) { - assert.equal(typeof obj.optionToString(i), 'string'); - } - let ctx = new rs2.Context(); - let sensors = ctx.querySensors(); - // make sure it would not crash - sensors.forEach((s) => { - for (let i = 0; i < obj.OPTION_COUNT; i++) { - let old = s.getOption(i); - s.setOption(i, 10); - if (typeof old === 'number') { - s.setOption(i, old); - } - } - }); - rs2.cleanup(); - }); -}); - -describe('infrared frame tests', function() { - let ctx; - let pipe; - let cfg; - before(function() { - ctx = new rs2.Context(); - pipe = new rs2.Pipeline(ctx); - cfg = new rs2.Config(); - }); - - after(function() { - rs2.cleanup(); - }); - - it('getInfraredFrame', () => { - cfg.enableStream(rs2.stream.STREAM_INFRARED, 1, 640, 480, rs2.format.FORMAT_Y8, 60); - pipe.start(cfg); - const frames = pipe.waitForFrames(); - assert.equal(frames.size === 1, true); - let frame = frames.getInfraredFrame(1); - assert.equal(frame.profile.streamType === rs2.stream.STREAM_INFRARED, true); - assert.equal(frame.profile.streamIndex === 1, true); - - // Get the frame that first match - frame = frames.getInfraredFrame(); - assert.equal(frame.profile.streamType === rs2.stream.STREAM_INFRARED, true); - assert.equal(frame.profile.streamIndex === 1, true); - pipe.stop(); - }); -}); - -describe('Native error tests', function() { - it('trigger native error test', () => { - const file = 'test.rec'; - fs.writeFileSync(file, 'dummy'); - const ctx = new rs2.Context(); - assert.throws(() => { - ctx.loadDevice(file); - }, (err) => { - assert.equal(err instanceof Error, true); - let errInfo = rs2.getError(); - assert.equal(errInfo.recoverable, false); - assert.equal(typeof errInfo.description, 'string'); - assert.equal(typeof errInfo.nativeFunction, 'string'); - return true; - }); - rs2.cleanup(); - fs.unlinkSync(file); - }); -}); - -describe('ROI test', function() { - it('set/get ROI test', () => { - let ctx = new rs2.Context(); - let sensors = ctx.querySensors(); - sensors.forEach((s) => { - let roi = rs2.ROISensor.from(s); - if (roi) { - roi.setRegionOfInterest(1, 1, 10, 10); - let val = roi.getRegionOfInterest(); - if (val) { - assert.equal(val.minX, 1); - assert.equal(val.minY, 1); - assert.equal(val.maxX, 10); - assert.equal(val.maxY, 10); - } else { - assert.equal(rs2.getError() instanceof Object, true); - } - } - }); - rs2.cleanup(); - }); -}); - -describe('new record/playback test', function() { - let pipe; - let cfg; - let device; - const file = 'record.bag'; - - it('record and playback', () => { - // record - pipe = new rs2.Pipeline(); - cfg = new rs2.Config(); - cfg.enableRecordToFile(file); - pipe.start(cfg); - device = pipe.getActiveProfile().getDevice(); - - // make sure it's not a playback device - let playback = rs2.PlaybackDevice.from(device); - assert.equal(playback, undefined); - - let recorder = rs2.RecorderDevice.from(device); - assert.equal(recorder instanceof rs2.RecorderDevice, true); - pipe.waitForFrames(); - pipe.waitForFrames(); - pipe.waitForFrames(); - pipe.stop(); - // make sure the recorded frames are flushed to file - rs2.cleanup(); - - assert.equal(fs.existsSync(file), true); - - // playback - cfg = new rs2.Config(); - cfg.enableDeviceFromFile(file); - pipe = new rs2.Pipeline(); - pipe.start(cfg); - device = pipe.getActiveProfile().getDevice(); - playback = rs2.PlaybackDevice.from(device); - assert.equal(playback instanceof rs2.PlaybackDevice, true); - - // make sure it's not a RecorderDevice - recorder = rs2.RecorderDevice.from(device); - assert.equal(recorder, undefined); - - let frames = pipe.waitForFrames(); - assert.equal(frames instanceof rs2.FrameSet, true); - pipe.stop(); - rs2.cleanup(); - fs.unlinkSync(file); - }).timeout(10000); -}); - -describe('frameset misc test', function() { - it('get any frame twice test', () => { - let pipe = new rs2.Pipeline(); - pipe.start(); - let frames = pipe.waitForFrames(); - let frame = frames.getFrame(rs2.stream.STREAM_ANY); - assert.equal(frame instanceof rs2.Frame, true); - frame = frames.getFrame(rs2.stream.STREAM_ANY); - assert.equal(frame instanceof rs2.Frame, true); - pipe.stop(); - rs2.cleanup(); - }); -}); - -describe('post processing filter tests', function() { - let ctx; - let pipe; - before(function() { - ctx = new rs2.Context(); - pipe = new rs2.Pipeline(ctx); - }); - - after(function() { - rs2.cleanup(); - }); - - it('hole-filling filter test', () => { - pipe.start(); - const frames = pipe.waitForFrames(); - assert.equal(frames.size > 0, true); - let filter = new rs2.HoleFillingFilter(); - let out = filter.process(frames.depthFrame); - assert.equal(out instanceof rs2.Frame, true); - assert.equal(out.isValid, true); - pipe.stop(); - }); -}); diff --git a/wrappers/nodejs/test/test-functional.js b/wrappers/nodejs/test/test-functional.js deleted file mode 100644 index 1ee667ff6f..0000000000 --- a/wrappers/nodejs/test/test-functional.js +++ /dev/null @@ -1,909 +0,0 @@ -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; -/* eslint-disable no-invalid-this */ -/* global describe, it, before, after, afterEach */ -const assert = require('assert'); -const fs = require('fs'); -let rs2; -try { - rs2 = require('node-librealsense'); -} catch (e) { - rs2 = require('../index.js'); -} - -let isRecord; -let isPlayback; -let recordFile; - -for (let i = 0; i < process.argv.length; i++) { - if (process.argv[i] === '--record') { - isRecord = true; - recordFile = process.argv[i + 1]; - } else if (process.argv[i] === '--playback') { - isPlayback = true; - recordFile = process.argv[i + 1]; - } -} - -if (isRecord || isPlayback) { - if (!recordFile || typeof recordFile !== 'string') { - throw new TypeError('record/playback file must be provided like\'--playback ut_record.data\''); - } - if (isPlayback && !fs.existsSync(recordFile)) { - throw new TypeError('the playback file \'' + recordFile + '\' doesn\'t exists'); - } -} - -function makeContext(section) { - if (isRecord) { - return new rs2.internal.RecordingContext(recordFile, section); - } else if (isPlayback) { - return new rs2.internal.PlaybackContext(recordFile, section); - } else { - return new rs2.Context(); - } -} - -describe('Pipeline tests', function() { - let ctx; - let pipe; - this.timeout(5000); - - before(function() { - ctx = makeContext('pipeline'); - pipe = new rs2.Pipeline(ctx); - const devices = ctx.queryDevices().devices; - assert(devices.length > 0); // Device must be connected - }); - - after(function() { - rs2.cleanup(); - }); - - if (!(isRecord || isPlayback)) { - it('Default pipeline', () => { - const pipe = new rs2.Pipeline(); - pipe.start(); - const frames = pipe.waitForFrames(); - assert.equal(frames.size > 0, true); - pipe.stop(); - }); - } - - it('Pipeline with context', () => { - pipe.start(); - const frames = pipe.waitForFrames(); - assert.equal(frames.size > 0, true); - pipe.stop(); - }); - - it('pipeline pollForFrames', () => { - pipe.start(); - let frames; - while (!frames) { - frames = pipe.pollForFrames(); - if (frames) { - assert.equal((frames instanceof rs2.FrameSet), true); - } - } - pipe.stop(); - }); -}); - -describe('Frameset test', function() { - let pipe; - let frameset; - let ctx; - this.timeout(5000); - - before(function() { - ctx = makeContext('frameset'); - pipe = new rs2.Pipeline(ctx); - pipe.start(); - frameset = pipe.waitForFrames(); - }); - - after(function() { - pipe.stop(); - rs2.cleanup(); - }); - - it('depthFrame test', () => { - let depth = frameset.depthFrame; - assert.equal(depth instanceof rs2.DepthFrame, true); - let distance = depth.getDistance(100, 100); - assert.equal(typeof distance, 'number'); - }); - - it('colorFrame test', () => { - let color = frameset.colorFrame; - assert.equal(color instanceof rs2.VideoFrame, true); - }); - - it('at test', () => { - for (let i=0; i { - let color = frameset.getFrame(rs2.stream.STREAM_COLOR); - let depth = frameset.getFrame(rs2.stream.STREAM_DEPTH); - assert.equal(color instanceof rs2.VideoFrame, true); - assert.equal(depth instanceof rs2.DepthFrame, true); - }); - - it('forEach test', () => { - let counter = 0; - function callback(frame) { - counter++; - assert.equal(frame instanceof rs2.Frame, true); - } - frameset.forEach(callback); - assert.equal(counter, frameset.size); - }); -}); - -describe('Frame test', function() { - let pipe; - let frameset; - let color; - let depth; - let ctx; - this.timeout(5000); - - before(function() { - ctx = makeContext('frame'); - pipe = new rs2.Pipeline(ctx); - pipe.start(); - frameset = pipe.waitForFrames(); - color = frameset.colorFrame; - depth = frameset.depthFrame; - }); - - after(function() { - pipe.stop(); - rs2.cleanup(); - }); - - it('format/stream/width/height/frameNumber/timestamp/isValid test', () => { - assert.equal(depth.format, rs2.format.FORMAT_Z16); - assert.equal(depth.streamType, rs2.stream.STREAM_DEPTH); - assert.equal(depth.isValid, true); - assert.equal(depth.timestamp > 0, true); - assert.equal(depth.frameNumber > 0, true); - assert.equal(depth.width > 0, true); - assert.equal(depth.height > 0, true); - assert.equal(depth.dataByteLength > 0, true); - assert.equal(depth.strideInBytes > 0, true); - - assert.equal(color.format, rs2.format.FORMAT_RGB8); - assert.equal(color.streamType, rs2.stream.STREAM_COLOR); - assert.equal(color.isValid, true); - assert.equal(color.timestamp > 0, true); - assert.equal(color.frameNumber > 0, true); - assert.equal(color.width > 0, true); - assert.equal(color.height > 0, true); - assert.equal(color.dataByteLength > 0, true); - assert.equal(color.strideInBytes > 0, true); - }); - - it('frame metadata test', () => { - for (let i=0; i { - assert.equal(depth.data.length*2, depth.dataByteLength); - assert.equal(color.data.length, color.dataByteLength); - }); - - it('strideInBytes test', () => { - assert.equal(depth.strideInBytes, depth.width*2); - assert.equal(color.strideInBytes, color.width*3); - }); - - it('getData test', () => { - const buf1 = new ArrayBuffer(depth.dataByteLength); - depth.getData(buf1); - const buf2 = Buffer.from(buf1); - const buf3 = Buffer.from(depth.data.buffer); - assert.equal(buf3.equals(buf2), true); - const buf21 = new ArrayBuffer(color.dataByteLength); - color.getData(buf21); - const buf22 = Buffer.from(buf21); - const buf23 = Buffer.from(color.data.buffer); - assert.equal(buf23.equals(buf22), true); - }); -}); - -if (!(isRecord || isPlayback)) { - describe('Colorizer test', function() { - let pipe; - let frameset; - let depth; - let colorizer; - let ctx; - this.timeout(5000); - - before(function() { - ctx = makeContext('colorizer'); - pipe = new rs2.Pipeline(ctx); - pipe.start(); - frameset = pipe.waitForFrames(); - depth = frameset.depthFrame; - colorizer = new rs2.Colorizer(); - }); - - after(function() { - pipe.stop(); - rs2.cleanup(); - }); - - it('colorize test', () => { - const depthRGB = colorizer.colorize(depth); - assert.equal(depthRGB.height, depth.height); - assert.equal(depthRGB.width, depth.width); - assert.equal(depthRGB.format, rs2.format.FORMAT_RGB8); - }); - it('colorizer option API test', () => { - for (let i = rs2.option.OPTION_BACKLIGHT_COMPENSATION; i < rs2.option.OPTION_COUNT; i++) { - let readonly = colorizer.isOptionReadOnly(i); - assert.equal((readonly === undefined) || (typeof readonly === 'boolean'), true); - let supports = colorizer.supportsOption(i); - assert.equal((supports === undefined) || (typeof supports === 'boolean'), true); - let value = colorizer.getOption(i); - assert.equal((value === undefined) || (typeof value === 'number'), true); - let des = colorizer.getOptionDescription(i); - assert.equal((des === undefined) || (typeof des === 'string'), true); - des = colorizer.getOptionValueDescription(i, 1); - assert.equal((des === undefined) || (typeof des === 'string'), true); - - if (supports && !readonly) { - let range = colorizer.getOptionRange(i); - for (let j = range.minvalue; j <= range.maxValue; j += range.step) { - colorizer.setOption(i, j); - let val = colorizer.getOption(i); - assert.equal(val, j); - } - } - } - }); - }); - - describe('Pointcloud and Points test', function() { - let pipe; - let frameset; - let color; - let depth; - let pc; - let ctx; - - before(function() { - ctx = new rs2.Context(); - pc = new rs2.PointCloud(); - pipe = new rs2.Pipeline(ctx); - pipe.start(); - frameset = pipe.waitForFrames(); - color = frameset.colorFrame; - depth = frameset.depthFrame; - }); - - after(function() { - pipe.stop(); - rs2.cleanup(); - }); - - it('map and calculate test', () => { - assert.equal(pc instanceof rs2.PointCloud, true); - - pc.mapTo(color); - const points = pc.calculate(depth); - const cnt = depth.width * depth.height; - assert.equal(points instanceof rs2.Points, true); - assert.equal(points.size, cnt); - const texCoordinates = points.textureCoordinates; - - assert.equal(points.vertices instanceof Float32Array, true); - assert.equal(texCoordinates instanceof Int32Array, true); - - assert.equal(points.vertices.length, cnt * 3); - assert.equal(texCoordinates.length, cnt * 2); - }); - }); -} - -describe('Context tests', function() { - let ctx; - this.timeout(5000); - - before(() => { - ctx = makeContext('context'); - }); - - after(() => { - rs2.cleanup(); - }); - - it('Query devices', () => { - const devList = ctx.queryDevices(); - assert.equal(devList instanceof rs2.DeviceList, true); - // The platform's camera would also be counted, so size may > 1 - assert.equal(devList.size >= 1, true); - assert.equal(devList.devices[0] instanceof rs2.Device, true); - assert.equal(devList.contains(devList.devices[0]), true); - devList.destroy(); - }); - - it('Query sensors', () => { - const sensors = ctx.querySensors(); - // The platform's camera would also be counted, so size may > 2 - assert.equal(sensors.length >= 2, true); - assert.equal(sensors[0] instanceof rs2.Sensor, true); - assert.equal(sensors[1] instanceof rs2.Sensor, true); - sensors.forEach((sensor) => { - sensor.destroy(); - }); - }); - - it('Get sensor parent', () => { - const sensors = ctx.querySensors(); - const dev = ctx.getSensorParent(sensors[0]); - assert.equal(dev instanceof rs2.Device, true); - sensors.forEach((sensor) => { - sensor.destroy(); - }); - }); -}); - -describe('Sensor tests', function() { - let ctx; - let sensors; - this.timeout(10000); - - before(() => { - ctx = makeContext('sensor'); - sensors = ctx.querySensors(); - }); - - after(() => { - rs2.cleanup(); - }); - - it('camera info', () => { - sensors.forEach((sensor) => { - for (let i = rs2.camera_info.CAMERA_INFO_NAME; i < rs2.camera_info.CAMERA_INFO_COUNT; i++) { - if (sensor.supportsCameraInfo(i)) { - let info = sensor.getCameraInfo(i); - assert.equal(typeof info, 'string'); - } - } - }); - }); - - it('Stream profiles', () => { - const profiles0 = sensors[0].getStreamProfiles(); - const profiles1 = sensors[1].getStreamProfiles(); - - assert.equal(profiles1.length > 0, true); - assert.equal(profiles0.length > 0, true); - profiles0.forEach((p) => { - assert.equal(p instanceof rs2.StreamProfile, true); - assert.equal(p instanceof rs2.StreamProfile, true); - assert.equal(p.streamType >= rs2.stream.STREAM_DEPTH && - p.streamType < rs2.stream.STREAM_COUNT, true); - assert.equal(p.format >= rs2.format.FORMAT_Z16 && p.format < rs2.format.FORMAT_COUNT, true); - assert.equal(p.fps>0, true); - assert.equal(typeof p.uniqueID, 'number'); - assert.equal(typeof p.isDefault, 'boolean'); - }); - profiles1.forEach((p) => { - assert.equal(p instanceof rs2.StreamProfile, true); - assert.equal(p instanceof rs2.StreamProfile, true); - }); - const extrin = profiles0[0].getExtrinsicsTo(profiles1[0]); - assert.equal(('rotation' in extrin), true); - assert.equal(('translation' in extrin), true); - - profiles0.forEach((p) => { - if (p instanceof rs2.VideoStreamProfile) { - assert.equal(typeof p.width, 'number'); - assert.equal(typeof p.height, 'number'); - let intrin; - try { - intrin = p.getIntrinsics(); - } catch (e) { - // some stream profiles have no intrinsics, and will trigger exception - // so only bypass these cases if it's still recoverable, otherwise, - // rethrow it. - if (e instanceof rs2.UnrecoverableError) { - throw e; - } - return; - } - - assert.equal('width' in intrin, true); - assert.equal('height' in intrin, true); - assert.equal('ppx' in intrin, true); - assert.equal('ppy' in intrin, true); - assert.equal('fx' in intrin, true); - assert.equal('fy' in intrin, true); - assert.equal('model' in intrin, true); - assert.equal('coeffs' in intrin, true); - - assert.equal(typeof intrin.width, 'number'); - assert.equal(typeof intrin.height, 'number'); - assert.equal(typeof intrin.ppx, 'number'); - assert.equal(typeof intrin.ppy, 'number'); - assert.equal(typeof intrin.fx, 'number'); - assert.equal(typeof intrin.fy, 'number'); - assert.equal(typeof intrin.model, 'number'); - assert.equal(Array.isArray(intrin.coeffs), true); - - const fov = rs2.util.fov(intrin); - assert.equal(typeof fov.h, 'number'); - assert.equal(typeof fov.v, 'number'); - } - }); - }); - - it('Open and start', () => { - return new Promise((resolve, reject) => { - const profiles0 = sensors[0].getStreamProfiles(); - sensors[0].open(profiles0[0]); - let started = true; - sensors[0].start((frame) => { - assert.equal(frame instanceof rs2.Frame, true); - // Add a timeout to stop to avoid failure during playback test - // and make sure to stop+close sensors[0] once - if (started) { - started = false; - setTimeout(() => { - sensors[0].stop(); - sensors[0].close(); - resolve(); - }, 0); - } - }); - }); - }); - it('Get depth scale', () => { - for (let i = 0; i < sensors.length; i++) { - if (sensors[i] instanceof rs2.DepthSensor) { - assert.equal(typeof sensors[i].depthScale === 'number', true); - } - } - }); - it('getOptionDescription', () => { - sensors.forEach((s) => { - for (let i = rs2.option.OPTION_BACKLIGHT_COMPENSATION; i < rs2.option.OPTION_COUNT; i++) { - let des = s.getOptionDescription(i); - assert.equal((des === undefined) || (typeof des === 'string'), true); - } - }); - }); - it('getOption', () => { - sensors.forEach((s) => { - for (let i = rs2.option.OPTION_BACKLIGHT_COMPENSATION; i < rs2.option.OPTION_COUNT; i++) { - let value = s.getOption(i); - assert.equal((value === undefined) || (typeof value === 'number'), true); - } - }); - }); - it('getOptionValueDescription', () => { - sensors.forEach((s) => { - for (let i = rs2.option.OPTION_BACKLIGHT_COMPENSATION; i < rs2.option.OPTION_COUNT; i++) { - let des = s.getOptionValueDescription(i, 1); - assert.equal((des === undefined) || (typeof des === 'string'), true); - } - }); - }); - it('setOption', () => { - sensors.forEach((s) => { - for (let i = rs2.option.OPTION_BACKLIGHT_COMPENSATION; i < rs2.option.OPTION_COUNT; i++) { - if (s.supportsOption(i) && !s.isOptionReadOnly(i)) { - let range = s.getOptionRange(i); - for (let j = range.minvalue; j <= range.maxValue; j += range.step) { - s.setOption(i, j); - let val = s.getOption(i); - assert.equal(val, j); - } - } - } - }); - }); - it('Notification test', () => { - return new Promise((resolve, reject) => { - let dev = ctx.queryDevices().devices[0]; - sensors[0].setNotificationsCallback((n) => { - assert.equal(typeof n.descr, 'string'); - assert.equal(typeof n.timestamp, 'number'); - assert.equal(typeof n.severity, 'string'); - assert.equal(typeof n.category, 'string'); - assert.equal(typeof n.serializedData, 'string'); - resolve(); - }); - // No need to manually trigger error during playback. - if (!isPlayback) { - setTimeout(() => { - dev.cxxDev.triggerErrorForTest(); - }, 5000); - } - }); - }); -}); - -// describe('Align tests', function() { -// let ctx; -// let align; -// let pipe; - -// before(() => { -// ctx = makeContext('align'); -// align = new rs2.Align(rs2.stream.STREAM_COLOR); -// pipe = new rs2.Pipeline(ctx); -// }); - -// after(() => { -// pipe.stop(); -// rs2.cleanup(); -// }); - -// it('process', () => { -// pipe.start(); -// const frameset = pipe.waitForFrames(); -// const output = align.process(frameset); -// const color = output.colorFrame; -// const depth = output.depthFrame; -// assert.equal(color instanceof rs2.VideoFrame, true); -// assert.equal(depth instanceof rs2.DepthFrame, true); -// }); -// }); - -describe(('syncer test'), function() { - let syncer; - let ctx; - let sensors; - this.timeout(5000); - - before(() => { - ctx = makeContext('syncer'); - syncer = new rs2.Syncer(); - sensors = ctx.querySensors(); - }); - - after(() => { - sensors[0].stop(); - rs2.cleanup(); - }); - it('sensor.start(syncer)', () => { - const profiles = sensors[0].getStreamProfiles(); - sensors[0].open(profiles[0]); - sensors[0].start(syncer); - - let frames = syncer.waitForFrames(5000); - assert.equal(frames instanceof rs2.FrameSet, true); - let gotFrame = false; - while (!gotFrame) { - let frames = syncer.pollForFrames(); - if (frames) { - assert.equal(frames instanceof rs2.FrameSet, true); - gotFrame = true; - } - } - profiles.forEach((p) => { - p.destroy(); - }); - }); -}); - -describe('Config test', function() { - let pipe; - let cfg; - let ctx; - this.timeout(5000); - - before(function() { - ctx = makeContext('config'); - pipe = new rs2.Pipeline(ctx); - cfg = new rs2.Config(); - }); - - after(function() { - pipe.stop(); - rs2.cleanup(); - }); - - it('resolve test', function() { - assert.equal(cfg.canResolve(pipe), true); - const profile = cfg.resolve(pipe); - assert.equal(profile instanceof rs2.PipelineProfile, true); - assert.equal(profile.isValid, true); - const dev = profile.getDevice(); - assert.equal(dev instanceof rs2.Device, true); - const profiles = profile.getStreams(); - assert.equal(Array.isArray(profiles), true); - assert.equal(profiles[0] instanceof rs2.StreamProfile, true); - const colorProfile = profile.getStream(rs2.stream.STREAM_COLOR); - assert.equal(colorProfile.streamType, rs2.stream.STREAM_COLOR); - }); - - it('enableStream test', function() { - cfg.disableAllStreams(); - cfg.enableStream(rs2.stream.STREAM_COLOR, -1, 640, 480, rs2.format.FORMAT_RGB8, 30); - const profile = cfg.resolve(pipe); - assert.equal(profile instanceof rs2.PipelineProfile, true); - const profiles = profile.getStreams(); - assert.equal(Array.isArray(profiles), true); - assert.equal(profiles.length, 1); - assert.equal((profiles[0] instanceof rs2.VideoStreamProfile), true); - assert.equal(profiles[0].streamType, rs2.stream.STREAM_COLOR); - assert.equal(profiles[0].format, rs2.format.FORMAT_RGB8); - assert.equal(profiles[0].width, 640); - assert.equal(profiles[0].height, 480); - assert.equal(profiles[0].fps, 30); - - const startProfile = pipe.start(cfg); - const startProfiles = startProfile.getStreams(); - assert.equal(Array.isArray(startProfiles), true); - assert.equal(startProfiles.length, 1); - assert.equal((startProfiles[0] instanceof rs2.VideoStreamProfile), true); - assert.equal(startProfiles[0].streamType, rs2.stream.STREAM_COLOR); - assert.equal(startProfiles[0].format, rs2.format.FORMAT_RGB8); - assert.equal(startProfiles[0].width, 640); - assert.equal(startProfiles[0].height, 480); - assert.equal(startProfiles[0].fps, 30); - - const activeProfile = pipe.getActiveProfile(); - const activeProfiles = activeProfile.getStreams(); - assert.equal(Array.isArray(activeProfiles), true); - assert.equal(activeProfiles.length, 1); - assert.equal((activeProfiles[0] instanceof rs2.VideoStreamProfile), true); - assert.equal(activeProfiles[0].streamType, rs2.stream.STREAM_COLOR); - assert.equal(activeProfiles[0].format, rs2.format.FORMAT_RGB8); - assert.equal(activeProfiles[0].width, 640); - assert.equal(activeProfiles[0].height, 480); - assert.equal(activeProfiles[0].fps, 30); - }); -}); - -describe(('DeviceHub test'), function() { - let hub; - let ctx; - - before(() => { - ctx = makeContext('deviceHub'); - hub = new rs2.DeviceHub(ctx); - }); - - after(() => { - rs2.cleanup(); - }); - it('API test', () => { - const dev = hub.waitForDevice(); - assert.equal(dev instanceof rs2.Device, true); - assert.equal(hub.isConnected(dev), true); - dev.destroy(); - }); -}); - -if (!(isRecord || isPlayback)) { - describe(('record & playback test'), function() { - let fileName = 'ut-record.bag'; - - afterEach(() => { - rs2.cleanup(); - }); - - after(() => { - if (fs.existsSync(fileName)) { - fs.unlinkSync(fileName); - } - }); - - function startRecording(file, cnt, callback) { - return new Promise((resolve, reject) => { - setTimeout(() => { - let ctx = new rs2.Context(); - let dev = ctx.queryDevices().devices[0]; - let recorder = new rs2.RecorderDevice(file, dev); - let sensors = recorder.querySensors(); - let sensor = sensors[0]; - let profiles = sensor.getStreamProfiles(); - assert.equal(recorder.fileName, file); - for (let i = 0; i < profiles.length; i++) { - if (profiles[i].streamType === rs2.stream.STREAM_DEPTH && - profiles[i].fps === 30 && - profiles[i].width === 640 && - profiles[i].height === 480 && - profiles[i].format === rs2.format.FORMAT_Z16) { - sensor.open(profiles[i]); - } - } - let counter = 0; - sensor.start((frame) => { - if (callback) { - callback(recorder, counter); - } - counter++; - if (counter === cnt) { - recorder.reset(); - rs2.cleanup(); - resolve(); - } - }); - }, 2000); - }); - } - - function startPlayback(file, callback) { - return new Promise((resolve, reject) => { - let ctx = new rs2.Context(); - let dev = ctx.loadDevice(file); - let sensors = dev.querySensors(); - let sensor = sensors[0]; - let profiles = sensor.getStreamProfiles(); - let cnt = 0; - - dev.setStatusChangedCallback((status) => { - callback(dev, status, cnt); - if (status.description === 'stopped') { - dev.stop(); - ctx.unloadDevice(file); - resolve(); - } - }); - sensor.open(profiles); - sensor.start((frame) => { - cnt++; - }); - }); - } - - it('record test', () => { - return new Promise((resolve, reject) => { - startRecording(fileName, 1, null).then(() => { - assert.equal(fs.existsSync(fileName), true); - fs.unlinkSync(fileName); - resolve(); - }); - }); - }).timeout(5000); - - it('pause/resume test', () => { - return new Promise((resolve, reject) => { - startRecording(fileName, 2, (recorder, cnt) => { - if (cnt === 1) { - recorder.pause(); - recorder.resume(); - } - }).then(() => { - assert.equal(fs.existsSync(fileName), true); - fs.unlinkSync(fileName); - resolve(); - }); - }); - }).timeout(5000); - - it('playback test', () => { - return new Promise((resolve, reject) => { - startRecording(fileName, 1, null).then(() => { - assert.equal(fs.existsSync(fileName), true); - return startPlayback(fileName, (playbackDev, status) => { - if (status.description === 'playing') { - assert.equal(playbackDev.fileName, 'ut-record.bag'); - assert.equal(typeof playbackDev.duration, 'number'); - assert.equal(typeof playbackDev.position, 'number'); - assert.equal(typeof playbackDev.isRealTime, 'boolean'); - assert.equal(playbackDev.currentStatus.description, 'playing'); - } - }); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - }); -} - -describe('Device tests', function() { - let dev; - this.timeout(5000); - - before(function() { - let ctx = makeContext('device'); - dev = ctx.queryDevices().devices[0]; - assert(dev instanceof rs2.Device, true); - }); - - after(function() { - rs2.cleanup(); - }); - - it('first', () => { - let sensor = dev.first; - assert.equal(sensor instanceof rs2.Sensor, true); - }); - - it('querySensors', () => { - let sensors = dev.querySensors(); - assert.equal(sensors.length > 0, true); - sensors.forEach((sensor) => { - assert.equal(sensor instanceof rs2.Sensor, true); - }); - }); - - it('camera info', () => { - for (let i = rs2.camera_info.CAMERA_INFO_NAME; i < rs2.camera_info.CAMERA_INFO_COUNT; i++) { - if (dev.supportsCameraInfo(i)) { - let info = dev.getCameraInfo(i); - assert.equal(typeof info, 'string'); - } - } - let obj = dev.getCameraInfo(); - assert.equal(typeof obj, 'object'); - assert.equal(typeof obj.serialNumber, 'string'); - assert.equal(typeof obj.firmwareVersion, 'string'); - assert.equal(typeof obj.physicalPort, 'string'); - assert.equal(typeof obj.debugOpCode, 'string'); - assert.equal(typeof obj.advancedMode, 'string'); - assert.equal(typeof obj.productId, 'string'); - }); -}); - -describe('filter tests', function() { - let ctx; - let decimationFilter; - let temporalFilter; - let spatialFilter; - let pipeline; - this.timeout(10000); - - before(function() { - ctx = makeContext('filter'); - decimationFilter = new rs2.DecimationFilter(); - temporalFilter = new rs2.TemporalFilter(); - spatialFilter = new rs2.SpatialFilter(); - pipeline = new rs2.Pipeline(ctx); - pipeline.start(); - }); - - after(function() { - pipeline.stop(); - rs2.cleanup(); - }); - - it('temppral filter', () => { - let frameset = pipeline.waitForFrames(); - let depthFrame = frameset.depthFrame; - let out = temporalFilter.process(depthFrame); - assert.equal(out instanceof rs2.DepthFrame, true); - assert.equal(typeof out.width, 'number'); - }); - - it('spatial filter', () => { - let frameset = pipeline.waitForFrames(); - let depthFrame = frameset.depthFrame; - let out = spatialFilter.process(depthFrame); - assert.equal(out instanceof rs2.DepthFrame, true); - assert.equal(typeof out.width, 'number'); - }).timeout(10000); // change the threshold to be 10 seconds to avoid timeout. - - it('decimation filter', () => { - let frameset = pipeline.waitForFrames(); - let depthFrame = frameset.depthFrame; - let out = decimationFilter.process(depthFrame); - assert.equal(out instanceof rs2.VideoFrame, true); - assert.equal(typeof out.width, 'number'); - }).timeout(10000); // change the threshold to be 10 seconds to avoid timeout. -}); diff --git a/wrappers/nodejs/test/test-pipeline.js b/wrappers/nodejs/test/test-pipeline.js deleted file mode 100644 index 02c565f735..0000000000 --- a/wrappers/nodejs/test/test-pipeline.js +++ /dev/null @@ -1,272 +0,0 @@ -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -/* global describe, it, before, after, beforeEach, afterEach */ -const assert = require('assert'); -let rs2; -try { - rs2 = require('node-librealsense'); -} catch (e) { - rs2 = require('../index.js'); -} - -let ctx; -let pipeline; -describe('Pipeline test', function() { - before(function() { - ctx = new rs2.Context(); - const devices = ctx.queryDevices().devices; - assert(devices.length > 0); // Device must be connected - }); - - after(function() { - rs2.cleanup(); - }); - - it('Testing constructor - 0 option', () => { - assert.doesNotThrow(() => { - new rs2.Pipeline(); - }); - }); - - it('Testing constructor - 2 options', () => { - assert.throws(() => { - new rs2.Pipeline(1, 2); - }); - }); - - it('Testing constructor - 1 invalid option', () => { - assert.throws(() => { - new rs2.Pipeline(1); - }); - }); - - it('Testing constructor - 1 context option', () => { - assert.doesNotThrow(() => { - new rs2.Pipeline(ctx); - }); - }); -}); - -describe('Pipeline method test', () => { - beforeEach(() => { - ctx = new rs2.Context(); - const devices = ctx.queryDevices().devices; - assert(devices.length > 0); // Device must be connected - pipeline = new rs2.Pipeline(); - }); - afterEach(() => { - rs2.cleanup(); - pipeline.stop(); - pipeline.destroy(); - }); - - it('Testing method destroy', () => { - assert.doesNotThrow(() => { - pipeline.start(); - pipeline.waitForFrames(); - pipeline.stop(); - }); - }); - - it('Testing method destroy w/o start', () => { - assert.doesNotThrow(() => { - pipeline.destroy(); - }); - assert.equal(pipeline.ctx, undefined); - assert.equal(pipeline.cxxPipeline, undefined); - assert.equal(pipeline.started, false); - assert.equal(pipeline.frameSet, undefined); - }); - - it('Testing method destroy after restart pipeline', () => { - pipeline.start(); - pipeline.waitForFrames(); - assert.doesNotThrow(() => { - pipeline.destroy(); - }); - assert.throws(() => { - pipeline.start(); - }); - }); - - it('Testing method waitForFrames', () => { - let frameSet; - assert.doesNotThrow(() => { - pipeline.start(); - frameSet = pipeline.waitForFrames(); - }); - let endTest = false; - let n = 0; - while (!endTest) { - frameSet = pipeline.waitForFrames(); - n++; - if (n > 1) console.log(`retring left ...${10 - n} times`); - if (frameSet !== undefined && frameSet.colorFrame !== undefined && - frameSet.depthFrame !== undefined) { - assert(frameSet.depthFrame instanceof rs2.VideoFrame); - assert(frameSet.colorFrame instanceof rs2.VideoFrame); - endTest = true; - } - if (n >= 10) { - assert(false, 'could not get colorFrame or depthFrame, try to reset camera'); - } - } - pipeline.stop(); - }); - - it('Testing method start', () => { - assert.doesNotThrow(() => { - let res = pipeline.start(); - pipeline.waitForFrames(); - assert(res instanceof rs2.PipelineProfile); - }); - assert.notEqual(pipeline, undefined); - assert.doesNotThrow(() => { - pipeline.start(); - pipeline.waitForFrames(); - pipeline.stop(); - }); - assert.equal(pipeline.started, false); - }); - - it('Testing method start w/ invalid args', () => { - assert.throws(() => { - pipeline.start('dummy'); - }); - pipeline.stop(); - }); - - it('Testing method start after stop', () => { - assert.doesNotThrow(() => { - pipeline.start(); - assert.equal(pipeline.started, true); - }); - assert.doesNotThrow(() => { - pipeline.stop(); - assert.equal(pipeline.started, false); - }); - assert.doesNotThrow(() => { - pipeline.start(); - assert.equal(pipeline.started, true); - }); - }); - - it('Testing method start after destroy', () => { - assert.doesNotThrow(() => { - pipeline.start(); - assert.equal(pipeline.started, true); - }); - assert.doesNotThrow(() => { - pipeline.destroy(); - assert.equal(pipeline.started, false); - }); - assert.throws(() => { - pipeline.start(); - assert.equal(pipeline.started, false); - }); - }); - - it('Testing method start w/ config', () => { - let config = new rs2.Config(); - assert.doesNotThrow(() => { - let res = pipeline.start(config); - assert(res instanceof rs2.PipelineProfile); - }); - assert.equal(pipeline.started, true); - pipeline.stop(); - }); - - it('Testing method start after started', () => { - assert.doesNotThrow(() => { - pipeline.start(); - assert.equal(pipeline.started, true); - let res = pipeline.start(); - assert.equal(typeof res, 'undefined'); - assert.equal(pipeline.started, true); - }); - }); - - it('Testing method stop', () => { - assert.notEqual(pipeline, undefined); - assert.doesNotThrow(() => { - pipeline.start(); - pipeline.waitForFrames(); - pipeline.stop(); - }); - }); - - it('Testing method stop and restart pipeline', () => { - assert.notEqual(pipeline, undefined); - assert.doesNotThrow(() => { - pipeline.start(); - pipeline.waitForFrames(); - pipeline.stop(); - }); - assert.equal(pipeline.started, false); - assert.doesNotThrow(() => { - pipeline.start(); - }); - assert.equal(pipeline.started, true); - pipeline.stop(); - }); - - it('Testing method stop when not start', () => { - assert.notEqual(pipeline, undefined); - assert.doesNotThrow(() => { - let res = pipeline.stop(); - assert(typeof res, 'undefined'); - }); - assert.equal(pipeline.started, false); - }); - - it('Testing method getActiveProfile', () => { - pipeline.start(); - assert.doesNotThrow(() => { - let res = pipeline.getActiveProfile(); - assert(typeof res, 'object'); - }); - pipeline.stop(); - }); - - it('Testing method getActiveProfile before pipe start', () => { - assert.doesNotThrow(() => { - let res = pipeline.getActiveProfile(); - assert(typeof res, 'undefined'); - pipeline.start(); - pipeline.waitForFrames(); - pipeline.stop(); - }); - }); - - it('Testing method getActiveProfile after pipe stop', () => { - assert.doesNotThrow(() => { - pipeline.start(); - pipeline.waitForFrames(); - pipeline.stop(); - let res = pipeline.getActiveProfile(); - assert(typeof res, 'undefined'); - }); - }); - - it('Testing method pollForFrames', () => { - let then = Date.now(); - pipeline.start(); - pipeline.waitForFrames(); - let res; - assert.doesNotThrow(() => { - while (Date.now() < then + 2000) { - res = pipeline.pollForFrames(); - if (res) { - assert(typeof res.size, 'number'); - assert(typeof res.depthFrame, 'object'); - assert(typeof res.colorFrame, 'object'); - break; - } - } - }); - }); -}); diff --git a/wrappers/nodejs/test/test-pipelineprofile.js b/wrappers/nodejs/test/test-pipelineprofile.js deleted file mode 100644 index 02a029c7f1..0000000000 --- a/wrappers/nodejs/test/test-pipelineprofile.js +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright (c) 2018 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -/* global describe, it, beforeEach, afterEach */ -const assert = require('assert'); -let rs2; -try { - rs2 = require('node-librealsense'); -} catch (e) { - rs2 = require('../index.js'); -} - -let ctx; -let pipeline; -let pipelineProfile; -let devices; - -describe('PipelineProfile test', function() { - beforeEach(function() { - ctx = new rs2.Context(); - devices = ctx.queryDevices().devices; - assert(devices.length > 0); // Device must be connected - pipeline = new rs2.Pipeline(ctx); - pipeline.start(); - pipelineProfile = pipeline.getActiveProfile(); - }); - - afterEach(function() { - pipeline.stop(); - pipeline.destroy(); - rs2.cleanup(); - }); - - it('Testing constructor - valid', () => { - assert.doesNotThrow(() => { - new rs2.PipelineProfile(); - }); - }); - - it('Testing member isValid', () => { - let res; - assert.doesNotThrow(() => { - res = pipelineProfile.isValid; - }); - assert.equal(typeof res, 'boolean'); - assert(typeof res !== undefined); - }); - - it('Testing method destroy', () => { - assert.doesNotThrow(() => { - let res = pipelineProfile.destroy(); - assert.equal(typeof res, 'undefined'); - }); - assert.equal(pipelineProfile.cxxPipelineProfile, undefined); - }); - - it('Testing method getDevice', () => { - assert.doesNotThrow(() => { - let res = pipelineProfile.getDevice(); - assert(res instanceof rs2.Device); - assert.equal(res.isValid, true); - }); - }); - - it('Testing method getDevice before pipeline.start', () => { - pipeline.destroy(); - let pipe = new rs2.Pipeline(ctx); - let pipeProfile = pipe.getActiveProfile(); - assert.throws(() => { - pipeProfile.getDevice(); - }); - assert.doesNotThrow(() => { - pipe.start(); - pipeProfile = pipe.getActiveProfile(); - let res = pipeProfile.getDevice(); - assert(res instanceof rs2.Device); - assert.equal(res.isValid, true); - }); - }); - - it('Testing method getStream w/o args', () => { - assert.throws(() => { - pipelineProfile.getStream(); - }); - }); - - it('Testing method getStream w/ invalid args', () => { - assert.throws(() => { - pipelineProfile.getStream('dummy'); - }); - }); - - it('Testing method getStream w/ invalid number', () => { - assert.throws(() => { - pipelineProfile.getStream(999); - }); - }); - - it('Testing method getStream, w/ three args', () => { - assert.throws(() => { - pipelineProfile.getStream(1, 1, 1); - }); - }); - - it('Testing method getStream, w/ invalid streamIndex', () => { - assert.doesNotThrow(() => { - let res = pipelineProfile.getStream(1, 999); - assert.equal(res, undefined); - }); - }); - - it('Testing method getStream, w/ one args', () => { - let res = pipelineProfile.getStreams(); - let valueArray = []; - res.forEach((s) => { - if (valueArray.indexOf(s.streamIndex) === -1) valueArray.push(s.streamIndex); - }); - valueArray.forEach((value) => { - assert.doesNotThrow(() => { - pipelineProfile.getStream(value); - }); - }); - }); - - it('Testing method getStreams', () => { - assert.doesNotThrow(() => { - let res = pipelineProfile.getStreams(); - assert.equal(Object.prototype.toString.call(res), '[object Array]'); - assert.notEqual(res, undefined); - res.forEach((s) => { - assert.equal(typeof s.format, 'number'); - assert.equal(typeof s.fps, 'number'); - assert.equal(typeof s.isDefault, 'boolean'); - assert.equal(typeof s.streamIndex, 'number'); - assert.equal(typeof s.streamType, 'number'); - assert.equal(typeof s.uniqueID, 'number'); - }); - }); - }); -}); - diff --git a/wrappers/nodejs/test/test-playbackdevice.js b/wrappers/nodejs/test/test-playbackdevice.js deleted file mode 100644 index 15882d1232..0000000000 --- a/wrappers/nodejs/test/test-playbackdevice.js +++ /dev/null @@ -1,482 +0,0 @@ -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -/* global describe, it, before, afterEach, after */ -const assert = require('assert'); -const fs = require('fs'); -let rs2; -try { - rs2 = require('node-librealsense'); -} catch (e) { - rs2 = require('../index.js'); -} - -let fileName = 'record.bag'; -describe('PlayBackDevice test', function() { - before(function(done) { - /* eslint-disable no-invalid-this */ - this.timeout(5000); - const ctx = new rs2.Context(); - const devices = ctx.queryDevices().devices; - assert(devices.length > 0); // Device must be connected - startRecording(fileName, 3, null).then(() => { - done(); - }); - }); - - afterEach(function() { - rs2.cleanup(); - }); - - after(function() { - if (fs.existsSync(fileName)) { - fs.unlinkSync(fileName); - } - }); - - function startRecording(file, cnt, callback) { - return new Promise((resolve, reject) => { - setTimeout(() => { - let ctx = new rs2.Context(); - let dev = ctx.queryDevices().devices[0]; - let recorder = new rs2.RecorderDevice(file, dev); - let sensors = recorder.querySensors(); - let sensor = sensors[0]; - let profiles = sensor.getStreamProfiles(); - for (let i = 0; i < profiles.length; i++) { - if (profiles[i].streamType === rs2.stream.STREAM_DEPTH && - profiles[i].fps === 30 && - profiles[i].width === 640 && - profiles[i].height === 480 && - profiles[i].format === rs2.format.FORMAT_Z16) { - sensor.open(profiles[i]); - } - } - let counter = 0; - sensor.start((frame) => { - if (callback) { - callback(recorder, counter); - } - counter++; - if (counter === cnt) { - recorder.reset(); - rs2.cleanup(); - resolve(); - } - }); - }, 2000); - }); - } - - function startPlayback(file, callback) { - let runCB = true; - return new Promise((resolve, reject) => { - let ctx = new rs2.Context(); - let dev = ctx.loadDevice(file); - let sensors = dev.querySensors(); - let sensor = sensors[0]; - let profiles = sensor.getStreamProfiles(); - let cnt = 0; - - dev.setStatusChangedCallback((status) => { - if (runCB) { - runCB = false; - callback(dev, status, cnt); - } - if (status.description === 'stopped') { - dev.stop(); - dev.destroy(); - ctx.unloadDevice(file); - rs2.cleanup(); - resolve(); - } - }); - sensor.open(profiles); - sensor.start((frame) => { - cnt++; - }); - }); - } - - it('Testing constructor - valid argument', () => { - let ctx = new rs2.Context(); - assert.doesNotThrow(() => { - ctx.loadDevice(fileName); - }); - }); - - it('Testing constructor - 0 argument', () => { - let ctx = new rs2.Context(); - assert.throws(() => { - ctx.loadDevice(); - }); - }); - - it('Testing constructor - 2 arguments', () => { - let ctx = new rs2.Context(); - assert.throws(() => { - ctx.loadDevice(fileName, 1); - }); - }); - - it('Testing constructor - invalid file argument', () => { - let ctx = new rs2.Context(); - assert.throws(() => { - ctx.loadDevice(1); - }); - }); - - it('Testing constructor - invalid file content', () => { - let ctx = new rs2.Context(); - assert.throws(() => { - ctx.loadDevice('./test-playbackdevice.js'); - }); - }); - - it('Testing member currentStatus', () => { - return new Promise((resolve, reject) => { - startPlayback(fileName, (playbackDev, status) => { - assert.equal(typeof playbackDev.currentStatus.status, 'number'); - assert.equal(playbackDev.currentStatus.status, status.status); - assert.equal(typeof playbackDev.currentStatus.description, 'string'); - assert.equal(playbackDev.currentStatus.description, status.description); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing member duration', () => { - return new Promise((resolve, reject) => { - startPlayback(fileName, (playbackDev) => { - assert.equal(typeof playbackDev.duration, 'number'); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing member fileName', () => { - return new Promise((resolve, reject) => { - startPlayback(fileName, (playbackDev) => { - assert.equal(typeof playbackDev.fileName, 'string'); - assert.equal(playbackDev.fileName, fileName); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing member first', () => { - return new Promise((resolve, reject) => { - startPlayback(fileName, (playbackDev) => { - assert.equal(typeof playbackDev.first, 'object'); - assert(playbackDev.first instanceof rs2.Sensor); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing member isRealTime', () => { - return new Promise((resolve, reject) => { - startPlayback(fileName, (playbackDev) => { - assert.equal(typeof playbackDev.isRealTime, 'boolean'); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing member isValid', () => { - return new Promise((resolve, reject) => { - startPlayback(fileName, (playbackDev) => { - assert.equal(typeof playbackDev.isValid, 'boolean'); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing member position', () => { - return new Promise((resolve, reject) => { - startPlayback(fileName, (playbackDev) => { - assert.equal(typeof playbackDev.position, 'number'); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method getCameraInfo - without argument', () => { - return new Promise((resolve, reject) => { - startPlayback(fileName, (playbackDev) => { - assert.doesNotThrow(() => { - playbackDev.getCameraInfo(); - }); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method getCameraInfo - return value', () => { - return new Promise((resolve, reject) => { - startPlayback(fileName, (playbackDev) => { - let rtn = playbackDev.getCameraInfo(); - assert.equal(typeof rtn.name, 'string'); - assert.equal(typeof rtn.serialNumber, 'string'); - assert.equal(typeof rtn.firmwareVersion, 'string'); - assert.equal(typeof rtn.physicalPort, 'string'); - assert.equal(typeof rtn.debugOpCode, 'string'); - assert.equal(typeof rtn.productId, 'string'); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method getCameraInfo - with argument', () => { - return new Promise((resolve, reject) => { - startPlayback(fileName, (playbackDev) => { - for (let i in rs2.camera_info) { - if (rs2.camera_info[i] && - i.toUpperCase() !== 'CAMERA_INFO_LOCATION' && // location is not ready - i.toUpperCase() !== 'CAMERA_INFO_COUNT' && // skip counter - i.toUpperCase() !== 'CAMERA_INFO_CAMERA_LOCKED' && - i.toUpperCase() !== 'CAMERA_INFO_ADVANCED_MODE' && - i !== 'cameraInfoToString' // skip method - ) { - assert.doesNotThrow(() => { // jshint ignore:line - playbackDev.getCameraInfo(rs2.camera_info[i]); - }); - } - } - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method getCameraInfo - with invalid argument', () => { - return new Promise((resolve, reject) => { - startPlayback(fileName, (playbackDev) => { - assert.throws(() => { - playbackDev.getCameraInfo('dummy'); - }); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method querySensors - return value', () => { - return new Promise((resolve, reject) => { - startPlayback(fileName, (playbackDev) => { - assert.doesNotThrow(() => { - playbackDev.querySensors(); - }); - assert.equal(Object.prototype.toString.call(playbackDev.querySensors()), '[object Array]'); - playbackDev.querySensors().forEach((i) => { - assert(playbackDev.querySensors()[0] instanceof rs2.Sensor); - }); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method reset', () => { - return new Promise((resolve, reject) => { - startPlayback(fileName, (playbackDev) => { - assert.doesNotThrow(() => { - playbackDev.reset(); - }); - assert.equal(typeof playbackDev.reset(), 'undefined'); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method supportsCameraInfo - without argument', () => { - return new Promise((resolve, reject) => { - startPlayback(fileName, (playbackDev) => { - assert.throws(() => { - playbackDev.supportsCameraInfo(); - }); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method supportsCameraInfo - return value', () => { - return new Promise((resolve, reject) => { - startPlayback(fileName, (playbackDev) => { - let rtn = playbackDev.supportsCameraInfo('serial-number'); - assert.equal(typeof rtn, 'boolean'); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method supportsCameraInfo - with invalid argument', () => { - return new Promise((resolve, reject) => { - startPlayback(fileName, (playbackDev) => { - assert.throws(() => { - playbackDev.supportsCameraInfo('dummy'); - }); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method supportsCameraInfo - with argument', () => { - return new Promise((resolve, reject) => { - startPlayback(fileName, (playbackDev) => { - for (let i in rs2.camera_info) { - if (rs2.camera_info[i] && - i.toUpperCase() !== 'CAMERA_INFO_LOCATION' && // BUG-7429 - i.toUpperCase() !== 'CAMERA_INFO_COUNT' && // skip counter - i !== 'cameraInfoToString' // skip method - ) { - assert.doesNotThrow(() => { // jshint ignore:line - playbackDev.supportsCameraInfo(rs2.camera_info[i]); - }); - } - } - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method pause - valid', () => { - return new Promise((resolve, reject) => { - startPlayback(fileName, (playbackDev, status, cnt) => { - assert.doesNotThrow(() => { - playbackDev.pause(); - playbackDev.resume(); - playbackDev.stop(); - }); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method resume - 1 argument', () => { - return new Promise((resolve, reject) => { - startPlayback(fileName, (playbackDev, status, cnt) => { - assert.doesNotThrow(() => { - playbackDev.pause(); - playbackDev.resume('dummy'); - }); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method querySensors - valid argument', () => { - return new Promise((resolve, reject) => { - startPlayback(fileName, (playbackDev, status, cnt) => { - assert.doesNotThrow(() => { - playbackDev.querySensors(); - }); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method querySensors - invalid argument', () => { - return new Promise((resolve, reject) => { - startPlayback(fileName, (playbackDev, status, cnt) => { - assert.doesNotThrow(() => { - playbackDev.querySensors('dummy'); - }); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method reset - valid argument', () => { - return new Promise((resolve, reject) => { - startPlayback(fileName, (playbackDev, status, cnt) => { - assert.doesNotThrow(() => { - playbackDev.reset(); - }); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method reset - invalid argument', () => { - return new Promise((resolve, reject) => { - startPlayback(fileName, (playbackDev, status, cnt) => { - assert.doesNotThrow(() => { - playbackDev.reset('dummy'); - }); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method seek - valid argument', () => { - return new Promise((resolve, reject) => { - startPlayback(fileName, (playbackDev, status, cnt) => { - assert.doesNotThrow(() => { - playbackDev.seek(1); - }); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method seek - invalid argument', () => { - return new Promise((resolve, reject) => { - startPlayback(fileName, (playbackDev, status, cnt) => { - assert.throws(() => { - playbackDev.seek('dummy'); - }); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method setPlaybackSpeed - valid argument', () => { - return new Promise((resolve, reject) => { - startPlayback(fileName, (playbackDev, status, cnt) => { - assert.doesNotThrow(() => { - playbackDev.setPlaybackSpeed(1); - }); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method setPlaybackSpeed - invalid argument', () => { - return new Promise((resolve, reject) => { - startPlayback(fileName, (playbackDev, status, cnt) => { - assert.throws(() => { - playbackDev.setPlaybackSpeed('dummy'); - }); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); -}); diff --git a/wrappers/nodejs/test/test-pointcloud.js b/wrappers/nodejs/test/test-pointcloud.js deleted file mode 100644 index f9619ea4c9..0000000000 --- a/wrappers/nodejs/test/test-pointcloud.js +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -/* global describe, it, before, after */ -const assert = require('assert'); -let rs2; -try { - rs2 = require('node-librealsense'); -} catch (e) { - rs2 = require('../index.js'); -} - -let ctx; -describe('Pointcloud test', function() { - before(function() { - ctx = new rs2.Context(); - const devices = ctx.queryDevices().devices; - assert(devices.length > 0); // Device must be connected - }); - - after(function() { - rs2.cleanup(); - }); - - it('Testing method destroy', () => { - let pointcloud; - assert.doesNotThrow(() => { - pointcloud= new rs2.PointCloud(); - pointcloud.destroy(); - }); - setTimeout(() => { - assert.equal(pointcloud.pointsFrame, undefined); - assert.equal(pointcloud.cxxPointCloud, undefined); - }, 100); - }); - - it('Testing method calculate', () => { - let pipeline; - let frameSet; - let pointcloud; - assert.doesNotThrow(() => { - pipeline = new rs2.Pipeline(); - pointcloud = new rs2.PointCloud(); - pipeline.start(); - }); - let endTest = false; - let n = 0; - while (!endTest) { - frameSet = pipeline.waitForFrames(); - n++; - console.log(`retring left ...${10 - n} times`); - if (frameSet !== undefined && frameSet.colorFrame !== undefined && - frameSet.depthFrame !== undefined) { - assert(frameSet.depthFrame instanceof rs2.DepthFrame); - assert(frameSet.colorFrame instanceof rs2.VideoFrame); - let points; - let pointsNull; - assert.doesNotThrow(() => { // jshint ignore:line - points = pointcloud.calculate(frameSet.depthFrame); - }); - assert(points instanceof rs2.Points); - assert.throws(() => { // jshint ignore:line - pointsNull = pointcloud.calculate(); - }); - assert(pointsNull === undefined); - pointcloud.destroy(); - endTest = true; - } - if (n >= 10) { - assert(false, 'could not get colorFrame or depthFrame, try to reset camera'); - } - } - frameSet.destroy(); - pipeline.destroy(); - }); - - it('Testing method mapTo', () => { - let pipeline; - let frameSet; - let pointcloud; - assert.doesNotThrow(() => { - pipeline = new rs2.Pipeline(); - pointcloud = new rs2.PointCloud(); - pipeline.start(); - }); - let endTest = false; - let n = 0; - while (!endTest) { - frameSet = pipeline.waitForFrames(); - n++; - console.log(`retring left ...${10 - n} times`); - if (frameSet !== undefined && frameSet.colorFrame !== undefined && - frameSet.depthFrame !== undefined) { - let rtn; - let rtnNull; - assert.doesNotThrow(() => { // jshint ignore:line - rtn = pointcloud.mapTo(frameSet.colorFrame); - }); - assert(rtn === undefined); - assert.throws(() => { // jshint ignore:line - rtnNull = pointcloud.mapTo(); - }); - assert(rtnNull === undefined); - pointcloud.destroy(); - endTest = true; - } - if (n >= 10) { - assert(false, 'could not get colorFrame or depthFrame, try to reset camera'); - } - } - frameSet.destroy(); - pipeline.destroy(); - }); -}); diff --git a/wrappers/nodejs/test/test-points.js b/wrappers/nodejs/test/test-points.js deleted file mode 100644 index 8ed7890a74..0000000000 --- a/wrappers/nodejs/test/test-points.js +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -/* global describe, it, beforeEach, afterEach */ -const assert = require('assert'); -const fs = require('fs'); -let rs2; -try { - rs2 = require('node-librealsense'); -} catch (e) { - rs2 = require('../index.js'); -} - -let ctx; -let pipeline; -let pointcloud; -let frameSet; -let points; -let files = 'points.ply'; -describe('Points test', function() { - beforeEach(function() { - ctx = new rs2.Context(); - const devices = ctx.queryDevices().devices; - assert(devices.length > 0); // Device must be connected - }); - - afterEach(function() { - pipeline.destroy(); - pipeline.stop(); - rs2.cleanup(); - frameSet.destroy(); - if (fs.existsSync(files)) { - fs.unlinkSync(files); - } - }); - - it('Testing member textureCoordinates', () => { - assert.doesNotThrow(() => { - pipeline = new rs2.Pipeline(); - pointcloud = new rs2.PointCloud(); - pipeline.start(); - }); - let endTest = false; - let n = 0; - while (!endTest) { - frameSet = pipeline.waitForFrames(); - n++; - console.log(`retring left ...${10 - n} times`); - if (frameSet !== undefined && frameSet.colorFrame !== undefined && - frameSet.depthFrame !== undefined) { - let points; - let arr; - assert.doesNotThrow(() => { // jshint ignore:line - points = pointcloud.calculate(frameSet.depthFrame); - arr = points.textureCoordinates; - }); - assert.equal(typeof arr[0], 'number'); - assert.equal(Object.prototype.toString.call(arr), '[object Int32Array]'); - pointcloud.destroy(); - endTest = true; - } - if (n >= 10) { - assert(false, 'could not get colorFrame or depthFrame, try to reset camera'); - } - } - }); - - it('Testing member vertices', () => { - assert.doesNotThrow(() => { - pipeline = new rs2.Pipeline(); - pointcloud = new rs2.PointCloud(); - pipeline.start(); - }); - let endTest = false; - let n = 0; - while (!endTest) { - frameSet = pipeline.waitForFrames(); - n++; - console.log(`retring left ...${10 - n} times`); - if (frameSet !== undefined && frameSet.colorFrame !== undefined && - frameSet.depthFrame !== undefined) { - let points; - let arr; - assert.doesNotThrow(() => { // jshint ignore:line - points = pointcloud.calculate(frameSet.depthFrame); - arr = points.vertices; - }); - assert.equal(typeof arr[0], 'number'); - assert.equal(Object.prototype.toString.call(arr), '[object Float32Array]'); - pointcloud.destroy(); - endTest = true; - } - if (n >= 10) { - assert(false, 'could not get colorFrame or depthFrame, try to reset camera'); - } - } - }); - - it('Testing member size', () => { - assert.doesNotThrow(() => { - pipeline = new rs2.Pipeline(); - pointcloud = new rs2.PointCloud(); - pipeline.start(); - }); - let endTest = false; - let n = 0; - while (!endTest) { - frameSet = pipeline.waitForFrames(); - n++; - console.log(`retring left ...${10 - n} times`); - if (frameSet !== undefined && frameSet.colorFrame !== undefined && - frameSet.depthFrame !== undefined) { - let points; - let arr; - assert.doesNotThrow(() => { // jshint ignore:line - points = pointcloud.calculate(frameSet.depthFrame); - arr = points.size; - }); - assert.equal(typeof arr, 'number'); - assert.equal(Object.prototype.toString.call(arr), '[object Number]'); - pointcloud.destroy(); - endTest = true; - } - if (n >= 10) { - assert(false, 'could not get colorFrame or depthFrame, try to reset camera'); - } - } - }); - - it('Testing method exportToPly without argument', () => { - assert.doesNotThrow(() => { - pipeline = new rs2.Pipeline(); - pointcloud = new rs2.PointCloud(); - pipeline.start(); - frameSet = pipeline.waitForFrames(); - points = pointcloud.calculate(frameSet.depthFrame); - }); - assert.throws(() => { - points.exportToPly(); - }); - }); - - it('Testing method exportToPly with three arguments', () => { - assert.doesNotThrow(() => { - pipeline = new rs2.Pipeline(); - pointcloud = new rs2.PointCloud(); - pipeline.start(); - frameSet = pipeline.waitForFrames(); - points = pointcloud.calculate(frameSet.depthFrame); - }); - assert.throws(() => { - points.exportToPly(files, files, files); - }); - }); - - it('Testing method exportToPly first argument with number', () => { - assert.doesNotThrow(() => { - pipeline = new rs2.Pipeline(); - pointcloud = new rs2.PointCloud(); - pipeline.start(); - frameSet = pipeline.waitForFrames(); - points = pointcloud.calculate(frameSet.depthFrame); - }); - assert.throws(() => { - points.exportToPly(1, 1); - }); - }); - - it('Testing method exportToPly second argument with number', () => { - assert.doesNotThrow(() => { - pipeline = new rs2.Pipeline(); - pointcloud = new rs2.PointCloud(); - pipeline.start(); - frameSet = pipeline.waitForFrames(); - points = pointcloud.calculate(frameSet.depthFrame); - }); - assert.throws(() => { - points.exportToPly(files, 1); - }); - }); - - it('Testing method exportToPly with depthFrame', () => { - assert.doesNotThrow(() => { - pipeline = new rs2.Pipeline(); - pointcloud = new rs2.PointCloud(); - pipeline.start(); - frameSet = pipeline.waitForFrames(); - }); - assert.doesNotThrow(() => { - points = pointcloud.calculate(frameSet.depthFrame); - points.exportToPly(files, frameSet.depthFrame); - assert.equal(fs.existsSync(files), true); - }); - }); - - it('Testing method exportToPly with colorFrame', () => { - assert.doesNotThrow(() => { - pipeline = new rs2.Pipeline(); - pointcloud = new rs2.PointCloud(); - pipeline.start(); - frameSet = pipeline.waitForFrames(); - }); - assert.doesNotThrow(() => { - points = pointcloud.calculate(frameSet.depthFrame); - points.exportToPly(files, frameSet.colorFrame); - assert.equal(fs.existsSync(files), true); - }); - }); - - it('Testing method exportToPly with videoFrame', () => { - assert.doesNotThrow(() => { - pipeline = new rs2.Pipeline(); - pointcloud = new rs2.PointCloud(); - pipeline.start(); - frameSet = pipeline.waitForFrames(); - points = pointcloud.calculate(frameSet.depthFrame); - }); - assert.doesNotThrow(() => { - let videoFrame = frameSet.at(1); - points.exportToPly(files, videoFrame); - assert.equal(fs.existsSync(files), true); - }); - }); -}); diff --git a/wrappers/nodejs/test/test-recorderdevice.js b/wrappers/nodejs/test/test-recorderdevice.js deleted file mode 100644 index 0940cd6c35..0000000000 --- a/wrappers/nodejs/test/test-recorderdevice.js +++ /dev/null @@ -1,375 +0,0 @@ -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -/* global describe, it, beforeEach, afterEach, after */ -const assert = require('assert'); -const fs = require('fs'); -const path = require('path'); -let rs2; -try { - rs2 = require('node-librealsense'); -} catch (e) { - rs2 = require('../index.js'); -} - -let ctx; -let dev; -let recorder; -let sensor; -let fileName = 'record.bag'; - -describe('RecorderDevice constructor test', () => { - beforeEach(() => { - ctx = new rs2.Context(); - const devices = ctx.queryDevices().devices; - assert(devices.length > 0); - dev = devices[0]; - }); - - afterEach(() => { - rs2.cleanup(); - }); - - after(() => { - if (fs.existsSync(fileName)) { - fs.unlinkSync(fileName); - } - }); - - it('Testing constructor - valid argument', () => { - assert.doesNotThrow(() => { - new rs2.RecorderDevice(fileName, dev); - }); - }); - - it('Testing constructor - 1 argument', () => { - assert.throws(() => { - new rs2.RecorderDevice(fileName); - }); - }); - - it('Testing constructor - invalid file argument', () => { - assert.throws(() => { - new rs2.RecorderDevice(1, dev); - }); - }); - - it('Testing constructor - invalid devices argument', () => { - assert.throws(() => { - new rs2.RecorderDevice(fileName, 1); - }); - }); - - it('Testing constructor - 5 arguments', () => { - assert.throws(() => { - new rs2.RecorderDevice(fileName, dev, undefined, true, true); - }); - }); -}); - -describe('RecorderDevice test', function() { - after(function() { - if (fs.existsSync(fileName)) { - fs.unlinkSync(fileName); - } - }); - afterEach(() => { - rs2.cleanup(); - }); - - function startRecording(file, cnt, callback) { - return new Promise((resolve, reject) => { - setTimeout(() => { - ctx = new rs2.Context(); - dev = ctx.queryDevices().devices[0]; - recorder = new rs2.RecorderDevice(file, dev); - let sensors = recorder.querySensors(); - sensor = sensors[0]; - let profiles = sensor.getStreamProfiles(); - for (let i = 0; i < profiles.length; i++) { - if (profiles[i].streamType === rs2.stream.STREAM_DEPTH && - profiles[i].fps === 30 && - profiles[i].width === 640 && - profiles[i].height === 480 && - profiles[i].format === rs2.format.FORMAT_Z16) { - sensor.open(profiles[i]); - } - } - let counter = 0; - sensor.start((frame) => { - if (callback) { - callback(recorder, counter); - } - counter++; - if (counter === cnt) { - sensor.stop(); - recorder.reset(); - rs2.cleanup(); - resolve(); - } - }); - }, 2000); - }); - } - - it('Testing method getCameraInfo - without argument', () => { - return new Promise((resolve, reject) => { - startRecording(fileName, 1, (recorder, cnt) => { - assert.doesNotThrow(() => { - recorder.getCameraInfo(); - }); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method getCameraInfo - return value', () => { - return new Promise((resolve, reject) => { - startRecording(fileName, 1, (recorder, cnt) => { - let rtn = recorder.getCameraInfo(); - assert.equal(typeof rtn.name, 'string'); - assert.equal(typeof rtn.serialNumber, 'string'); - assert.equal(typeof rtn.firmwareVersion, 'string'); - assert.equal(typeof rtn.physicalPort, 'string'); - assert.equal(typeof rtn.debugOpCode, 'string'); - assert.equal(typeof rtn.productId, 'string'); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method getCameraInfo - with argument', () => { - return new Promise((resolve, reject) => { - startRecording(fileName, 1, (recorder, cnt) => { - for (let i in rs2.camera_info) { - if (rs2.camera_info[i] && - i.toUpperCase() !== 'CAMERA_INFO_LOCATION' && // location is not ready - i.toUpperCase() !== 'CAMERA_INFO_COUNT' && // skip counter - i.toUpperCase() !== 'CAMERA_INFO_CAMERA_LOCKED' && - i.toUpperCase() !== 'CAMERA_INFO_ADVANCED_MODE' && - i !== 'cameraInfoToString' // skip method - ) { - assert.doesNotThrow(() => { // jshint ignore:line - recorder.getCameraInfo(rs2.camera_info[i]); - }); - } - } - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method getCameraInfo - with invalid argument', () => { - return new Promise((resolve, reject) => { - startRecording(fileName, 1, (recorder, cnt) => { - assert.throws(() => { - recorder.getCameraInfo('dummy'); - }); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method querySensors - return value', () => { - return new Promise((resolve, reject) => { - startRecording(fileName, 1, (recorder, cnt) => { - assert.doesNotThrow(() => { - recorder.querySensors(); - }); - assert.equal(Object.prototype.toString.call(recorder.querySensors()), '[object Array]'); - recorder.querySensors().forEach((i) => { - assert(recorder.querySensors()[0] instanceof rs2.Sensor); - }); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method reset', () => { - return new Promise((resolve, reject) => { - startRecording(fileName, 1, (recorder, cnt) => { - assert.doesNotThrow(() => { - recorder.reset(); - }); - assert.equal(typeof recorder.reset(), 'undefined'); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method supportsCameraInfo - without argument', () => { - return new Promise((resolve, reject) => { - startRecording(fileName, 1, (recorder, cnt) => { - assert.throws(() => { - recorder.supportsCameraInfo(); - }); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method supportsCameraInfo - return value', () => { - return new Promise((resolve, reject) => { - startRecording(fileName, 1, (recorder, cnt) => { - let rtn = recorder.supportsCameraInfo('serial-number'); - assert.equal(typeof rtn, 'boolean'); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method supportsCameraInfo - with invalid argument', () => { - return new Promise((resolve, reject) => { - startRecording(fileName, 1, (recorder, cnt) => { - assert.throws(() => { - recorder.supportsCameraInfo('dummy'); - }); - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method supportsCameraInfo - with argument', () => { - return new Promise((resolve, reject) => { - startRecording(fileName, 1, (recorder, cnt) => { - for (let i in rs2.camera_info) { - if (rs2.camera_info[i] && - i.toUpperCase() !== 'CAMERA_INFO_LOCATION' && // BUG-7429 - i.toUpperCase() !== 'CAMERA_INFO_COUNT' && // skip counter - i !== 'cameraInfoToString' // skip method - ) { - assert.doesNotThrow(() => { // jshint ignore:line - recorder.supportsCameraInfo(rs2.camera_info[i]); - }); - } - } - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method pause - valid', () => { - return new Promise((resolve, reject) => { - startRecording(fileName, 1, (recorder, cnt) => { - if (cnt === 1) { - assert.doesNotThrow(() => { - recorder.pause(); - recorder.resume(); - }); - } - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method pause - 1 argument', () => { - return new Promise((resolve, reject) => { - startRecording(fileName, 1, (recorder, cnt) => { - if (cnt === 1) { - assert.doesNotThrow(() => { - recorder.pause('dummy'); - recorder.resume(); - }); - } - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method resume - 1 argument', () => { - return new Promise((resolve, reject) => { - startRecording(fileName, 1, (recorder, cnt) => { - if (cnt === 1) { - assert.doesNotThrow(() => { - recorder.pause(); - recorder.resume('dummy'); - }); - } - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing method pause resume - more than once', () => { - return new Promise((resolve, reject) => { - startRecording(fileName, 1, (recorder, cnt) => { - if (cnt === 1) { - assert.doesNotThrow(() => { - recorder.pause(); - recorder.resume(); - recorder.pause(); - recorder.resume(); - recorder.pause(); - recorder.resume(); - }); - } - }).then(() => { - resolve(); - }); - }); - }).timeout(5000); - - it('Testing member - fileName', () => { - return new Promise((resolve, reject) => { - startRecording(fileName, 1, (recorder, cnt) => { - if (cnt === 1) { - assert(recorder.fileName === fileName); - } - }).then(() => { - assert(fs.existsSync(fileName)); - resolve(); - }).catch((e) => { - reject(e); - }); - }); - }).timeout(5000); - - it('Testing member - fileName with absolute path', () => { - fileName = path.join(__dirname, 'record.bag'); - return new Promise((resolve, reject) => { - startRecording(fileName, 1, (recorder, cnt) => { - if (cnt === 1) { - assert(recorder.fileName === fileName); - assert(fs.existsSync(fileName)); - } - }).then(() => { - resolve(); - }).catch((e) => { - reject(e); - }); - }); - }).timeout(5000); - - it('Testing member - fileName is existing', () => { - return new Promise((resolve, reject) => { - fs.closeSync(fs.openSync(fileName, 'w')); - assert(fs.existsSync(fileName)); - startRecording(fileName, 1, (recorder, cnt) => { - if (cnt === 1) { - assert(recorder.fileName === fileName); - assert(fs.existsSync(fileName)); - } - }).then(() => { - resolve(); - }).catch((e) => { - reject(e); - }); - }); - }).timeout(5000); -}); diff --git a/wrappers/nodejs/test/test-sensor-extensions.js b/wrappers/nodejs/test/test-sensor-extensions.js deleted file mode 100644 index c215f4e7b7..0000000000 --- a/wrappers/nodejs/test/test-sensor-extensions.js +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; -/* global describe, it, before, after */ -const assert = require('assert'); -let rs2; -// let pipeline; -try { - rs2 = require('node-librealsense'); -} catch (e) { - rs2 = require('../index.js'); -} - -let device; -// let frameset; -let devInfo; -let motionProductList = ['0AD5', '0AFE', '0AFF', '0B00', '0B01', '0B3A', '0B3D']; -const ctx = new rs2.Context(); -let devices = ctx.queryDevices().devices; -assert(devices.length > 0); // Device must be connected -device = devices[0]; -devInfo = device.getCameraInfo(); - - -describe('Sensor extensions test', function() { - before(function() { - // const ctx = new rs2.Context(); - // let devices = ctx.queryDevices().devices; - // assert(devices.length > 0); // Device must be connected - // device = devices[0] - // devInfo = device.getCameraInfo(); - }); - - after(function() { - rs2.cleanup(); - }); - - it('Testing constructor - 0 argument', () => { - assert.throws(() => { - new rs2.Align(); - }); - }); - - it('Testing ColorSensor extention', () => { - const productsList = ['0AA5, 0B48, 0AD3, 0AD4, 0AD5, 0B01, 0B07, 0B3A, 0B3D']; - let rtn = device.getCameraInfo(); - if (productsList.includes(rtn.productId)) { - const sensors = device.querySensors(); - let isFound = false; - for (let i = 0; i < sensors.length; i++) { - if (sensors[i] instanceof rs2.ColorSensor) { - const sensor = sensors[i]; - const profile = sensor.getStreamProfiles()[0]; - assert(profile.streamType === rs2.stream.STREAM_COLOR && - profile.format == rs2.format.FORMAT_RGB8); - isFound = true; - } - } - assert(isFound); - } - }); - - it('Testing FisheyeSensor extention', () => { - const productsList = ['0AD5', '0AFE', '0AFF', '0B00', '0B01']; - let rtn = device.getCameraInfo(); - if (productsList.includes(rtn.productId)) { - const sensors = device.querySensors(); - let isFound = false; - for (let i = 0; i < sensors.length; i++) { - if (sensors[i] instanceof rs2.FisheyeSensor) { - const sensor = sensors[i]; - const profile = sensor.getStreamProfiles()[0]; - assert(profile.streamType === rs2.stream.STREAM_COLOR && - profile.format == rs2.format.FORMAT_RGB8); - isFound = true; - } - } - assert(isFound); - } - }); - - if (motionProductList.includes(devInfo.productId)) { - it('Testing MotionSensor extention', () => { - const productsList = ['0AD5', '0AFE', '0AFF', '0B00', '0B01', '0B3A', '0B3D']; - let rtn = device.getCameraInfo(); - if (productsList.includes(rtn.productId)) { - const sensors = device.querySensors(); - let isFound = false; - for (let i = 0; i < sensors.length; i++) { - if (sensors[i] instanceof rs2.MotionSensor) { - const sensor = sensors[i]; - const profile = sensor.getStreamProfiles()[0]; - assert([rs2.stream.STREAM_GYRO, rs2.stream.STREAM_ACCEL].includes(profile.streamType)); - assert([rs2.format.FORMAT_MOTION_RAW, rs2.format.FORMAT_MOTION_XYZ32F] - .includes(profile.format)); - isFound = true; - } - } - assert(isFound); - } - }); - } -}); diff --git a/wrappers/nodejs/test/test-sensor.js b/wrappers/nodejs/test/test-sensor.js deleted file mode 100644 index c01dda9cca..0000000000 --- a/wrappers/nodejs/test/test-sensor.js +++ /dev/null @@ -1,545 +0,0 @@ -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -/* global describe, it, beforeEach, afterEach */ -const assert = require('assert'); -let rs2; -try { - rs2 = require('node-librealsense'); -} catch (e) { - rs2 = require('../index.js'); -} - -let ctx; -let sensors; -describe('Sensor test', function() { - beforeEach(function() { - ctx = new rs2.Context(); - sensors = ctx.querySensors(); - assert(sensors.length > 0); // Sensor must be connected - }); - - afterEach(function() { - rs2.cleanup(); - }); - - const optionsTestArray = Object.values(rs2.option); - optionsTestArray.pop(); - optionsTestArray.pop(); - it('Testing member - isValid', () => { - sensors.forEach((sensor) => { - assert.equal(typeof sensor.isValid, 'boolean'); - }); - }); - - it('Testing method isOptionReadOnly', () => { - sensors.forEach((sensor) => { - Object.keys(rs2.option).forEach((o) => { - if (o === 'OPTION_COUNT' || o === 'optionToString') return; - if (sensor.supportsOption(rs2.option[o])) { - assert.equal(typeof sensor.isOptionReadOnly(rs2.option[o]), 'boolean'); - } else { - assert.equal(typeof sensor.isOptionReadOnly(rs2.option[o]), 'undefined'); - } - }); - optionsTestArray.forEach((o) => { - if (sensor.supportsOption(o)) { - assert.equal(typeof sensor.isOptionReadOnly(o), 'boolean'); - } else { - assert.equal(typeof sensor.isOptionReadOnly(o), 'undefined'); - } - }); - }); - }); - - it('Testing method isOptionReadOnly, invalid value', () => { - sensors.forEach((sensor) => { - assert.throws(() => { - sensor.isOptionReadOnly('dummy'); - }); - }); - }); - - it('Testing method supportsOption', () => { - sensors.forEach((sensor) => { - Object.keys(rs2.option).forEach((o) => { - if (o === 'OPTION_COUNT' || o === 'optionToString') return; - assert.equal(typeof sensor.supportsOption(rs2.option[o]), 'boolean'); - }); - optionsTestArray.forEach((o) => { - assert.equal(typeof sensor.supportsOption(o), 'boolean'); - }); - }); - }); - - it('Testing method supportsOption, invalid value', () => { - sensors.forEach((sensor) => { - assert.throws(() => { - sensor.supportsOption('dummy'); - }); - }); - }); - - it('Testing method supportsOption, null value', () => { - sensors.forEach((sensor) => { - assert.throws(() => { - sensor.supportsOption(); - }); - assert.throws(() => { - sensor.supportsOption(null); - }); - assert.throws(() => { - sensor.supportsOption(undefined); - }); - }); - }); - - it('Testing method getOption', () => { - sensors.forEach((sensor) => { - Object.keys(rs2.option).forEach((o) => { - if (o === 'OPTION_COUNT' || o === 'optionToString') return; - if (sensor.supportsOption(rs2.option[o])) { - assert.equal(typeof sensor.getOption(rs2.option[o]), 'number'); - } else { - assert.equal(typeof sensor.getOption(rs2.option[o]), 'undefined'); - } - }); - optionsTestArray.forEach((o) => { - if (sensor.supportsOption(o)) { - assert.equal(typeof sensor.getOption(o), 'number'); - } else { - assert.equal(typeof sensor.getOption(o), 'undefined'); - } - }); - }); - }); - - it('Testing method getOption, invalid value', () => { - sensors.forEach((sensor) => { - optionsTestArray.forEach((o) => { - assert.throws(() => { - sensor.getOption('dummy'); - }); - assert.throws(() => { - sensor.getOption(); - }); - assert.throws(() => { - sensor.getOption(null); - }); - assert.throws(() => { - sensor.getOption(undefined); - }); - }); - }); - }); - - it('Testing method getOptionRange', () => { - sensors.forEach((sensor) => { - Object.keys(rs2.option).forEach((o) => { - if (o === 'OPTION_COUNT' || o === 'optionToString') return; - if (sensor.supportsOption(rs2.option[o])) { - const r = sensor.getOptionRange(rs2.option[o]); - assert.equal(typeof r, 'object'); - assert.equal(typeof r.minValue, 'number'); - assert.equal(typeof r.maxValue, 'number'); - assert.equal(typeof r.defaultValue, 'number'); - assert.equal(typeof r.step, 'number'); - } else { - assert.equal(typeof sensor.getOptionRange(rs2.option[o]), 'undefined'); - } - }); - optionsTestArray.forEach((o) => { - if (sensor.supportsOption(o)) { - const r = sensor.getOptionRange(o); - assert.equal(typeof r, 'object'); - assert.equal(typeof r.minValue, 'number'); - assert.equal(typeof r.maxValue, 'number'); - assert.equal(typeof r.defaultValue, 'number'); - assert.equal(typeof r.step, 'number'); - } else { - assert.equal(typeof sensor.getOptionRange(o), 'undefined'); - } - }); - }); - }); - - it('Testing method setOption', () => { - sensors.forEach((sensor) => { - optionsTestArray.forEach((o) => { - assert.doesNotThrow(() => { - sensor.setOption(o, 10); - }); - }); - Object.keys(rs2.option).forEach((o) => { - if (o === 'OPTION_COUNT' || o === 'optionToString') return; - // retrun if sensor does not support option - if (!sensor.supportsOption(rs2.option[o])) return; - const v = sensor.getOption(rs2.option[o]); - let vSet; - const r = sensor.getOptionRange(rs2.option[o]); - if ((v - r.step) < r.minValue) { - vSet = v + r.step; - } else { - vSet = v - r.step; - } - sensor.setOption(rs2.option[o], vSet); - const vNew = sensor.getOption(rs2.option[o]); - if (o.toUpperCase() === 'OPTION_DEPTH_UNITS') { - assert.equal(Math.round(vNew * 100000)/100000, Math.round(vSet * 100000)/100000); - } else { - assert.equal(vNew, vSet); - } - }); - }); - }).timeout(30 * 1000); - - it('Testing method getOptionDescription', () => { - sensors.forEach((sensor) => { - optionsTestArray.forEach((o) => { - assert(typeof sensor.getOptionDescription(o) === 'string' || - typeof sensor.getOptionDescription(o) === 'undefined' - ); - }); - }); - }); - - it('Testing method getOptionValueDescription', () => { - sensors.forEach((sensor) => { - optionsTestArray.forEach((o) => { - let value; - if (sensor.supportsOption(o)) { - value = sensor.getOption(o); - } else { - value = 0; - } - assert(typeof sensor.getOptionValueDescription(o, value) === 'undefined' || - typeof sensor.getOptionValueDescription(o, value) === 'string' - ); - }); - }); - }); - - it('Testing method getStreamProfiles', () => { - sensors.forEach((sensor) => { - let profiles; - assert.doesNotThrow(() => { - profiles = sensor.getStreamProfiles(); - }); - /* eslint-disable guard-for-in */ - for (let i in profiles) { - assert.equal(typeof profiles[i].format, 'number'); - assert.equal(typeof profiles[i].fps, 'number'); - assert.equal(typeof profiles[i].isDefault, 'boolean'); - assert.equal(typeof profiles[i].streamIndex, 'number'); - assert.equal(typeof profiles[i].streamType, 'number'); - assert.equal(typeof profiles[i].uniqueID, 'number'); - } - }); - }); - - it('Testing method open, streamProfile', () => { - sensors.forEach((sensor) => { - const profiles = sensor.getStreamProfiles(); - for (let i in profiles) { - assert.doesNotThrow(() => { // jshint ignore:line - sensor.open(profiles[i]); - sensor.close(); - }); - } - }); - }).timeout(5000); - - it('Testing method open, profileArray', () => { - let dict = {}; - let sensor = sensors[0]; - let profiles; - assert.doesNotThrow(() => { - profiles = sensor.getStreamProfiles(); - }); - /* eslint-disable guard-for-in */ - for (let i in profiles) { - let strings = '' + profiles[i].widthValue + profiles[i].heightValue + - profiles[i].fps + profiles[i].formatValue; - if (dict.hasOwnProperty(strings)) { - let strs = dict[strings]; - strs.push(i); - dict[strings] = strs; - } else { - dict[strings] = [i]; - } - } - /* eslint-disable guard-for-in */ - for (let m in Object.values(dict)) { - let arr = []; - if (Object.values(dict)[m].length <= 1) continue; - /* eslint-disable guard-for-in */ - for (let j in Object.values(dict)[m]) { - arr.push(profiles[Object.values(dict)[m][j]]); - } - sensor.open(arr); - sensor.close(); - break; - } - }); - - it('Testing method open, w/ two args', () => { - sensors.forEach((sensor) => { - const profiles = sensor.getStreamProfiles(); - for (let i in profiles) { - assert.throws(() => { // jshint ignore:line - sensor.open(profiles[i], profiles); - sensor.close(); - }); - } - }); - }); - - it('Testing method open, w/o args', () => { - sensors.forEach((sensor) => { - assert.throws(() => { - sensor.open(); - sensor.close(); - }); - }); - }); - - it('Testing method open, w/ invaild args', () => { - sensors.forEach((sensor) => { - assert.throws(() => { - sensor.open('dummy'); - sensor.close(); - }); - }); - }); - - it('Testing method destroy check reopen', () => { - sensors.forEach((sensor) => { - const profiles = sensor.getStreamProfiles(); - assert.doesNotThrow(() => { - sensor.destroy(); - assert.equal(sensor.cxxSensor, undefined); - assert.equal(sensor._events, null); - }); - assert.throws(() => { - sensor.open(profiles); - sensor.close(); - }); - }); - }); - - it('Testing method start, with callback', () => { - function testSingleProfile(sensor, profile) { - assert.doesNotThrow(() => { // jshint ignore:line - sensor.open(profile); - }); - return new Promise((resolve, reject) => { - sensor.start((frame) => { // jshint ignore:line - assert.equal(typeof frame, 'object'); - assert.equal(typeof frame.isValid, 'boolean'); - let expectDataType; - switch (frame.format) { - case rs2.format.FORMAT_Z16: - case rs2.format.FORMAT_DISPARITY16: - case rs2.format.FORMAT_Y16: - case rs2.format.FORMAT_RAW16: - expectDataType = '[object Uint16Array]'; - break; - case rs2.format.FORMAT_YUYV: - case rs2.format.FORMAT_UYVY: - case rs2.format.FORMAT_RGB8: - case rs2.format.FORMAT_BGR8: - case rs2.format.FORMAT_RGBA8: - case rs2.format.FORMAT_BGRA8: - case rs2.format.FORMAT_Y8: - case rs2.format.FORMAT_RAW8: - case rs2.format.FORMAT_MOTION_RAW: - case rs2.format.FORMAT_GPIO_RAW: - case rs2.format.FORMAT_RAW10: - case rs2.format.FORMAT_ANY: - expectDataType = '[object Uint8Array]'; - break; - case rs2.format.FORMAT_XYZ32F: - case rs2.format.FORMAT_MOTION_XYZ32F: - case rs2.format.FORMAT_6DOF: - case rs2.format.FORMAT_DISPARITY32: - expectDataType = '[object Uint32Array]'; - break; - } - assert.equal(Object.prototype.toString.call(frame.data), expectDataType); - assert.equal(typeof frame.width, 'number'); - assert.equal(typeof frame.height, 'number'); - assert.equal(typeof frame.frameNumber, 'number'); - assert.equal(typeof frame.timestamp, 'number'); - assert.equal(typeof frame.streamType, 'number'); - assert.equal(typeof frame.dataByteLength, 'number'); - assert.equal(typeof frame.strideInBytes, 'number'); - assert.equal(typeof frame.bitsPerPixel, 'number'); - assert.equal(typeof frame.timestampDomain, 'number'); - sensor.stop(); - sensor.close(); - resolve(); - }); - }); - } - /* jshint ignore:start */ - async function runTest() { - for (let ii in sensors) { - let sensor = sensors[ii]; - const profiles = sensor.getStreamProfiles(); - for (let i in profiles) { - await testSingleProfile(sensor, profiles[i]); - } - } - } - return runTest(); - /* jshint ignore:end */ - }).timeout(150000); - - it('Testing method start, w/ syncer', () => { - let syncer = new rs2.Syncer(); - sensors.forEach((sensor) => { - const profiles = sensor.getStreamProfiles(); - for (let i in profiles) { - assert.doesNotThrow(() => { // jshint ignore:line - sensor.open(profiles[i]); - }); - sensor.start(syncer); - sensor.stop(); - sensor.close(); - } - }); - }).timeout(3000); - - it('Testing method close', () => { - sensors.forEach((sensor) => { - assert.throws(() => { - sensor.close(); - }); - }); - }); - - it('Testing method destroy', () => { - sensors.forEach((sensor) => { - assert.doesNotThrow(() => { - sensor.destroy(); - }); - }); - }); - - it('Testing method setNotificationsCallback notification', () => { - return new Promise((resolve, reject) => { - let dev = ctx.queryDevices().devices[0]; - sensors[0].setNotificationsCallback((n) => { - assert.equal(typeof n.descr, 'string'); - assert.equal(typeof n.timestamp, 'number'); - assert.equal(typeof n.severity, 'string'); - assert.equal(typeof n.category, 'string'); - resolve(); - }); - setTimeout(() => { - dev.cxxDev.triggerErrorForTest(); - }, 100); - }); - }); - - it('Testing method setNotificationsCallback w/o args', () => { - sensors.forEach((sensor) => { - assert.throws(() => { - sensor.setNotificationsCallback(); - }); - }); - }); - - it('Testing method setNotificationsCallback w/ invaild args', () => { - sensors.forEach((sensor) => { - assert.throws(() => { - sensor.setNotificationsCallback('dummy'); - }); - }); - }); - - it('Testing method supportsCameraInfo w/ number', () => { - sensors.forEach((sensor) => { - assert.doesNotThrow(() => { - for (let i = rs2.camera_info.CAMERA_INFO_NAME; i < rs2.camera_info.CAMERA_INFO_COUNT; i++) { - let obj = sensor.supportsCameraInfo(i); - assert.equal(typeof obj, 'boolean'); - } - }); - }); - }); - - it('Testing method getCameraInfo w/ number', () => { - sensors.forEach((sensor) => { - assert.doesNotThrow(() => { - for (let i = rs2.camera_info.CAMERA_INFO_NAME; i < rs2.camera_info.CAMERA_INFO_COUNT; i++) { - if (sensor.supportsCameraInfo(i)) { - let obj = sensor.getCameraInfo(i); - assert.equal(typeof obj, 'string'); - } - } - }); - }); - }); - - it('Testing method getCameraInfo w/ string', () => { - sensors.forEach((sensor) => { - assert.doesNotThrow(() => { - for (let i = rs2.camera_info.CAMERA_INFO_NAME; i < rs2.camera_info.CAMERA_INFO_COUNT; i++) { - let info = rs2.camera_info.cameraInfoToString(i); - if (sensor.supportsCameraInfo(info)) { - let obj = sensor.getCameraInfo(info); - assert.equal(typeof obj, 'string'); - } - } - }); - }); - }); - - it('Testing method supportsCameraInfo w/ string', () => { - sensors.forEach((sensor) => { - assert.doesNotThrow(() => { - for (let i = rs2.camera_info.CAMERA_INFO_NAME; i < rs2.camera_info.CAMERA_INFO_COUNT; i++) { - let info = rs2.camera_info.cameraInfoToString(i); - let obj = sensor.supportsCameraInfo(info); - assert.equal(typeof obj, 'boolean'); - } - }); - }); - }); - - it('Testing method getCameraInfo w/ invaild info', () => { - sensors.forEach((sensor) => { - assert.throws(() => { - sensor.getCameraInfo('dummy'); - }); - }); - }); - - it('Testing method supportsCameraInfo w/ invaild info', () => { - sensors.forEach((sensor) => { - assert.throws(() => { - sensor.supportsCameraInfo('dummy'); - }); - }); - }); - - it('Testing method supportsCameraInfo w/o args ', () => { - sensors.forEach((sensor) => { - assert.throws(() => { - sensor.supportsCameraInfo(); - }); - }); - }); - - it('Testing method getCameraInfo w/o args', () => { - sensors.forEach((sensor) => { - assert.throws(() => { - sensor.getCameraInfo(); - }); - }); - }); -}); diff --git a/wrappers/nodejs/test/test-streamprofile.js b/wrappers/nodejs/test/test-streamprofile.js deleted file mode 100644 index ed9b76cdb2..0000000000 --- a/wrappers/nodejs/test/test-streamprofile.js +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -/* global describe, it, before, after */ -const assert = require('assert'); -let rs2; -try { - rs2 = require('node-librealsense'); -} catch (e) { - rs2 = require('../index.js'); -} - -let ctx; -let pipeline; -let pipelineProfile; -let streamProfiles; - -describe('StreamProfile test', function() { - before(function() { - ctx = new rs2.Context(); - const devices = ctx.queryDevices().devices; - assert(devices.length > 0); // Device must be connected - pipeline = new rs2.Pipeline(ctx); - pipeline.start(); - pipelineProfile = pipeline.getActiveProfile(); - streamProfiles = pipelineProfile.getStreams(); - }); - - after(function() { - pipeline.stop(); - pipeline.destroy(); - rs2.cleanup(); - }); - - it('Testing constructor - 0 option', () => { - assert.throws(() => { - new rs2.StreamProfile(); - }); - }); - - it('Testing member - streamIndex', () => { - streamProfiles.forEach( (stream) => { - assert.equal(typeof stream.streamIndex, 'number'); - }); - }); - - it('Testing member - streamType', () => { - streamProfiles.forEach( (stream) => { - assert.equal(typeof stream.streamType, 'number'); - }); - }); - - it('Testing member - format', () => { - streamProfiles.forEach( (stream) => { - assert.equal(typeof stream.format, 'number'); - }); - }); - - it('Testing member - fps', () => { - streamProfiles.forEach( (stream) => { - assert.equal(typeof stream.fps, 'number'); - }); - }); - - it('Testing member - uniqueID', () => { - streamProfiles.forEach( (stream) => { - assert.equal(typeof stream.uniqueID, 'number'); - }); - }); - - it('Testing member - isDefault', () => { - streamProfiles.forEach( (stream) => { - assert.equal(typeof stream.isDefault, 'boolean'); - }); - }); - - it('Testing method getExtrinsicsTo - 0 argument', () => { - streamProfiles.forEach( (stream) => { - assert.throws(() => { - stream.getExtrinsicsTo(); - }); - }); - }); - - it('Testing method getExtrinsicsTo - valid argument', () => { - let ExtrinsicsObject; - assert.doesNotThrow(() => { - ExtrinsicsObject = streamProfiles[0].getExtrinsicsTo(streamProfiles[1]); - }); - assert.equal(Object.prototype.toString.call(ExtrinsicsObject.rotation), '[object Array]'); - }); - - it('Testing method getExtrinsicsTo - invalid argument', () => { - assert.throws(() => { - streamProfiles[0].getExtrinsicsTo('dummy'); - }); - }); - - it('Testing method streamToString - with stream number', () => { - const streams = [ - 'any', - 'depth', - 'color', - 'infrared', - 'fisheye', - 'gyro', - 'accel', - 'gpio', - 'pose', - 'confidence', - ]; - assert.doesNotThrow(() => { - for (let i = rs2.stream.STREAM_ANY; i < rs2.stream.STREAM_COUNT; i++) { - let res = rs2.stream.streamToString(i); - assert.equal(res, streams[i]); - } - }); - }); - - it('Testing method streamToString - with two arguments', () => { - assert.throws(() => { - rs2.stream.streamToString(1, 1); - }); - }); - - it('Testing method streamToString - without argument', () => { - assert.throws(() => { - rs2.stream.streamToString(); - }); - }); - - it('Testing method streamToString - with stream string', () => { - const streams = [ - 'stream_any', - 'stream_depth', - 'stream_color', - 'stream_infrared', - 'stream_fisheye', - 'stream_gyro', - 'stream_accel', - 'stream_gpio', - 'stream_pose', - 'stream_confidence', - ]; - streams.forEach((s) => { - assert.doesNotThrow(() => { - rs2.stream.streamToString(rs2.stream[s]); - }); - }); - }); -}); diff --git a/wrappers/nodejs/test/test-videoframe.js b/wrappers/nodejs/test/test-videoframe.js deleted file mode 100644 index 5c5756693b..0000000000 --- a/wrappers/nodejs/test/test-videoframe.js +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -/* global describe, it, before, after */ -const assert = require('assert'); -let rs2; -try { - rs2 = require('node-librealsense'); -} catch (e) { - rs2 = require('../index.js'); -} - -let frame; -let pipeline; -describe('VideoFrame test', function() { - before(function() { - pipeline = new rs2.Pipeline(); - pipeline.start(); - while (!frame) { - const frameset = pipeline.waitForFrames(); - frame = frameset.at(1); - } - }); - - after(function() { - pipeline.destroy(); - rs2.cleanup(); - }); - - it('Testing constructor', () => { - assert.doesNotThrow(() => { - new rs2.VideoFrame(); - }); - }); - - it('Testing property isValid', () => { - assert.equal(typeof frame.isValid, 'boolean'); - }); - - it('Testing property data', () => { - assert(Object.prototype.toString.call(frame.data), '[object Uint16Array]' || - Object.prototype.toString.call(frame.data), '[object Uint8Array]' - ); - }); - - it('Testing property width', () => { - assert.equal(typeof frame.width, 'number'); - }); - - it('Testing property height', () => { - assert.equal(typeof frame.height, 'number'); - }); - - it('Testing property frameNumber', () => { - assert.equal(typeof frame.frameNumber, 'number'); - }); - - it('Testing property timestamp', () => { - assert.equal(typeof frame.timestamp, 'number'); - }); - - it('Testing property streamType', () => { - assert.equal(typeof frame.streamType, 'number'); - }); - - it('Testing property dataByteLength', () => { - assert.equal(typeof frame.dataByteLength, 'number'); - }); - - it('Testing property strideInBytes', () => { - assert.equal(typeof frame.strideInBytes, 'number'); - }); - - it('Testing property bitsPerPixel', () => { - assert.equal(typeof frame.bitsPerPixel, 'number'); - }); - - it('Testing property bytesPerPixel', () => { - assert.equal(typeof frame.bytesPerPixel, 'number'); - assert.equal(frame.bytesPerPixel, frame.bitsPerPixel/8); - }); - - it('Testing property timestampDomain', () => { - assert.equal(typeof frame.timestampDomain, 'number'); - }); - - it('Testing method frameMetadata - 0 argument', () => { - assert.throws(() => { - frame.frameMetadata(); - }); - }); - - it('Testing method frameMetadata - invalid argument', () => { - assert.throws(() => { - frame.frameMetadata('dummy'); - }); - }); - - it('Testing method frameMetadata - valid argument', () => { - for (let i in rs2.frame_metadata) { - if (rs2.frame_metadata[i] && - i.toUpperCase() !== 'FRAME_METADATA_COUNT' && // skip counter - i !== 'frameMetadataToString' // skip method - ) { - if (frame.supportsFrameMetadata(rs2.frame_metadata[i])) { - assert.doesNotThrow(() => { // jshint ignore:line - frame.frameMetadata(rs2.frame_metadata[i]); - }); - assert.equal(Object.prototype.toString.call( - frame.frameMetadata(rs2.frame_metadata[i]) - ), '[object Uint8Array]'); - } else { - assert.throws(() => { // jshint ignore:line - frame.frameMetadata(rs2.frame_metadata[i]); - }); - } - } - } - }); - - it('Testing method getData - 0 argument', () => { - assert.doesNotThrow(() => { - frame.getData(); - }); - assert( - Object.prototype.toString.call(frame.getData()), '[object Uint16Array]' || - Object.prototype.toString.call(frame.getData()), '[object Uint8Array]' || - Object.prototype.toString.call(frame.getData()), '[object Buffer]' - ); - }); - - it('Testing method getData - buffer argument', () => { - const len = frame.dataByteLength; - let buf = new ArrayBuffer(len); - assert.doesNotThrow(() => { - frame.getData(buf); - }); - assert( - Object.prototype.toString.call(buf), '[object Uint16Array]' || - Object.prototype.toString.call(buf), '[object Uint8Array]' || - Object.prototype.toString.call(buf), '[object Buffer]' - ); - }); - - it('Testing method getData - 2 argument', () => { - assert.throws(() => { - frame.getData(1, 2); - }); - }); - - it('Testing method getData - invalid argument', () => { - assert.throws(() => { - frame.getData('dummy'); - }); - }); - - it('Testing method supportsFrameMetadata - invalid argument', () => { - assert.throws(() => { - frame.supportsFrameMetadata('dummy'); - }); - }); - - it('Testing method supportsFrameMetadata - valid argument', () => { - for (let i in rs2.frame_metadata) { - if (rs2.frame_metadata[i] && - i.toUpperCase() !== 'FRAME_METADATA_COUNT' && // skip counter - i !== 'frameMetadataToString' // skip method - ) { - assert.doesNotThrow(() => { // jshint ignore:line - frame.supportsFrameMetadata(rs2.frame_metadata[i]); - }); - assert.equal(Object.prototype.toString.call( - frame.supportsFrameMetadata(rs2.frame_metadata[i]) - ), '[object Boolean]'); - } - } - }); - - it('Testing method destroy', () => { - assert.doesNotThrow(() => { - frame.destroy(); - }); - }); -}); diff --git a/wrappers/nodejs/test/test-videostreamprofile.js b/wrappers/nodejs/test/test-videostreamprofile.js deleted file mode 100644 index 1d8b91be24..0000000000 --- a/wrappers/nodejs/test/test-videostreamprofile.js +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -/* global describe, it, before, after */ -const assert = require('assert'); -let rs2; -try { - rs2 = require('node-librealsense'); -} catch (e) { - rs2 = require('../index.js'); -} - -let ctx; -let pipeline; -let pipelineProfile; -let streamProfiles; - -describe('VideoStreamProfile test', function() { - before(function() { - ctx = new rs2.Context(); - const devices = ctx.queryDevices().devices; - assert(devices.length > 0); // Device must be connected - pipeline = new rs2.Pipeline(ctx); - pipeline.start(); - pipelineProfile = pipeline.getActiveProfile(); - streamProfiles = pipelineProfile.getStreams(); - }); - - after(function() { - pipeline.stop(); - pipeline.destroy(); - rs2.cleanup(); - }); - - it('Testing constructor - 0 option', () => { - assert.throws(() => { - new rs2.StreamProfile(); - }); - }); - - it('Testing member - width', () => { - streamProfiles.forEach( (stream) => { - assert.equal(typeof stream.width, 'number'); - }); - }); - - it('Testing member - height', () => { - streamProfiles.forEach( (stream) => { - assert.equal(typeof stream.height, 'number'); - }); - }); - - it('Testing member - streamIndex', () => { - streamProfiles.forEach( (stream) => { - assert.equal(typeof stream.streamIndex, 'number'); - }); - }); - - it('Testing member - streamType', () => { - streamProfiles.forEach( (stream) => { - assert.equal(typeof stream.streamType, 'number'); - }); - }); - - it('Testing member - format', () => { - streamProfiles.forEach( (stream) => { - assert.equal(typeof stream.format, 'number'); - }); - }); - - it('Testing member - fps', () => { - streamProfiles.forEach( (stream) => { - assert.equal(typeof stream.fps, 'number'); - }); - }); - - it('Testing member - uniqueID', () => { - streamProfiles.forEach( (stream) => { - assert.equal(typeof stream.uniqueID, 'number'); - }); - }); - - it('Testing member - isDefault', () => { - streamProfiles.forEach( (stream) => { - assert.equal(typeof stream.isDefault, 'boolean'); - }); - }); - - it('Testing mothod getExtrinsicsTo - 0 argument', () => { - streamProfiles.forEach( (stream) => { - assert.throws(() => { - stream.getExtrinsicsTo(); - }); - }); - }); - - it('Testing method getExtrinsicsTo - valid argument', () => { - let ExtrinsicsObject; - assert.doesNotThrow(() => { - ExtrinsicsObject = streamProfiles[0].getExtrinsicsTo(streamProfiles[1]); - }); - assert.equal(Object.prototype.toString.call(ExtrinsicsObject.rotation), '[object Array]'); - }); - - it('Testing method getExtrinsicsTo - invalid argument', () => { - assert.throws(() => { - streamProfiles[0].getExtrinsicsTo('dummy'); - }); - }); - - it('Testing method getIntrinsics - valid argument', () => { - streamProfiles.forEach((stream) => { - let intrinsics = stream.getIntrinsics(); - assert.equal(typeof intrinsics.width, 'number'); - assert.equal(typeof intrinsics.height, 'number'); - assert.equal(typeof intrinsics.ppx, 'number'); - assert.equal(typeof intrinsics.ppy, 'number'); - assert.equal(typeof intrinsics.fx, 'number'); - assert.equal(typeof intrinsics.fy, 'number'); - assert.equal(typeof intrinsics.model, 'number'); - assert.equal(Object.prototype.toString.call(intrinsics.coeffs), '[object Array]'); - assert.equal(intrinsics.coeffs.length, 5); - }); - }); - - it('Testing method getIntrinsics - invalid argument', () => { - streamProfiles.forEach((stream) => { - assert.doesNotThrow(() => { - stream.getIntrinsics('dummy'); - }); - }); - }); -}); diff --git a/wrappers/nodejs/tools/enums.py b/wrappers/nodejs/tools/enums.py deleted file mode 100644 index 6c488dee02..0000000000 --- a/wrappers/nodejs/tools/enums.py +++ /dev/null @@ -1,75 +0,0 @@ -# -*- coding: utf-8 -*- -import re -import os -import sys -import argparse - - -ENUM_H_REGEXP = r'^[ ]*(RS2_\w+)' -ENUM_CPP_REGEXP = r'^[ ]*_FORCE_SET_ENUM\((\w+)\)' -ENUM_JS_REGEXP = r'RS2\.(RS2_\w+)' - - -def files_gen(path, ends): - for root, dirs, files in os.walk(path): - for file in files: - if file.endswith(ends): - yield os.path.join(root, file) - - -def get_first_by_regexp(line, regexp): - res = re.findall(regexp, line) - if res: - return res[0] - return '' - - -def get_enums_from_folder(folder_path, ends, regexp): - file_paths = files_gen(folder_path, ends) - enums = [] - for file_path in file_paths: - enums += get_enums_from_file(file_path, regexp) - return enums - - -def get_enums_from_file(file_path, regexp): - enums = [] - with open(file_path) as f: - for line in f: - enum = get_first_by_regexp(line, regexp) - if enum: - enums.append(enum) - - return enums - - -def run(include_folder_path, addon_folder_path): - - include_enums = get_enums_from_folder(include_folder_path, '.h', ENUM_H_REGEXP) - cpp_enums = get_enums_from_folder(addon_folder_path, '.cpp', ENUM_CPP_REGEXP) - # js_enums = get_enums_from_file(js_file_path, ENUM_JS_REGEXP) - - include_enums.sort() - cpp_enums.sort() - # js_enums.sort() - - # print(len(include_enums), len(cpp_enums), len(js_enums)) - return list(set(include_enums) - set(cpp_enums)) - - -if __name__ == '__main__': - parser = argparse.ArgumentParser(description='Ping script') - parser.add_argument('-i', action='store', dest='include_folder_path', required=True) - parser.add_argument('-a', action='store', dest='addon_folder_path', required=True) - parser.add_argument('-v', '--verbose', action='store_true', help='print missing enums') - - args = parser.parse_args() - - missed = run(args.include_folder_path, args.addon_folder_path) - - if missed: - missed.sort() - message = "[ERROR] Node.js wrapper has missing enum values: %s" % (', '.join(missed)) - sys.exit(message if args.verbose else 1) - - sys.exit() diff --git a/wrappers/nodejs/tools/linter.js b/wrappers/nodejs/tools/linter.js deleted file mode 100755 index bd296f148b..0000000000 --- a/wrappers/nodejs/tools/linter.js +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env node - -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -'use strict'; - -const os = require('os'); -const path = require('path'); -const recursive = require('recursive-readdir'); -const spawn = require('child_process').spawnSync; -const which = require('which'); - -let errors = []; - -function doCppLint(files) { - if (!files) return; - - let cpplint = (os.platform() == 'win32') ? which.sync('cpplint', {pathExt: '.EXE;.PY'}) - : which.sync('cpplint.py'); - if (!cpplint) { - console.log('You need install depot_tools, and add to PATH.' + - ' https://dev.chromium.org/developers/how-tos/install-depot-tools'); - process.exit(1); - } - - let cmdOptions = [cpplint]; - cmdOptions = cmdOptions.concat(files); - // cpplint report result in stderr, $? is always 0 whatever there are errors or not. - // So we need check the last line as "Total errors found: 0" - let output = spawn('python', cmdOptions).stderr.toString().split(os.EOL); - if (output[output.length - 2] != 'Total errors found: 0') { - errors = errors.concat(output); - } -} - -function doJsLint(files) { - if (!files) return; - - let jsLinterDir = path.join(__dirname, 'node_modules', '.bin'); - - for (let linter of ['eslint', 'jshint']) { - let output = null; - if (os.platform() == 'win32') { - output = spawn(path.join(jsLinterDir, linter + '.cmd'), files).stdout.toString(); - } else { - output = spawn('node', [path.join(jsLinterDir, linter)].concat(files)).stdout.toString(); - } - if (output) { - let lines = output.split('\n'); - if (lines.length > 0) errors = errors.concat(lines); - } - } -} - -recursive(path.dirname(__dirname), - // ignore files - ['node_modules', 'prettify'], - function(err, files) { - let cppFiles = []; - let jsFiles = []; - for (let f of files) { - if (path.extname(f) == '.js') { - jsFiles.push(f); - } else if (path.extname(f) == '.cpp') { - cppFiles.push(f); - } - } - - doCppLint(cppFiles); - doJsLint(jsFiles); - - if (errors.length >= 1) { - for (let l of errors) console.log(l); - process.exit(1); - } -}); diff --git a/wrappers/nodejs/tools/package-lock.json b/wrappers/nodejs/tools/package-lock.json deleted file mode 100644 index 231784b18e..0000000000 --- a/wrappers/nodejs/tools/package-lock.json +++ /dev/null @@ -1,1219 +0,0 @@ -{ - "name": "node-librealsense-tools", - "version": "0.0.1", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "acorn": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.1.2.tgz", - "integrity": "sha512-o96FZLJBPY1lvTuJylGA9Bk3t/GKPPJG8H0ydQQl01crzwJgspa4AEIq/pVTXigmK0PHVQhiAtn8WMBLL9D2WA==" - }, - "acorn-jsx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", - "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", - "requires": { - "acorn": "3.3.0" - }, - "dependencies": { - "acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=" - } - } - }, - "ajv": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.2.2.tgz", - "integrity": "sha1-R8aNaehvXZUxA7AHSpQw3GPaXjk=", - "requires": { - "co": "4.6.0", - "fast-deep-equal": "1.0.0", - "json-schema-traverse": "0.3.1", - "json-stable-stringify": "1.0.1" - } - }, - "ajv-keywords": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", - "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=" - }, - "ansi-escapes": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-2.0.0.tgz", - "integrity": "sha1-W65SvkJIeN2Xg+iRDj/Cki6DyBs=" - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" - }, - "argparse": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", - "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", - "requires": { - "sprintf-js": "1.0.3" - } - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "requires": { - "array-uniq": "1.0.3" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "requires": { - "chalk": "1.1.3", - "esutils": "2.0.2", - "js-tokens": "3.0.2" - }, - "dependencies": { - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "2.1.1" - } - } - } - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "brace-expansion": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - } - }, - "caller-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", - "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "requires": { - "callsites": "0.2.0" - } - }, - "callsites": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", - "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=" - }, - "chalk": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", - "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==", - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.4.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "requires": { - "color-convert": "1.9.0" - } - }, - "supports-color": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", - "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", - "requires": { - "has-flag": "2.0.0" - } - } - } - }, - "circular-json": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==" - }, - "cli": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", - "integrity": "sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ=", - "requires": { - "exit": "0.1.2", - "glob": "7.1.2" - } - }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "requires": { - "restore-cursor": "2.0.0" - } - }, - "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" - }, - "color-convert": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.0.tgz", - "integrity": "sha1-Gsz5fdc5uYO/mU1W/sj5WFNkG3o=", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "concat-stream": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", - "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.3", - "typedarray": "0.0.6" - } - }, - "console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "requires": { - "date-now": "0.1.4" - } - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "requires": { - "lru-cache": "4.1.1", - "shebang-command": "1.2.0", - "which": "1.3.0" - } - }, - "date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=" - }, - "debug": { - "version": "2.6.8", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", - "requires": { - "ms": "2.0.0" - } - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" - }, - "del": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", - "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", - "requires": { - "globby": "5.0.0", - "is-path-cwd": "1.0.0", - "is-path-in-cwd": "1.0.0", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "rimraf": "2.6.1" - } - }, - "doctrine": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.0.tgz", - "integrity": "sha1-xz2NKQnSIpHhoAejlYBNqLZl/mM=", - "requires": { - "esutils": "2.0.2", - "isarray": "1.0.0" - } - }, - "dom-serializer": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", - "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", - "requires": { - "domelementtype": "1.1.3", - "entities": "1.1.1" - }, - "dependencies": { - "domelementtype": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", - "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=" - }, - "entities": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", - "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=" - } - } - }, - "domelementtype": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", - "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=" - }, - "domhandler": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", - "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", - "requires": { - "domelementtype": "1.3.0" - } - }, - "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "requires": { - "dom-serializer": "0.1.0", - "domelementtype": "1.3.0" - } - }, - "entities": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", - "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=" - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" - }, - "eslint": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.6.1.tgz", - "integrity": "sha1-3cf8f9cL+TIFsLNEm7FqHp59SVA=", - "requires": { - "ajv": "5.2.2", - "babel-code-frame": "6.26.0", - "chalk": "2.1.0", - "concat-stream": "1.6.0", - "cross-spawn": "5.1.0", - "debug": "2.6.8", - "doctrine": "2.0.0", - "eslint-scope": "3.7.1", - "espree": "3.5.0", - "esquery": "1.0.0", - "estraverse": "4.2.0", - "esutils": "2.0.2", - "file-entry-cache": "2.0.0", - "functional-red-black-tree": "1.0.1", - "glob": "7.1.2", - "globals": "9.18.0", - "ignore": "3.3.5", - "imurmurhash": "0.1.4", - "inquirer": "3.2.3", - "is-resolvable": "1.0.0", - "js-yaml": "3.9.1", - "json-stable-stringify": "1.0.1", - "levn": "0.3.0", - "lodash": "4.17.4", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "natural-compare": "1.4.0", - "optionator": "0.8.2", - "path-is-inside": "1.0.2", - "pluralize": "4.0.0", - "progress": "2.0.0", - "require-uncached": "1.0.3", - "semver": "5.4.1", - "strip-ansi": "4.0.0", - "strip-json-comments": "2.0.1", - "table": "4.0.1", - "text-table": "0.2.0" - } - }, - "eslint-config-google": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/eslint-config-google/-/eslint-config-google-0.9.1.tgz", - "integrity": "sha512-5A83D+lH0PA81QMESKbLJd/a3ic8tPZtwUmqNrxMRo54nfFaUvtt89q/+icQ+fd66c2xQHn0KyFkzJDoAUfpZA==" - }, - "eslint-config-standard": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz", - "integrity": "sha1-wGHk0GbzedwXzVYsZOgZtN1FRZE=" - }, - "eslint-plugin-header": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-header/-/eslint-plugin-header-1.1.0.tgz", - "integrity": "sha1-Buwt244dUbB5MqTAVX48SamTodQ=" - }, - "eslint-plugin-promise": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.5.0.tgz", - "integrity": "sha1-ePu2/+BHIBYnVp6FpsU3OvKmj8o=" - }, - "eslint-plugin-standard": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz", - "integrity": "sha1-NNDJFbRe3G8BA5PH7vOCOwhWXPI=" - }, - "eslint-scope": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", - "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", - "requires": { - "esrecurse": "4.2.0", - "estraverse": "4.2.0" - } - }, - "espree": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.0.tgz", - "integrity": "sha1-mDWGJb3QVYYeon4oZ+pyn69GPY0=", - "requires": { - "acorn": "5.1.2", - "acorn-jsx": "3.0.1" - } - }, - "esprima": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" - }, - "esquery": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", - "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", - "requires": { - "estraverse": "4.2.0" - } - }, - "esrecurse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", - "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", - "requires": { - "estraverse": "4.2.0", - "object-assign": "4.1.1" - } - }, - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" - }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" - }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=" - }, - "external-editor": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.0.4.tgz", - "integrity": "sha1-HtkZnanL/i7y96MbL96LDRI2iXI=", - "requires": { - "iconv-lite": "0.4.18", - "jschardet": "1.5.1", - "tmp": "0.0.31" - } - }, - "fast-deep-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", - "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=" - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" - }, - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "requires": { - "escape-string-regexp": "1.0.5" - } - }, - "file-entry-cache": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", - "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", - "requires": { - "flat-cache": "1.2.2", - "object-assign": "4.1.1" - } - }, - "flat-cache": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.2.2.tgz", - "integrity": "sha1-+oZxTnLCHbiGAXYezy9VXRq8a5Y=", - "requires": { - "circular-json": "0.3.3", - "del": "2.2.2", - "graceful-fs": "4.1.11", - "write": "0.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==" - }, - "globby": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", - "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", - "requires": { - "array-union": "1.0.2", - "arrify": "1.0.1", - "glob": "7.1.2", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "requires": { - "ansi-regex": "2.1.1" - } - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" - }, - "htmlparser2": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", - "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", - "requires": { - "domelementtype": "1.3.0", - "domhandler": "2.3.0", - "domutils": "1.5.1", - "entities": "1.0.0", - "readable-stream": "1.1.14" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - } - } - }, - "iconv-lite": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz", - "integrity": "sha512-sr1ZQph3UwHTR0XftSbK85OvBbxe/abLGzEnPENCQwmHf7sck8Oyu4ob3LgBxWWxRoM+QszeUyl7jbqapu2TqA==" - }, - "ignore": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.5.tgz", - "integrity": "sha512-JLH93mL8amZQhh/p6mfQgVBH3M6epNq3DfsXsTSuSrInVjwyYlFE1nv2AgfRCC8PoOhM0jwQ5v8s9LgbK7yGDw==" - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "inquirer": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.2.3.tgz", - "integrity": "sha512-Bc3KbimpDTOeQdDj18Ir/rlsGuhBSSNqdOnxaAuKhpkdnMMuKsEGbZD2v5KFF9oso2OU+BPh7+/u5obmFDRmWw==", - "requires": { - "ansi-escapes": "2.0.0", - "chalk": "2.1.0", - "cli-cursor": "2.1.0", - "cli-width": "2.2.0", - "external-editor": "2.0.4", - "figures": "2.0.0", - "lodash": "4.17.4", - "mute-stream": "0.0.7", - "run-async": "2.3.0", - "rx-lite": "4.0.8", - "rx-lite-aggregates": "4.0.8", - "string-width": "2.1.1", - "strip-ansi": "4.0.0", - "through": "2.3.8" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, - "is-path-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=" - }, - "is-path-in-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", - "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", - "requires": { - "is-path-inside": "1.0.0" - } - }, - "is-path-inside": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", - "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", - "requires": { - "path-is-inside": "1.0.2" - } - }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" - }, - "is-resolvable": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz", - "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=", - "requires": { - "tryit": "1.0.3" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" - }, - "js-yaml": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.9.1.tgz", - "integrity": "sha512-CbcG379L1e+mWBnLvHWWeLs8GyV/EMw862uLI3c+GxVyDHWZcjZinwuBd3iW2pgxgIlksW/1vNJa4to+RvDOww==", - "requires": { - "argparse": "1.0.9", - "esprima": "4.0.0" - } - }, - "jschardet": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-1.5.1.tgz", - "integrity": "sha512-vE2hT1D0HLZCLLclfBSfkfTTedhVj0fubHpJBHKwwUWX0nSbhPAfk+SG9rTX95BYNmau8rGFfCeaT6T5OW1C2A==" - }, - "jshint": { - "version": "2.9.5", - "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.9.5.tgz", - "integrity": "sha1-HnJSkVzmgbQIJ+4UJIxG006apiw=", - "requires": { - "cli": "1.0.1", - "console-browserify": "1.1.0", - "exit": "0.1.2", - "htmlparser2": "3.8.3", - "lodash": "3.7.0", - "minimatch": "3.0.4", - "shelljs": "0.3.0", - "strip-json-comments": "1.0.4" - }, - "dependencies": { - "lodash": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.7.0.tgz", - "integrity": "sha1-Nni9irmVBXwHreg27S7wh9qBHUU=" - }, - "strip-json-comments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", - "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=" - } - } - }, - "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" - }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "requires": { - "jsonify": "0.0.0" - } - }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "requires": { - "prelude-ls": "1.1.2", - "type-check": "0.3.2" - } - }, - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" - }, - "lru-cache": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", - "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", - "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" - } - }, - "mimic-fn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", - "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=" - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "1.1.8" - } - }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1.0.2" - } - }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "requires": { - "mimic-fn": "1.1.0" - } - }, - "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "requires": { - "deep-is": "0.1.3", - "fast-levenshtein": "2.0.6", - "levn": "0.3.0", - "prelude-ls": "1.1.2", - "type-check": "0.3.2", - "wordwrap": "1.0.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "requires": { - "pinkie": "2.0.4" - } - }, - "pluralize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-4.0.0.tgz", - "integrity": "sha1-WbcIwcAZCi9pLxx2GMRGsFL9F2I=" - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" - }, - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" - }, - "progress": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", - "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=" - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "recursive-readdir": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.1.tgz", - "integrity": "sha1-kO8jHQd4xc4JPJpI105cVCLROpk=", - "requires": { - "minimatch": "3.0.3" - }, - "dependencies": { - "minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=", - "requires": { - "brace-expansion": "1.1.8" - } - } - } - }, - "require-uncached": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", - "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", - "requires": { - "caller-path": "0.1.0", - "resolve-from": "1.0.1" - } - }, - "resolve-from": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=" - }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "requires": { - "onetime": "2.0.1", - "signal-exit": "3.0.2" - } - }, - "rimraf": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", - "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", - "requires": { - "glob": "7.1.2" - } - }, - "run-async": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "requires": { - "is-promise": "2.1.0" - } - }, - "rx-lite": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", - "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=" - }, - "rx-lite-aggregates": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", - "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", - "requires": { - "rx-lite": "4.0.8" - } - }, - "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" - }, - "semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "requires": { - "shebang-regex": "1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" - }, - "shelljs": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz", - "integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E=" - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" - }, - "slice-ansi": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", - "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=" - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "requires": { - "safe-buffer": "5.1.1" - } - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "3.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - } - } - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" - }, - "table": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/table/-/table-4.0.1.tgz", - "integrity": "sha1-qBFsEz+sLGH0pCCrbN9cTWHw5DU=", - "requires": { - "ajv": "4.11.8", - "ajv-keywords": "1.5.1", - "chalk": "1.1.3", - "lodash": "4.17.4", - "slice-ansi": "0.0.4", - "string-width": "2.1.1" - }, - "dependencies": { - "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", - "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" - } - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "2.1.1" - } - } - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "tmp": { - "version": "0.0.31", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz", - "integrity": "sha1-jzirlDjhcxXl29izZX6L+yd65Kc=", - "requires": { - "os-tmpdir": "1.0.2" - } - }, - "tryit": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", - "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=" - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "requires": { - "prelude-ls": "1.1.2" - } - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "which": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", - "requires": { - "isexe": "2.0.0" - } - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "write": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", - "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", - "requires": { - "mkdirp": "0.5.1" - } - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" - } - } -} diff --git a/wrappers/nodejs/tools/package.json b/wrappers/nodejs/tools/package.json deleted file mode 100644 index f39d88b859..0000000000 --- a/wrappers/nodejs/tools/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "node-librealsense-tools", - "version": "0.0.1", - "description": "Tools dir under librealsense/wrappers/nodejs", - "main": "index.js", - "scripts": { - "linter": "./linter.js && exit 1" - }, - "author": "Halton Huo ", - "license": "Apache 2.0", - "dependencies": { - "eslint": "4.6.1", - "eslint-config-google": "^0.9.1", - "eslint-config-standard": "^10.2.1", - "eslint-plugin-header": "^1.1.0", - "eslint-plugin-promise": "^3.5.0", - "eslint-plugin-standard": "^3.0.1", - "jshint": "^2.9.5", - "recursive-readdir": "^2.2.1", - "which": "^1.3.0" - } -}

    )CdQ3F!eKyF|9D2V!F-rhUpJ8J+l7g0OBBVM#THTI&O8)>EGR%u6Gd9D9pm5!S}%&6DxW}^f|7=Y zPoO3(pTZY#?(7(|!5}5Nn!D%DotZmlW)?smSMcEE<^aT$6gw#LlwubPI9BYTffL0! zyu-EPCnz{Y#ZR&1d{F!hr_NW!&#~mXis$jseXDo@U)-kR7sMBeUt-T&RQw9By@BF9 z3f?cpmw4m-R{RHncaC**(V--ipJ<~6LkW2fi6RVfh%vcYt9@z>&M0LBSf-Q|Et8wU zCt43_*JB)mHR71wb`K@~5Cizwp{`A2uuJ^_Bcl3k{7ree$8&@l?;^2nagS+NqCDBfkB?pJws=PbK~+A7|2 z{gCDJKI-i%m4LD$n{WIwWR|c+NRy`C1#)1sSBI7FiH6z-QkhY&Q_|%I3exQ zQ`X1M?cZH4^M&BSyr;2z$+^SZUMA*0001Z+HKHROw(}?!13=vX`$@Br+fGR zZ%e`5O6%Txi$Yrz0gF{}p>fY>OnlS0Uevf}oDXW;D{d2gcE<2)oFcV80@g$H)63L{HN*d{8kVzKVW(;E)$9N_%kx5Ku3R9WJbY?JW^G#k0Wdx>E$NBBVtKRLiL?sA*s%w`TdsNz1=+~FRNdB8&+@iBD0 zXFTC4C-8-Cwv(4U=LLQ~^Oa4^rG|OTr5?ItoaPMYxxh`%a*kVU z;HYGAjq6;IY{`*awo0DlOMw(hkrYdb(O28l;MYvSx*ChcQW4f^QL5UdE3HbqvbxB$pfSg`>Cj#;?~00;nMAg}==M6d%RaIhCe zARtS)01i=0um)3FSgr#ump{<1pq_<0a34Kp8x=7I1^|9 diff --git a/wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-Regular-webfont.eot b/wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-Regular-webfont.eot deleted file mode 100644 index 6bbc3cf58cb011a6b4bf3cb1612ce212608f7274..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19836 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-Regular-webfont.woff b/wrappers/nodejs/doc/jsdoc-template/static/fonts/OpenSans-Regular-webfont.woff deleted file mode 100644 index e231183dce4c7b452afc9e7799586fd285e146f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22660 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 ML;wL%uV=LY00kR;TmS$7 diff --git a/wrappers/nodejs/doc/jsdoc-template/static/scripts/linenumber.js b/wrappers/nodejs/doc/jsdoc-template/static/scripts/linenumber.js deleted file mode 100644 index f625b0815e..0000000000 --- a/wrappers/nodejs/doc/jsdoc-template/static/scripts/linenumber.js +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2017 Intel Corporation. All rights reserved. -// Use of this source code is governed by an Apache 2.0 license -// that can be found in the LICENSE file. - -/* global document */ -(function() { - let source = document.getElementsByClassName('prettyprint source linenums'); - let i = 0; - let lineNumber = 0; - let lineId; - let lines; - let totalLines; - let anchorHash; - - if (source && source[0]) { - anchorHash = document.location.hash.substring(1); - lines = source[0].getElementsByTagName('li'); - totalLines = lines.length; - - for (; i < totalLines; i++) { - lineNumber++; - lineId = 'line' + lineNumber; - lines[i].id = lineId; - if (lineId === anchorHash) { - lines[i].className += ' selected'; - } - } - } -})(); diff --git a/wrappers/nodejs/doc/jsdoc-template/static/scripts/prettify/lang-css.js b/wrappers/nodejs/doc/jsdoc-template/static/scripts/prettify/lang-css.js deleted file mode 100644 index 041e1f5906..0000000000 --- a/wrappers/nodejs/doc/jsdoc-template/static/scripts/prettify/lang-css.js +++ /dev/null @@ -1,2 +0,0 @@ -PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com", -/^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]); diff --git a/wrappers/nodejs/doc/jsdoc-template/static/scripts/prettify/prettify.js b/wrappers/nodejs/doc/jsdoc-template/static/scripts/prettify/prettify.js deleted file mode 100644 index eef5ad7e6a..0000000000 --- a/wrappers/nodejs/doc/jsdoc-template/static/scripts/prettify/prettify.js +++ /dev/null @@ -1,28 +0,0 @@ -var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; -(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a= -[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;ci[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m), -l=[],p={},d=0,g=e.length;d=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, -q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/, -q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g, -"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a), -a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e} -for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], -"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"], -H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], -J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+ -I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]), -["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css", -/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}), -["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes", -hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p=0){var k=k.match(g),f,b;if(b= -!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p th:last-child { border-right: 1px solid #ddd; } - -.ancestors, .attribs { color: #999; } -.ancestors a, .attribs a -{ - color: #999 !important; - text-decoration: none; -} - -.clear -{ - clear: both; -} - -.important -{ - font-weight: bold; - color: #950B02; -} - -.yes-def { - text-indent: -1000px; -} - -.type-signature { - color: #aaa; -} - -.name, .signature { - font-family: Consolas, Monaco, 'Andale Mono', monospace; -} - -.name { - background-color: #FFFFD3; -} - -.details { margin-top: 14px; border-left: 2px solid #DDD; } -.details dt { width: 120px; float: left; padding-left: 10px; padding-top: 6px; } -.details dd { margin-left: 70px; } -.details ul { margin: 0; } -.details ul { list-style-type: none; } -.details li { margin-left: 30px; padding-top: 6px; } -.details pre.prettyprint { margin: 0 } -.details .object-value { padding-top: 0; } - -.description { - margin-bottom: 1em; - margin-top: 1em; -} - -.code-caption -{ - font-style: italic; - font-size: 107%; - margin: 0; -} - -.prettyprint -{ - border: 1px solid #ddd; - width: 80%; - overflow: auto; -} - -.prettyprint.source { - width: inherit; -} - -.prettyprint code -{ - font-size: 100%; - line-height: 18px; - display: block; - padding: 4px 12px; - margin: 0; - background-color: #fff; - color: #4D4E53; -} - -.prettyprint code span.line -{ - display: inline-block; -} - -.prettyprint.linenums -{ - padding-left: 70px; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -.prettyprint.linenums ol -{ - padding-left: 0; -} - -.prettyprint.linenums li -{ - border-left: 3px #ddd solid; -} - -.prettyprint.linenums li.selected, -.prettyprint.linenums li.selected * -{ - background-color: lightyellow; -} - -.prettyprint.linenums li * -{ - -webkit-user-select: text; - -moz-user-select: text; - -ms-user-select: text; - user-select: text; -} - -.params .name, .props .name, .name code { - color: #4D4E53; - font-family: Consolas, Monaco, 'Andale Mono', monospace; - font-size: 100%; -} - -.params td.description > p:first-child, -.props td.description > p:first-child -{ - margin-top: 0; - padding-top: 0; -} - -.params td.description > p:last-child, -.props td.description > p:last-child -{ - margin-bottom: 0; - padding-bottom: 0; -} - -.disabled { - color: #454545; -} diff --git a/wrappers/nodejs/doc/jsdoc-template/static/styles/prettify-jsdoc.css b/wrappers/nodejs/doc/jsdoc-template/static/styles/prettify-jsdoc.css deleted file mode 100644 index 5a2526e374..0000000000 --- a/wrappers/nodejs/doc/jsdoc-template/static/styles/prettify-jsdoc.css +++ /dev/null @@ -1,111 +0,0 @@ -/* JSDoc prettify.js theme */ - -/* plain text */ -.pln { - color: #000000; - font-weight: normal; - font-style: normal; -} - -/* string content */ -.str { - color: #006400; - font-weight: normal; - font-style: normal; -} - -/* a keyword */ -.kwd { - color: #000000; - font-weight: bold; - font-style: normal; -} - -/* a comment */ -.com { - font-weight: normal; - font-style: italic; -} - -/* a type name */ -.typ { - color: #000000; - font-weight: normal; - font-style: normal; -} - -/* a literal value */ -.lit { - color: #006400; - font-weight: normal; - font-style: normal; -} - -/* punctuation */ -.pun { - color: #000000; - font-weight: bold; - font-style: normal; -} - -/* lisp open bracket */ -.opn { - color: #000000; - font-weight: bold; - font-style: normal; -} - -/* lisp close bracket */ -.clo { - color: #000000; - font-weight: bold; - font-style: normal; -} - -/* a markup tag name */ -.tag { - color: #006400; - font-weight: normal; - font-style: normal; -} - -/* a markup attribute name */ -.atn { - color: #006400; - font-weight: normal; - font-style: normal; -} - -/* a markup attribute value */ -.atv { - color: #006400; - font-weight: normal; - font-style: normal; -} - -/* a declaration */ -.dec { - color: #000000; - font-weight: bold; - font-style: normal; -} - -/* a variable name */ -.var { - color: #000000; - font-weight: normal; - font-style: normal; -} - -/* a function name */ -.fun { - color: #000000; - font-weight: bold; - font-style: normal; -} - -/* Specify class=linenums on a pre to get line numbering */ -ol.linenums { - margin-top: 0; - margin-bottom: 0; -} diff --git a/wrappers/nodejs/doc/jsdoc-template/static/styles/prettify-tomorrow.css b/wrappers/nodejs/doc/jsdoc-template/static/styles/prettify-tomorrow.css deleted file mode 100644 index b6f92a78db..0000000000 --- a/wrappers/nodejs/doc/jsdoc-template/static/styles/prettify-tomorrow.css +++ /dev/null @@ -1,132 +0,0 @@ -/* Tomorrow Theme */ -/* Original theme - https://github.com/chriskempson/tomorrow-theme */ -/* Pretty printing styles. Used with prettify.js. */ -/* SPAN elements with the classes below are added by prettyprint. */ -/* plain text */ -.pln { - color: #4d4d4c; } - -@media screen { - /* string content */ - .str { - color: #718c00; } - - /* a keyword */ - .kwd { - color: #8959a8; } - - /* a comment */ - .com { - color: #8e908c; } - - /* a type name */ - .typ { - color: #4271ae; } - - /* a literal value */ - .lit { - color: #f5871f; } - - /* punctuation */ - .pun { - color: #4d4d4c; } - - /* lisp open bracket */ - .opn { - color: #4d4d4c; } - - /* lisp close bracket */ - .clo { - color: #4d4d4c; } - - /* a markup tag name */ - .tag { - color: #c82829; } - - /* a markup attribute name */ - .atn { - color: #f5871f; } - - /* a markup attribute value */ - .atv { - color: #3e999f; } - - /* a declaration */ - .dec { - color: #f5871f; } - - /* a variable name */ - .var { - color: #c82829; } - - /* a function name */ - .fun { - color: #4271ae; } } -/* Use higher contrast and text-weight for printable form. */ -@media print, projection { - .str { - color: #060; } - - .kwd { - color: #006; - font-weight: bold; } - - .com { - color: #600; - font-style: italic; } - - .typ { - color: #404; - font-weight: bold; } - - .lit { - color: #044; } - - .pun, .opn, .clo { - color: #440; } - - .tag { - color: #006; - font-weight: bold; } - - .atn { - color: #404; } - - .atv { - color: #060; } } -/* Style */ -/* -pre.prettyprint { - background: white; - font-family: Consolas, Monaco, 'Andale Mono', monospace; - font-size: 12px; - line-height: 1.5; - border: 1px solid #ccc; - padding: 10px; } -*/ - -/* Specify class=linenums on a pre to get line numbering */ -ol.linenums { - margin-top: 0; - margin-bottom: 0; } - -/* IE indents via margin-left */ -li.L0, -li.L1, -li.L2, -li.L3, -li.L4, -li.L5, -li.L6, -li.L7, -li.L8, -li.L9 { - /* */ } - -/* Alternate shading for lines */ -li.L1, -li.L3, -li.L5, -li.L7, -li.L9 { - /* */ } diff --git a/wrappers/nodejs/doc/jsdoc-template/tmpl/augments.tmpl b/wrappers/nodejs/doc/jsdoc-template/tmpl/augments.tmpl deleted file mode 100644 index 446d28aa53..0000000000 --- a/wrappers/nodejs/doc/jsdoc-template/tmpl/augments.tmpl +++ /dev/null @@ -1,10 +0,0 @@ - - - -