Compare commits
154 Commits
Author | SHA1 | Date |
---|---|---|
dsc | 330edacab9 | |
dsc | ec6474a840 | |
dsc | 69e1749856 | |
dsc | e93488af9b | |
dsc | a8861c62ea | |
dsc | e6651d55ff | |
dsc | 9c58913ee2 | |
dsc | 24ff2b7120 | |
dsc | 7c4f99c85d | |
wowario | 7cc5fd880e | |
wowario | ed9edb5ad6 | |
dsc | c0323ee329 | |
dsc | 40493475ba | |
dsc | 4098e8c0e5 | |
dsc | ca234008b9 | |
dsc | 2ebb41a371 | |
dsc | 6cf4299f78 | |
dsc | df0459da69 | |
dsc | 46accb1077 | |
dsc | 7a91ba5a84 | |
dsc | f83ceb2a96 | |
dsc | d332121d7c | |
dsc | d151b47895 | |
dsc | caa8731410 | |
dsc | dc3ee66e3b | |
dsc | 289f9ab1d2 | |
dsc | 73747e05a7 | |
dsc | 3051ce5118 | |
dsc | fb32fa2fd2 | |
dsc | b3eab6085f | |
dsc | 835aecb79d | |
dsc | 6cba5d0487 | |
dsc | 50b78cee51 | |
dsc | 1b6f648a0b | |
dsc | 6b2f8f847e | |
dsc | 917f8b5812 | |
dsc | a62fb95fbf | |
dsc | c3b0d00a72 | |
dsc | d6dfd678b8 | |
dsc | 8b215c1e73 | |
dsc | 96295a52de | |
dsc | ccd0e8e64b | |
dsc | 3b3ec89306 | |
dsc | 373fe8e02a | |
dsc | 14d9793193 | |
dsc | 65ceab6323 | |
bruh | 6b2118ecf6 | |
dsc | ca78025735 | |
leonardgit6 | c5eb13145f | |
leonardgit6 | 946443bf8c | |
dsc | ae33c2f1b0 | |
dsc | c97c0d597b | |
dsc | ee3713b16b | |
dsc | ae39e71061 | |
dsc | 7e5cac9fa3 | |
dsc | b61b2b1630 | |
wowario | 1b1d1db14d | |
dsc | 81ec0183ea | |
wowario | f5046cea54 | |
dsc | 624f13b2d9 | |
wowario | 0d502f0e45 | |
dsc | 6549ca4e1d | |
dsc | 37578dde7b | |
wowario | 225ae1233e | |
wowario | d8cb29c4d4 | |
wowario | 502785f233 | |
wowario | e3cf87906b | |
wowario | 5c3821007d | |
dsc | c02e084dcf | |
dsc | 85d4e0ac6d | |
dsc | fbca9c9340 | |
dsc | d9d0ac1830 | |
wowario | 3adb2a6fe7 | |
wowario | 742ad82b88 | |
dsc | a1ce8f866a | |
wowario | 24e8942ac5 | |
dsc | 3163d68e9e | |
dsc | a6e1a6877f | |
wowario | ac1ed1873a | |
dsc | 2ccefe0883 | |
wowario | 06f09e1f2e | |
dsc | c3e9fbb25a | |
wowario | 096b28318c | |
wowario | 562d071c62 | |
dsc | 474d4b1994 | |
dsc | 49b55768f7 | |
dsc | 640a4d72e0 | |
dsc | 0e37f97aa2 | |
dsc | 499ad4a3aa | |
dsc | 8b5bdc4c6a | |
dsc | cfee938516 | |
dsc | c024323eab | |
dsc | a2ad4692a3 | |
dsc | c50a341527 | |
dsc | a68ebf3564 | |
dsc | 98b1982157 | |
wowario | c86228a404 | |
wowario | a389589fbb | |
wowario | 392e9b99cf | |
wowario | 51c7422f6e | |
dsc | 7c8d070ab5 | |
dsc | aa89690788 | |
dsc | c82cad87fa | |
dsc | a5f3b915e5 | |
dsc | 395cbcd9db | |
dsc | ee247cba8a | |
dsc | bcc0aeeaa9 | |
dsc | de5bea9cdf | |
dsc | d846790905 | |
dsc | 13331ee5e7 | |
dsc | 5bb95053fb | |
dsc | bd38e5e1d8 | |
dsc | 8b1250030b | |
dsc | c0cb90bf79 | |
dsc | c3723ac58a | |
dsc | aad58b1c83 | |
dsc | 96034902d1 | |
dsc | e918955210 | |
wowario | 5f746999c2 | |
wowario | 1c51407109 | |
wowario | 5f402464ad | |
wowario | 7a14d53ba0 | |
wowario | ca72462125 | |
wowario | 11048f96fa | |
wowario | 144c19fab1 | |
wowario | 32bb391c2e | |
wowario | d23ffd1972 | |
wowario | 9a75c5a986 | |
wowario | 82ac1c2daf | |
wowario | 6a256bb1a0 | |
wowario | fafc8e4d7d | |
wowario | fdc7e348f0 | |
wowario | 2bdef17e18 | |
wowario | 718741b036 | |
wowario | 8dc0a5bfaf | |
wowario | 6b0ea884cb | |
wowario | a488a24514 | |
wowario | fb3fc3bd8d | |
dsc | 8968a8cbce | |
wowario | a7d2c67e67 | |
wowario | 40a575a5d6 | |
wowario | f5b23c2e7e | |
wowario | 7993442a34 | |
wowario | 8f4acf3b60 | |
wowario | c59627b661 | |
wowario | 705426d489 | |
wowario | 81ad7bdb46 | |
wowario | f110cad24b | |
wowario | f989d2ae83 | |
wowario | 686b37e630 | |
wowario | 1265307bd0 | |
wowario | 955167d37f | |
wowario | 1f83c35103 | |
wowario | a517fedd96 |
10
.drone.yml
|
@ -26,9 +26,9 @@ volumes:
|
|||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: windows-build
|
||||
name: windows-deploy
|
||||
steps:
|
||||
- name: windows-build
|
||||
- name: windows-deploy
|
||||
image: wowlet/wowlet-win:v0.1
|
||||
volumes:
|
||||
- name: cache
|
||||
|
@ -46,5 +46,9 @@ volumes:
|
|||
- name: files
|
||||
host:
|
||||
path: /home/wow/wowlet_windows
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
- master
|
||||
event:
|
||||
- tag
|
||||
...
|
||||
|
|
|
@ -8,8 +8,8 @@ build/*
|
|||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
cmake_install.cmake
|
||||
feather_autogen/
|
||||
feather.cbp
|
||||
wowlet_autogen/
|
||||
wowlet.cbp
|
||||
src/tor/*
|
||||
!src/tor/.gitkeep
|
||||
src/config-feather.h
|
||||
src/config-wowlet.h
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
[submodule "contrib/KDMacTouchBar"]
|
||||
path = contrib/KDMacTouchBar
|
||||
url = https://github.com/KDAB/KDMacTouchBar.git
|
||||
[submodule "monero"]
|
||||
path = monero
|
||||
url = https://git.wownero.com/wownero/wownero
|
||||
branch = wowlet
|
||||
[submodule "contrib/quirc"]
|
||||
path = contrib/quirc
|
||||
url = https://github.com/dlbeer/quirc.git
|
||||
[submodule "wownero"]
|
||||
path = wownero
|
||||
url = https://git.wownero.com/wownero/wownero.git
|
||||
|
|
108
BUILDING.md
|
@ -1,108 +0,0 @@
|
|||
## Buildbot builds
|
||||
|
||||
The docker build bins can be found here: https://build.wownero.org/files/
|
||||
|
||||
## Docker static builds
|
||||
|
||||
Static builds via Docker are done in 3 steps:
|
||||
|
||||
1. Cloning this repository (+submodules)
|
||||
2. Creating a base Docker image
|
||||
3. Using the base image to compile a build
|
||||
|
||||
### Linux (reproducible)
|
||||
|
||||
The docker image for reproducible Linux static builds uses Ubuntu 16.04 and compiles the required libraries statically
|
||||
so that the resulting Feather binary is static. For more information, check the Dockerfile: `Dockerfile`.
|
||||
|
||||
#### 1. Clone
|
||||
|
||||
```bash
|
||||
git clone --branch master --recursive https://git.wownero.com/wowlet/wowlet.git
|
||||
cd wowlet
|
||||
```
|
||||
|
||||
Replace `master` with the desired version tag (e.g. `beta-4`) to build the release binary.
|
||||
|
||||
#### 2. Base image
|
||||
|
||||
```bash
|
||||
docker build --tag wowlet:linux --build-arg THREADS=4 .
|
||||
```
|
||||
|
||||
Building the base image takes a while. You only need to build the base image once.
|
||||
|
||||
#### 3. Build
|
||||
|
||||
##### Standalone binary
|
||||
|
||||
```bash
|
||||
docker run --rm -it -v $PWD:/wowlet -w /wowlet wowlet:linux sh -c 'make release-static -j4'
|
||||
```
|
||||
|
||||
If you're re-running a build make sure to `rm -rf build/` first.
|
||||
|
||||
The resulting binary can be found in `build/bin/wowlet`.
|
||||
|
||||
##### AppImage
|
||||
|
||||
First create the standalone binary using the Docker command in the previous step.
|
||||
|
||||
```bash
|
||||
docker run --rm -it -v $PWD:/wowlet -w /wowlet wowlet:linux contrib/build-appimage.sh
|
||||
```
|
||||
|
||||
### Windows (reproducible)
|
||||
|
||||
#### 1. Clone
|
||||
|
||||
```bash
|
||||
git clone --branch master --recursive https://git.wownero.com/wowlet/wowlet.git
|
||||
cd wowlet
|
||||
```
|
||||
|
||||
Replace `master` with the desired version tag (e.g. `beta-4`) to build the release binary.
|
||||
|
||||
#### 2. Base image
|
||||
|
||||
|
||||
```bash
|
||||
docker build -f Dockerfile.windows --tag wowlet:win --build-arg THREADS=4 .
|
||||
```
|
||||
|
||||
Building the base image takes a while. You only need to build the base image once.
|
||||
|
||||
#### 3. Build
|
||||
|
||||
```bash
|
||||
docker run --rm -it -v $PWD:/wowlet -w /wowlet wowlet:win sh -c 'make depends root=/depends target=x86_64-w64-mingw32 tag=win-x64 -j4'
|
||||
```
|
||||
|
||||
If you're re-running a build make sure to `rm -rf build/` first.
|
||||
|
||||
The resulting binary can be found in `build/x86_64-w64-mingw32/release/bin/wowlet.exe`.
|
||||
|
||||
## macOS
|
||||
|
||||
For MacOS it's easiest to leverage [brew](https://brew.sh) to install the required dependencies.
|
||||
|
||||
```bash
|
||||
HOMEBREW_OPTFLAGS="-march=core2" HOMEBREW_OPTIMIZATION_LEVEL="O0" \
|
||||
brew install boost zmq openssl libpgm miniupnpc libsodium expat libunwind-headers protobuf libgcrypt qrencode ccache cmake pkgconfig git
|
||||
```
|
||||
|
||||
Clone the repository.
|
||||
|
||||
```bash
|
||||
git clone --recursive https://git.wownero.com/wowlet/wowlet.git
|
||||
```
|
||||
|
||||
Get the latest LTS from here: https://www.qt.io/offline-installers and install.
|
||||
|
||||
Build Feather.
|
||||
|
||||
```bash
|
||||
CMAKE_PREFIX_PATH=~/Qt5.15.1/5.15.1/clang_64 make mac-release
|
||||
```
|
||||
|
||||
The resulting Mac OS application can be found `build/bin/wowlet.app` and will **not** have Tor embedded.
|
212
CMakeLists.txt
|
@ -1,20 +1,21 @@
|
|||
cmake_minimum_required(VERSION 3.13)
|
||||
project(feather)
|
||||
project(wowlet)
|
||||
|
||||
message(STATUS "Initiating compile using CMake ${CMAKE_VERSION}")
|
||||
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
set(VERSION_MAJOR "0")
|
||||
set(VERSION_MAJOR "4")
|
||||
set(VERSION_MINOR "1")
|
||||
set(VERSION_REVISION "0")
|
||||
set(VERSION "beta-1")
|
||||
set(VERSION_REVISION "1")
|
||||
set(VERSION "beta-8")
|
||||
|
||||
option(FETCH_DEPS "Download dependencies if they are not found" ON)
|
||||
option(XMRIG "Include XMRig module" ON)
|
||||
option(TOR_BIN "Path to Tor binary to embed inside Feather" OFF)
|
||||
option(OPENVR "Include OpenVR support")
|
||||
option(ANDROID "Android deployment")
|
||||
option(ANDROID_DEBUG "View the Android app on desktop")
|
||||
option(TOR_BIN "Path to Tor binary to embed inside WOWlet")
|
||||
option(STATIC "Link libraries statically, requires static Qt")
|
||||
option(USE_DEVICE_TREZOR "Trezor support compilation" OFF)
|
||||
option(DONATE_BEG "Prompt donation window every once in a while" ON)
|
||||
option(USE_DEVICE_TREZOR "Trezor support compilation")
|
||||
list(INSERT CMAKE_MODULE_PATH 0 "${CMAKE_SOURCE_DIR}/cmake")
|
||||
include(CheckCCompilerFlag)
|
||||
include(CheckCXXCompilerFlag)
|
||||
|
@ -24,26 +25,20 @@ include(FindCcache)
|
|||
include(CheckIncludeFile)
|
||||
include(CheckSymbolExists)
|
||||
|
||||
if(DEBUG)
|
||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||
endif()
|
||||
|
||||
# Update and init submodules by default
|
||||
if(NOT MANUAL_SUBMODULES)
|
||||
find_package(Git)
|
||||
if(GIT_FOUND)
|
||||
message(STATUS "Initializing submodules")
|
||||
execute_process(COMMAND git "submodule" "update" "--init" "--recursive")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(WOWNERO_HEAD "f611d5c9e32bc62f1735f6571b0bdb95cc020531")
|
||||
set(WOWNERO_HEAD "a21819cc22587e16af00e2c3d8f70156c11310a0")
|
||||
set(BUILD_GUI_DEPS ON)
|
||||
set(ARCH "x86-64")
|
||||
set(BUILD_64 ON)
|
||||
set(BUILD_64 ON CACHE BOOL "Build 64-bit binaries")
|
||||
set(INSTALL_VENDORED_LIBUNBOUND ${STATIC})
|
||||
set(USE_SINGLE_BUILDDIR ON)
|
||||
|
||||
# Are we in debug mode?
|
||||
set(_CMAKE_BUILD_TYPE "")
|
||||
string(TOUPPER "${CMAKE_BUILD_TYPE}" _CMAKE_BUILD_TYPE)
|
||||
if("${_CMAKE_BUILD_TYPE}" STREQUAL "DEBUG")
|
||||
set(DEBUG ON)
|
||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||
endif()
|
||||
|
||||
check_include_file(sys/prctl.h HAVE_SYS_PRCTL_H)
|
||||
check_symbol_exists(prctl "sys/prctl.h" HAVE_PRCTL)
|
||||
|
||||
|
@ -56,7 +51,7 @@ if(STATIC)
|
|||
# manually set the unbound submodule the right commit that has the fix.
|
||||
# This only works with -DMANUAL_SUBMODULES=1
|
||||
message(STATUS "applying unbound static build fix contrib/unbound_static.patch")
|
||||
execute_process(COMMAND bash -c "git -C ${CMAKE_SOURCE_DIR}/monero/external/unbound apply ${CMAKE_SOURCE_DIR}/contrib/unbound_static.patch")
|
||||
execute_process(COMMAND bash -c "git -C ${CMAKE_SOURCE_DIR}/wownero/external/unbound apply ${CMAKE_SOURCE_DIR}/contrib/unbound_static.patch")
|
||||
|
||||
set(Boost_USE_STATIC_LIBS ON)
|
||||
set(Boost_USE_STATIC_RUNTIME ON)
|
||||
|
@ -89,31 +84,18 @@ function (add_linker_flag_if_supported flag var)
|
|||
endfunction()
|
||||
|
||||
find_package(Git)
|
||||
if(GIT_FOUND)
|
||||
execute_process(COMMAND git rev-parse "HEAD" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/monero OUTPUT_VARIABLE _WOWNERO_HEAD OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(NOT _WOWNERO_HEAD STREQUAL WOWNERO_HEAD)
|
||||
message(FATAL_ERROR "[submodule] Monero HEAD was at ${_WOWNERO_HEAD} but should be at ${WOWNERO_HEAD}")
|
||||
else()
|
||||
message(STATUS "[submodule] Monero HEAD @ ${WOWNERO_HEAD}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_subdirectory(monero)
|
||||
set_property(TARGET wallet_merged PROPERTY FOLDER "monero")
|
||||
get_directory_property(ARCH_WIDTH DIRECTORY "monero" DEFINITION ARCH_WIDTH)
|
||||
get_directory_property(UNBOUND_LIBRARY DIRECTORY "monero" DEFINITION UNBOUND_LIBRARY)
|
||||
add_subdirectory(wownero)
|
||||
get_directory_property(ARCH_WIDTH DIRECTORY "wownero" DEFINITION ARCH_WIDTH)
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
include(VersionMonero)
|
||||
include(VersionFeather)
|
||||
include(VersionWowlet)
|
||||
|
||||
include_directories(${EASYLOGGING_INCLUDE})
|
||||
link_directories(${EASYLOGGING_LIBRARY_DIRS})
|
||||
|
||||
# OpenSSL
|
||||
if(APPLE AND NOT OPENSSL_ROOT_DIR)
|
||||
execute_process(COMMAND brew --prefix openssl OUTPUT_VARIABLE OPENSSL_ROOT_DIR OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
endif()
|
||||
find_package(OpenSSL REQUIRED)
|
||||
message(STATUS "OpenSSL: Version ${OPENSSL_VERSION}")
|
||||
message(STATUS "OpenSSL: include dir at ${OPENSSL_INCLUDE_DIR}")
|
||||
|
@ -126,49 +108,28 @@ message(STATUS "libsodium: libraries at ${SODIUM_LIBRARY}")
|
|||
# HIDApi
|
||||
set(HIDAPI_FOUND OFF)
|
||||
|
||||
# Unbound
|
||||
find_package(Unbound REQUIRED)
|
||||
|
||||
# QrEncode
|
||||
find_package(QREncode REQUIRED)
|
||||
|
||||
# Tevador 14 word Monero seed
|
||||
find_package(monero-seed CONFIG)
|
||||
if(NOT monero-seed_FOUND)
|
||||
if(FETCH_DEPS)
|
||||
FetchContent_Declare(monero-seed
|
||||
GIT_REPOSITORY https://git.wownero.com/feather/monero-seed.git)
|
||||
FetchContent_GetProperties(monero-seed)
|
||||
if(NOT monero-seed_POPULATED)
|
||||
message(STATUS "Fetching monero-seed")
|
||||
FetchContent_Populate(monero-seed)
|
||||
add_subdirectory(${monero-seed_SOURCE_DIR} ${monero-seed_BINARY_DIR})
|
||||
endif()
|
||||
add_library(monero-seed::monero-seed ALIAS monero-seed)
|
||||
else()
|
||||
message(FATAL_ERROR "monero-seed was not installed and fetching deps is disabled")
|
||||
endif()
|
||||
endif()
|
||||
# Tevador 14 word seed (https://git.wownero.com/wowlet/wownero-seed)
|
||||
find_package(wownero-seed CONFIG REQUIRED)
|
||||
|
||||
# Boost
|
||||
if(DEBUG)
|
||||
set(Boost_DEBUG ON)
|
||||
endif()
|
||||
if(APPLE AND NOT BOOST_ROOT)
|
||||
execute_process(COMMAND brew --prefix boost OUTPUT_VARIABLE BOOST_ROOT OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
endif()
|
||||
|
||||
if(MINGW)
|
||||
set(Boost_THREADAPI win32)
|
||||
endif()
|
||||
find_package(Boost 1.58 REQUIRED COMPONENTS
|
||||
system
|
||||
filesystem
|
||||
thread
|
||||
date_time
|
||||
chrono
|
||||
regex
|
||||
serialization
|
||||
program_options
|
||||
locale)
|
||||
set(_BOOST_COMPONENTS system filesystem thread date_time chrono regex serialization program_options locale)
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
find_package(Boost 1.58 REQUIRED COMPONENTS ${_BOOST_COMPONENTS})
|
||||
|
||||
if(UNIX AND NOT ANDROID)
|
||||
if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
# https://github.com/monero-project/monero-gui/issues/3142#issuecomment-705940446
|
||||
set(CMAKE_SKIP_RPATH ON)
|
||||
|
@ -190,40 +151,57 @@ if("$ENV{DRONE}" STREQUAL "true")
|
|||
message(STATUS "We are inside a static compile with Drone CI")
|
||||
endif()
|
||||
|
||||
# To build Feather with embedded (and static) Tor, pass CMake -DTOR_BIN=/path/to/tor
|
||||
if(UNIX)
|
||||
if(NOT CMAKE_PREFIX_PATH AND DEFINED ENV{CMAKE_PREFIX_PATH})
|
||||
message(STATUS "Using CMAKE_PREFIX_PATH environment variable: '$ENV{CMAKE_PREFIX_PATH}'")
|
||||
set(CMAKE_PREFIX_PATH $ENV{CMAKE_PREFIX_PATH})
|
||||
endif()
|
||||
if(APPLE AND NOT CMAKE_PREFIX_PATH)
|
||||
execute_process(COMMAND brew --prefix qt5 OUTPUT_VARIABLE QT5_DIR OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
list(APPEND CMAKE_PREFIX_PATH ${QT5_DIR})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(TOR_BIN)
|
||||
if(APPLE)
|
||||
execute_process(COMMAND bash -c "touch ${CMAKE_CURRENT_SOURCE_DIR}/src/tor/libevent-2.1.7.dylib")
|
||||
endif()
|
||||
|
||||
execute_process(COMMAND bash -c "${TOR_BIN} --version --quiet" OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE out RESULT_VARIABLE ret)
|
||||
if (ret EQUAL "0")
|
||||
set(TOR_VERSION "${out}")
|
||||
endif()
|
||||
message(STATUS "${TOR_VERSION}")
|
||||
configure_file("cmake/config-feather.h.cmake" "${CMAKE_CURRENT_SOURCE_DIR}/src/config-feather.h")
|
||||
|
||||
# on the buildbot Tor is baked into the image
|
||||
# To build WOWlet with embedded & static Tor, pass CMake -DTOR_BIN=/path/to/tor_executable
|
||||
# The CMake below will copy the Tor binary into src/assets/exec
|
||||
#
|
||||
# For release:
|
||||
# ## Linux / Window
|
||||
# on the buildbot(s) Tor is baked into the image
|
||||
# - linux: See `Dockerfile`
|
||||
# - windows: See `Dockerfile.windows`
|
||||
# - macos: taken from Tor Browser official release
|
||||
if(REPRODUCIBLE) # Always copy Tor when doing a reproducible build to prevent old versions from getting included
|
||||
set(TOR_COPY_CMD "cp ${TOR_BIN} ${CMAKE_CURRENT_SOURCE_DIR}/src/assets/exec/tor")
|
||||
else()
|
||||
set(TOR_COPY_CMD "cp -u ${TOR_BIN} ${CMAKE_CURRENT_SOURCE_DIR}/src/assets/exec/tor")
|
||||
if(NOT EXISTS "${TOR_BIN}")
|
||||
message(FATAL_ERROR "TOR_BIN is set, but file does not exist: '${TOR_BIN}'")
|
||||
endif()
|
||||
message(STATUS "${TOR_COPY_CMD}")
|
||||
|
||||
# copy the Tor executable over
|
||||
set(TOR_COPY_CMD "cp ${TOR_BIN} ${CMAKE_CURRENT_SOURCE_DIR}/src/assets/exec/tor")
|
||||
message(STATUS "Tor cmd: ${TOR_COPY_CMD}")
|
||||
|
||||
execute_process(COMMAND bash -c "${TOR_COPY_CMD}" RESULT_VARIABLE ret)
|
||||
if(ret EQUAL "1")
|
||||
message(FATAL_ERROR "Tor copy failure: ${TOR_COPY_CMD}")
|
||||
endif()
|
||||
|
||||
# get Tor version while we're at it
|
||||
if(NOT TOR_VERSION)
|
||||
execute_process(COMMAND bash -c "${TOR_BIN} --version --quiet | head -n1" OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE out RESULT_VARIABLE ret)
|
||||
if (ret EQUAL "0")
|
||||
set(TOR_VERSION "${out}")
|
||||
endif()
|
||||
endif()
|
||||
message(STATUS "Tor version: ${TOR_VERSION}")
|
||||
configure_file("cmake/config-wowlet.h.cmake" "${CMAKE_CURRENT_SOURCE_DIR}/src/config-wowlet.h")
|
||||
|
||||
message(STATUS "Embedding Tor binary at ${TOR_BIN}")
|
||||
else()
|
||||
message(STATUS "Skipping Tor inclusion because -DTOR_BIN=Off")
|
||||
endif()
|
||||
|
||||
if(MINGW)
|
||||
find_package(Iconv REQUIRED)
|
||||
|
||||
string(REGEX MATCH "^[^/]:/[^/]*" msys2_install_path "${CMAKE_C_COMPILER}")
|
||||
message(STATUS "MSYS location: ${msys2_install_path}")
|
||||
set(CMAKE_INCLUDE_PATH "${msys2_install_path}/mingw${ARCH_WIDTH}/include")
|
||||
|
@ -244,12 +222,10 @@ if(MINGW)
|
|||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wa,-mbig-obj")
|
||||
set(EXTRA_LIBRARIES mswsock;ws2_32;iphlpapi;crypt32;bcrypt)
|
||||
if(DEPENDS)
|
||||
set(ICU_LIBRARIES iconv)
|
||||
set(ICU_LIBRARIES iconv)
|
||||
else()
|
||||
set(ICU_LIBRARIES icuio icuin icuuc icudt icutu iconv)
|
||||
endif()
|
||||
elseif(APPLE)
|
||||
set(EXTRA_LIBRARIES "-framework AppKit")
|
||||
elseif(OPENBSD)
|
||||
set(EXTRA_LIBRARIES "")
|
||||
elseif(FREEBSD)
|
||||
|
@ -259,30 +235,13 @@ elseif(DRAGONFLY)
|
|||
set(EXTRA_LIBRARIES execinfo ${COMPAT})
|
||||
elseif(CMAKE_SYSTEM_NAME MATCHES "(SunOS|Solaris)")
|
||||
set(EXTRA_LIBRARIES socket nsl resolv)
|
||||
elseif(NOT MSVC AND NOT DEPENDS)
|
||||
elseif(NOT MSVC AND NOT DEPENDS AND NOT ANDROID)
|
||||
find_library(RT rt)
|
||||
set(EXTRA_LIBRARIES ${RT})
|
||||
endif()
|
||||
|
||||
list(APPEND EXTRA_LIBRARIES ${CMAKE_DL_LIBS})
|
||||
|
||||
if(APPLE)
|
||||
include_directories(SYSTEM /usr/include/malloc)
|
||||
if(POLICY CMP0042)
|
||||
cmake_policy(SET CMP0042 NEW)
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64 -fvisibility=default -std=c++11")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=default -DGTEST_HAS_TR1_TUPLE=0")
|
||||
endif()
|
||||
|
||||
if (APPLE AND NOT IOS)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64 -fvisibility=default -std=c++11")
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=default -DGTEST_HAS_TR1_TUPLE=0")
|
||||
endif()
|
||||
|
||||
# warnings
|
||||
# @TODO: enable these 2 for migration to Qt 6
|
||||
#add_c_flag_if_supported(-Werror C_SECURITY_FLAGS)
|
||||
|
@ -317,12 +276,7 @@ if (NOT (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_C_COMPILER_VERSION VER
|
|||
endif()
|
||||
|
||||
# linker
|
||||
if (APPLE)
|
||||
add_linker_flag_if_supported(-Wl,-bind_at_load LD_SECURITY_FLAGS)
|
||||
add_linker_flag_if_supported(-Wl,-dead_strip LD_SECURITY_FLAGS)
|
||||
add_linker_flag_if_supported(-Wl,-dead_strip_dylibs LD_SECURITY_FLAGS)
|
||||
endif()
|
||||
if (NOT APPLE AND NOT (WIN32 AND CMAKE_C_COMPILER_ID STREQUAL "GNU"))
|
||||
if (NOT (WIN32 AND CMAKE_C_COMPILER_ID STREQUAL "GNU"))
|
||||
# Windows binaries die on startup with PIE when compiled with GCC
|
||||
add_linker_flag_if_supported(-pie LD_SECURITY_FLAGS)
|
||||
endif()
|
||||
|
@ -352,6 +306,11 @@ if(STATIC)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
if(LINUX_ACTIVATION)
|
||||
find_package(Cairo REQUIRED)
|
||||
find_package(Xfixes REQUIRED)
|
||||
endif()
|
||||
|
||||
# With GCC 6.1.1 the compiled binary malfunctions due to aliasing. Until that
|
||||
# is fixed in the code (Issue #847), force compiler to be conservative.
|
||||
add_c_flag_if_supported(-fno-strict-aliasing C_SECURITY_FLAGS)
|
||||
|
@ -368,8 +327,21 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 ${C_SECURITY_FLAGS}")
|
|||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ${CXX_SECURITY_FLAGS}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LD_SECURITY_FLAGS} ${STATIC_FLAGS}")
|
||||
|
||||
if(APPLE)
|
||||
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/contrib/KDMacTouchBar")
|
||||
if(OPENVR)
|
||||
# Add contrib/openvr as library
|
||||
add_definitions(-DVR_API_PUBLIC)
|
||||
add_definitions(-DOPENVR_BUILD_STATIC) # is this needed?
|
||||
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/contrib/openvr")
|
||||
endif()
|
||||
|
||||
if(WITH_SCANNER)
|
||||
add_library(quirc STATIC
|
||||
contrib/quirc/lib/decode.c
|
||||
contrib/quirc/lib/identify.c
|
||||
contrib/quirc/lib/quirc.c
|
||||
contrib/quirc/lib/version_db.c
|
||||
)
|
||||
target_include_directories(quirc PUBLIC contrib/quirc/lib)
|
||||
endif()
|
||||
|
||||
add_subdirectory(src)
|
||||
|
|
65
Dockerfile
|
@ -17,7 +17,6 @@ RUN wget https://www.openssl.org/source/openssl-1.1.1i.tar.gz && \
|
|||
cd openssl-1.1.1i && \
|
||||
./config no-shared no-dso --prefix=/usr/local/openssl && \
|
||||
make -j$THREADS && \
|
||||
make test && \
|
||||
make -j$THREADS install_sw && \
|
||||
rm -rf $(pwd)
|
||||
|
||||
|
@ -66,10 +65,10 @@ RUN git clone -b tor-0.4.5.5-rc --depth 1 https://git.torproject.org/tor.git &&
|
|||
rm -rf $(pwd) && \
|
||||
strip -s -D /usr/local/tor/bin/tor
|
||||
|
||||
FROM ubuntu:16.04
|
||||
FROM ubuntu:18.04
|
||||
|
||||
ARG THREADS=1
|
||||
ARG QT_VERSION=5.15.2
|
||||
ARG QT_VERSION=v5.15.2
|
||||
|
||||
ENV CFLAGS="-fPIC"
|
||||
ENV CPPFLAGS="-fPIC"
|
||||
|
@ -95,7 +94,7 @@ RUN apt-get update && \
|
|||
# libusb
|
||||
libudev-dev \
|
||||
# fontconfig
|
||||
autopoint gettext gperf libpng12-dev \
|
||||
autopoint gettext gperf libpng-dev \
|
||||
# libxcb
|
||||
libpthread-stubs0-dev \
|
||||
# xorgproto
|
||||
|
@ -161,7 +160,7 @@ RUN git clone -b 0.4.0 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb-
|
|||
cd libxcb-util && \
|
||||
git reset --hard acf790d7752f36e450d476ad79807d4012ec863b && \
|
||||
git submodule init && \
|
||||
git clone --depth 1 https://gitlab.freedesktop.org/xorg/util/xcb-util-m4 m4 && \
|
||||
git clone https://gitlab.freedesktop.org/xorg/util/xcb-util-m4 m4 && \
|
||||
git -C m4 reset --hard f662e3a93ebdec3d1c9374382dcc070093a42fed && \
|
||||
./autogen.sh --enable-shared --disable-static && \
|
||||
make -j$THREADS && \
|
||||
|
@ -172,7 +171,7 @@ RUN git clone -b 0.4.0 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb-
|
|||
cd libxcb-image && \
|
||||
git reset --hard d882052fb2ce439c6483fce944ba8f16f7294639 && \
|
||||
git submodule init && \
|
||||
git clone --depth 1 https://gitlab.freedesktop.org/xorg/util/xcb-util-m4 m4 && \
|
||||
git clone https://gitlab.freedesktop.org/xorg/util/xcb-util-m4 m4 && \
|
||||
git -C m4 reset --hard f662e3a93ebdec3d1c9374382dcc070093a42fed && \
|
||||
./autogen.sh --enable-shared --disable-static && \
|
||||
make -j$THREADS && \
|
||||
|
@ -183,7 +182,7 @@ RUN git clone -b 0.4.0 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb-
|
|||
cd libxcb-keysyms && \
|
||||
git reset --hard 0e51ee5570a6a80bdf98770b975dfe8a57f4eeb1 && \
|
||||
git submodule init && \
|
||||
git clone --depth 1 https://gitlab.freedesktop.org/xorg/util/xcb-util-m4 m4 && \
|
||||
git clone https://gitlab.freedesktop.org/xorg/util/xcb-util-m4 m4 && \
|
||||
git -C m4 reset --hard f662e3a93ebdec3d1c9374382dcc070093a42fed && \
|
||||
./autogen.sh --enable-shared --disable-static && \
|
||||
make -j$THREADS && \
|
||||
|
@ -194,7 +193,7 @@ RUN git clone -b 0.3.9 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb-
|
|||
cd libxcb-render-util && \
|
||||
git reset --hard 0317caf63de532fd7a0493ed6afa871a67253747 && \
|
||||
git submodule init && \
|
||||
git clone --depth 1 https://gitlab.freedesktop.org/xorg/util/xcb-util-m4 m4 && \
|
||||
git clone https://gitlab.freedesktop.org/xorg/util/xcb-util-m4 m4 && \
|
||||
git -C m4 reset --hard f662e3a93ebdec3d1c9374382dcc070093a42fed && \
|
||||
./autogen.sh --enable-shared --disable-static && \
|
||||
make -j$THREADS && \
|
||||
|
@ -205,7 +204,7 @@ RUN git clone -b 0.4.1 --depth 1 https://gitlab.freedesktop.org/xorg/lib/libxcb-
|
|||
cd libxcb-wm && \
|
||||
git reset --hard 24eb17df2e1245885e72c9d4bbb0a0f69f0700f2 && \
|
||||
git submodule init && \
|
||||
git clone --depth 1 https://gitlab.freedesktop.org/xorg/util/xcb-util-m4 m4 && \
|
||||
git clone https://gitlab.freedesktop.org/xorg/util/xcb-util-m4 m4 && \
|
||||
git -C m4 reset --hard f662e3a93ebdec3d1c9374382dcc070093a42fed && \
|
||||
./autogen.sh --enable-shared --disable-static && \
|
||||
make -j$THREADS && \
|
||||
|
@ -262,7 +261,7 @@ RUN git clone -b release-64-2 --depth 1 https://github.com/unicode-org/icu && \
|
|||
make -j$THREADS install && \
|
||||
rm -rf $(pwd)
|
||||
|
||||
RUN wget https://dl.bintray.com/boostorg/release/1.73.0/source/boost_1_73_0.tar.gz && \
|
||||
RUN wget https://boostorg.jfrog.io/artifactory/main/release/1.73.0/source/boost_1_73_0.tar.gz && \
|
||||
echo "9995e192e68528793755692917f9eb6422f3052a53c5e13ba278a228af6c7acf boost_1_73_0.tar.gz" | sha256sum -c && \
|
||||
tar -xzf boost_1_73_0.tar.gz && \
|
||||
rm boost_1_73_0.tar.gz && \
|
||||
|
@ -278,22 +277,46 @@ RUN wget https://www.openssl.org/source/openssl-1.1.1i.tar.gz && \
|
|||
cd openssl-1.1.1i && \
|
||||
./config no-shared no-dso --prefix=/usr/local/openssl && \
|
||||
make -j$THREADS && \
|
||||
make test && \
|
||||
make -j$THREADS install_sw && \
|
||||
rm -rf $(pwd)
|
||||
|
||||
RUN wget https://github.com/libexpat/libexpat/releases/download/R_2_4_8/expat-2.4.8.tar.bz2 && \
|
||||
echo "a247a7f6bbb21cf2ca81ea4cbb916bfb9717ca523631675f99b3d4a5678dcd16 expat-2.4.8.tar.bz2" | sha256sum -c && \
|
||||
tar -xf expat-2.4.8.tar.bz2 && \
|
||||
rm expat-2.4.8.tar.bz2 && \
|
||||
cd expat-2.4.8 && \
|
||||
./configure --enable-static --disable-shared --prefix=/usr/local/expat/ && \
|
||||
make -j$THREADS && \
|
||||
make -j$THREADS install && \
|
||||
rm -rf $(pwd)
|
||||
|
||||
RUN wget https://www.nlnetlabs.nl/downloads/unbound/unbound-1.16.2.tar.gz && \
|
||||
echo "2e32f283820c24c51ca1dd8afecfdb747c7385a137abe865c99db4b257403581 unbound-1.16.2.tar.gz" | sha256sum -c && \
|
||||
tar -xzf unbound-1.16.2.tar.gz && \
|
||||
rm unbound-1.16.2.tar.gz && \
|
||||
cd unbound-1.16.2 && \
|
||||
./configure --disable-shared --enable-static --without-pyunbound --with-libexpat=/usr/local/expat/ --with-ssl=/usr/local/openssl/ --with-libevent=no --without-pythonmodule --disable-flto --with-pthreads --with-libunbound-only --with-pic && \
|
||||
make -j$THREADS && \
|
||||
make -j$THREADS install && \
|
||||
rm -rf $(pwd)
|
||||
|
||||
RUN rm /usr/lib/x86_64-linux-gnu/libX11.a && \
|
||||
rm /usr/lib/x86_64-linux-gnu/libXext.a && \
|
||||
rm /usr/lib/x86_64-linux-gnu/libX11-xcb.a && \
|
||||
git clone git://code.qt.io/qt/qt5.git -b ${QT_VERSION} --depth 1 && \
|
||||
cd qt5 && \
|
||||
git clone git://code.qt.io/qt/qtbase.git -b ${QT_VERSION} --depth 1 && \
|
||||
git clone git://code.qt.io/qt/qtdeclarative.git -b ${QT_VERSION} --depth 1 && \
|
||||
git clone git://code.qt.io/qt/qtgraphicaleffects.git -b ${QT_VERSION} --depth 1 && \
|
||||
git clone git://code.qt.io/qt/qtimageformats.git -b ${QT_VERSION} --depth 1 && \
|
||||
git clone git://code.qt.io/qt/qtmultimedia.git -b ${QT_VERSION} --depth 1 && \
|
||||
git clone git://code.qt.io/qt/qtquickcontrols.git -b ${QT_VERSION} --depth 1 && \
|
||||
git clone git://code.qt.io/qt/qtquickcontrols2.git -b ${QT_VERSION} --depth 1 && \
|
||||
git clone git://code.qt.io/qt/qtsvg.git -b ${QT_VERSION} --depth 1 && \
|
||||
git clone git://code.qt.io/qt/qttools.git -b ${QT_VERSION} --depth 1 && \
|
||||
git clone git://code.qt.io/qt/qttranslations.git -b ${QT_VERSION} --depth 1 && \
|
||||
git clone git://code.qt.io/qt/qtx11extras.git -b ${QT_VERSION} --depth 1 && \
|
||||
git clone git://code.qt.io/qt/qtxmlpatterns.git -b ${QT_VERSION} --depth 1 && \
|
||||
git clone git://code.qt.io/qt/qtwebsockets.git -b ${QT_VERSION} --depth 1 && \
|
||||
sed -ri s/\(Libs:.*\)/\\1\ -lexpat/ /usr/local/lib/pkgconfig/fontconfig.pc && \
|
||||
sed -ri s/\(Libs:.*\)/\\1\ -lz/ /usr/local/lib/pkgconfig/freetype2.pc && \
|
||||
|
@ -301,18 +324,14 @@ RUN rm /usr/lib/x86_64-linux-gnu/libX11.a && \
|
|||
sed -i s/\\/usr\\/X11R6\\/lib64/\\/usr\\/local\\/lib/ qtbase/mkspecs/linux-g++-64/qmake.conf && \
|
||||
OPENSSL_LIBS="-lssl -lcrypto -lpthread -ldl" \
|
||||
./configure --prefix=/usr -platform linux-g++-64 -opensource -confirm-license -release -static -no-avx \
|
||||
-no-opengl -qpa xcb --xcb -xcb-xlib -feature-xlib -openssl-linked -I /usr/local/openssl/include \
|
||||
-L /usr/local/openssl/lib -system-freetype -fontconfig -glib \
|
||||
-no-dbus -no-sql-sqlite -no-use-gold-linker -no-kms \
|
||||
-opengl desktop -qpa xcb -xcb -xcb-xlib -feature-xlib -system-freetype -fontconfig -glib \
|
||||
-no-dbus -no-feature-qml-worker-script -no-linuxfb -no-openssl -no-sql-sqlite -no-kms -no-use-gold-linker \
|
||||
-qt-harfbuzz -qt-libjpeg -qt-libpng -qt-pcre -qt-zlib \
|
||||
-skip qt3d -skip qtandroidextras -skip qtcanvas3d -skip qtcharts -skip qtconnectivity -skip qtdatavis3d \
|
||||
-skip qtdoc -skip qtquickcontrols -skip qtquickcontrols2 -skip qtspeech -skip qtgamepad \
|
||||
-skip qtlocation -skip qtmacextras -skip qtnetworkauth -skip qtpurchasing -optimize-size \
|
||||
-skip qtdoc -skip qtgamepad -skip qtlocation -skip qtmacextras -skip qtnetworkauth -skip qtpurchasing \
|
||||
-skip qtscript -skip qtscxml -skip qtsensors -skip qtserialbus -skip qtserialport -skip qtspeech -skip qttools \
|
||||
-skip qtvirtualkeyboard -skip qtwayland -skip qtwebchannel -skip qtwebengine -skip qtwebview \
|
||||
-skip qtwinextras -skip qtx11extras -skip gamepad -skip serialbus -skip location -skip webengine \
|
||||
-skip qtdeclarative \
|
||||
-no-feature-cups -no-feature-ftp -no-feature-pdf -no-feature-animation \
|
||||
-nomake examples -nomake tests -nomake tools && \
|
||||
make -j$THREADS && \
|
||||
make -j$THREADS install && \
|
||||
|
@ -392,9 +411,9 @@ RUN git clone -b v4.0.2 --depth 1 https://github.com/fukuchi/libqrencode.git &&
|
|||
make -j$THREADS install && \
|
||||
rm -rf $(pwd)
|
||||
|
||||
RUN git clone https://git.wownero.com/feather/monero-seed.git && \
|
||||
cd monero-seed && \
|
||||
git reset --hard 4674ef09b6faa6fe602ab5ae0b9ca8e1fd7d5e1b && \
|
||||
RUN git clone https://git.wownero.com/wowlet/wownero-seed.git && \
|
||||
cd wownero-seed && \
|
||||
git reset --hard ef6910b6bb3b61757c36e2e5db0927d75f1731c8 && \
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -Bbuild && \
|
||||
make -Cbuild -j$THREADS && \
|
||||
make -Cbuild install && \
|
||||
|
@ -414,3 +433,7 @@ RUN mkdir linuxdeployqt && \
|
|||
chmod +x linuxdeployqt-7-x86_64.AppImage && \
|
||||
./linuxdeployqt-7-x86_64.AppImage --appimage-extract && \
|
||||
rm linuxdeployqt-7-x86_64.AppImage
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get -o Dpkg::Options::="--force-confold" install -q -y --force-yes libcairo2-dev libxinerama-dev
|
||||
RUN git config --global --add safe.directory /wowlet
|
|
@ -0,0 +1,244 @@
|
|||
FROM debian:stretch
|
||||
|
||||
ARG THREADS=1
|
||||
ARG ANDROID_NDK_REVISION=21d
|
||||
ARG ANDROID_NDK_HASH=bcf4023eb8cb6976a4c7cff0a8a8f145f162bf4d
|
||||
ARG ANDROID_SDK_REVISION=4333796
|
||||
ARG ANDROID_SDK_HASH=92ffee5a1d98d856634e8b71132e8a95d96c83a63fde1099be3d86df3106def9
|
||||
ARG QT_VERSION=5.15.2
|
||||
|
||||
WORKDIR /opt/android
|
||||
ENV WORKDIR=/opt/android
|
||||
|
||||
ENV ANDROID_NATIVE_API_LEVEL=28
|
||||
ENV ANDROID_API=android-${ANDROID_NATIVE_API_LEVEL}
|
||||
ENV ANDROID_CLANG=aarch64-linux-android${ANDROID_NATIVE_API_LEVEL}-clang
|
||||
ENV ANDROID_CLANGPP=aarch64-linux-android${ANDROID_NATIVE_API_LEVEL}-clang++
|
||||
ENV ANDROID_NDK_ROOT=${WORKDIR}/android-ndk-r${ANDROID_NDK_REVISION}
|
||||
ENV ANDROID_SDK_ROOT=${WORKDIR}/tools
|
||||
ENV JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
|
||||
ENV PATH=${JAVA_HOME}/bin:${PATH}
|
||||
ENV PREFIX=${WORKDIR}/prefix
|
||||
ENV TOOLCHAIN_DIR=${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y ant automake build-essential ca-certificates-java file gettext git libc6 libncurses5 \
|
||||
libssl-dev libstdc++6 libtinfo5 libtool libz1 openjdk-8-jdk-headless openjdk-8-jre-headless pkg-config python3 \
|
||||
unzip wget
|
||||
|
||||
RUN wget -q https://dl.google.com/android/repository/sdk-tools-linux-${ANDROID_SDK_REVISION}.zip \
|
||||
&& unzip -q sdk-tools-linux-${ANDROID_SDK_REVISION}.zip \
|
||||
&& rm -f sdk-tools-linux-${ANDROID_SDK_REVISION}.zip
|
||||
|
||||
RUN wget -q https://dl.google.com/android/repository/android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip \
|
||||
&& unzip -q android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip \
|
||||
&& rm -f android-ndk-r${ANDROID_NDK_REVISION}-linux-x86_64.zip
|
||||
|
||||
RUN cd ${ANDROID_SDK_ROOT} && echo y | ./bin/sdkmanager "platform-tools" "platforms;${ANDROID_API}" "tools" > /dev/null
|
||||
RUN cp -r ${WORKDIR}/platforms ${WORKDIR}/platform-tools ${ANDROID_SDK_ROOT}
|
||||
|
||||
ENV HOST_PATH=${PATH}
|
||||
ENV PATH=${TOOLCHAIN_DIR}/aarch64-linux-android/bin:${TOOLCHAIN_DIR}/bin:${PATH}
|
||||
|
||||
ARG ZLIB_VERSION=1.2.11
|
||||
ARG ZLIB_HASH=c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1
|
||||
RUN wget -q https://zlib.net/zlib-${ZLIB_VERSION}.tar.gz \
|
||||
&& tar -xzf zlib-${ZLIB_VERSION}.tar.gz \
|
||||
&& rm zlib-${ZLIB_VERSION}.tar.gz \
|
||||
&& cd zlib-${ZLIB_VERSION} \
|
||||
&& CC=${ANDROID_CLANG} CXX=${ANDROID_CLANGPP} ./configure --prefix=${PREFIX} --static \
|
||||
&& make -j${THREADS} \
|
||||
&& make -j${THREADS} install \
|
||||
&& rm -rf $(pwd)
|
||||
|
||||
RUN git clone git://code.qt.io/qt/qt5.git -b ${QT_VERSION} --depth 1 \
|
||||
&& cd qt5 \
|
||||
&& perl init-repository --module-subset=default,-qtwebengine \
|
||||
&& PATH=${HOST_PATH} ./configure -v -developer-build -release \
|
||||
-xplatform android-clang \
|
||||
-android-ndk-platform ${ANDROID_API} \
|
||||
-android-ndk ${ANDROID_NDK_ROOT} \
|
||||
-android-sdk ${ANDROID_SDK_ROOT} \
|
||||
-android-ndk-host linux-x86_64 \
|
||||
-no-dbus \
|
||||
-opengl es2 \
|
||||
-no-use-gold-linker \
|
||||
-no-sql-mysql \
|
||||
-opensource -confirm-license \
|
||||
-android-arch arm64-v8a \
|
||||
-prefix ${PREFIX} \
|
||||
-nomake tools -nomake tests -nomake examples \
|
||||
-skip qtwebengine \
|
||||
-skip qtserialport \
|
||||
-skip qtconnectivity \
|
||||
-skip qttranslations \
|
||||
-skip qtpurchasing \
|
||||
-skip qtgamepad -skip qtscript -skip qtdoc \
|
||||
-no-warnings-are-errors \
|
||||
&& sed -i '213,215d' qtbase/src/3rdparty/pcre2/src/sljit/sljitConfigInternal.h \
|
||||
&& PATH=${HOST_PATH} make -j${THREADS} \
|
||||
&& PATH=${HOST_PATH} make -j${THREADS} install \
|
||||
&& cd qttools/src/linguist/lrelease \
|
||||
&& ../../../../qtbase/bin/qmake \
|
||||
&& PATH=${HOST_PATH} make -j${THREADS} install \
|
||||
&& cd ../../../.. \
|
||||
&& rm -rf $(pwd)
|
||||
|
||||
ARG ICONV_VERSION=1.16
|
||||
ARG ICONV_HASH=e6a1b1b589654277ee790cce3734f07876ac4ccfaecbee8afa0b649cf529cc04
|
||||
RUN wget -q http://ftp.gnu.org/pub/gnu/libiconv/libiconv-${ICONV_VERSION}.tar.gz \
|
||||
&& echo "${ICONV_HASH} libiconv-${ICONV_VERSION}.tar.gz" | sha256sum -c \
|
||||
&& tar -xzf libiconv-${ICONV_VERSION}.tar.gz \
|
||||
&& rm -f libiconv-${ICONV_VERSION}.tar.gz \
|
||||
&& cd libiconv-${ICONV_VERSION} \
|
||||
&& CC=${ANDROID_CLANG} CXX=${ANDROID_CLANGPP} ./configure --build=x86_64-linux-gnu --host=aarch64 --prefix=${PREFIX} --disable-rpath \
|
||||
&& make -j${THREADS} \
|
||||
&& make -j${THREADS} install
|
||||
|
||||
ARG BOOST_VERSION=1_74_0
|
||||
ARG BOOST_VERSION_DOT=1.74.0
|
||||
ARG BOOST_HASH=83bfc1507731a0906e387fc28b7ef5417d591429e51e788417fe9ff025e116b1
|
||||
RUN wget -q https://dl.bintray.com/boostorg/release/${BOOST_VERSION_DOT}/source/boost_${BOOST_VERSION}.tar.bz2 \
|
||||
&& echo "${BOOST_HASH} boost_${BOOST_VERSION}.tar.bz2" | sha256sum -c \
|
||||
&& tar -xf boost_${BOOST_VERSION}.tar.bz2 \
|
||||
&& rm -f boost_${BOOST_VERSION}.tar.bz2 \
|
||||
&& cd boost_${BOOST_VERSION} \
|
||||
&& PATH=${HOST_PATH} ./bootstrap.sh --prefix=${PREFIX} \
|
||||
&& PATH=${TOOLCHAIN_DIR}/bin:${HOST_PATH} ./b2 --build-type=minimal link=static runtime-link=static \
|
||||
--with-chrono --with-date_time --with-filesystem --with-program_options --with-regex --with-serialization \
|
||||
--with-system --with-thread --with-locale --build-dir=android --stagedir=android toolset=clang threading=multi \
|
||||
threadapi=pthread target-os=android -sICONV_PATH=${PREFIX} \
|
||||
cflags='--target=aarch64-linux-android' \
|
||||
cxxflags='--target=aarch64-linux-android' \
|
||||
linkflags='--target=aarch64-linux-android --sysroot=${ANDROID_NDK_ROOT}/platforms/${ANDROID_API}/arch-arm64 ${ANDROID_NDK_ROOT}/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libc++_shared.so -nostdlib++' \
|
||||
install -j${THREADS} \
|
||||
&& rm -rf $(pwd)
|
||||
|
||||
ARG OPENSSL_VERSION=1.1.1g
|
||||
ARG OPENSSL_HASH=ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46
|
||||
RUN wget -q https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz \
|
||||
&& tar -xzf openssl-${OPENSSL_VERSION}.tar.gz \
|
||||
&& rm openssl-${OPENSSL_VERSION}.tar.gz \
|
||||
&& cd openssl-${OPENSSL_VERSION} \
|
||||
&& ANDROID_NDK_HOME=${ANDROID_NDK_ROOT} ./Configure CC=${ANDROID_CLANG} CXX=${ANDROID_CLANGPP} \
|
||||
android-arm64 no-asm no-shared --static \
|
||||
--with-zlib-include=${PREFIX}/include --with-zlib-lib=${PREFIX}/lib \
|
||||
--prefix=${PREFIX} --openssldir=${PREFIX} \
|
||||
&& sed -i 's/CNF_EX_LIBS=-ldl -pthread//g;s/BIN_CFLAGS=-pie $(CNF_CFLAGS) $(CFLAGS)//g' Makefile \
|
||||
&& ANDROID_NDK_HOME=${ANDROID_NDK_ROOT} make -j${THREADS} \
|
||||
&& make -j${THREADS} install \
|
||||
&& rm -rf $(pwd)
|
||||
|
||||
ARG ZMQ_VERSION=v4.3.3
|
||||
ARG ZMQ_HASH=04f5bbedee58c538934374dc45182d8fc5926fa3
|
||||
RUN git clone https://github.com/zeromq/libzmq.git -b ${ZMQ_VERSION} --depth 1 \
|
||||
&& cd libzmq \
|
||||
&& git checkout ${ZMQ_HASH} \
|
||||
&& ./autogen.sh \
|
||||
&& CC=${ANDROID_CLANG} CXX=${ANDROID_CLANGPP} ./configure --prefix=${PREFIX} --host=aarch64-linux-android \
|
||||
--enable-static --disable-shared \
|
||||
&& make -j${THREADS} \
|
||||
&& make -j${THREADS} install \
|
||||
&& rm -rf $(pwd)
|
||||
|
||||
ARG SODIUM_VERSION=1.0.18
|
||||
ARG SODIUM_HASH=4f5e89fa84ce1d178a6765b8b46f2b6f91216677
|
||||
RUN set -ex \
|
||||
&& git clone https://github.com/jedisct1/libsodium.git -b ${SODIUM_VERSION} --depth 1 \
|
||||
&& cd libsodium \
|
||||
&& test `git rev-parse HEAD` = ${SODIUM_HASH} || exit 1 \
|
||||
&& ./autogen.sh \
|
||||
&& CC=${ANDROID_CLANG} CXX=${ANDROID_CLANGPP} ./configure --prefix=${PREFIX} --host=aarch64-linux-android --enable-static --disable-shared \
|
||||
&& make -j${THREADS} install \
|
||||
&& rm -rf $(pwd)
|
||||
|
||||
RUN git clone -b libgpg-error-1.38 --depth 1 git://git.gnupg.org/libgpg-error.git \
|
||||
&& cd libgpg-error \
|
||||
&& git reset --hard 71d278824c5fe61865f7927a2ed1aa3115f9e439 \
|
||||
&& ./autogen.sh \
|
||||
&& CC=${ANDROID_CLANG} CXX=${ANDROID_CLANGPP} ./configure --host=aarch64-linux-android --prefix=${PREFIX} --disable-rpath --disable-shared --enable-static --disable-doc --disable-tests \
|
||||
&& PATH=${TOOLCHAIN_DIR}/bin:${HOST_PATH} make -j${THREADS} \
|
||||
&& make -j${THREADS} install \
|
||||
&& rm -rf $(pwd)
|
||||
|
||||
RUN git clone -b libgcrypt-1.8.5 --depth 1 git://git.gnupg.org/libgcrypt.git \
|
||||
&& cd libgcrypt \
|
||||
&& git reset --hard 56606331bc2a80536db9fc11ad53695126007298 \
|
||||
&& ./autogen.sh \
|
||||
&& CC=${ANDROID_CLANG} CXX=${ANDROID_CLANGPP} ./configure --host=aarch64-linux-android --prefix=${PREFIX} --with-gpg-error-prefix=${PREFIX} --disable-shared --enable-static --disable-doc --disable-tests \
|
||||
&& PATH=${TOOLCHAIN_DIR}/bin:${HOST_PATH} make -j${THREADS} \
|
||||
&& make -j${THREADS} install \
|
||||
&& rm -rf $(pwd)
|
||||
|
||||
RUN cd tools \
|
||||
&& wget -q http://dl-ssl.google.com/android/repository/tools_r25.2.5-linux.zip \
|
||||
&& unzip -q tools_r25.2.5-linux.zip \
|
||||
&& rm -f tools_r25.2.5-linux.zip \
|
||||
&& echo y | ${ANDROID_SDK_ROOT}/tools/android update sdk --no-ui --all --filter build-tools-28.0.3
|
||||
|
||||
RUN git clone -b v3.19.7 --depth 1 https://github.com/Kitware/CMake \
|
||||
&& cd CMake \
|
||||
&& git reset --hard 22612dd53a46c7f9b4c3f4b7dbe5c78f9afd9581 \
|
||||
&& PATH=${HOST_PATH} ./bootstrap \
|
||||
&& PATH=${HOST_PATH} make -j${THREADS} \
|
||||
&& PATH=${HOST_PATH} make -j${THREADS} install \
|
||||
&& rm -rf $(pwd)
|
||||
|
||||
RUN git clone -b v1.6.35 --depth 1 https://github.com/glennrp/libpng.git && \
|
||||
cd libpng && \
|
||||
git reset --hard c17d164b4467f099b4484dfd4a279da0bc1dbd4a \
|
||||
&& CC=${ANDROID_CLANG} CXX=${ANDROID_CLANGPP} ./configure --with-zlib-prefix="${PREFIX}" --host=aarch64-linux-android --prefix=${PREFIX} --disable-shared --enable-static \
|
||||
&& PATH=${TOOLCHAIN_DIR}/bin:${HOST_PATH} make -j${THREADS} \
|
||||
&& make -j${THREADS} install \
|
||||
&& rm -rf $(pwd)
|
||||
|
||||
# @TODO: don't hardcode ANDROID_PLATFORM
|
||||
RUN git clone -b v4.0.2 --depth 1 https://github.com/fukuchi/libqrencode.git && \
|
||||
cd libqrencode && \
|
||||
git reset --hard 59ee597f913fcfda7a010a6e106fbee2595f68e4 && \
|
||||
CC=${ANDROID_CLANG} CXX=${ANDROID_CLANGPP} cmake \
|
||||
-DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake" \
|
||||
-DANDROID_PLATFORM="28" \
|
||||
-DBUILD_SHARED_LIBS=OFF \
|
||||
-DARCH="armv8-a" \
|
||||
-DANDROID_ABI="arm64-v8a" \
|
||||
-DANDROID_TOOLCHAIN=clang \
|
||||
-DCMAKE_PREFIX_PATH="${PREFIX}" \
|
||||
-DPNG_PNG_INCLUDE_DIR="${PREFIX}/include/libpng16/" \
|
||||
-DPNG_LIBRARY="${PREFIX}/lib/libqtlibpng_arm64-v8a.a" \
|
||||
-DICONV_LIBRARY=/opt/android/prefix/lib/libiconv.a \
|
||||
-DICONV_INCLUDE_DIR=/opt/android/prefix/include/ \
|
||||
-DCMAKE_INSTALL_PREFIX="${PREFIX}" && \
|
||||
make -j$THREADS && \
|
||||
make -j$THREADS install && \
|
||||
rm -rf $(pwd)
|
||||
|
||||
RUN ls -al && uname -a
|
||||
|
||||
# @TODO: switch to Release
|
||||
CMD set -ex \
|
||||
&& cd /wowlet \
|
||||
&& mkdir -p build/Android/release \
|
||||
&& cd build/Android/release \
|
||||
&& E=1 cmake \
|
||||
-DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake" \
|
||||
-DCMAKE_PREFIX_PATH="${PREFIX}" \
|
||||
-DCMAKE_FIND_ROOT_PATH="${PREFIX}" \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DARCH="armv8-a" \
|
||||
-DANDROID_NATIVE_API_LEVEL=${ANDROID_NATIVE_API_LEVEL} \
|
||||
-DANDROID_ABI="arm64-v8a" \
|
||||
-DANDROID_TOOLCHAIN=clang \
|
||||
-DBoost_USE_STATIC_RUNTIME=ON \
|
||||
-DLRELEASE_PATH="${PREFIX}/bin" \
|
||||
-DQT_ANDROID_APPLICATION_BINARY="wowlet" \
|
||||
-DWITH_SCANNER=ON \
|
||||
-DUSE_DEVICE_TREZOR=OFF \
|
||||
-DUSE_SINGLE_BUILDDIR=ON \
|
||||
-DMANUAL_SUBMODULES=1 \
|
||||
-DUSE_SINGLE_BUILDDIR=ON \
|
||||
-DANDROID=ON \
|
||||
../../.. \
|
||||
&& PATH=${HOST_PATH} make generate_translations_header \
|
||||
&& make -j${THREADS} -C src \
|
||||
&& make -j${THREADS} apk
|
|
@ -1,23 +1,24 @@
|
|||
FROM ubuntu:20.04
|
||||
|
||||
ARG THREADS=1
|
||||
ARG QT_VERSION=5.15.2
|
||||
ARG QT_VERSION=v5.15.2
|
||||
ENV SOURCE_DATE_EPOCH=1397818193
|
||||
|
||||
ENV OPENSSL_ROOT_DIR=/usr/local/openssl/
|
||||
ENV TOR_BIN=/usr/local/tor/bin/tor.exe
|
||||
ENV TOR_VERSION='tor-0.4.5.7'
|
||||
|
||||
RUN apt update && \
|
||||
DEBIAN_FRONTEND=noninteractive apt install -y curl wget zip automake build-essential cmake gcc-mingw-w64 g++-mingw-w64 gettext git libtool pkg-config \
|
||||
DEBIAN_FRONTEND=noninteractive apt install -y curl nano wget zip automake build-essential cmake gcc-mingw-w64 g++-mingw-w64 gettext git libtool pkg-config \
|
||||
python && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN update-alternatives --set x86_64-w64-mingw32-g++ $(which x86_64-w64-mingw32-g++-posix) && \
|
||||
update-alternatives --set x86_64-w64-mingw32-gcc $(which x86_64-w64-mingw32-gcc-posix)
|
||||
|
||||
RUN git clone -b v0.17.1.9 --depth 1 https://github.com/monero-project/monero && \
|
||||
RUN git clone -b v0.18.2.0 --depth 1 https://github.com/monero-project/monero && \
|
||||
cd monero && \
|
||||
git reset --hard 8fef32e45c80aec41f25be9d1d8fb75adc883c64 && \
|
||||
git reset --hard 99be9a044f3854f339548e2d99c539c18d7b1b01 && \
|
||||
cp -a contrib/depends / && \
|
||||
cd .. && \
|
||||
rm -rf monero
|
||||
|
@ -27,8 +28,12 @@ RUN make -j$THREADS -C /depends HOST=x86_64-w64-mingw32 NO_QT=1
|
|||
RUN git clone git://code.qt.io/qt/qt5.git -b ${QT_VERSION} --depth 1 && \
|
||||
cd qt5 && \
|
||||
git clone git://code.qt.io/qt/qtbase.git -b ${QT_VERSION} --depth 1 && \
|
||||
git clone git://code.qt.io/qt/qtdeclarative.git -b ${QT_VERSION} --depth 1 && \
|
||||
git clone git://code.qt.io/qt/qtgraphicaleffects.git -b ${QT_VERSION} --depth 1 && \
|
||||
git clone git://code.qt.io/qt/qtimageformats.git -b ${QT_VERSION} --depth 1 && \
|
||||
git clone git://code.qt.io/qt/qtmultimedia.git -b ${QT_VERSION} --depth 1 && \
|
||||
git clone git://code.qt.io/qt/qtquickcontrols.git -b ${QT_VERSION} --depth 1 && \
|
||||
git clone git://code.qt.io/qt/qtquickcontrols2.git -b ${QT_VERSION} --depth 1 && \
|
||||
git clone git://code.qt.io/qt/qtsvg.git -b ${QT_VERSION} --depth 1 && \
|
||||
git clone git://code.qt.io/qt/qttools.git -b ${QT_VERSION} --depth 1 && \
|
||||
git clone git://code.qt.io/qt/qttranslations.git -b ${QT_VERSION} --depth 1 && \
|
||||
|
@ -38,8 +43,8 @@ RUN git clone git://code.qt.io/qt/qt5.git -b ${QT_VERSION} --depth 1 && \
|
|||
./configure --prefix=/depends/x86_64-w64-mingw32 -xplatform win32-g++ \
|
||||
-device-option CROSS_COMPILE=/usr/bin/x86_64-w64-mingw32- \
|
||||
-I $(pwd)/qtbase/src/3rdparty/angle/include \
|
||||
-opensource -confirm-license -release -static -static-runtime -no-opengl \
|
||||
-no-avx -openssl -I /depends/x86_64-w64-mingw32/include -L /depends/x86_64-w64-mingw32/lib \
|
||||
-opensource -confirm-license -release -static -static-runtime -opengl dynamic -no-angle \
|
||||
-no-feature-qml-worker-script -no-avx -openssl -I /depends/x86_64-w64-mingw32/include -L /depends/x86_64-w64-mingw32/lib \
|
||||
-qt-freetype -qt-harfbuzz -qt-libjpeg -qt-libpng -qt-pcre -qt-zlib \
|
||||
-skip gamepad -skip location -skip qt3d -skip qtactiveqt -skip qtandroidextras \
|
||||
-skip qtcanvas3d -skip qtcharts -skip qtconnectivity -skip qtdatavis3d -skip qtdoc \
|
||||
|
@ -47,7 +52,6 @@ RUN git clone git://code.qt.io/qt/qt5.git -b ${QT_VERSION} --depth 1 && \
|
|||
-skip qtscript -skip qtscxml -skip qtsensors -skip qtserialbus -skip qtserialport \
|
||||
-skip qtspeech -skip qttools -skip qtvirtualkeyboard -skip qtwayland -skip qtwebchannel \
|
||||
-skip qtwebengine -skip qtwebview -skip qtwinextras -skip qtx11extras \
|
||||
-skip qtdeclarative -skip qtquickcontrols -skip qtquickcontrols2 \
|
||||
-skip serialbus -skip webengine \
|
||||
-nomake examples -nomake tests -nomake tools && \
|
||||
make -j$THREADS && \
|
||||
|
@ -92,9 +96,9 @@ RUN git clone -b v1.2.11 --depth 1 https://github.com/madler/zlib && \
|
|||
rm -rf $(pwd)
|
||||
|
||||
# libpng -> libqrencode
|
||||
RUN git clone -b libpng16 --depth 1 https://github.com/glennrp/libpng.git && \
|
||||
RUN git clone -b libpng16 https://github.com/glennrp/libpng.git && \
|
||||
cd libpng && \
|
||||
git reset --hard dbe3e0c43e549a1602286144d94b0666549b18e6 && \
|
||||
git reset --hard a37d4836519517bdce6cb9d956092321eca3e73b && \
|
||||
CPPFLAGS="-I/depends/x86_64-w64-mingw32/include" LDFLAGS="-L/depends/x86_64-w64-mingw32/lib" \
|
||||
./configure --host=x86_64-w64-mingw32 --prefix=/depends/x86_64-w64-mingw32 && \
|
||||
make -j$THREADS && \
|
||||
|
@ -122,11 +126,11 @@ RUN wget https://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.16.tar.gz && \
|
|||
rm -rf $(pwd)
|
||||
|
||||
# OpenSSL -> Tor
|
||||
RUN wget https://www.openssl.org/source/openssl-1.1.1i.tar.gz && \
|
||||
echo "e8be6a35fe41d10603c3cc635e93289ed00bf34b79671a3a4de64fcee00d5242 openssl-1.1.1i.tar.gz" | sha256sum -c && \
|
||||
tar -xzf openssl-1.1.1i.tar.gz && \
|
||||
rm openssl-1.1.1i.tar.gz && \
|
||||
cd openssl-1.1.1i && \
|
||||
RUN wget https://www.openssl.org/source/openssl-1.1.1k.tar.gz && \
|
||||
echo "892a0875b9872acd04a9fde79b1f943075d5ea162415de3047c327df33fbaee5 openssl-1.1.1k.tar.gz" | sha256sum -c && \
|
||||
tar -xzf openssl-1.1.1k.tar.gz && \
|
||||
rm openssl-1.1.1k.tar.gz && \
|
||||
cd openssl-1.1.1k && \
|
||||
./Configure mingw64 no-shared no-dso --cross-compile-prefix=x86_64-w64-mingw32- --prefix=/usr/local/openssl && \
|
||||
make -j$THREADS && \
|
||||
make -j$THREADS install_sw && \
|
||||
|
@ -146,10 +150,9 @@ RUN wget https://github.com/libevent/libevent/releases/download/release-2.1.11-s
|
|||
make -j$THREADS install && \
|
||||
rm -rf $(pwd)
|
||||
|
||||
ENV TOR_VERSION=0.4.5.5-rc
|
||||
RUN git clone -b tor-0.4.5.5-rc --depth 1 https://git.torproject.org/tor.git && \
|
||||
RUN git clone -b tor-0.4.5.7 --depth 1 https://git.torproject.org/tor.git && \
|
||||
cd tor && \
|
||||
git reset --hard b36a00e9a9d3eb4b2949951afaa72e45fb7e68cd && \
|
||||
git reset --hard 83f895c015de55201e5f226f84a866f30f5ee14b && \
|
||||
./autogen.sh && \
|
||||
./configure --host=x86_64-w64-mingw32 \
|
||||
--disable-asciidoc \
|
||||
|
@ -172,12 +175,15 @@ RUN git clone -b tor-0.4.5.5-rc --depth 1 https://git.torproject.org/tor.git &&
|
|||
rm -rf $(pwd) && \
|
||||
strip -s -D /usr/local/tor/bin/tor.exe
|
||||
|
||||
RUN git clone https://git.wownero.com/feather/monero-seed.git && \
|
||||
cd monero-seed && \
|
||||
git reset --hard 4674ef09b6faa6fe602ab5ae0b9ca8e1fd7d5e1b && \
|
||||
RUN git clone https://git.wownero.com/wowlet/wownero-seed.git && \
|
||||
cd wownero-seed && \
|
||||
git reset --hard ef6910b6bb3b61757c36e2e5db0927d75f1731c8 && \
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/depends/x86_64-w64-mingw32 \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_TOOLCHAIN_FILE=/depends/x86_64-w64-mingw32/share/toolchain.cmake -Bbuild && \
|
||||
make -Cbuild -j$THREADS && \
|
||||
make -Cbuild install && \
|
||||
rm -rf $(pwd)
|
||||
|
||||
RUN git config --global --add safe.directory /wowlet
|
||||
RUN git config --global --add safe.directory /wowlet/wownero
|
||||
|
|
|
@ -48,7 +48,7 @@ RUN apt install -y \
|
|||
wget \
|
||||
xz-utils
|
||||
|
||||
RUN git clone -b feather-patch --depth 1 https://git.wownero.com/feather/mxe.git && \
|
||||
RUN git clone -b wowlet-patch --depth 1 https://git.wownero.com/wowlet/mxe.git && \
|
||||
cd mxe && \
|
||||
make -j$THREADS MXE_TARGETS='x86_64-w64-mingw32.static' gcc libqrencode pkgconf libgpg_error libgcrypt cmake libsodium lzma readline libzmq boost qtbase qtsvg qtwebsockets qtimageformats qtmultimedia
|
||||
|
||||
|
@ -67,7 +67,7 @@ RUN ln -s /mxe/usr/x86_64-w64-mingw32.static/lib/libsicuin.a /mxe/usr/x86_64-w64
|
|||
|
||||
ENV PATH="/mxe/usr/bin/:$PATH"
|
||||
|
||||
RUN git clone https://git.wownero.com/feather/monero-seed.git && \
|
||||
RUN git clone https://git.wownero.com/wowlet/monero-seed.git && \
|
||||
cd monero-seed && \
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -Bbuild && \
|
||||
make -Cbuild -j$THREADS && \
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
# this image is used internally for the buildbot
|
||||
FROM ubuntu:20.04
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt clean && apt update
|
||||
RUN apt install -y git build-essential wget curl ngrep unzip file ssh zip
|
||||
|
||||
RUN cat /dev/zero | ssh-keygen -q -N ""
|
||||
|
||||
RUN cat ~/.ssh/id_rsa.pub
|
||||
|
||||
RUN printf "Host *\n StrictHostKeyChecking no" > ~/.ssh/config
|
104
HACKING.md
|
@ -1,104 +0,0 @@
|
|||
# Documentation for developers
|
||||
|
||||
Feather is developed primarily on Linux. It uses Qt 5.15.* and chances are that your
|
||||
distro's package manager has a lower version. It is therefore recommended that you install
|
||||
Qt manually using the online installer, which can be found here: https://www.qt.io/download
|
||||
(under open-source).
|
||||
|
||||
## Jetbrains Clion
|
||||
|
||||
Feather was developed using JetBrains Clion since it integrates nicely
|
||||
with CMake and comes with a built-in debugger. To pass CMake flags to CLion,
|
||||
go to `File->Settings->Build->CMake`, set Build Type to `Debug` and set your
|
||||
preferred CMake options/definitions.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Ubuntu/Debian
|
||||
|
||||
```bash
|
||||
apt install -y git cmake libqrencode-dev build-essential cmake libboost-all-dev \
|
||||
miniupnpc libunbound-dev graphviz doxygen libunwind8-dev pkg-config libssl-dev \
|
||||
libzmq3-dev libsodium-dev libhidapi-dev libnorm-dev libusb-1.0-0-dev libpgm-dev \
|
||||
libprotobuf-dev protobuf-compiler libgcrypt20-dev
|
||||
```
|
||||
|
||||
## Mac OS
|
||||
|
||||
```bash
|
||||
brew install boost zmq openssl libpgm miniupnpc libsodium expat libunwind-headers \
|
||||
protobuf libgcrypt qrencode ccache cmake pkgconfig git
|
||||
```
|
||||
|
||||
## CMake
|
||||
|
||||
After installing Qt you might have a folder called `/home/$user/Qt/`. You need to pass this to CMake
|
||||
via the `CMAKE_PREFIX_PATH` definition. For me this is:
|
||||
|
||||
```
|
||||
-DCMAKE_PREFIX_PATH=/home/dsc/QtNew/5.15.0/gcc_64
|
||||
```
|
||||
|
||||
There are some Monero/Feather related options/definitions that you may pass:
|
||||
|
||||
- `-DXMRIG=OFF` - disable XMRig feature
|
||||
- `-DTOR_BIN=/path/to/tor` - Embed a Tor executable inside Feather
|
||||
- `-DDONATE_BEG=OFF` - disable the dreaded donate requests
|
||||
|
||||
And:
|
||||
|
||||
```
|
||||
-DMANUAL_SUBMODULES=1
|
||||
-DUSE_DEVICE_TREZOR=OFF
|
||||
-DUSE_SINGLE_BUILDDIR=ON
|
||||
-DDEV_MODE=ON
|
||||
```
|
||||
|
||||
If you have OpenSSL installed in a custom location, try:
|
||||
|
||||
```
|
||||
-DOPENSSL_INCLUDE_DIR=/usr/local/lib/openssl-1.1.1g/include
|
||||
-DOPENSSL_SSL_LIBRARY=/usr/local/lib/openssl-1.1.1g/libssl.so.1.1
|
||||
-DOPENSSL_CRYPTO_LIBRARY=/usr/local/lib/openssl-1.1.1g/libcrypto.so.1.1
|
||||
```
|
||||
|
||||
I prefer also enabling verbose makefiles, which may be useful in some situations.
|
||||
|
||||
```
|
||||
-DCMAKE_VERBOSE_MAKEFILE=ON
|
||||
```
|
||||
|
||||
Enable debugging symbols:
|
||||
|
||||
```bash
|
||||
-DCMAKE_BUILD_TYPE=Debug
|
||||
```
|
||||
|
||||
## Feather
|
||||
|
||||
It's best to install Tor locally as a service and start Feather with `--use-local-tor`, this
|
||||
prevents the child process from starting up and saves time.
|
||||
|
||||
#### Ubuntu/Debian
|
||||
|
||||
```bash
|
||||
apt install -y tor
|
||||
sudo service tor start
|
||||
```
|
||||
|
||||
#### Mac OS
|
||||
|
||||
```bash
|
||||
brew install tor
|
||||
brew services start tor
|
||||
```
|
||||
|
||||
To skip the wizards and open a wallet directly use `--wallet-file`:
|
||||
|
||||
```bash
|
||||
./feather --use-local-tor --wallet-file /home/user/Monero/wallets/bla.keys
|
||||
```
|
||||
|
||||
It is recommended that you use `--stagenet` for development. Testnet is also possible,
|
||||
but you'll have to provide Feather a testnet node of your own.
|
||||
|
21
Makefile
|
@ -27,10 +27,9 @@
|
|||
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
|
||||
CMAKEFLAGS = \
|
||||
-DARCH=x86_64 \
|
||||
-DBUILD_64=On \
|
||||
-DBUILD_TESTS=Off \
|
||||
-DXMRIG=Off \
|
||||
-DOPENVR=Off \
|
||||
-DTOR_BIN=Off \
|
||||
-DCMAKE_CXX_STANDARD=11 \
|
||||
-DCMAKE_VERBOSE_MAKEFILE=On \
|
||||
|
@ -41,6 +40,8 @@ CMAKEFLAGS = \
|
|||
$(CMAKEFLAGS_EXTRA)
|
||||
|
||||
release-static: CMAKEFLAGS += -DBUILD_TAG="linux-x64"
|
||||
release-static: CMAKEFLAGS += -DXMRIG=OFF
|
||||
release-static: CMAKEFLAGS += -DARCH=x86-64
|
||||
release-static: CMAKEFLAGS += -DTOR_BIN=$(or ${TOR_BIN},OFF)
|
||||
release-static: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Release
|
||||
release-static: CMAKEFLAGS += -DREPRODUCIBLE=$(or ${SOURCE_DATE_EPOCH},OFF)
|
||||
|
@ -52,8 +53,14 @@ depends:
|
|||
mkdir -p build/$(target)/release
|
||||
cd build/$(target)/release && cmake -D STATIC=ON -DREPRODUCIBLE=$(or ${SOURCE_DATE_EPOCH},OFF) -DTOR_VERSION=$(or ${TOR_VERSION}, OFF) -DTOR_BIN=$(or ${TOR_BIN},OFF) -D DEV_MODE=$(or ${DEV_MODE},OFF) -D BUILD_TAG=$(tag) -D CMAKE_BUILD_TYPE=Release -D CMAKE_TOOLCHAIN_FILE=$(root)/$(target)/share/toolchain.cmake ../../.. && $(MAKE)
|
||||
|
||||
windows:
|
||||
mkdir -p build/$(target)/release
|
||||
cd build/$(target)/release && cmake -D STATIC=ON -DZLIB_ROOT=/usr/x86_64-w64-mingw32/ -DREPRODUCIBLE=$(or ${SOURCE_DATE_EPOCH},OFF) -DTOR_VERSION=$(or ${TOR_VERSION}, OFF) -DOPENVR=ON -DWITH_SCANNER=ON -DTOR_BIN=$(or ${TOR_BIN},OFF) -D DEV_MODE=$(or ${DEV_MODE},OFF) -D BUILD_TAG=$(tag) -D CMAKE_BUILD_TYPE=Release -D CMAKE_TOOLCHAIN_FILE=$(root)/$(target)/share/toolchain.cmake ../../.. && $(MAKE)
|
||||
|
||||
|
||||
windows-mxe-release: CMAKEFLAGS += -DBUILD_TAG="win-x64"
|
||||
windows-mxe-release: CMAKEFLAGS += -DTOR_BIN=$(or ${TOR_BIN},OFF)
|
||||
windows-mxe-debug: CMAKEFLAGS += -DOPENVR=On
|
||||
windows-mxe-release: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Release
|
||||
windows-mxe-release:
|
||||
cmake -Bbuild $(CMAKEFLAGS)
|
||||
|
@ -61,16 +68,8 @@ windows-mxe-release:
|
|||
|
||||
windows-mxe-debug: CMAKEFLAGS += -DBUILD_TAG="win-x64"
|
||||
windows-mxe-debug: CMAKEFLAGS += -DTOR_BIN=$(or ${TOR_BIN},OFF)
|
||||
windows-mxe-debug: CMAKEFLAGS += -DOPENVR=On
|
||||
windows-mxe-debug: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Debug
|
||||
windows-mxe-debug:
|
||||
cmake -Bbuild $(CMAKEFLAGS)
|
||||
$(MAKE) -Cbuild
|
||||
|
||||
mac-release: CMAKEFLAGS += -DSTATIC=Off
|
||||
mac-release: CMAKEFLAGS += -DTOR_BIN=$(or ${TOR_BIN},OFF)
|
||||
mac-release: CMAKEFLAGS += -DBUILD_TAG="mac-x64"
|
||||
mac-release: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Release
|
||||
mac-release:
|
||||
cmake -Bbuild $(CMAKEFLAGS)
|
||||
$(MAKE) -Cbuild
|
||||
$(MAKE) -Cbuild deploy
|
||||
|
|
10
README.md
|
@ -1,12 +1,14 @@
|
|||
[![Build Status](https://ci.wownero.com/api/badges/wowlet/wowlet/status.svg)](https://ci.wownero.com/wowlet/wowlet)
|
||||
|
||||
# WOWlet- a free Wownero desktop wallet
|
||||
|
||||
WOWlet is a free, open-source Wownero client for Linux, Mac OS, and Windows.
|
||||
|
||||
WOWlet is a free, open-source Wownero client for Linux with ports for Mac OS and Windows.
|
||||
![https://i.imgur.com/l7fUf0f.png](https://i.imgur.com/l7fUf0f.png)
|
||||
|
||||
## Development resources
|
||||
|
||||
* Git: [git.wownero.com/wowlet/wowlet](https://git.wownero.com/wowlet/wowlet)
|
||||
* IRC: `#wownero` on Freenode
|
||||
* IRC: `#wownero-dev` on [OFTC](https://oftc.net/)
|
||||
* [Building WOWlet from source](https://git.wownero.com/wowlet/wowlet/src/branch/master/docs/BUILDING.md)
|
||||
* [Working on WOWlet](https://git.wownero.com/wowlet/wowlet/src/branch/master/docs/HACKING.md)
|
||||
|
||||
Copyright (c) 2020-2021 The Monero Project.
|
||||
|
|
|
@ -2,27 +2,4 @@ if(APPLE OR (WIN32 AND NOT STATIC))
|
|||
add_custom_target(deploy)
|
||||
get_target_property(_qmake_executable Qt5::qmake IMPORTED_LOCATION)
|
||||
get_filename_component(_qt_bin_dir "${_qmake_executable}" DIRECTORY)
|
||||
|
||||
if(APPLE AND NOT IOS)
|
||||
find_program(MACDEPLOYQT_EXECUTABLE macdeployqt HINTS "${_qt_bin_dir}")
|
||||
add_custom_command(TARGET deploy
|
||||
POST_BUILD
|
||||
COMMAND "${MACDEPLOYQT_EXECUTABLE}" "$<TARGET_FILE_DIR:wowlet>/../.." -always-overwrite
|
||||
COMMENT "Running macdeployqt..."
|
||||
)
|
||||
|
||||
# workaround for a Qt bug that requires manually adding libqsvg.dylib to bundle
|
||||
find_file(_qt_svg_dylib "libqsvg.dylib" PATHS "${CMAKE_PREFIX_PATH}/plugins/imageformats" NO_DEFAULT_PATH)
|
||||
if(_qt_svg_dylib)
|
||||
add_custom_command(TARGET deploy
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${_qt_svg_dylib} $<TARGET_FILE_DIR:wowlet>/../PlugIns/imageformats/
|
||||
COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change "${CMAKE_PREFIX_PATH}/lib/QtGui.framework/Versions/5/QtGui" "@executable_path/../Frameworks/QtGui.framework/Versions/5/QtGui" $<TARGET_FILE_DIR:wowlet>/../PlugIns/imageformats/libqsvg.dylib
|
||||
COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change "${CMAKE_PREFIX_PATH}/lib/QtWidgets.framework/Versions/5/QtWidgets" "@executable_path/../Frameworks/QtGui.framework/Versions/5/QtGui" $<TARGET_FILE_DIR:wowlet>/../PlugIns/imageformats/libqsvg.dylib
|
||||
COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change "${CMAKE_PREFIX_PATH}/lib/QtSvg.framework/Versions/5/QtSvg" "@executable_path/../Frameworks/QtGui.framework/Versions/5/QtGui" $<TARGET_FILE_DIR:wowlet>/../PlugIns/imageformats/libqsvg.dylib
|
||||
COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change "${CMAKE_PREFIX_PATH}/lib/QtCore.framework/Versions/5/QtCore" "@executable_path/../Frameworks/QtGui.framework/Versions/5/QtGui" $<TARGET_FILE_DIR:wowlet>/../PlugIns/imageformats/libqsvg.dylib
|
||||
COMMENT "Copying libqsvg.dylib, running install_name_tool"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
# - Try to find Cairo
|
||||
# Once done, this will define
|
||||
#
|
||||
# CAIRO_FOUND - system has Cairo
|
||||
# CAIRO_INCLUDE_DIRS - the Cairo include directories
|
||||
# CAIRO_LIBRARIES - link these to use Cairo
|
||||
#
|
||||
# Copyright (C) 2012 Raphael Kubo da Costa <rakuco@webkit.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND ITS CONTRIBUTORS ``AS
|
||||
# IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ITS
|
||||
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
FIND_PACKAGE(PkgConfig)
|
||||
PKG_CHECK_MODULES(PC_CAIRO cairo) # FIXME: After we require CMake 2.8.2 we can pass QUIET to this call.
|
||||
|
||||
FIND_PATH(CAIRO_INCLUDE_DIRS
|
||||
NAMES cairo.h
|
||||
HINTS ${PC_CAIRO_INCLUDEDIR}
|
||||
${PC_CAIRO_INCLUDE_DIRS}
|
||||
PATH_SUFFIXES cairo
|
||||
)
|
||||
|
||||
FIND_LIBRARY(CAIRO_LIBRARIES
|
||||
NAMES cairo
|
||||
HINTS ${PC_CAIRO_LIBDIR}
|
||||
${PC_CAIRO_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
IF (CAIRO_INCLUDE_DIRS)
|
||||
IF (EXISTS "${CAIRO_INCLUDE_DIRS}/cairo-version.h")
|
||||
FILE(READ "${CAIRO_INCLUDE_DIRS}/cairo-version.h" CAIRO_VERSION_CONTENT)
|
||||
|
||||
STRING(REGEX MATCH "#define +CAIRO_VERSION_MAJOR +([0-9]+)" _dummy "${CAIRO_VERSION_CONTENT}")
|
||||
SET(CAIRO_VERSION_MAJOR "${CMAKE_MATCH_1}")
|
||||
|
||||
STRING(REGEX MATCH "#define +CAIRO_VERSION_MINOR +([0-9]+)" _dummy "${CAIRO_VERSION_CONTENT}")
|
||||
SET(CAIRO_VERSION_MINOR "${CMAKE_MATCH_1}")
|
||||
|
||||
STRING(REGEX MATCH "#define +CAIRO_VERSION_MICRO +([0-9]+)" _dummy "${CAIRO_VERSION_CONTENT}")
|
||||
SET(CAIRO_VERSION_MICRO "${CMAKE_MATCH_1}")
|
||||
|
||||
SET(CAIRO_VERSION "${CAIRO_VERSION_MAJOR}.${CAIRO_VERSION_MINOR}.${CAIRO_VERSION_MICRO}")
|
||||
ENDIF ()
|
||||
ENDIF ()
|
||||
|
||||
# FIXME: Should not be needed anymore once we start depending on CMake 2.8.3
|
||||
SET(VERSION_OK TRUE)
|
||||
IF (Cairo_FIND_VERSION)
|
||||
IF (Cairo_FIND_VERSION_EXACT)
|
||||
IF ("${Cairo_FIND_VERSION}" VERSION_EQUAL "${CAIRO_VERSION}")
|
||||
# FIXME: Use IF (NOT ...) with CMake 2.8.2+ to get rid of the ELSE block
|
||||
ELSE ()
|
||||
SET(VERSION_OK FALSE)
|
||||
ENDIF ()
|
||||
ELSE ()
|
||||
IF ("${Cairo_FIND_VERSION}" VERSION_GREATER "${CAIRO_VERSION}")
|
||||
SET(VERSION_OK FALSE)
|
||||
ENDIF ()
|
||||
ENDIF ()
|
||||
ENDIF ()
|
||||
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Cairo DEFAULT_MSG CAIRO_INCLUDE_DIRS CAIRO_LIBRARIES VERSION_OK)
|
|
@ -0,0 +1,26 @@
|
|||
# - Find XFixes
|
||||
# Find the XFixes libraries
|
||||
#
|
||||
# This module defines the following variables:
|
||||
# XFIXES_FOUND - 1 if XFIXES_INCLUDE_DIR & XFIXES_LIBRARY are found, 0 otherwise
|
||||
# XFIXES_INCLUDE_DIR - where to find Xlib.h, etc.
|
||||
# XFIXES_LIBRARY - the X11 library
|
||||
#
|
||||
|
||||
find_path( XFIXES_INCLUDE_DIR
|
||||
NAMES X11/extensions/Xfixes.h
|
||||
PATH_SUFFIXES X11/extensions
|
||||
DOC "The XFixes include directory" )
|
||||
|
||||
find_library( XFIXES_LIBRARY
|
||||
NAMES Xfixes
|
||||
PATHS /usr/lib /lib
|
||||
DOC "The XFixes library" )
|
||||
|
||||
if( XFIXES_INCLUDE_DIR AND XFIXES_LIBRARY )
|
||||
set( XFIXES_FOUND 1 )
|
||||
else()
|
||||
set( XFIXES_FOUND 0 )
|
||||
endif()
|
||||
|
||||
mark_as_advanced( XFIXES_INCLUDE_DIR XFIXES_LIBRARY )
|
|
@ -35,7 +35,7 @@ if(RET)
|
|||
message(WARNING "Cannot determine current commit. Make sure that you are building either from a Git working tree or from a source archive.")
|
||||
set(VERSIONTAG "unknown")
|
||||
set(VERSION_IS_RELEASE "false")
|
||||
configure_file("monero/src/version.cpp.in" "${TO}")
|
||||
configure_file("wownero/src/version.cpp.in" "${TO}")
|
||||
else()
|
||||
string(SUBSTRING ${COMMIT} 0 9 COMMIT)
|
||||
message(STATUS "You are currently on commit ${COMMIT}")
|
||||
|
@ -61,5 +61,5 @@ else()
|
|||
set(VERSION_IS_RELEASE "false")
|
||||
endif()
|
||||
endif()
|
||||
configure_file("monero/src/version.cpp.in" "${TO}")
|
||||
configure_file("wownero/src/version.cpp.in" "${TO}")
|
||||
endif()
|
|
@ -4,7 +4,7 @@
|
|||
find_package(Git QUIET)
|
||||
# Check what commit we're on
|
||||
execute_process(COMMAND "${GIT_EXECUTABLE}" rev-parse --short=9 HEAD RESULT_VARIABLE RET OUTPUT_VARIABLE COMMIT OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/monero)
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/wownero)
|
||||
|
||||
if(RET)
|
||||
# Something went wrong, set the version tag to -unknown
|
||||
|
@ -37,7 +37,7 @@ endif()
|
|||
|
||||
# Check latest tagged release
|
||||
execute_process(COMMAND "${GIT_EXECUTABLE}" describe --abbrev=0 RESULT_VARIABLE RET OUTPUT_VARIABLE TAG OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/monero)
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/wownero)
|
||||
|
||||
if(RET)
|
||||
message(WARNING "Cannot determine most recent tag. Make sure that you are building either from a Git working tree or from a source archive.")
|
||||
|
@ -46,4 +46,4 @@ else ()
|
|||
set(MONERO_VERSION "${TAG}")
|
||||
endif()
|
||||
|
||||
configure_file("cmake/config-feather.h.cmake" "${CMAKE_CURRENT_SOURCE_DIR}/src/config-feather.h")
|
||||
configure_file("cmake/config-wowlet.h.cmake" "${CMAKE_CURRENT_SOURCE_DIR}/src/config-wowlet.h")
|
|
@ -10,8 +10,8 @@ if(RET)
|
|||
# Something went wrong, set the version tag to -unknown
|
||||
|
||||
message(WARNING "Cannot determine current commit. Make sure that you are building either from a Git working tree or from a source archive.")
|
||||
set(FEATHER_BRANCH "unknown")
|
||||
configure_file("cmake/config-feather.h.cmake" "${CMAKE_CURRENT_SOURCE_DIR}/src/config-feather.h")
|
||||
set(WOWLET_BRANCH "unknown")
|
||||
configure_file("cmake/config-wowlet.h.cmake" "${CMAKE_CURRENT_SOURCE_DIR}/src/config-wowlet.h")
|
||||
else()
|
||||
string(SUBSTRING ${COMMIT} 0 9 COMMIT)
|
||||
message(STATUS "You are currently on commit ${COMMIT}")
|
||||
|
@ -21,19 +21,19 @@ else()
|
|||
|
||||
if(NOT TAGGEDCOMMIT)
|
||||
message(STATUS "Cannot determine most recent tag. Make sure that you are building either from a Git working tree or from a source archive.")
|
||||
set(FEATHER_BRANCH "${COMMIT}")
|
||||
set(WOWLET_BRANCH "${COMMIT}")
|
||||
else()
|
||||
message(STATUS "The most recent tag was at ${TAGGEDCOMMIT}")
|
||||
|
||||
# Check if we're building that tagged commit or a different one
|
||||
if(COMMIT STREQUAL TAGGEDCOMMIT)
|
||||
message(STATUS "You are building a tagged release")
|
||||
set(FEATHER_BRANCH "release")
|
||||
set(WOWLET_BRANCH "release")
|
||||
else()
|
||||
message(STATUS "You are ahead of or behind a tagged release")
|
||||
set(FEATHER_BRANCH "${COMMIT}")
|
||||
set(WOWLET_BRANCH "${COMMIT}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
configure_file("cmake/config-feather.h.cmake" "${CMAKE_CURRENT_SOURCE_DIR}/src/config-feather.h")
|
||||
configure_file("cmake/config-wowlet.h.cmake" "${CMAKE_CURRENT_SOURCE_DIR}/src/config-wowlet.h")
|
||||
endif()
|
|
@ -1,12 +0,0 @@
|
|||
#ifndef FEATHER_VERSION_H
|
||||
#define FEATHER_VERSION_H
|
||||
|
||||
#define FEATHER_VERSION "@VERSION@"
|
||||
#define FEATHER_BRANCH "@FEATHER_BRANCH@"
|
||||
|
||||
#define MONERO_VERSION "@MONERO_VERSION@"
|
||||
#define MONERO_BRANCH "@MONERO_BRANCH@"
|
||||
|
||||
#define TOR_VERSION "@TOR_VERSION@"
|
||||
|
||||
#endif //FEATHER_VERSION_H
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef WOWLET_VERSION_H
|
||||
#define WOWLET_VERSION_H
|
||||
|
||||
#define WOWLET_VERSION "@VERSION@"
|
||||
#define WOWLET_BRANCH "@WOWLET_BRANCH@"
|
||||
#define WOWLET_VERSION_SEMVER "@VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_REVISION@"
|
||||
|
||||
#define MONERO_VERSION "@MONERO_VERSION@"
|
||||
#define MONERO_BRANCH "@MONERO_BRANCH@"
|
||||
|
||||
#define TOR_VERSION "@TOR_VERSION@"
|
||||
|
||||
#endif //WOWLET_VERSION_H
|
|
@ -1,33 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
unset SOURCE_DATE_EPOCH
|
||||
|
||||
APPDIR="$PWD/wowlet.AppDir"
|
||||
|
||||
mkdir -p "$APPDIR"
|
||||
mkdir -p "$APPDIR/usr/share/applications/"
|
||||
mkdir -p "$APPDIR/usr/bin"
|
||||
|
||||
cp "$PWD/src/assets/wowlet.desktop" "$APPDIR/usr/share/applications/wowlet.desktop"
|
||||
cp "$PWD/src/assets/images/appicons/64x64.png" "$APPDIR/wowlet.png"
|
||||
cp "$PWD/build/bin/wowlet" "$APPDIR/usr/bin/wowlet"
|
||||
|
||||
LD_LIBRARY_PATH=/usr/local/lib /linuxdeployqt/squashfs-root/AppRun wowlet.AppDir/usr/share/applications/wowlet.desktop -bundle-non-qt-libs
|
||||
|
||||
find wowlet.AppDir/ -exec touch -h -a -m -t 202101010100.00 {} \;
|
||||
|
||||
# Manually create AppImage (reproducibly)
|
||||
|
||||
# download runtime
|
||||
wget -nc https://github.com/AppImage/AppImageKit/releases/download/12/runtime-x86_64
|
||||
echo "24da8e0e149b7211cbfb00a545189a1101cb18d1f27d4cfc1895837d2c30bc30 runtime-x86_64" | sha256sum -c
|
||||
|
||||
mksquashfs wowlet.AppDir wowlet.squashfs -info -root-owned -no-xattrs -noappend -fstime 0
|
||||
# mksquashfs writes a timestamp to the header
|
||||
printf '\x00\x00\x00\x00' | dd conv=notrunc of=wowlet.squashfs bs=1 seek=$((0x8))
|
||||
|
||||
rm -f wowlet.AppImage
|
||||
cat runtime-x86_64 >> wowlet.AppImage
|
||||
cat wowlet.squashfs >> wowlet.AppImage
|
||||
chmod a+x wowlet.AppImage
|
|
@ -0,0 +1,46 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Make directories
|
||||
|
||||
DEBDIR="$PWD/wowlet.DebDir"
|
||||
mkdir -p "$DEBDIR"
|
||||
mkdir -p "$DEBDIR/DEBIAN/"
|
||||
mkdir -p "$DEBDIR/debian/"
|
||||
mkdir -p "$DEBDIR/usr/bin/"
|
||||
mkdir -p "$DEBDIR/usr/share/doc/wowlet/"
|
||||
mkdir -p "$DEBDIR/usr/share/metainfo/"
|
||||
mkdir -p "$DEBDIR/usr/share/applications/"
|
||||
mkdir -p "$DEBDIR/usr/share/man/man1/"
|
||||
mkdir -p "$DEBDIR/usr/share/icons/hicolor/scalable/apps/"
|
||||
mkdir -p "$DEBDIR/usr/share/icons/hicolor/48x48/apps/"
|
||||
mkdir -p "$DEBDIR/usr/share/icons/hicolor/64x64/apps/"
|
||||
mkdir -p "$DEBDIR/usr/share/icons/hicolor/96x96/apps/"
|
||||
mkdir -p "$DEBDIR/usr/share/icons/hicolor/128x128/apps/"
|
||||
mkdir -p "$DEBDIR/usr/share/icons/hicolor/192x192/apps/"
|
||||
mkdir -p "$DEBDIR/usr/share/icons/hicolor/256x256/apps/"
|
||||
|
||||
# Copy over assets
|
||||
|
||||
cp "$PWD/contrib/debian/control" "$DEBDIR/DEBIAN/control"
|
||||
cp "$PWD/contrib/debian/copyright" "$DEBDIR/debian/copyright"
|
||||
cp "$PWD/contrib/debian/copyright" "$DEBDIR/usr/share/doc/wowlet/copyright"
|
||||
cp "$PWD/contrib/debian/changelog.gz" "$DEBDIR/usr/share/doc/wowlet/changelog.gz"
|
||||
cp "$PWD/src/assets/org.wowlet.wowlet.metainfo.xml" "$DEBDIR/usr/share/metainfo/org.wowlet.wowlet.metainfo.xml"
|
||||
cp "$PWD/README.md" "$DEBDIR/usr/share/doc/wowlet/README"
|
||||
cp "$PWD/docs/SECURITY.md" "$DEBDIR/usr/share/doc/wowlet/SECURITY"
|
||||
cp "$PWD/build/bin/wowlet" "$DEBDIR/usr/bin/wowlet"
|
||||
cp "$PWD/src/assets/org.wowlet.wowlet.desktop" "$DEBDIR/usr/share/applications/org.wowlet.wowlet.desktop"
|
||||
cp "$PWD/src/assets/wowlet.1.gz" "$DEBDIR/usr/share/man/man1/wowlet.1.gz"
|
||||
cp "$PWD/src/assets/images/appicons/wowlet.svg" "$DEBDIR/usr/share/icons/hicolor/scalable/apps/wowlet.svg"
|
||||
cp "$PWD/src/assets/images/appicons/48x48.png" "$DEBDIR/usr/share/icons/hicolor/48x48/apps/wowlet.png"
|
||||
cp "$PWD/src/assets/images/appicons/64x64.png" "$DEBDIR/usr/share/icons/hicolor/64x64/apps/wowlet.png"
|
||||
cp "$PWD/src/assets/images/appicons/96x96.png" "$DEBDIR/usr/share/icons/hicolor/96x96/apps/wowlet.png"
|
||||
cp "$PWD/src/assets/images/appicons/128x128.png" "$DEBDIR/usr/share/icons/hicolor/128x128/apps/wowlet.png"
|
||||
cp "$PWD/src/assets/images/appicons/192x192.png" "$DEBDIR/usr/share/icons/hicolor/192x192/apps/wowlet.png"
|
||||
cp "$PWD/src/assets/images/appicons/256x256.png" "$DEBDIR/usr/share/icons/hicolor/256x256/apps/wowlet.png"
|
||||
|
||||
# Build deb package
|
||||
|
||||
dpkg-deb --build $DEBDIR
|
||||
mv wowlet.DebDir.deb wowlet_2.1_amd64.deb
|
|
@ -0,0 +1,12 @@
|
|||
Package: wowlet
|
||||
Version: 2.1
|
||||
Section: net
|
||||
Priority: optional
|
||||
Architecture: amd64
|
||||
Essential: no
|
||||
Installed-Size: 76800
|
||||
Maintainer: wowario <wowario@protonmail.com>
|
||||
Description: WOWlet is a free, open-source Wownero client for Linux with ports for Mac OS and Windows.
|
||||
Tag: office::finance
|
||||
Homepage: https://git.wownero.com/wowlet/wowlet
|
||||
Depends: libxcb-icccm4, libxcb-image0, libxcb-keysyms1, libxcb-render-util0, libxcb-xkb1, libxkbcommon-x11-0
|
|
@ -0,0 +1,31 @@
|
|||
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: wowlet
|
||||
Source: https://git.wownero.com/wowlet/wowlet
|
||||
|
||||
Files: *
|
||||
Copyright: (c) 2020-2021 The Monero Project
|
||||
License: BSD-3-clause
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,93 @@
|
|||
# Set project name.
|
||||
project(OpenVRSDK)
|
||||
|
||||
# Fetch the version from the headers
|
||||
set(VERSION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/headers/openvr.h")
|
||||
|
||||
set(VERSION_MAJOR_REGEX "\tstatic const uint32_t k_nSteamVRVersionMajor = (.+);")
|
||||
set(VERSION_MINOR_REGEX "\tstatic const uint32_t k_nSteamVRVersionMinor = (.+);")
|
||||
set(VERSION_BUILD_REGEX "\tstatic const uint32_t k_nSteamVRVersionBuild = (.+);")
|
||||
|
||||
file(STRINGS "${VERSION_FILE}" VERSION_MAJOR_STRING REGEX "${VERSION_MAJOR_REGEX}")
|
||||
file(STRINGS "${VERSION_FILE}" VERSION_MINOR_STRING REGEX "${VERSION_MINOR_REGEX}")
|
||||
file(STRINGS "${VERSION_FILE}" VERSION_BUILD_STRING REGEX "${VERSION_BUILD_REGEX}")
|
||||
|
||||
string(REGEX REPLACE "${VERSION_MAJOR_REGEX}" "\\1" VERSION_MAJOR ${VERSION_MAJOR_STRING})
|
||||
string(REGEX REPLACE "${VERSION_MINOR_REGEX}" "\\1" VERSION_MINOR ${VERSION_MINOR_STRING})
|
||||
string(REGEX REPLACE "${VERSION_BUILD_REGEX}" "\\1" VERSION_BUILD ${VERSION_BUILD_STRING})
|
||||
|
||||
set(OPENVR_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_BUILD}")
|
||||
|
||||
# Setup some options.
|
||||
option(BUILD_SHARED "Builds the library as shared library" OFF)
|
||||
option(BUILD_FRAMEWORK "Builds the library as an apple Framework" OFF)
|
||||
option(BUILD_UNIVERSAL "Builds the shared or framework as a universal (fat, 32- & 64-bit) binary" ON)
|
||||
option(BUILD_OSX_I386 "Builds the shared or framework as a 32-bit binary, even on a 64-bit platform" OFF)
|
||||
option(USE_LIBCXX "Uses libc++ instead of libstdc++" ON)
|
||||
option(USE_CUSTOM_LIBCXX "Uses a custom libc++" OFF)
|
||||
|
||||
add_definitions( -DVR_API_PUBLIC )
|
||||
|
||||
# Check if 32 or 64 bit system.
|
||||
set(SIZEOF_VOIDP ${CMAKE_SIZEOF_VOID_P})
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(PROCESSOR_ARCH "64")
|
||||
else()
|
||||
set(PROCESSOR_ARCH "32")
|
||||
endif()
|
||||
|
||||
# Get platform.
|
||||
if(WIN32)
|
||||
set(PLATFORM_NAME "win")
|
||||
if(NOT BUILD_SHARED)
|
||||
add_definitions(-DOPENVR_BUILD_STATIC)
|
||||
endif()
|
||||
elseif(UNIX AND NOT APPLE)
|
||||
if(CMAKE_SYSTEM_NAME MATCHES ".*Linux")
|
||||
set(PLATFORM_NAME "linux")
|
||||
add_definitions(-DLINUX -DPOSIX)
|
||||
if(PROCESSOR_ARCH MATCHES "64")
|
||||
add_definitions(-DLINUX64)
|
||||
endif()
|
||||
endif()
|
||||
elseif(APPLE)
|
||||
if(CMAKE_SYSTEM_NAME MATCHES ".*Darwin.*" OR CMAKE_SYSTEM_NAME MATCHES ".*MacOS.*")
|
||||
set(PLATFORM_NAME "osx")
|
||||
add_definitions(-DOSX -DPOSIX)
|
||||
if(BUILD_UNIVERSAL)
|
||||
set(CMAKE_OSX_ARCHITECTURES "i386;x86_64")
|
||||
endif()
|
||||
if(BUILD_OSX_I386)
|
||||
set(PROCESSOR_ARCH "32")
|
||||
set(CMAKE_OSX_ARCHITECTURES "i386")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Set output folder for static and shared libraries
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin/${PLATFORM_NAME}${PROCESSOR_ARCH})
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin/${PLATFORM_NAME}${PROCESSOR_ARCH})
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin/${PLATFORM_NAME}${PROCESSOR_ARCH})
|
||||
|
||||
# Enable some properties.
|
||||
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
# Enable c++11 and hide symbols which shouldn't be visible
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fPIC -fvisibility=hidden")
|
||||
|
||||
# Set custom libc++ usage here
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "Clang" AND USE_LIBCXX)
|
||||
if(USE_CUSTOM_LIBCXX)
|
||||
if(BUILD_SHARED)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -stdlib=libc++")
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdinc++")
|
||||
include_directories( ${LIBCXX_INCLUDE} ${LIBCXX_ABI_INCLUDE})
|
||||
message(STATUS "Using custom libc++")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
||||
message(STATUS "Using libc++")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_subdirectory(src)
|
|
@ -0,0 +1,27 @@
|
|||
Copyright (c) 2015, Valve Corporation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,19 @@
|
|||
### Warning
|
||||
|
||||
**Hard forked from commit `4c85abcb7f7f1f02adaf3812018c99fc593bc341` @ openvr**.
|
||||
|
||||
At the time of writing, the above version does not compile. Had to make several changes. In addition,
|
||||
binary blobs where removed from the repository.
|
||||
|
||||
### OpenVR SDK
|
||||
|
||||
OpenVR is an API and runtime that allows access to VR hardware from multiple
|
||||
vendors without requiring that applications have specific knowledge of the
|
||||
hardware they are targeting. This repository is an SDK that contains the API
|
||||
and samples. The runtime is under SteamVR in Tools on Steam.
|
||||
|
||||
### Documentation
|
||||
|
||||
Documentation for the API is available on the [GitHub Wiki](https://github.com/ValveSoftware/openvr/wiki/API-Documentation)
|
||||
|
||||
More information on OpenVR and SteamVR can be found on http://steamvr.com
|
|
@ -0,0 +1,9 @@
|
|||
set(CMAKE_SYSTEM_NAME Linux)
|
||||
|
||||
set(CMAKE_C_COMPILER clang)
|
||||
set(CMAKE_CXX_COMPILER clang++)
|
||||
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
|
@ -0,0 +1,116 @@
|
|||
# Project name.
|
||||
project(openvr_api)
|
||||
|
||||
set( LIBNAME "openvr_api" )
|
||||
set(OPENVR_HEADER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../headers)
|
||||
|
||||
# Set some properies for specific files.
|
||||
if(APPLE)
|
||||
set(CMAKE_MACOSX_RPATH 1)
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||
set_source_files_properties(vrcommon/pathtools_public.cpp vrcommon/vrpathregistry_public.cpp PROPERTIES COMPILE_FLAGS "-x objective-c++")
|
||||
endif()
|
||||
if(BUILD_SHARED OR BUILD_FRAMEWORK)
|
||||
find_library(FOUNDATION_FRAMEWORK Foundation)
|
||||
mark_as_advanced(FOUNDATION_FRAMEWORK)
|
||||
set(EXTRA_LIBS ${EXTRA_LIBS} ${FOUNDATION_FRAMEWORK})
|
||||
endif(BUILD_SHARED OR BUILD_FRAMEWORK)
|
||||
elseif(WIN32)
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
add_definitions( -DWIN64 )
|
||||
set( LIBNAME "openvr_api64" )
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Add include folders.
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../headers ${CMAKE_CURRENT_SOURCE_DIR}/vrcommon)
|
||||
|
||||
if(USE_CUSTOM_LIBCXX)
|
||||
link_directories(
|
||||
${LIBCXX_LIB_DIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
# Set the source group and files.
|
||||
set(CORE_FILES
|
||||
openvr_api_public.cpp
|
||||
jsoncpp.cpp
|
||||
)
|
||||
set(VRCOMMON_FILES
|
||||
vrcommon/dirtools_public.cpp
|
||||
vrcommon/envvartools_public.cpp
|
||||
vrcommon/pathtools_public.cpp
|
||||
vrcommon/sharedlibtools_public.cpp
|
||||
vrcommon/hmderrors_public.cpp
|
||||
vrcommon/vrpathregistry_public.cpp
|
||||
vrcommon/strtools_public.cpp
|
||||
)
|
||||
|
||||
set(SOURCE_FILES
|
||||
${CORE_FILES}
|
||||
${VRCOMMON_FILES}
|
||||
)
|
||||
|
||||
set(PUBLIC_HEADER_FILES
|
||||
${OPENVR_HEADER_DIR}/openvr_driver.h
|
||||
${OPENVR_HEADER_DIR}/openvr_capi.h
|
||||
${OPENVR_HEADER_DIR}/openvr.h
|
||||
)
|
||||
|
||||
source_group("Src" FILES
|
||||
${CORE_FILES}
|
||||
)
|
||||
|
||||
source_group("VRCommon" FILES
|
||||
${VRCOMMON_FILES}
|
||||
)
|
||||
|
||||
# Build the library.
|
||||
if(BUILD_SHARED)
|
||||
add_library(${LIBNAME} SHARED ${SOURCE_FILES})
|
||||
elseif(BUILD_FRAMEWORK)
|
||||
set( LIBNAME "OpenVR" )
|
||||
add_library( ${LIBNAME}
|
||||
SHARED ${SOURCE_FILES}
|
||||
${CMAKE_SOURCE_DIR}/headers/openvr.h
|
||||
${CMAKE_SOURCE_DIR}/headers/openvr_api.cs
|
||||
${CMAKE_SOURCE_DIR}/headers/openvr_api.json
|
||||
${CMAKE_SOURCE_DIR}/headers/openvr_capi.h
|
||||
${CMAKE_SOURCE_DIR}/headers/openvr_driver.h
|
||||
)
|
||||
set_target_properties(OpenVR PROPERTIES
|
||||
FRAMEWORK TRUE
|
||||
FRAMEWORK_VERSION A
|
||||
MACOSX_FRAMEWORK_IDENTIFIER com.valvesoftware.OpenVR.framework
|
||||
MACOSX_FRAMEWORK_INFO_PLIST ${CMAKE_SOURCE_DIR}/src/Info.plist
|
||||
# "current version" in semantic format in Mach-O binary file
|
||||
VERSION 1.0.6
|
||||
# "compatibility version" in semantic format in Mach-O binary file
|
||||
SOVERSION 1.0.0
|
||||
PUBLIC_HEADER "${CMAKE_SOURCE_DIR}/headers/openvr.h;${CMAKE_SOURCE_DIR}/headers/openvr_api.cs;${CMAKE_SOURCE_DIR}/headers/openvr_api.json;${CMAKE_SOURCE_DIR}/headers/openvr_capi.h;${CMAKE_SOURCE_DIR}/headers/openvr_driver.h"
|
||||
LINKER_LANGUAGE CXX
|
||||
)
|
||||
else()
|
||||
add_library(${LIBNAME} STATIC ${SOURCE_FILES})
|
||||
endif()
|
||||
|
||||
if(USE_CUSTOM_LIBCXX)
|
||||
set(EXTRA_LIBS ${EXTRA_LIBS} c++ c++abi)
|
||||
endif()
|
||||
|
||||
target_link_libraries(${LIBNAME} ${EXTRA_LIBS} ${CMAKE_DL_LIBS})
|
||||
target_include_directories(${LIBNAME} PUBLIC ${OPENVR_HEADER_DIR})
|
||||
|
||||
install(TARGETS ${LIBNAME} DESTINATION lib)
|
||||
install(FILES ${PUBLIC_HEADER_FILES} DESTINATION include/openvr)
|
||||
|
||||
# Generate a .pc file for linux environments
|
||||
if(PLATFORM_NAME MATCHES "linux")
|
||||
set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files")
|
||||
CONFIGURE_FILE("openvr.pc.in" "openvr.pc" @ONLY)
|
||||
|
||||
set(OPENVR_PC ${CMAKE_CURRENT_BINARY_DIR}/openvr.pc)
|
||||
if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL )
|
||||
install(FILES ${OPENVR_PC} DESTINATION "${INSTALL_PKGCONFIG_DIR}")
|
||||
endif()
|
||||
endif()
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.valvesoftware.OpenVR.framework</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>OpenVR</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,39 @@
|
|||
This is the source code for the OpenVR API client binding library which connects
|
||||
OpenVR applications to the SteamVR runtime, taking into account the version
|
||||
of the OpenVR interface they were compiled against.
|
||||
|
||||
The client binding library - openvr_api.dll on Windows, openvr_api.so on
|
||||
Linux, and openvr_api.dylib or OpenVR.framework on macOS - knows how to find
|
||||
and read the SteamVR runtime installation information which allows it to
|
||||
find and dynamically connect to the installed runtime. In combination with the
|
||||
interface version identifiers from /include/openvr.h which are baked
|
||||
into applications at the time they are built, the OpenVR API client
|
||||
binding library captures and conveys to the SteamVR runtime the version
|
||||
of the OpenVR API interface behavior that the application expects.
|
||||
|
||||
Applications carry with them a private/local copy of the client binding
|
||||
library when they ship, and they should install it locally to their
|
||||
application. Applications should not install the client binding library
|
||||
globally or attempt to link to a globally installed client binding library.
|
||||
Doing so negates at least part of the ability for the client binding library
|
||||
to accurately reflect the version of the OpenVR API that the application
|
||||
was built against, and so hinders compatibility support in the face of
|
||||
API changes.
|
||||
|
||||
Most applications should simply link to and redistribute with their application
|
||||
the pre-built client binding library found in the /bin directory of this
|
||||
repository. Some small number of applications which have specific requirements
|
||||
around redistributing only binaries they build themselves should build
|
||||
the client library from this source and either statically link it into
|
||||
their application or redistribute the binary they build.
|
||||
|
||||
This is a cmake project, to build it use the version of cmake appropriate
|
||||
for your platform. For example, to build on a POSIX system simply perform
|
||||
|
||||
cd src; mkdir _build; cd _build; cmake ..; make
|
||||
|
||||
and you will end up with the static library /src/bin/<arch>/libopenvr_api.a
|
||||
|
||||
To build a shared library, pass -DBUILD_SHARED=1 to cmake.
|
||||
To build as a framework on apple platforms, pass -DBUILD_FRAMEWORK=1 to cmake.
|
||||
To see a complete list of configurable build options, use `cmake -LAH`
|
|
@ -0,0 +1,35 @@
|
|||
//========= Copyright Valve Corporation ============//
|
||||
#pragma once
|
||||
|
||||
namespace vr
|
||||
{
|
||||
|
||||
class IVRClientCore
|
||||
{
|
||||
public:
|
||||
/** Initializes the system */
|
||||
virtual EVRInitError Init( vr::EVRApplicationType eApplicationType, const char *pStartupInfo ) = 0;
|
||||
|
||||
/** cleans up everything in vrclient.dll and prepares the DLL to be unloaded */
|
||||
virtual void Cleanup() = 0;
|
||||
|
||||
/** checks to see if the specified interface/version is supported in this vrclient.dll */
|
||||
virtual EVRInitError IsInterfaceVersionValid( const char *pchInterfaceVersion ) = 0;
|
||||
|
||||
/** Retrieves any interface from vrclient.dll */
|
||||
virtual void *GetGenericInterface( const char *pchNameAndVersion, EVRInitError *peError ) = 0;
|
||||
|
||||
/** Returns true if any driver has an HMD attached. Can be called outside of Init/Cleanup */
|
||||
virtual bool BIsHmdPresent() = 0;
|
||||
|
||||
/** Returns an English error string from inside vrclient.dll which might be newer than the API DLL */
|
||||
virtual const char *GetEnglishStringForHmdError( vr::EVRInitError eError ) = 0;
|
||||
|
||||
/** Returns an error symbol from inside vrclient.dll which might be newer than the API DLL */
|
||||
virtual const char *GetIDForVRInitError( vr::EVRInitError eError ) = 0;
|
||||
};
|
||||
|
||||
static const char * const IVRClientCore_Version = "IVRClientCore_003";
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,284 @@
|
|||
/// Json-cpp amalgated forward header (http://jsoncpp.sourceforge.net/).
|
||||
/// It is intended to be used with #include "json/json-forwards.h"
|
||||
/// This header provides forward declaration for all JsonCpp types.
|
||||
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
// Beginning of content of file: LICENSE
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
The JsonCpp library's source code, including accompanying documentation,
|
||||
tests and demonstration applications, are licensed under the following
|
||||
conditions...
|
||||
|
||||
The author (Baptiste Lepilleur) explicitly disclaims copyright in all
|
||||
jurisdictions which recognize such a disclaimer. In such jurisdictions,
|
||||
this software is released into the Public Domain.
|
||||
|
||||
In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
|
||||
2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is
|
||||
released under the terms of the MIT License (see below).
|
||||
|
||||
In jurisdictions which recognize Public Domain property, the user of this
|
||||
software may choose to accept it either as 1) Public Domain, 2) under the
|
||||
conditions of the MIT License (see below), or 3) under the terms of dual
|
||||
Public Domain/MIT License conditions described here, as they choose.
|
||||
|
||||
The MIT License is about as close to Public Domain as a license can get, and is
|
||||
described in clear, concise terms at:
|
||||
|
||||
http://en.wikipedia.org/wiki/MIT_License
|
||||
|
||||
The full text of the MIT License follows:
|
||||
|
||||
========================================================================
|
||||
Copyright (c) 2007-2010 Baptiste Lepilleur
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use, copy,
|
||||
modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
========================================================================
|
||||
(END LICENSE TEXT)
|
||||
|
||||
The MIT license is compatible with both the GPL and commercial
|
||||
software, affording one all of the rights of Public Domain with the
|
||||
minor nuisance of being required to keep the above copyright notice
|
||||
and license text in the source code. Note also that by accepting the
|
||||
Public Domain "license" you can re-license your copy using whatever
|
||||
license you like.
|
||||
|
||||
*/
|
||||
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
// End of content of file: LICENSE
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef JSON_FORWARD_AMALGATED_H_INCLUDED
|
||||
# define JSON_FORWARD_AMALGATED_H_INCLUDED
|
||||
/// If defined, indicates that the source file is amalgated
|
||||
/// to prevent private header inclusion.
|
||||
#define JSON_IS_AMALGAMATION
|
||||
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
// Beginning of content of file: include/json/config.h
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Copyright 2007-2010 Baptiste Lepilleur
|
||||
// Distributed under MIT license, or public domain if desired and
|
||||
// recognized in your jurisdiction.
|
||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||
|
||||
#ifndef JSON_CONFIG_H_INCLUDED
|
||||
#define JSON_CONFIG_H_INCLUDED
|
||||
|
||||
/// If defined, indicates that json library is embedded in CppTL library.
|
||||
//# define JSON_IN_CPPTL 1
|
||||
|
||||
/// If defined, indicates that json may leverage CppTL library
|
||||
//# define JSON_USE_CPPTL 1
|
||||
/// If defined, indicates that cpptl vector based map should be used instead of
|
||||
/// std::map
|
||||
/// as Value container.
|
||||
//# define JSON_USE_CPPTL_SMALLMAP 1
|
||||
|
||||
// If non-zero, the library uses exceptions to report bad input instead of C
|
||||
// assertion macros. The default is to use exceptions.
|
||||
#ifndef JSON_USE_EXCEPTION
|
||||
#define JSON_USE_EXCEPTION 1
|
||||
#endif
|
||||
|
||||
/// If defined, indicates that the source file is amalgated
|
||||
/// to prevent private header inclusion.
|
||||
/// Remarks: it is automatically defined in the generated amalgated header.
|
||||
// #define JSON_IS_AMALGAMATION
|
||||
|
||||
#ifdef JSON_IN_CPPTL
|
||||
#include <cpptl/config.h>
|
||||
#ifndef JSON_USE_CPPTL
|
||||
#define JSON_USE_CPPTL 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef JSON_IN_CPPTL
|
||||
#define JSON_API CPPTL_API
|
||||
#elif defined(JSON_DLL_BUILD)
|
||||
#if defined(_MSC_VER)
|
||||
#define JSON_API __declspec(dllexport)
|
||||
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
|
||||
#endif // if defined(_MSC_VER)
|
||||
#elif defined(JSON_DLL)
|
||||
#if defined(_MSC_VER)
|
||||
#define JSON_API __declspec(dllimport)
|
||||
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
|
||||
#endif // if defined(_MSC_VER)
|
||||
#endif // ifdef JSON_IN_CPPTL
|
||||
#if !defined(JSON_API)
|
||||
#define JSON_API
|
||||
#endif
|
||||
|
||||
// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for
|
||||
// integer
|
||||
// Storages, and 64 bits integer support is disabled.
|
||||
// #define JSON_NO_INT64 1
|
||||
|
||||
#if defined(_MSC_VER) // MSVC
|
||||
# if _MSC_VER <= 1200 // MSVC 6
|
||||
// Microsoft Visual Studio 6 only support conversion from __int64 to double
|
||||
// (no conversion from unsigned __int64).
|
||||
# define JSON_USE_INT64_DOUBLE_CONVERSION 1
|
||||
// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255'
|
||||
// characters in the debug information)
|
||||
// All projects I've ever seen with VS6 were using this globally (not bothering
|
||||
// with pragma push/pop).
|
||||
# pragma warning(disable : 4786)
|
||||
# endif // MSVC 6
|
||||
|
||||
# if _MSC_VER >= 1500 // MSVC 2008
|
||||
/// Indicates that the following function is deprecated.
|
||||
# define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
|
||||
# endif
|
||||
|
||||
#endif // defined(_MSC_VER)
|
||||
|
||||
|
||||
#ifndef JSON_HAS_RVALUE_REFERENCES
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1600 // MSVC >= 2010
|
||||
#define JSON_HAS_RVALUE_REFERENCES 1
|
||||
#endif // MSVC >= 2010
|
||||
|
||||
#ifdef __clang__
|
||||
#if __has_feature(cxx_rvalue_references)
|
||||
#define JSON_HAS_RVALUE_REFERENCES 1
|
||||
#endif // has_feature
|
||||
|
||||
#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
|
||||
#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L)
|
||||
#define JSON_HAS_RVALUE_REFERENCES 1
|
||||
#endif // GXX_EXPERIMENTAL
|
||||
|
||||
#endif // __clang__ || __GNUC__
|
||||
|
||||
#endif // not defined JSON_HAS_RVALUE_REFERENCES
|
||||
|
||||
#ifndef JSON_HAS_RVALUE_REFERENCES
|
||||
#define JSON_HAS_RVALUE_REFERENCES 0
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
|
||||
# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
|
||||
# define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message)))
|
||||
# elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
|
||||
# define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__))
|
||||
# endif // GNUC version
|
||||
#endif // __clang__ || __GNUC__
|
||||
|
||||
#if !defined(JSONCPP_DEPRECATED)
|
||||
#define JSONCPP_DEPRECATED(message)
|
||||
#endif // if !defined(JSONCPP_DEPRECATED)
|
||||
|
||||
namespace Json {
|
||||
typedef int Int;
|
||||
typedef unsigned int UInt;
|
||||
#if defined(JSON_NO_INT64)
|
||||
typedef int LargestInt;
|
||||
typedef unsigned int LargestUInt;
|
||||
#undef JSON_HAS_INT64
|
||||
#else // if defined(JSON_NO_INT64)
|
||||
// For Microsoft Visual use specific types as long long is not supported
|
||||
#if defined(_MSC_VER) // Microsoft Visual Studio
|
||||
typedef __int64 Int64;
|
||||
typedef unsigned __int64 UInt64;
|
||||
#else // if defined(_MSC_VER) // Other platforms, use long long
|
||||
typedef long long int Int64;
|
||||
typedef unsigned long long int UInt64;
|
||||
#endif // if defined(_MSC_VER)
|
||||
typedef Int64 LargestInt;
|
||||
typedef UInt64 LargestUInt;
|
||||
#define JSON_HAS_INT64
|
||||
#endif // if defined(JSON_NO_INT64)
|
||||
} // end namespace Json
|
||||
|
||||
#endif // JSON_CONFIG_H_INCLUDED
|
||||
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
// End of content of file: include/json/config.h
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
// Beginning of content of file: include/json/forwards.h
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Copyright 2007-2010 Baptiste Lepilleur
|
||||
// Distributed under MIT license, or public domain if desired and
|
||||
// recognized in your jurisdiction.
|
||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||
|
||||
#ifndef JSON_FORWARDS_H_INCLUDED
|
||||
#define JSON_FORWARDS_H_INCLUDED
|
||||
|
||||
#if !defined(JSON_IS_AMALGAMATION)
|
||||
#include "config.h"
|
||||
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||
|
||||
namespace Json {
|
||||
|
||||
// writer.h
|
||||
class FastWriter;
|
||||
class StyledWriter;
|
||||
|
||||
// reader.h
|
||||
class Reader;
|
||||
|
||||
// features.h
|
||||
class Features;
|
||||
|
||||
// value.h
|
||||
typedef unsigned int ArrayIndex;
|
||||
class StaticString;
|
||||
class Path;
|
||||
class PathArgument;
|
||||
class Value;
|
||||
class ValueIteratorBase;
|
||||
class ValueIterator;
|
||||
class ValueConstIterator;
|
||||
|
||||
} // namespace Json
|
||||
|
||||
#endif // JSON_FORWARDS_H_INCLUDED
|
||||
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
// End of content of file: include/json/forwards.h
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif //ifndef JSON_FORWARD_AMALGATED_H_INCLUDED
|
|
@ -0,0 +1,11 @@
|
|||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
exec_prefix=${prefix}
|
||||
libdir=${prefix}/lib
|
||||
includedir=${prefix}/include/openvr
|
||||
|
||||
Name: openvr
|
||||
Description: OpenVR is an API and runtime that allos access to VR hardware.
|
||||
Version: @OPENVR_VERSION@
|
||||
|
||||
Libs: -L${libdir} -lopenvr_api -ldl
|
||||
Cflags: -I${includedir}
|
|
@ -0,0 +1,356 @@
|
|||
//========= Copyright Valve Corporation ============//
|
||||
#define VR_API_EXPORT 1
|
||||
#define VR_API_PUBLIC 1
|
||||
#include "openvr.h"
|
||||
#include "ivrclientcore.h"
|
||||
#include <vrcommon/pathtools_public.h>
|
||||
#include <vrcommon/sharedlibtools_public.h>
|
||||
#include <vrcommon/envvartools_public.h>
|
||||
#include "hmderrors_public.h"
|
||||
#include <vrcommon/strtools_public.h>
|
||||
#include <vrcommon/vrpathregistry_public.h>
|
||||
#include <mutex>
|
||||
|
||||
using vr::EVRInitError;
|
||||
using vr::IVRSystem;
|
||||
using vr::IVRClientCore;
|
||||
using vr::VRInitError_None;
|
||||
|
||||
// figure out how to import from the VR API dll
|
||||
#if defined(_WIN32)
|
||||
#define DYNAMIC_LIB_EXT ".dll"
|
||||
#define PROGRAM_EXT ".exe"
|
||||
|
||||
#if !defined(OPENVR_BUILD_STATIC)
|
||||
#define VR_EXPORT_INTERFACE extern "C" __declspec( dllexport )
|
||||
#else
|
||||
#define VR_EXPORT_INTERFACE extern "C"
|
||||
#endif
|
||||
|
||||
#elif defined(__GNUC__) || defined(COMPILER_GCC) || defined(__APPLE__)
|
||||
|
||||
#define VR_EXPORT_INTERFACE extern "C" __attribute__((visibility("default")))
|
||||
|
||||
#else
|
||||
#error "Unsupported Platform."
|
||||
#endif
|
||||
|
||||
namespace vr
|
||||
{
|
||||
|
||||
static void *g_pVRModule = NULL;
|
||||
static IVRClientCore *g_pHmdSystem = NULL;
|
||||
static std::recursive_mutex g_mutexSystem;
|
||||
|
||||
|
||||
typedef void* (*VRClientCoreFactoryFn)(const char *pInterfaceName, int *pReturnCode);
|
||||
|
||||
static uint32_t g_nVRToken = 0;
|
||||
|
||||
uint32_t VR_GetInitToken()
|
||||
{
|
||||
return g_nVRToken;
|
||||
}
|
||||
|
||||
EVRInitError VR_LoadHmdSystemInternal();
|
||||
void CleanupInternalInterfaces();
|
||||
|
||||
|
||||
uint32_t VR_InitInternal2( EVRInitError *peError, vr::EVRApplicationType eApplicationType, const char *pStartupInfo )
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock( g_mutexSystem );
|
||||
|
||||
EVRInitError err = VR_LoadHmdSystemInternal();
|
||||
if ( err == vr::VRInitError_None )
|
||||
{
|
||||
err = g_pHmdSystem->Init( eApplicationType, pStartupInfo );
|
||||
}
|
||||
|
||||
if ( peError )
|
||||
*peError = err;
|
||||
|
||||
if ( err != VRInitError_None )
|
||||
{
|
||||
SharedLib_Unload( g_pVRModule );
|
||||
g_pHmdSystem = NULL;
|
||||
g_pVRModule = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ++g_nVRToken;
|
||||
}
|
||||
|
||||
VR_INTERFACE uint32_t VR_CALLTYPE VR_InitInternal( EVRInitError *peError, EVRApplicationType eApplicationType );
|
||||
|
||||
uint32_t VR_InitInternal( EVRInitError *peError, vr::EVRApplicationType eApplicationType )
|
||||
{
|
||||
return VR_InitInternal2( peError, eApplicationType, nullptr );
|
||||
}
|
||||
|
||||
void VR_ShutdownInternal()
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock( g_mutexSystem );
|
||||
|
||||
#if !defined( VR_API_PUBLIC )
|
||||
CleanupInternalInterfaces();
|
||||
#endif
|
||||
|
||||
if ( g_pHmdSystem )
|
||||
{
|
||||
g_pHmdSystem->Cleanup();
|
||||
g_pHmdSystem = NULL;
|
||||
}
|
||||
|
||||
if ( g_pVRModule )
|
||||
{
|
||||
SharedLib_Unload( g_pVRModule );
|
||||
g_pVRModule = NULL;
|
||||
}
|
||||
|
||||
++g_nVRToken;
|
||||
}
|
||||
|
||||
EVRInitError VR_LoadHmdSystemInternal()
|
||||
{
|
||||
std::string sRuntimePath, sConfigPath, sLogPath;
|
||||
|
||||
bool bReadPathRegistry = CVRPathRegistry_Public::GetPaths( &sRuntimePath, &sConfigPath, &sLogPath, NULL, NULL );
|
||||
if( !bReadPathRegistry )
|
||||
{
|
||||
return vr::VRInitError_Init_PathRegistryNotFound;
|
||||
}
|
||||
|
||||
// figure out where we're going to look for vrclient.dll
|
||||
// see if the specified path actually exists.
|
||||
if( !Path_IsDirectory( sRuntimePath ) )
|
||||
{
|
||||
return vr::VRInitError_Init_InstallationNotFound;
|
||||
}
|
||||
|
||||
// Because we don't have a way to select debug vs. release yet we'll just
|
||||
// use debug if it's there
|
||||
#if defined( LINUX64 ) || defined( LINUXARM64 )
|
||||
std::string sTestPath = Path_Join( sRuntimePath, "bin", PLATSUBDIR );
|
||||
#else
|
||||
std::string sTestPath = Path_Join( sRuntimePath, "bin" );
|
||||
#endif
|
||||
if( !Path_IsDirectory( sTestPath ) )
|
||||
{
|
||||
return vr::VRInitError_Init_InstallationCorrupt;
|
||||
}
|
||||
|
||||
#if defined( WIN64 )
|
||||
std::string sDLLPath = Path_Join( sTestPath, "vrclient_x64" DYNAMIC_LIB_EXT );
|
||||
#else
|
||||
std::string sDLLPath = Path_Join( sTestPath, "vrclient" DYNAMIC_LIB_EXT );
|
||||
#endif
|
||||
|
||||
// only look in the override
|
||||
void *pMod = SharedLib_Load( sDLLPath.c_str() );
|
||||
// nothing more to do if we can't load the DLL
|
||||
if( !pMod )
|
||||
{
|
||||
return vr::VRInitError_Init_VRClientDLLNotFound;
|
||||
}
|
||||
|
||||
VRClientCoreFactoryFn fnFactory = ( VRClientCoreFactoryFn )( SharedLib_GetFunction( pMod, "VRClientCoreFactory" ) );
|
||||
if( !fnFactory )
|
||||
{
|
||||
SharedLib_Unload( pMod );
|
||||
return vr::VRInitError_Init_FactoryNotFound;
|
||||
}
|
||||
|
||||
int nReturnCode = 0;
|
||||
g_pHmdSystem = static_cast< IVRClientCore * > ( fnFactory( vr::IVRClientCore_Version, &nReturnCode ) );
|
||||
if( !g_pHmdSystem )
|
||||
{
|
||||
SharedLib_Unload( pMod );
|
||||
return vr::VRInitError_Init_InterfaceNotFound;
|
||||
}
|
||||
|
||||
g_pVRModule = pMod;
|
||||
return VRInitError_None;
|
||||
}
|
||||
|
||||
|
||||
void *VR_GetGenericInterface(const char *pchInterfaceVersion, EVRInitError *peError)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock( g_mutexSystem );
|
||||
|
||||
if (!g_pHmdSystem)
|
||||
{
|
||||
if (peError)
|
||||
*peError = vr::VRInitError_Init_NotInitialized;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return g_pHmdSystem->GetGenericInterface(pchInterfaceVersion, peError);
|
||||
}
|
||||
|
||||
bool VR_IsInterfaceVersionValid(const char *pchInterfaceVersion)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock( g_mutexSystem );
|
||||
|
||||
if (!g_pHmdSystem)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return g_pHmdSystem->IsInterfaceVersionValid(pchInterfaceVersion) == VRInitError_None;
|
||||
}
|
||||
|
||||
bool VR_IsHmdPresent()
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock( g_mutexSystem );
|
||||
|
||||
if( g_pHmdSystem )
|
||||
{
|
||||
// if we're already initialized, just call through
|
||||
return g_pHmdSystem->BIsHmdPresent();
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise we need to do a bit more work
|
||||
EVRInitError err = VR_LoadHmdSystemInternal();
|
||||
if( err != VRInitError_None )
|
||||
return false;
|
||||
|
||||
bool bHasHmd = g_pHmdSystem->BIsHmdPresent();
|
||||
|
||||
g_pHmdSystem = NULL;
|
||||
SharedLib_Unload( g_pVRModule );
|
||||
g_pVRModule = NULL;
|
||||
|
||||
return bHasHmd;
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns true if the OpenVR runtime is installed. */
|
||||
bool VR_IsRuntimeInstalled()
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock( g_mutexSystem );
|
||||
|
||||
if( g_pHmdSystem )
|
||||
{
|
||||
// if we're already initialized, OpenVR is obviously installed
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise we need to do a bit more work
|
||||
std::string sRuntimePath, sConfigPath, sLogPath;
|
||||
|
||||
bool bReadPathRegistry = CVRPathRegistry_Public::GetPaths( &sRuntimePath, &sConfigPath, &sLogPath, NULL, NULL );
|
||||
if( !bReadPathRegistry )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// figure out where we're going to look for vrclient.dll
|
||||
// see if the specified path actually exists.
|
||||
if( !Path_IsDirectory( sRuntimePath ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// the installation may be corrupt in some way, but it certainly looks installed
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// Purpose: This is the old Runtime Path interface that is no longer exported in the
|
||||
// latest header. We still want to export it from the DLL, though, so updating
|
||||
// to a new DLL doesn't break old compiled code. This version was not thread
|
||||
// safe and could change the buffer pointer to by a previous result on a
|
||||
// subsequent call
|
||||
// -------------------------------------------------------------------------------
|
||||
VR_EXPORT_INTERFACE const char *VR_CALLTYPE VR_RuntimePath();
|
||||
|
||||
/** Returns where OpenVR runtime is installed. */
|
||||
const char *VR_RuntimePath()
|
||||
{
|
||||
static char rchBuffer[1024];
|
||||
uint32_t unRequiredSize;
|
||||
if ( VR_GetRuntimePath( rchBuffer, sizeof( rchBuffer ), &unRequiredSize ) && unRequiredSize < sizeof( rchBuffer ) )
|
||||
{
|
||||
return rchBuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Returns where OpenVR runtime is installed. */
|
||||
bool VR_GetRuntimePath( char *pchPathBuffer, uint32_t unBufferSize, uint32_t *punRequiredBufferSize )
|
||||
{
|
||||
// otherwise we need to do a bit more work
|
||||
std::string sRuntimePath;
|
||||
|
||||
*punRequiredBufferSize = 0;
|
||||
|
||||
bool bReadPathRegistry = CVRPathRegistry_Public::GetPaths( &sRuntimePath, nullptr, nullptr, nullptr, nullptr );
|
||||
if ( !bReadPathRegistry )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// figure out where we're going to look for vrclient.dll
|
||||
// see if the specified path actually exists.
|
||||
if ( !Path_IsDirectory( sRuntimePath ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
*punRequiredBufferSize = (uint32_t)sRuntimePath.size() + 1;
|
||||
if ( sRuntimePath.size() >= unBufferSize )
|
||||
{
|
||||
*pchPathBuffer = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy_safe( pchPathBuffer, unBufferSize, sRuntimePath.c_str() );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/** Returns the symbol version of an HMD error. */
|
||||
const char *VR_GetVRInitErrorAsSymbol( EVRInitError error )
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock( g_mutexSystem );
|
||||
|
||||
if( g_pHmdSystem )
|
||||
return g_pHmdSystem->GetIDForVRInitError( error );
|
||||
else
|
||||
return GetIDForVRInitError( error );
|
||||
}
|
||||
|
||||
|
||||
/** Returns the english string version of an HMD error. */
|
||||
const char *VR_GetVRInitErrorAsEnglishDescription( EVRInitError error )
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock( g_mutexSystem );
|
||||
|
||||
if ( g_pHmdSystem )
|
||||
return g_pHmdSystem->GetEnglishStringForHmdError( error );
|
||||
else
|
||||
return GetEnglishStringForHmdError( error );
|
||||
}
|
||||
|
||||
|
||||
VR_INTERFACE const char *VR_CALLTYPE VR_GetStringForHmdError( vr::EVRInitError error );
|
||||
|
||||
/** Returns the english string version of an HMD error. */
|
||||
const char *VR_GetStringForHmdError( EVRInitError error )
|
||||
{
|
||||
return VR_GetVRInitErrorAsEnglishDescription( error );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
//========= Copyright Valve Corporation ============//
|
||||
#include <vrcommon/dirtools_public.h>
|
||||
#include <vrcommon/strtools_public.h>
|
||||
#include <vrcommon/pathtools_public.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "windows.h"
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#if defined( OSX )
|
||||
#include <sys/syslimits.h>
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: utility function to create dirs & subdirs
|
||||
//-----------------------------------------------------------------------------
|
||||
bool BCreateDirectoryRecursive( const char *pchPath )
|
||||
{
|
||||
// Does it already exist?
|
||||
if ( Path_IsDirectory( pchPath ) )
|
||||
return true;
|
||||
|
||||
// copy the path into something we can munge
|
||||
int len = (int)strlen( pchPath );
|
||||
char *path = (char *)malloc( len + 1 );
|
||||
strcpy( path, pchPath );
|
||||
|
||||
// Walk backwards to first non-existing dir that we find
|
||||
char *s = path + len - 1;
|
||||
|
||||
const char slash = Path_GetSlash();
|
||||
while ( s > path )
|
||||
{
|
||||
if ( *s == slash )
|
||||
{
|
||||
*s = '\0';
|
||||
bool bExists = Path_IsDirectory( path );
|
||||
*s = slash;
|
||||
|
||||
if ( bExists )
|
||||
{
|
||||
++s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
--s;
|
||||
}
|
||||
|
||||
// and then move forwards from there
|
||||
|
||||
while ( *s )
|
||||
{
|
||||
if ( *s == slash )
|
||||
{
|
||||
*s = '\0';
|
||||
BCreateDirectory( path );
|
||||
*s = slash;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
|
||||
bool bRetVal = BCreateDirectory( path );
|
||||
free( path );
|
||||
return bRetVal;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Creates the directory, returning true if it is created, or if it already existed
|
||||
//-----------------------------------------------------------------------------
|
||||
bool BCreateDirectory( const char *pchPath )
|
||||
{
|
||||
#ifdef WIN32
|
||||
std::wstring wPath = UTF8to16( pchPath );
|
||||
if ( ::CreateDirectoryW( wPath.c_str(), NULL ) )
|
||||
return true;
|
||||
|
||||
if ( ::GetLastError() == ERROR_ALREADY_EXISTS )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
#else
|
||||
int i = mkdir( pchPath, S_IRWXU | S_IRWXG | S_IRWXO );
|
||||
if ( i == 0 )
|
||||
return true;
|
||||
if ( errno == EEXIST )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
//========= Copyright Valve Corporation ============//
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
|
||||
extern bool BCreateDirectoryRecursive( const char *pchPath );
|
||||
extern bool BCreateDirectory( const char *pchPath );
|
||||
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
//========= Copyright Valve Corporation ============//
|
||||
#include <vrcommon/envvartools_public.h>
|
||||
#include <vrcommon/strtools_public.h>
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
#include <cctype>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
|
||||
#undef GetEnvironmentVariable
|
||||
#undef SetEnvironmentVariable
|
||||
#endif
|
||||
|
||||
|
||||
std::string GetEnvironmentVariable( const char *pchVarName )
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
char rchValue[32767]; // max size for an env var on Windows
|
||||
DWORD cChars = GetEnvironmentVariableA( pchVarName, rchValue, sizeof( rchValue ) );
|
||||
if( cChars == 0 )
|
||||
return "";
|
||||
else
|
||||
return rchValue;
|
||||
#elif defined(POSIX)
|
||||
char *pchValue = getenv( pchVarName );
|
||||
if( pchValue )
|
||||
return pchValue;
|
||||
else
|
||||
return "";
|
||||
#else
|
||||
#error "Unsupported Platform"
|
||||
#endif
|
||||
}
|
||||
|
||||
bool GetEnvironmentVariableAsBool( const char *pchVarName, bool bDefault )
|
||||
{
|
||||
std::string sValue = GetEnvironmentVariable( pchVarName );
|
||||
|
||||
if ( sValue.empty() )
|
||||
{
|
||||
return bDefault;
|
||||
}
|
||||
|
||||
sValue = StringToLower( sValue );
|
||||
std::string sYesValues[] = { "y", "yes", "true" };
|
||||
std::string sNoValues[] = { "n", "no", "false" };
|
||||
|
||||
for ( std::string &sMatch : sYesValues )
|
||||
{
|
||||
if ( sMatch == sValue )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for ( std::string &sMatch : sNoValues )
|
||||
{
|
||||
if ( sMatch == sValue )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( std::isdigit( sValue.at(0) ) )
|
||||
{
|
||||
return atoi( sValue.c_str() ) != 0;
|
||||
}
|
||||
|
||||
fprintf( stderr,
|
||||
"GetEnvironmentVariableAsBool(%s): Unable to parse value '%s', using default %d\n",
|
||||
pchVarName, sValue.c_str(), bDefault );
|
||||
return bDefault;
|
||||
}
|
||||
|
||||
bool SetEnvironmentVariable( const char *pchVarName, const char *pchVarValue )
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
return 0 != SetEnvironmentVariableA( pchVarName, pchVarValue );
|
||||
#elif defined(POSIX)
|
||||
if( pchVarValue == NULL )
|
||||
return 0 == unsetenv( pchVarName );
|
||||
else
|
||||
return 0 == setenv( pchVarName, pchVarValue, 1 );
|
||||
#else
|
||||
#error "Unsupported Platform"
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
//========= Copyright Valve Corporation ============//
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
std::string GetEnvironmentVariable( const char *pchVarName );
|
||||
bool GetEnvironmentVariableAsBool( const char *pchVarName, bool bDefault );
|
||||
bool SetEnvironmentVariable( const char *pchVarName, const char *pchVarValue );
|
|
@ -0,0 +1,338 @@
|
|||
//========= Copyright Valve Corporation ============//
|
||||
#include "openvr.h"
|
||||
#include "hmderrors_public.h"
|
||||
#include <stdio.h>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace vr;
|
||||
|
||||
#define RETURN_ENUM_AS_STRING(enumValue) case enumValue: return #enumValue;
|
||||
|
||||
|
||||
const char *GetEnglishStringForHmdError( vr::EVRInitError eError )
|
||||
{
|
||||
switch( eError )
|
||||
{
|
||||
case VRInitError_None: return "No Error (0)";
|
||||
|
||||
case VRInitError_Init_InstallationNotFound: return "Installation Not Found (100)";
|
||||
case VRInitError_Init_InstallationCorrupt: return "Installation Corrupt (101)";
|
||||
case VRInitError_Init_VRClientDLLNotFound: return "vrclient Shared Lib Not Found (102)";
|
||||
case VRInitError_Init_FileNotFound: return "File Not Found (103)";
|
||||
case VRInitError_Init_FactoryNotFound: return "Factory Function Not Found (104)";
|
||||
case VRInitError_Init_InterfaceNotFound: return "Interface Not Found (105)";
|
||||
case VRInitError_Init_InvalidInterface: return "Invalid Interface (106)";
|
||||
case VRInitError_Init_UserConfigDirectoryInvalid: return "User Config Directory Invalid (107)";
|
||||
case VRInitError_Init_HmdNotFound: return "Hmd Not Found (108)";
|
||||
case VRInitError_Init_NotInitialized: return "Not Initialized (109)";
|
||||
case VRInitError_Init_PathRegistryNotFound: return "Installation path could not be located (110)";
|
||||
case VRInitError_Init_NoConfigPath: return "Config path could not be located (111)";
|
||||
case VRInitError_Init_NoLogPath: return "Log path could not be located (112)";
|
||||
case VRInitError_Init_PathRegistryNotWritable: return "Unable to write path registry (113)";
|
||||
case VRInitError_Init_AppInfoInitFailed: return "App info manager init failed (114)";
|
||||
case VRInitError_Init_Retry: return "Internal Retry (115)";
|
||||
case VRInitError_Init_InitCanceledByUser: return "User Canceled Init (116)";
|
||||
case VRInitError_Init_AnotherAppLaunching: return "Another app was already launching (117)";
|
||||
case VRInitError_Init_SettingsInitFailed: return "Settings manager init failed (118)";
|
||||
case VRInitError_Init_ShuttingDown: return "VR system shutting down (119)";
|
||||
case VRInitError_Init_TooManyObjects: return "Too many tracked objects (120)";
|
||||
case VRInitError_Init_NoServerForBackgroundApp: return "Not starting vrserver for background app (121)";
|
||||
case VRInitError_Init_NotSupportedWithCompositor: return "The requested interface is incompatible with the compositor and the compositor is running (122)";
|
||||
case VRInitError_Init_NotAvailableToUtilityApps: return "This interface is not available to utility applications (123)";
|
||||
case VRInitError_Init_Internal: return "vrserver internal error (124)";
|
||||
case VRInitError_Init_HmdDriverIdIsNone: return "Hmd DriverId is invalid (125)";
|
||||
case VRInitError_Init_HmdNotFoundPresenceFailed: return "Hmd Not Found Presence Failed (126)";
|
||||
case VRInitError_Init_VRMonitorNotFound: return "VR Monitor Not Found (127)";
|
||||
case VRInitError_Init_VRMonitorStartupFailed: return "VR Monitor startup failed (128)";
|
||||
case VRInitError_Init_LowPowerWatchdogNotSupported: return "Low Power Watchdog Not Supported (129)";
|
||||
case VRInitError_Init_InvalidApplicationType: return "Invalid Application Type (130)";
|
||||
case VRInitError_Init_NotAvailableToWatchdogApps: return "Not available to watchdog apps (131)";
|
||||
case VRInitError_Init_WatchdogDisabledInSettings: return "Watchdog disabled in settings (132)";
|
||||
case VRInitError_Init_VRDashboardNotFound: return "VR Dashboard Not Found (133)";
|
||||
case VRInitError_Init_VRDashboardStartupFailed: return "VR Dashboard startup failed (134)";
|
||||
case VRInitError_Init_VRHomeNotFound: return "VR Home Not Found (135)";
|
||||
case VRInitError_Init_VRHomeStartupFailed: return "VR home startup failed (136)";
|
||||
case VRInitError_Init_RebootingBusy: return "Rebooting In Progress (137)";
|
||||
case VRInitError_Init_FirmwareUpdateBusy: return "Firmware Update In Progress (138)";
|
||||
case VRInitError_Init_FirmwareRecoveryBusy: return "Firmware Recovery In Progress (139)";
|
||||
case VRInitError_Init_USBServiceBusy: return "USB Service Busy (140)";
|
||||
|
||||
case VRInitError_Driver_Failed: return "Driver Failed (200)";
|
||||
case VRInitError_Driver_Unknown: return "Driver Not Known (201)";
|
||||
case VRInitError_Driver_HmdUnknown: return "HMD Not Known (202)";
|
||||
case VRInitError_Driver_NotLoaded: return "Driver Not Loaded (203)";
|
||||
case VRInitError_Driver_RuntimeOutOfDate: return "Driver runtime is out of date (204)";
|
||||
case VRInitError_Driver_HmdInUse: return "HMD already in use by another application (205)";
|
||||
case VRInitError_Driver_NotCalibrated: return "Device is not calibrated (206)";
|
||||
case VRInitError_Driver_CalibrationInvalid: return "Device Calibration is invalid (207)";
|
||||
case VRInitError_Driver_HmdDisplayNotFound: return "HMD detected over USB, but Monitor not found (208)";
|
||||
case VRInitError_Driver_TrackedDeviceInterfaceUnknown: return "Driver Tracked Device Interface unknown (209)";
|
||||
// case VRInitError_Driver_HmdDisplayNotFoundAfterFix: return "HMD detected over USB, but Monitor not found after attempt to fix (210)"; // taken out upon Ben's request: He thinks that there is no need to separate that error from 208
|
||||
case VRInitError_Driver_HmdDriverIdOutOfBounds: return "Hmd DriverId is our of bounds (211)";
|
||||
case VRInitError_Driver_HmdDisplayMirrored: return "HMD detected over USB, but Monitor may be mirrored instead of extended (212)";
|
||||
case VRInitError_Driver_HmdDisplayNotFoundLaptop: return "On laptop, HMD detected over USB, but Monitor not found (213)";
|
||||
|
||||
case VRInitError_IPC_ServerInitFailed: return "VR Server Init Failed (300)";
|
||||
case VRInitError_IPC_ConnectFailed: return "Connect to VR Server Failed (301)";
|
||||
case VRInitError_IPC_SharedStateInitFailed: return "Shared IPC State Init Failed (302)";
|
||||
case VRInitError_IPC_CompositorInitFailed: return "Shared IPC Compositor Init Failed (303)";
|
||||
case VRInitError_IPC_MutexInitFailed: return "Shared IPC Mutex Init Failed (304)";
|
||||
case VRInitError_IPC_Failed: return "Shared IPC Failed (305)";
|
||||
case VRInitError_IPC_CompositorConnectFailed: return "Shared IPC Compositor Connect Failed (306)";
|
||||
case VRInitError_IPC_CompositorInvalidConnectResponse: return "Shared IPC Compositor Invalid Connect Response (307)";
|
||||
case VRInitError_IPC_ConnectFailedAfterMultipleAttempts: return "Shared IPC Connect Failed After Multiple Attempts (308)";
|
||||
case VRInitError_IPC_ConnectFailedAfterTargetExited: return "Shared IPC Connect Failed After Target Exited (309)";
|
||||
case VRInitError_IPC_NamespaceUnavailable: return "Shared IPC Namespace Unavailable (310)";
|
||||
|
||||
case VRInitError_Compositor_Failed: return "Compositor failed to initialize (400)";
|
||||
case VRInitError_Compositor_D3D11HardwareRequired: return "Compositor failed to find DX11 hardware (401)";
|
||||
case VRInitError_Compositor_FirmwareRequiresUpdate: return "Compositor requires mandatory firmware update (402)";
|
||||
case VRInitError_Compositor_OverlayInitFailed: return "Compositor initialization succeeded, but overlay init failed (403)";
|
||||
case VRInitError_Compositor_ScreenshotsInitFailed: return "Compositor initialization succeeded, but screenshot init failed (404)";
|
||||
case VRInitError_Compositor_UnableToCreateDevice: return "Compositor unable to create graphics device (405)";
|
||||
|
||||
// Oculus
|
||||
case VRInitError_VendorSpecific_UnableToConnectToOculusRuntime: return "Unable to connect to Oculus Runtime (1000)";
|
||||
case VRInitError_VendorSpecific_OculusRuntimeBadInstall: return "Unable to connect to Oculus Runtime, possible bad install (1114)";
|
||||
|
||||
// Lighthouse
|
||||
case VRInitError_VendorSpecific_HmdFound_CantOpenDevice: return "HMD found, but can not open device (1101)";
|
||||
case VRInitError_VendorSpecific_HmdFound_UnableToRequestConfigStart: return "HMD found, but unable to request config (1102)";
|
||||
case VRInitError_VendorSpecific_HmdFound_NoStoredConfig: return "HMD found, but no stored config (1103)";
|
||||
case VRInitError_VendorSpecific_HmdFound_ConfigFailedSanityCheck: return "HMD found, but failed configuration check (1113)";
|
||||
case VRInitError_VendorSpecific_HmdFound_ConfigTooBig: return "HMD found, but config too big (1104)";
|
||||
case VRInitError_VendorSpecific_HmdFound_ConfigTooSmall: return "HMD found, but config too small (1105)";
|
||||
case VRInitError_VendorSpecific_HmdFound_UnableToInitZLib: return "HMD found, but unable to init ZLib (1106)";
|
||||
case VRInitError_VendorSpecific_HmdFound_CantReadFirmwareVersion: return "HMD found, but problems with the data (1107)";
|
||||
case VRInitError_VendorSpecific_HmdFound_UnableToSendUserDataStart: return "HMD found, but problems with the data (1108)";
|
||||
case VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataStart: return "HMD found, but problems with the data (1109)";
|
||||
case VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataNext: return "HMD found, but problems with the data (1110)";
|
||||
case VRInitError_VendorSpecific_HmdFound_UserDataAddressRange: return "HMD found, but problems with the data (1111)";
|
||||
case VRInitError_VendorSpecific_HmdFound_UserDataError: return "HMD found, but problems with the data (1112)";
|
||||
|
||||
case VRInitError_Steam_SteamInstallationNotFound: return "Unable to find Steam installation (2000)";
|
||||
|
||||
default:
|
||||
return GetIDForVRInitError( eError );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
const char *GetIDForVRInitError( vr::EVRInitError eError )
|
||||
{
|
||||
switch( eError )
|
||||
{
|
||||
RETURN_ENUM_AS_STRING( VRInitError_None );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Unknown );
|
||||
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_InstallationNotFound );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_InstallationCorrupt );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_VRClientDLLNotFound );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_FileNotFound );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_FactoryNotFound );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_InterfaceNotFound );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_InvalidInterface );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_UserConfigDirectoryInvalid );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_HmdNotFound );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_NotInitialized );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_PathRegistryNotFound );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_NoConfigPath );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_NoLogPath );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_PathRegistryNotWritable );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_AppInfoInitFailed );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_Retry );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_InitCanceledByUser );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_AnotherAppLaunching );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_SettingsInitFailed );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_ShuttingDown );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_TooManyObjects );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_NoServerForBackgroundApp );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_NotSupportedWithCompositor );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_NotAvailableToUtilityApps );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_Internal );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_HmdDriverIdIsNone );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_HmdNotFoundPresenceFailed );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_VRMonitorNotFound );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_VRMonitorStartupFailed );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_LowPowerWatchdogNotSupported );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_InvalidApplicationType );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_NotAvailableToWatchdogApps );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_WatchdogDisabledInSettings );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_VRDashboardNotFound );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_VRDashboardStartupFailed );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_VRHomeNotFound );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_VRHomeStartupFailed );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_RebootingBusy );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_FirmwareUpdateBusy );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_FirmwareRecoveryBusy );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_USBServiceBusy );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_VRWebHelperStartupFailed );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_TrackerManagerInitFailed );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_AlreadyRunning );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_FailedForVrMonitor);
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_PropertyManagerInitFailed );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_WebServerFailed );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_IllegalTypeTransition );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_MismatchedRuntimes );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_InvalidProcessId );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_VRServiceStartupFailed );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_PrismNeedsNewDrivers );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_PrismStartupTimedOut );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_CouldNotStartPrism );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_CreateDriverDirectDeviceFailed );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Init_PrismExitedUnexpectedly );
|
||||
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Driver_Failed );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Driver_Unknown );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Driver_HmdUnknown);
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Driver_NotLoaded);
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Driver_RuntimeOutOfDate);
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Driver_HmdInUse);
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Driver_NotCalibrated);
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Driver_CalibrationInvalid);
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Driver_HmdDisplayNotFound);
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Driver_TrackedDeviceInterfaceUnknown );
|
||||
// RETURN_ENUM_AS_STRING( VRInitError_Driver_HmdDisplayNotFoundAfterFix );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Driver_HmdDriverIdOutOfBounds );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Driver_HmdDisplayMirrored );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Driver_HmdDisplayNotFoundLaptop );
|
||||
|
||||
RETURN_ENUM_AS_STRING( VRInitError_IPC_ServerInitFailed);
|
||||
RETURN_ENUM_AS_STRING( VRInitError_IPC_ConnectFailed);
|
||||
RETURN_ENUM_AS_STRING( VRInitError_IPC_SharedStateInitFailed);
|
||||
RETURN_ENUM_AS_STRING( VRInitError_IPC_CompositorInitFailed);
|
||||
RETURN_ENUM_AS_STRING( VRInitError_IPC_MutexInitFailed);
|
||||
RETURN_ENUM_AS_STRING( VRInitError_IPC_Failed);
|
||||
RETURN_ENUM_AS_STRING( VRInitError_IPC_CompositorConnectFailed);
|
||||
RETURN_ENUM_AS_STRING( VRInitError_IPC_CompositorInvalidConnectResponse);
|
||||
RETURN_ENUM_AS_STRING( VRInitError_IPC_ConnectFailedAfterMultipleAttempts );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_IPC_ConnectFailedAfterTargetExited );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_IPC_NamespaceUnavailable );
|
||||
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_Failed );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_D3D11HardwareRequired );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_FirmwareRequiresUpdate );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_OverlayInitFailed );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_ScreenshotsInitFailed );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_UnableToCreateDevice );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_SharedStateIsNull );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_NotificationManagerIsNull );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_ResourceManagerClientIsNull );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_MessageOverlaySharedStateInitFailure );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_PropertiesInterfaceIsNull );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateFullscreenWindowFailed );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_SettingsInterfaceIsNull );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_FailedToShowWindow );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_DistortInterfaceIsNull );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_DisplayFrequencyFailure );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_RendererInitializationFailed );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_DXGIFactoryInterfaceIsNull );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_DXGIFactoryCreateFailed );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_DXGIFactoryQueryFailed );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_InvalidAdapterDesktop );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_InvalidHmdAttachment );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_InvalidOutputDesktop );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_InvalidDeviceProvided );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_D3D11RendererInitializationFailed );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_FailedToFindDisplayMode );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_FailedToCreateSwapChain );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_FailedToGetBackBuffer );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_FailedToCreateRenderTarget );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_FailedToCreateDXGI2SwapChain );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_FailedtoGetDXGI2BackBuffer );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_FailedToCreateDXGI2RenderTarget );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_FailedToGetDXGIDeviceInterface );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_SelectDisplayMode );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_FailedToCreateNvAPIRenderTargets );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_NvAPISetDisplayMode );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_FailedToCreateDirectModeDisplay );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_InvalidHmdPropertyContainer );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_UpdateDisplayFrequency );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateRasterizerState );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateWireframeRasterizerState );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateSamplerState );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateClampToBorderSamplerState );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateAnisoSamplerState );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateOverlaySamplerState );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreatePanoramaSamplerState );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateFontSamplerState );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateNoBlendState );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateBlendState );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateAlphaBlendState );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateBlendStateMaskR );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateBlendStateMaskG );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateBlendStateMaskB );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateDepthStencilState );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateDepthStencilStateNoWrite );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateDepthStencilStateNoDepth );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateFlushTexture );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateDistortionSurfaces );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateConstantBuffer );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateHmdPoseConstantBuffer );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateHmdPoseStagingConstantBuffer );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateSharedFrameInfoConstantBuffer );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateOverlayConstantBuffer );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateSceneTextureIndexConstantBuffer );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateReadableSceneTextureIndexConstantBuffer );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateLayerGraphicsTextureIndexConstantBuffer );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateLayerComputeTextureIndexConstantBuffer );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateLayerComputeSceneTextureIndexConstantBuffer );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateComputeHmdPoseConstantBuffer );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateGeomConstantBuffer );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreatePanelMaskConstantBuffer );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreatePixelSimUBO );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateMSAARenderTextures );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateResolveRenderTextures );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateComputeResolveRenderTextures );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateDriverDirectModeResolveTextures );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_OpenDriverDirectModeResolveTextures );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateFallbackSyncTexture );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_ShareFallbackSyncTexture );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateOverlayIndexBuffer );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateOverlayVertexBuffer );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateTextVertexBuffer );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateTextIndexBuffer );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateMirrorTextures );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateLastFrameRenderTexture );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateMirrorOverlay );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_FailedToCreateVirtualDisplayBackbuffer );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_DisplayModeNotSupported );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateOverlayInvalidCall );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_CreateOverlayAlreadyInitialized );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_FailedToCreateMailbox );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_WindowInterfaceIsNull );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_SystemLayerCreateInstance );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Compositor_SystemLayerCreateSession );
|
||||
|
||||
// Vendor-specific errors
|
||||
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_UnableToConnectToOculusRuntime);
|
||||
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_WindowsNotInDevMode );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_OculusRuntimeBadInstall );
|
||||
|
||||
// Lighthouse
|
||||
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_CantOpenDevice);
|
||||
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_UnableToRequestConfigStart);
|
||||
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_NoStoredConfig);
|
||||
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_ConfigFailedSanityCheck );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_ConfigTooBig );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_ConfigTooSmall );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_UnableToInitZLib );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_CantReadFirmwareVersion );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_UnableToSendUserDataStart );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataStart );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataNext );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_UserDataAddressRange );
|
||||
RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_UserDataError );
|
||||
|
||||
RETURN_ENUM_AS_STRING( VRInitError_Steam_SteamInstallationNotFound );
|
||||
|
||||
default:
|
||||
{
|
||||
static char buf[128];
|
||||
sprintf( buf, "Unknown error (%d)", eError );
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
//========= Copyright Valve Corporation ============//
|
||||
#pragma once
|
||||
|
||||
const char *GetEnglishStringForHmdError( vr::EVRInitError eError );
|
||||
const char *GetIDForVRInitError( vr::EVRInitError eError );
|
||||
|
|
@ -0,0 +1,988 @@
|
|||
//========= Copyright Valve Corporation ============//
|
||||
#include <vrcommon/strtools_public.h>
|
||||
#include <vrcommon/pathtools_public.h>
|
||||
|
||||
#if defined( _WIN32)
|
||||
#include <windows.h>
|
||||
#include <direct.h>
|
||||
#include <shobjidl.h>
|
||||
#include <knownfolders.h>
|
||||
#include <shlobj.h>
|
||||
#include <share.h>
|
||||
|
||||
#undef GetEnvironmentVariable
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
|
||||
#if defined OSX
|
||||
#include <Foundation/Foundation.h>
|
||||
#include <AppKit/AppKit.h>
|
||||
#include <mach-o/dyld.h>
|
||||
#define _S_IFDIR S_IFDIR // really from tier0/platform.h which we dont have yet
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
/** Returns the path (including filename) to the current executable */
|
||||
std::string Path_GetExecutablePath()
|
||||
{
|
||||
#if defined( _WIN32 )
|
||||
wchar_t *pwchPath = new wchar_t[MAX_UNICODE_PATH];
|
||||
char *pchPath = new char[MAX_UNICODE_PATH_IN_UTF8];
|
||||
::GetModuleFileNameW( NULL, pwchPath, MAX_UNICODE_PATH );
|
||||
WideCharToMultiByte( CP_UTF8, 0, pwchPath, -1, pchPath, MAX_UNICODE_PATH_IN_UTF8, NULL, NULL );
|
||||
delete[] pwchPath;
|
||||
|
||||
std::string sPath = pchPath;
|
||||
delete[] pchPath;
|
||||
return sPath;
|
||||
#elif defined( OSX )
|
||||
char rchPath[1024];
|
||||
uint32_t nBuff = sizeof( rchPath );
|
||||
bool bSuccess = _NSGetExecutablePath(rchPath, &nBuff) == 0;
|
||||
rchPath[nBuff-1] = '\0';
|
||||
if( bSuccess )
|
||||
return rchPath;
|
||||
else
|
||||
return "";
|
||||
#elif defined LINUX
|
||||
char rchPath[1024];
|
||||
size_t nBuff = sizeof( rchPath );
|
||||
ssize_t nRead = readlink("/proc/self/exe", rchPath, nBuff-1 );
|
||||
if ( nRead != -1 )
|
||||
{
|
||||
rchPath[ nRead ] = 0;
|
||||
return rchPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
#else
|
||||
AssertMsg( false, "Implement Plat_GetExecutablePath" );
|
||||
return "";
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/** Returns the path of the current working directory */
|
||||
std::string Path_GetWorkingDirectory()
|
||||
{
|
||||
std::string sPath;
|
||||
#if defined( _WIN32 )
|
||||
wchar_t buf[MAX_UNICODE_PATH];
|
||||
sPath = UTF16to8( _wgetcwd( buf, MAX_UNICODE_PATH ) );
|
||||
#else
|
||||
char buf[ 1024 ];
|
||||
sPath = getcwd( buf, sizeof( buf ) );
|
||||
#endif
|
||||
return sPath;
|
||||
}
|
||||
|
||||
/** Sets the path of the current working directory. Returns true if this was successful. */
|
||||
bool Path_SetWorkingDirectory( const std::string & sPath )
|
||||
{
|
||||
bool bSuccess;
|
||||
#if defined( _WIN32 )
|
||||
std::wstring wsPath = UTF8to16( sPath.c_str() );
|
||||
bSuccess = 0 == _wchdir( wsPath.c_str() );
|
||||
#else
|
||||
bSuccess = 0 == chdir( sPath.c_str() );
|
||||
#endif
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
/** Gets the path to a temporary directory. */
|
||||
std::string Path_GetTemporaryDirectory()
|
||||
{
|
||||
#if defined( _WIN32 )
|
||||
wchar_t buf[MAX_UNICODE_PATH];
|
||||
if ( GetTempPathW( MAX_UNICODE_PATH, buf ) == 0 )
|
||||
return Path_GetWorkingDirectory();
|
||||
return UTF16to8( buf );
|
||||
#else
|
||||
const char *pchTmpDir = getenv( "TMPDIR" );
|
||||
if ( pchTmpDir == NULL )
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return pchTmpDir;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Returns the specified path without its filename */
|
||||
std::string Path_StripFilename( const std::string & sPath, char slash )
|
||||
{
|
||||
if( slash == 0 )
|
||||
slash = Path_GetSlash();
|
||||
|
||||
std::string::size_type n = sPath.find_last_of( slash );
|
||||
if( n == std::string::npos )
|
||||
return sPath;
|
||||
else
|
||||
return std::string( sPath.begin(), sPath.begin() + n );
|
||||
}
|
||||
|
||||
/** returns just the filename from the provided full or relative path. */
|
||||
std::string Path_StripDirectory( const std::string & sPath, char slash )
|
||||
{
|
||||
if( slash == 0 )
|
||||
slash = Path_GetSlash();
|
||||
|
||||
std::string::size_type n = sPath.find_last_of( slash );
|
||||
if( n == std::string::npos )
|
||||
return sPath;
|
||||
else
|
||||
return std::string( sPath.begin() + n + 1, sPath.end() );
|
||||
}
|
||||
|
||||
/** returns just the filename with no extension of the provided filename.
|
||||
* If there is a path the path is left intact. */
|
||||
std::string Path_StripExtension( const std::string & sPath )
|
||||
{
|
||||
for( std::string::const_reverse_iterator i = sPath.rbegin(); i != sPath.rend(); i++ )
|
||||
{
|
||||
if( *i == '.' )
|
||||
{
|
||||
return std::string( sPath.begin(), i.base() - 1 );
|
||||
}
|
||||
|
||||
// if we find a slash there is no extension
|
||||
if( *i == '\\' || *i == '/' )
|
||||
break;
|
||||
}
|
||||
|
||||
// we didn't find an extension
|
||||
return sPath;
|
||||
}
|
||||
|
||||
/** returns just extension of the provided filename (if any). */
|
||||
std::string Path_GetExtension( const std::string & sPath )
|
||||
{
|
||||
for ( std::string::const_reverse_iterator i = sPath.rbegin(); i != sPath.rend(); i++ )
|
||||
{
|
||||
if ( *i == '.' )
|
||||
{
|
||||
return std::string( i.base(), sPath.end() );
|
||||
}
|
||||
|
||||
// if we find a slash there is no extension
|
||||
if ( *i == '\\' || *i == '/' )
|
||||
break;
|
||||
}
|
||||
|
||||
// we didn't find an extension
|
||||
return "";
|
||||
}
|
||||
|
||||
bool Path_IsAbsolute( const std::string & sPath )
|
||||
{
|
||||
if( sPath.empty() )
|
||||
return false;
|
||||
|
||||
#ifdef _WIN32
|
||||
if ( sPath.size() < 3 ) // must be c:\x or \\x at least
|
||||
return false;
|
||||
|
||||
if ( sPath[1] == ':' ) // drive letter plus slash, but must test both slash cases
|
||||
{
|
||||
if ( sPath[2] == '\\' || sPath[2] == '/' )
|
||||
return true;
|
||||
}
|
||||
else if ( sPath[0] == '\\' && sPath[1] == '\\' ) // UNC path
|
||||
return true;
|
||||
#else
|
||||
if( sPath[0] == '\\' || sPath[0] == '/' ) // any leading slash
|
||||
return true;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/** Makes an absolute path from a relative path and a base path */
|
||||
std::string Path_MakeAbsolute( const std::string & sRelativePath, const std::string & sBasePath )
|
||||
{
|
||||
if( Path_IsAbsolute( sRelativePath ) )
|
||||
return Path_Compact( sRelativePath );
|
||||
else
|
||||
{
|
||||
if( !Path_IsAbsolute( sBasePath ) )
|
||||
return "";
|
||||
|
||||
std::string sCompacted = Path_Compact( Path_Join( sBasePath, sRelativePath ) );
|
||||
if( Path_IsAbsolute( sCompacted ) )
|
||||
return sCompacted;
|
||||
else
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Fixes the directory separators for the current platform */
|
||||
std::string Path_FixSlashes( const std::string & sPath, char slash )
|
||||
{
|
||||
if( slash == 0 )
|
||||
slash = Path_GetSlash();
|
||||
|
||||
std::string sFixed = sPath;
|
||||
for( std::string::iterator i = sFixed.begin(); i != sFixed.end(); i++ )
|
||||
{
|
||||
if( *i == '/' || *i == '\\' )
|
||||
*i = slash;
|
||||
}
|
||||
|
||||
return sFixed;
|
||||
}
|
||||
|
||||
|
||||
char Path_GetSlash()
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
return '\\';
|
||||
#else
|
||||
return '/';
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Jams two paths together with the right kind of slash */
|
||||
std::string Path_Join( const std::string & first, const std::string & second, char slash )
|
||||
{
|
||||
if( slash == 0 )
|
||||
slash = Path_GetSlash();
|
||||
|
||||
// only insert a slash if we don't already have one
|
||||
std::string::size_type nLen = first.length();
|
||||
if( !nLen )
|
||||
return second;
|
||||
#if defined(_WIN32)
|
||||
if( first.back() == '\\' || first.back() == '/' )
|
||||
nLen--;
|
||||
#else
|
||||
char last_char = first[first.length()-1];
|
||||
if (last_char == '\\' || last_char == '/')
|
||||
nLen--;
|
||||
#endif
|
||||
|
||||
return first.substr( 0, nLen ) + std::string( 1, slash ) + second;
|
||||
}
|
||||
|
||||
|
||||
std::string Path_Join( const std::string & first, const std::string & second, const std::string & third, char slash )
|
||||
{
|
||||
return Path_Join( Path_Join( first, second, slash ), third, slash );
|
||||
}
|
||||
|
||||
std::string Path_Join( const std::string & first, const std::string & second, const std::string & third, const std::string &fourth, char slash )
|
||||
{
|
||||
return Path_Join( Path_Join( Path_Join( first, second, slash ), third, slash ), fourth, slash );
|
||||
}
|
||||
|
||||
std::string Path_Join(
|
||||
const std::string & first,
|
||||
const std::string & second,
|
||||
const std::string & third,
|
||||
const std::string & fourth,
|
||||
const std::string & fifth,
|
||||
char slash )
|
||||
{
|
||||
return Path_Join( Path_Join( Path_Join( Path_Join( first, second, slash ), third, slash ), fourth, slash ), fifth, slash );
|
||||
}
|
||||
|
||||
|
||||
std::string Path_RemoveTrailingSlash( const std::string & sRawPath, char slash )
|
||||
{
|
||||
if ( slash == 0 )
|
||||
slash = Path_GetSlash();
|
||||
|
||||
std::string sPath = sRawPath;
|
||||
std::string::size_type nCurrent = sRawPath.length();
|
||||
if ( nCurrent == 0 )
|
||||
return sPath;
|
||||
|
||||
int nLastFound = -1;
|
||||
nCurrent--;
|
||||
while( nCurrent != 0 )
|
||||
{
|
||||
if ( sRawPath[ nCurrent ] == slash )
|
||||
{
|
||||
nLastFound = (int)nCurrent;
|
||||
nCurrent--;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( nLastFound >= 0 )
|
||||
{
|
||||
sPath.erase( nLastFound, std::string::npos );
|
||||
}
|
||||
|
||||
return sPath;
|
||||
}
|
||||
|
||||
|
||||
/** Removes redundant <dir>/.. elements in the path. Returns an empty path if the
|
||||
* specified path has a broken number of directories for its number of ..s */
|
||||
std::string Path_Compact( const std::string & sRawPath, char slash )
|
||||
{
|
||||
if( slash == 0 )
|
||||
slash = Path_GetSlash();
|
||||
|
||||
std::string sPath = Path_FixSlashes( sRawPath, slash );
|
||||
std::string sSlashString( 1, slash );
|
||||
|
||||
// strip out all /./
|
||||
for( std::string::size_type i = 0; (i + 3) < sPath.length(); )
|
||||
{
|
||||
if( sPath[ i ] == slash && sPath[ i+1 ] == '.' && sPath[ i+2 ] == slash )
|
||||
{
|
||||
sPath.replace( i, 3, sSlashString );
|
||||
}
|
||||
else
|
||||
{
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// get rid of trailing /. but leave the path separator
|
||||
if( sPath.length() > 2 )
|
||||
{
|
||||
std::string::size_type len = sPath.length();
|
||||
if( sPath[ len-1 ] == '.' && sPath[ len-2 ] == slash )
|
||||
{
|
||||
sPath.pop_back();
|
||||
//Not sure why the following line of code was used for a while. It causes problems with strlen.
|
||||
//sPath[len-1] = 0; // for now, at least
|
||||
}
|
||||
}
|
||||
|
||||
// get rid of leading ./
|
||||
if( sPath.length() > 2 )
|
||||
{
|
||||
if( sPath[ 0 ] == '.' && sPath[ 1 ] == slash )
|
||||
{
|
||||
sPath.replace( 0, 2, "" );
|
||||
}
|
||||
}
|
||||
|
||||
// each time we encounter .. back up until we've found the previous directory name
|
||||
// then get rid of both
|
||||
std::string::size_type i = 0;
|
||||
while( i < sPath.length() )
|
||||
{
|
||||
if( i > 0 && sPath.length() - i >= 2
|
||||
&& sPath[i] == '.'
|
||||
&& sPath[i+1] == '.'
|
||||
&& ( i + 2 == sPath.length() || sPath[ i+2 ] == slash )
|
||||
&& sPath[ i-1 ] == slash )
|
||||
{
|
||||
// check if we've hit the start of the string and have a bogus path
|
||||
if( i == 1 )
|
||||
return "";
|
||||
|
||||
// find the separator before i-1
|
||||
std::string::size_type iDirStart = i-2;
|
||||
while( iDirStart > 0 && sPath[ iDirStart - 1 ] != slash )
|
||||
--iDirStart;
|
||||
|
||||
// remove everything from iDirStart to i+2
|
||||
sPath.replace( iDirStart, (i - iDirStart) + 3, "" );
|
||||
|
||||
// start over
|
||||
i = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
return sPath;
|
||||
}
|
||||
|
||||
|
||||
/** Returns true if these two paths are the same without respect for internal . or ..
|
||||
* sequences, slash type, or case (on case-insensitive platforms). */
|
||||
bool Path_IsSamePath( const std::string & sPath1, const std::string & sPath2 )
|
||||
{
|
||||
std::string sCompact1 = Path_Compact( sPath1 );
|
||||
std::string sCompact2 = Path_Compact( sPath2 );
|
||||
#if defined(WIN32)
|
||||
return !stricmp( sCompact1.c_str(), sCompact2.c_str() );
|
||||
#else
|
||||
return !strcmp( sCompact1.c_str(), sCompact2.c_str() );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/** Returns the path to the current DLL or exe */
|
||||
std::string Path_GetThisModulePath()
|
||||
{
|
||||
// gets the path of vrclient.dll itself
|
||||
#ifdef WIN32
|
||||
HMODULE hmodule = NULL;
|
||||
|
||||
::GetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, reinterpret_cast<LPCTSTR>(Path_GetThisModulePath), &hmodule );
|
||||
|
||||
wchar_t *pwchPath = new wchar_t[MAX_UNICODE_PATH];
|
||||
char *pchPath = new char[ MAX_UNICODE_PATH_IN_UTF8 ];
|
||||
::GetModuleFileNameW( hmodule, pwchPath, MAX_UNICODE_PATH );
|
||||
WideCharToMultiByte( CP_UTF8, 0, pwchPath, -1, pchPath, MAX_UNICODE_PATH_IN_UTF8, NULL, NULL );
|
||||
delete[] pwchPath;
|
||||
|
||||
std::string sPath = pchPath;
|
||||
delete [] pchPath;
|
||||
return sPath;
|
||||
|
||||
#elif defined( OSX ) || defined( LINUX )
|
||||
// get the addr of a function in vrclient.so and then ask the dlopen system about it
|
||||
Dl_info info;
|
||||
dladdr( (void *)Path_GetThisModulePath, &info );
|
||||
return info.dli_fname;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
/** returns true if the specified path exists and is a directory */
|
||||
bool Path_IsDirectory( const std::string & sPath )
|
||||
{
|
||||
std::string sFixedPath = Path_FixSlashes( sPath );
|
||||
if( sFixedPath.empty() )
|
||||
return false;
|
||||
char cLast = sFixedPath[ sFixedPath.length() - 1 ];
|
||||
if( cLast == '/' || cLast == '\\' )
|
||||
sFixedPath.erase( sFixedPath.end() - 1, sFixedPath.end() );
|
||||
|
||||
// see if the specified path actually exists.
|
||||
|
||||
#if defined(POSIX)
|
||||
struct stat buf;
|
||||
if ( stat( sFixedPath.c_str(), &buf ) == -1 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined( LINUX ) || defined( OSX )
|
||||
return S_ISDIR( buf.st_mode );
|
||||
#else
|
||||
return (buf.st_mode & _S_IFDIR) != 0;
|
||||
#endif
|
||||
|
||||
#else
|
||||
struct _stat buf;
|
||||
std::wstring wsFixedPath = UTF8to16( sFixedPath.c_str() );
|
||||
if ( _wstat( wsFixedPath.c_str(), &buf ) == -1 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return (buf.st_mode & _S_IFDIR) != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** returns true if the specified path represents an app bundle */
|
||||
bool Path_IsAppBundle( const std::string & sPath )
|
||||
{
|
||||
#if defined(OSX)
|
||||
@autoreleasepool {
|
||||
NSBundle *bundle = [ NSBundle bundleWithPath: [ NSString stringWithUTF8String:sPath.c_str() ] ];
|
||||
bool bisAppBundle = ( nullptr != bundle );
|
||||
return bisAppBundle;
|
||||
}
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: returns true if the the path exists
|
||||
//-----------------------------------------------------------------------------
|
||||
bool Path_Exists( const std::string & sPath )
|
||||
{
|
||||
std::string sFixedPath = Path_FixSlashes( sPath );
|
||||
if( sFixedPath.empty() )
|
||||
return false;
|
||||
|
||||
#ifdef _WIN32
|
||||
struct _stat buf;
|
||||
std::wstring wsFixedPath = UTF8to16( sFixedPath.c_str() );
|
||||
if ( _wstat( wsFixedPath.c_str(), &buf ) == -1 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
struct stat buf;
|
||||
if ( stat ( sFixedPath.c_str(), &buf ) == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: helper to find a directory upstream from a given path
|
||||
//-----------------------------------------------------------------------------
|
||||
std::string Path_FindParentDirectoryRecursively( const std::string &strStartDirectory, const std::string &strDirectoryName )
|
||||
{
|
||||
std::string strFoundPath = "";
|
||||
std::string strCurrentPath = Path_FixSlashes( strStartDirectory );
|
||||
if ( strCurrentPath.length() == 0 )
|
||||
return "";
|
||||
|
||||
bool bExists = Path_Exists( strCurrentPath );
|
||||
std::string strCurrentDirectoryName = Path_StripDirectory( strCurrentPath );
|
||||
if ( bExists && stricmp( strCurrentDirectoryName.c_str(), strDirectoryName.c_str() ) == 0 )
|
||||
return strCurrentPath;
|
||||
|
||||
while( bExists && strCurrentPath.length() != 0 )
|
||||
{
|
||||
strCurrentPath = Path_StripFilename( strCurrentPath );
|
||||
strCurrentDirectoryName = Path_StripDirectory( strCurrentPath );
|
||||
bExists = Path_Exists( strCurrentPath );
|
||||
if ( bExists && stricmp( strCurrentDirectoryName.c_str(), strDirectoryName.c_str() ) == 0 )
|
||||
return strCurrentPath;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: helper to find a subdirectory upstream from a given path
|
||||
//-----------------------------------------------------------------------------
|
||||
std::string Path_FindParentSubDirectoryRecursively( const std::string &strStartDirectory, const std::string &strDirectoryName )
|
||||
{
|
||||
std::string strFoundPath = "";
|
||||
std::string strCurrentPath = Path_FixSlashes( strStartDirectory );
|
||||
if ( strCurrentPath.length() == 0 )
|
||||
return "";
|
||||
|
||||
bool bExists = Path_Exists( strCurrentPath );
|
||||
while( bExists && strCurrentPath.length() != 0 )
|
||||
{
|
||||
strCurrentPath = Path_StripFilename( strCurrentPath );
|
||||
bExists = Path_Exists( strCurrentPath );
|
||||
|
||||
if( Path_Exists( Path_Join( strCurrentPath, strDirectoryName ) ) )
|
||||
{
|
||||
strFoundPath = Path_Join( strCurrentPath, strDirectoryName );
|
||||
break;
|
||||
}
|
||||
}
|
||||
return strFoundPath;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: reading and writing files in the vortex directory
|
||||
//-----------------------------------------------------------------------------
|
||||
std::vector<uint8_t> Path_ReadBinaryFile( const std::string & strFilename )
|
||||
{
|
||||
FILE *f;
|
||||
#if defined( POSIX )
|
||||
f = fopen( strFilename.c_str(), "rb" );
|
||||
#else
|
||||
std::wstring wstrFilename = UTF8to16( strFilename.c_str() );
|
||||
// the open operation needs to be sharable, therefore use of _wfsopen instead of _wfopen_s
|
||||
f = _wfsopen( wstrFilename.c_str(), L"rb", _SH_DENYNO );
|
||||
#endif
|
||||
|
||||
std::vector<uint8_t> vecFileContents;
|
||||
|
||||
if ( f != NULL )
|
||||
{
|
||||
fseek( f, 0, SEEK_END );
|
||||
int size = ftell( f );
|
||||
fseek( f, 0, SEEK_SET );
|
||||
|
||||
vecFileContents.resize( size );
|
||||
if ( fread( &vecFileContents[ 0 ], size, 1, f ) == 1 )
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
vecFileContents.clear();
|
||||
}
|
||||
|
||||
fclose( f );
|
||||
}
|
||||
|
||||
return vecFileContents ;
|
||||
}
|
||||
|
||||
|
||||
unsigned char * Path_ReadBinaryFile( const std::string &strFilename, int *pSize )
|
||||
{
|
||||
FILE *f;
|
||||
#if defined( POSIX )
|
||||
f = fopen( strFilename.c_str(), "rb" );
|
||||
#else
|
||||
std::wstring wstrFilename = UTF8to16( strFilename.c_str() );
|
||||
// the open operation needs to be sharable, therefore use of _wfsopen instead of _wfopen_s
|
||||
f = _wfsopen( wstrFilename.c_str(), L"rb", _SH_DENYNO );
|
||||
#endif
|
||||
|
||||
unsigned char* buf = NULL;
|
||||
|
||||
if ( f != NULL )
|
||||
{
|
||||
fseek(f, 0, SEEK_END);
|
||||
int size = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
buf = new unsigned char[size];
|
||||
if (buf && fread(buf, size, 1, f) == 1)
|
||||
{
|
||||
if (pSize)
|
||||
*pSize = size;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete[] buf;
|
||||
buf = 0;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
uint32_t Path_ReadBinaryFile( const std::string &strFilename, unsigned char *pBuffer, uint32_t unSize )
|
||||
{
|
||||
FILE *f;
|
||||
#if defined( POSIX )
|
||||
f = fopen( strFilename.c_str(), "rb" );
|
||||
#else
|
||||
std::wstring wstrFilename = UTF8to16( strFilename.c_str() );
|
||||
errno_t err = _wfopen_s( &f, wstrFilename.c_str(), L"rb" );
|
||||
if ( err != 0 )
|
||||
{
|
||||
f = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t unSizeToReturn = 0;
|
||||
|
||||
if ( f != NULL )
|
||||
{
|
||||
fseek( f, 0, SEEK_END );
|
||||
uint32_t size = (uint32_t)ftell( f );
|
||||
fseek( f, 0, SEEK_SET );
|
||||
|
||||
if ( size > unSize || !pBuffer )
|
||||
{
|
||||
unSizeToReturn = (uint32_t)size;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( fread( pBuffer, size, 1, f ) == 1 )
|
||||
{
|
||||
unSizeToReturn = (uint32_t)size;
|
||||
}
|
||||
}
|
||||
|
||||
fclose( f );
|
||||
}
|
||||
|
||||
return unSizeToReturn;
|
||||
}
|
||||
|
||||
bool Path_WriteBinaryFile(const std::string &strFilename, unsigned char *pData, unsigned nSize)
|
||||
{
|
||||
FILE *f;
|
||||
#if defined( POSIX )
|
||||
f = fopen(strFilename.c_str(), "wb");
|
||||
#else
|
||||
std::wstring wstrFilename = UTF8to16( strFilename.c_str() );
|
||||
errno_t err = _wfopen_s( &f, wstrFilename.c_str(), L"wb" );
|
||||
if (err != 0)
|
||||
{
|
||||
f = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t written = 0;
|
||||
if (f != NULL) {
|
||||
written = fwrite(pData, sizeof(unsigned char), nSize, f);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
return written == nSize ? true : false;
|
||||
}
|
||||
|
||||
std::string Path_ReadTextFile( const std::string &strFilename )
|
||||
{
|
||||
// doing it this way seems backwards, but I don't
|
||||
// see an easy way to do this with C/C++ style IO
|
||||
// that isn't worse...
|
||||
int size;
|
||||
unsigned char* buf = Path_ReadBinaryFile( strFilename, &size );
|
||||
if (!buf)
|
||||
return "";
|
||||
|
||||
// convert CRLF -> LF
|
||||
size_t outsize = 1;
|
||||
for (int i=1; i < size; i++)
|
||||
{
|
||||
if (buf[i] == '\n' && buf[i-1] == '\r') // CRLF
|
||||
buf[outsize-1] = '\n'; // ->LF
|
||||
else
|
||||
buf[outsize++] = buf[i]; // just copy
|
||||
}
|
||||
|
||||
std::string ret((char *)buf, outsize);
|
||||
delete[] buf;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
bool Path_MakeWritable( const std::string &strFilename )
|
||||
{
|
||||
#if defined ( _WIN32 )
|
||||
std::wstring wstrFilename = UTF8to16( strFilename.c_str() );
|
||||
|
||||
DWORD dwAttrs = GetFileAttributesW( wstrFilename.c_str() );
|
||||
if ( dwAttrs != INVALID_FILE_ATTRIBUTES && ( dwAttrs & FILE_ATTRIBUTE_READONLY ) )
|
||||
{
|
||||
return SetFileAttributesW( wstrFilename.c_str(), dwAttrs & ~FILE_ATTRIBUTE_READONLY );
|
||||
}
|
||||
#else
|
||||
struct stat sb;
|
||||
|
||||
if ( stat( strFilename.c_str(), &sb ) == 0 && !( sb.st_mode & S_IWUSR ) )
|
||||
{
|
||||
return ( chmod( strFilename.c_str(), sb.st_mode | S_IWUSR ) == 0 );
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Path_WriteStringToTextFile( const std::string &strFilename, const char *pchData )
|
||||
{
|
||||
FILE *f;
|
||||
#if defined( POSIX )
|
||||
f = fopen( strFilename.c_str(), "w" );
|
||||
#else
|
||||
std::wstring wstrFilename = UTF8to16( strFilename.c_str() );
|
||||
errno_t err = _wfopen_s( &f, wstrFilename.c_str(), L"w" );
|
||||
if ( err != 0 )
|
||||
{
|
||||
f = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool ok = false;
|
||||
|
||||
if ( f != NULL )
|
||||
{
|
||||
ok = fputs( pchData, f) >= 0;
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool Path_WriteStringToTextFileAtomic( const std::string &strFilename, const char *pchData )
|
||||
{
|
||||
std::string strTmpFilename = strFilename + ".tmp";
|
||||
|
||||
if ( !Path_WriteStringToTextFile( strTmpFilename, pchData ) )
|
||||
return false;
|
||||
|
||||
// Platform specific atomic file replacement
|
||||
#if defined( _WIN32 )
|
||||
std::wstring wsFilename = UTF8to16( strFilename.c_str() );
|
||||
std::wstring wsTmpFilename = UTF8to16( strTmpFilename.c_str() );
|
||||
if ( !::ReplaceFileW( wsFilename.c_str(), wsTmpFilename.c_str(), nullptr, 0, 0, 0 ) )
|
||||
{
|
||||
// if we couldn't ReplaceFile, try a non-atomic write as a fallback
|
||||
if ( !Path_WriteStringToTextFile( strFilename, pchData ) )
|
||||
return false;
|
||||
}
|
||||
#elif defined( POSIX )
|
||||
if ( rename( strTmpFilename.c_str(), strFilename.c_str() ) == -1 )
|
||||
return false;
|
||||
#else
|
||||
#error Do not know how to write atomic file
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#if defined(WIN32)
|
||||
#define FILE_URL_PREFIX "file:///"
|
||||
#else
|
||||
#define FILE_URL_PREFIX "file://"
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------------------------
|
||||
// Purpose: Turns a path to a file on disk into a URL (or just returns the value if it's already a URL)
|
||||
// ----------------------------------------------------------------------------------------------------------------------------
|
||||
std::string Path_FilePathToUrl( const std::string & sRelativePath, const std::string & sBasePath )
|
||||
{
|
||||
if ( StringHasPrefix( sRelativePath, "http://" )
|
||||
|| StringHasPrefix( sRelativePath, "https://" )
|
||||
|| StringHasPrefix( sRelativePath, "vr-input-workshop://" )
|
||||
|| StringHasPrefix( sRelativePath, "file://" )
|
||||
)
|
||||
{
|
||||
return sRelativePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string sAbsolute = Path_MakeAbsolute( sRelativePath, sBasePath );
|
||||
if ( sAbsolute.empty() )
|
||||
return sAbsolute;
|
||||
sAbsolute = Path_FixSlashes( sAbsolute, '/' );
|
||||
|
||||
size_t unBufferSize = sAbsolute.length() * 3;
|
||||
char *pchBuffer = (char *)alloca( unBufferSize );
|
||||
V_URLEncodeFullPath( pchBuffer, (int)unBufferSize, sAbsolute.c_str(), (int)sAbsolute.length() );
|
||||
|
||||
return std::string( FILE_URL_PREFIX ) + pchBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// Purpose: Strips off file:// off a URL and returns the path. For other kinds of URLs an empty string is returned
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
std::string Path_UrlToFilePath( const std::string & sFileUrl )
|
||||
{
|
||||
if ( !strnicmp( sFileUrl.c_str(), FILE_URL_PREFIX, strlen( FILE_URL_PREFIX ) ) )
|
||||
{
|
||||
char *pchBuffer = (char *)alloca( sFileUrl.length() );
|
||||
V_URLDecodeNoPlusForSpace( pchBuffer, (int)sFileUrl.length(),
|
||||
sFileUrl.c_str() + strlen( FILE_URL_PREFIX ), (int)( sFileUrl.length() - strlen( FILE_URL_PREFIX ) ) );
|
||||
|
||||
return Path_FixSlashes( pchBuffer );
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// Purpose: Returns the root of the directory the system wants us to store user documents in
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
std::string GetUserDocumentsPath()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
WCHAR rwchPath[MAX_PATH];
|
||||
|
||||
if ( !SUCCEEDED( SHGetFolderPathW( NULL, CSIDL_MYDOCUMENTS | CSIDL_FLAG_CREATE, NULL, 0, rwchPath ) ) )
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
// Convert the path to UTF-8 and store in the output
|
||||
std::string sUserPath = UTF16to8( rwchPath );
|
||||
|
||||
return sUserPath;
|
||||
#elif defined( OSX )
|
||||
@autoreleasepool {
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES );
|
||||
if ( [paths count] == 0 )
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
return [[paths objectAtIndex:0] UTF8String];
|
||||
}
|
||||
#elif defined( LINUX )
|
||||
// @todo: not solved/changed as part of OSX - still not real - just removed old class based steam cut and paste
|
||||
const char *pchHome = getenv( "HOME" );
|
||||
if ( pchHome == NULL )
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return pchHome;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// Purpose: deletes / unlinks a single file
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
bool Path_UnlinkFile( const std::string &strFilename )
|
||||
{
|
||||
#ifdef _WIN32
|
||||
std::wstring wsFilename = UTF8to16( strFilename.c_str() );
|
||||
return ( 0 != DeleteFileW( wsFilename.c_str() ) );
|
||||
#else
|
||||
return ( 0 == unlink( strFilename.c_str() ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// Limits the set of characters that are allowed in filenames
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
std::string Path_SanitizeFilename( const std::string& sFilename )
|
||||
{
|
||||
std::string sFixed = sFilename;
|
||||
std::string::iterator iLastDot = sFixed.end();
|
||||
for ( std::string::iterator i = sFixed.begin(); i != sFixed.end(); i++ )
|
||||
{
|
||||
if ( *i == '.' )
|
||||
{
|
||||
iLastDot = i;
|
||||
}
|
||||
|
||||
// path-related characters are forbidden (except the last period)
|
||||
switch ( *i )
|
||||
{
|
||||
case '\0':
|
||||
case '.':
|
||||
case '\\':
|
||||
case '/':
|
||||
case ':':
|
||||
case '|':
|
||||
case '?':
|
||||
case '>':
|
||||
case '<':
|
||||
case '&':
|
||||
case '%':
|
||||
case '@':
|
||||
case '$':
|
||||
case '*':
|
||||
case '\"':
|
||||
*i = '_';
|
||||
break;
|
||||
|
||||
default:
|
||||
if ( *i < 32 )
|
||||
{
|
||||
*i = '_';
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( iLastDot != sFixed.end() && iLastDot != sFixed.begin()
|
||||
&& iLastDot+1 != sFixed.end() )
|
||||
{
|
||||
*iLastDot = '.';
|
||||
}
|
||||
|
||||
return sFixed;
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
//========= Copyright Valve Corporation ============//
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
|
||||
/** Returns the path (including filename) to the current executable */
|
||||
std::string Path_GetExecutablePath();
|
||||
|
||||
/** Returns the path of the current working directory */
|
||||
std::string Path_GetWorkingDirectory();
|
||||
|
||||
/** Sets the path of the current working directory. Returns true if this was successful. */
|
||||
bool Path_SetWorkingDirectory( const std::string & sPath );
|
||||
|
||||
/** Gets the path to a temporary directory. */
|
||||
std::string Path_GetTemporaryDirectory();
|
||||
|
||||
/** returns the path (including filename) of the current shared lib or DLL */
|
||||
std::string Path_GetThisModulePath();
|
||||
|
||||
/** Returns the specified path without its filename.
|
||||
* If slash is unspecified the native path separator of the current platform
|
||||
* will be used. */
|
||||
std::string Path_StripFilename( const std::string & sPath, char slash = 0 );
|
||||
|
||||
/** returns just the filename from the provided full or relative path. */
|
||||
std::string Path_StripDirectory( const std::string & sPath, char slash = 0 );
|
||||
|
||||
/** returns just the filename with no extension of the provided filename.
|
||||
* If there is a path the path is left intact. */
|
||||
std::string Path_StripExtension( const std::string & sPath );
|
||||
|
||||
/** returns just extension of the provided filename (if any). */
|
||||
std::string Path_GetExtension( const std::string & sPath );
|
||||
|
||||
/** Returns true if the path is absolute */
|
||||
bool Path_IsAbsolute( const std::string & sPath );
|
||||
|
||||
/** Makes an absolute path from a relative path and a base path */
|
||||
std::string Path_MakeAbsolute( const std::string & sRelativePath, const std::string & sBasePath );
|
||||
|
||||
/** Fixes the directory separators for the current platform.
|
||||
* If slash is unspecified the native path separator of the current platform
|
||||
* will be used. */
|
||||
std::string Path_FixSlashes( const std::string & sPath, char slash = 0 );
|
||||
|
||||
/** Returns the path separator for the current platform */
|
||||
char Path_GetSlash();
|
||||
|
||||
/** Jams two paths together with the right kind of slash */
|
||||
std::string Path_Join( const std::string & first, const std::string & second, char slash = 0 );
|
||||
std::string Path_Join( const std::string & first, const std::string & second, const std::string & third, char slash = 0 );
|
||||
std::string Path_Join( const std::string & first, const std::string & second, const std::string & third, const std::string &fourth, char slash = 0 );
|
||||
std::string Path_Join(
|
||||
const std::string & first,
|
||||
const std::string & second,
|
||||
const std::string & third,
|
||||
const std::string & fourth,
|
||||
const std::string & fifth,
|
||||
char slash = 0 );
|
||||
|
||||
|
||||
/** Removes redundant <dir>/.. elements in the path. Returns an empty path if the
|
||||
* specified path has a broken number of directories for its number of ..s.
|
||||
* If slash is unspecified the native path separator of the current platform
|
||||
* will be used. */
|
||||
std::string Path_Compact( const std::string & sRawPath, char slash = 0 );
|
||||
|
||||
/** Returns true if these two paths are the same without respect for internal . or ..
|
||||
* sequences, slash type, or case (on case-insensitive platforms). */
|
||||
bool Path_IsSamePath( const std::string & sPath1, const std::string & sPath2 );
|
||||
|
||||
//** Removed trailing slashes */
|
||||
std::string Path_RemoveTrailingSlash( const std::string & sRawPath, char slash = 0 );
|
||||
|
||||
/** returns true if the specified path exists and is a directory */
|
||||
bool Path_IsDirectory( const std::string & sPath );
|
||||
|
||||
/** returns true if the specified path represents an app bundle */
|
||||
bool Path_IsAppBundle( const std::string & sPath );
|
||||
|
||||
/** returns true if the the path exists */
|
||||
bool Path_Exists( const std::string & sPath );
|
||||
|
||||
/** Helper functions to find parent directories or subdirectories of parent directories */
|
||||
std::string Path_FindParentDirectoryRecursively( const std::string &strStartDirectory, const std::string &strDirectoryName );
|
||||
std::string Path_FindParentSubDirectoryRecursively( const std::string &strStartDirectory, const std::string &strDirectoryName );
|
||||
|
||||
/** Make a text file writable. */
|
||||
bool Path_MakeWritable( const std::string &strFilename );
|
||||
|
||||
/** Path operations to read or write text/binary files */
|
||||
unsigned char * Path_ReadBinaryFile( const std::string &strFilename, int *pSize );
|
||||
uint32_t Path_ReadBinaryFile( const std::string &strFilename, unsigned char *pBuffer, uint32_t unSize );
|
||||
std::vector<uint8_t> Path_ReadBinaryFile( const std::string & strFilename );
|
||||
bool Path_WriteBinaryFile( const std::string &strFilename, unsigned char *pData, unsigned nSize );
|
||||
std::string Path_ReadTextFile( const std::string &strFilename );
|
||||
bool Path_WriteStringToTextFile( const std::string &strFilename, const char *pchData );
|
||||
bool Path_WriteStringToTextFileAtomic( const std::string &strFilename, const char *pchData );
|
||||
|
||||
/** Returns a file:// url for paths, or an http or https url if that's what was provided */
|
||||
std::string Path_FilePathToUrl( const std::string & sRelativePath, const std::string & sBasePath );
|
||||
|
||||
/** Strips off file:// off a URL and returns the path. For other kinds of URLs an empty string is returned */
|
||||
std::string Path_UrlToFilePath( const std::string & sFileUrl );
|
||||
|
||||
/** Returns the root of the directory the system wants us to store user documents in */
|
||||
std::string GetUserDocumentsPath();
|
||||
|
||||
/** deletes / unlinks a single file */
|
||||
bool Path_UnlinkFile( const std::string &strFilename );
|
||||
|
||||
std::string Path_SanitizeFilename( const std::string& sFilename );
|
||||
|
||||
#ifndef MAX_UNICODE_PATH
|
||||
#define MAX_UNICODE_PATH 32767
|
||||
#endif
|
||||
|
||||
#ifndef MAX_UNICODE_PATH_IN_UTF8
|
||||
#define MAX_UNICODE_PATH_IN_UTF8 (MAX_UNICODE_PATH * 4)
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
#if defined(WIN32)
|
||||
#define DYNAMIC_LIB_EXT ".dll"
|
||||
#define PROGRAM_EXT ".exe"
|
||||
#ifdef _WIN64
|
||||
#define PLATSUBDIR "win64"
|
||||
#else
|
||||
#define PLATSUBDIR "win32"
|
||||
#endif
|
||||
#elif defined(OSX)
|
||||
#define DYNAMIC_LIB_EXT ".dylib"
|
||||
#define PLATSUBDIR "osx32"
|
||||
#define PROGRAM_EXT ""
|
||||
#elif defined(LINUX)
|
||||
#define DYNAMIC_LIB_EXT ".so"
|
||||
#define PROGRAM_EXT ""
|
||||
#if defined( LINUX32 )
|
||||
#define PLATSUBDIR "linux32"
|
||||
#elif defined( ANDROIDARM64 )
|
||||
#define PLATSUBDIR "androidarm64"
|
||||
#elif defined( LINUXARM64 )
|
||||
#define PLATSUBDIR "linuxarm64"
|
||||
#else
|
||||
#define PLATSUBDIR "linux64"
|
||||
#endif
|
||||
#else
|
||||
#warning "Unknown platform for PLATSUBDIR"
|
||||
#define PLATSUBDIR "unknown_platform"
|
||||
#endif
|
|
@ -0,0 +1,63 @@
|
|||
//========= Copyright Valve Corporation ============//
|
||||
#include <vrcommon/sharedlibtools_public.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if defined(POSIX)
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
|
||||
SharedLibHandle SharedLib_Load( const char *pchPath, uint32_t *pErrorCode )
|
||||
{
|
||||
SharedLibHandle pHandle = nullptr;
|
||||
#if defined( _WIN32)
|
||||
pHandle = ( SharedLibHandle )LoadLibraryEx( pchPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH );
|
||||
#elif defined(POSIX)
|
||||
pHandle = (SharedLibHandle) dlopen(pchPath, RTLD_LOCAL|RTLD_NOW);
|
||||
#endif
|
||||
|
||||
if ( pErrorCode )
|
||||
{
|
||||
if ( pHandle == nullptr )
|
||||
{
|
||||
#if defined( _WIN32)
|
||||
*pErrorCode = ( uint32_t ) GetLastError();
|
||||
#elif defined(POSIX)
|
||||
*pErrorCode = 1;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
*pErrorCode = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return pHandle;
|
||||
}
|
||||
|
||||
void *SharedLib_GetFunction( SharedLibHandle lib, const char *pchFunctionName)
|
||||
{
|
||||
#if defined( _WIN32)
|
||||
return (void*)GetProcAddress( (HMODULE)lib, pchFunctionName );
|
||||
#elif defined(POSIX)
|
||||
return dlsym( lib, pchFunctionName );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void SharedLib_Unload( SharedLibHandle lib )
|
||||
{
|
||||
if ( !lib )
|
||||
return;
|
||||
#if defined( _WIN32)
|
||||
FreeLibrary( (HMODULE)lib );
|
||||
#elif defined(POSIX)
|
||||
dlclose( lib );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
//========= Copyright Valve Corporation ============//
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef void *SharedLibHandle;
|
||||
|
||||
SharedLibHandle SharedLib_Load( const char *pchPath, uint32_t *pErrorCode = nullptr );
|
||||
void *SharedLib_GetFunction( SharedLibHandle lib, const char *pchFunctionName);
|
||||
void SharedLib_Unload( SharedLibHandle lib );
|
||||
|
||||
|
|
@ -0,0 +1,606 @@
|
|||
//========= Copyright Valve Corporation ============//
|
||||
#include <vrcommon/strtools_public.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sstream>
|
||||
#include <codecvt>
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
#include <locale>
|
||||
#include <codecvt>
|
||||
#include <stdarg.h>
|
||||
|
||||
#if defined( _WIN32 )
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if defined( OSX ) || defined( LINUX )
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: stricmp -> strcasecmp bridge
|
||||
//-----------------------------------------------------------------------------
|
||||
int stricmp( const char *pStr1, const char *pStr2 )
|
||||
{
|
||||
return strcasecmp( pStr1, pStr2 );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: strincmp -> strncasecmp bridge
|
||||
//-----------------------------------------------------------------------------
|
||||
int strnicmp( const char *pStr1, const char *pStr2, size_t unBufferLen )
|
||||
{
|
||||
return strncasecmp( pStr1, pStr2, unBufferLen );
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool StringHasPrefix( const std::string & sString, const std::string & sPrefix )
|
||||
{
|
||||
return 0 == strnicmp( sString.c_str(), sPrefix.c_str(), sPrefix.length() );
|
||||
}
|
||||
|
||||
bool StringHasPrefixCaseSensitive( const std::string & sString, const std::string & sPrefix )
|
||||
{
|
||||
return 0 == strncmp( sString.c_str(), sPrefix.c_str(), sPrefix.length() );
|
||||
}
|
||||
|
||||
|
||||
bool StringHasSuffix( const std::string &sString, const std::string &sSuffix )
|
||||
{
|
||||
size_t cStrLen = sString.length();
|
||||
size_t cSuffixLen = sSuffix.length();
|
||||
|
||||
if ( cSuffixLen > cStrLen )
|
||||
return false;
|
||||
|
||||
std::string sStringSuffix = sString.substr( cStrLen - cSuffixLen, cSuffixLen );
|
||||
|
||||
return 0 == stricmp( sStringSuffix.c_str(), sSuffix.c_str() );
|
||||
}
|
||||
|
||||
bool StringHasSuffixCaseSensitive( const std::string &sString, const std::string &sSuffix )
|
||||
{
|
||||
size_t cStrLen = sString.length();
|
||||
size_t cSuffixLen = sSuffix.length();
|
||||
|
||||
if ( cSuffixLen > cStrLen )
|
||||
return false;
|
||||
|
||||
std::string sStringSuffix = sString.substr( cStrLen - cSuffixLen, cSuffixLen );
|
||||
|
||||
return 0 == strncmp( sStringSuffix.c_str(), sSuffix.c_str(),cSuffixLen );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef std::codecvt_utf8< wchar_t > convert_type;
|
||||
|
||||
std::string UTF16to8(const wchar_t * in)
|
||||
{
|
||||
static std::wstring_convert< convert_type, wchar_t > s_converter; // construction of this can be expensive (or even serialized) depending on locale
|
||||
|
||||
try
|
||||
{
|
||||
return s_converter.to_bytes( in );
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
}
|
||||
|
||||
std::string UTF16to8( const std::wstring & in ) { return UTF16to8( in.c_str() ); }
|
||||
|
||||
|
||||
std::wstring UTF8to16(const char * in)
|
||||
{
|
||||
static std::wstring_convert< convert_type, wchar_t > s_converter; // construction of this can be expensive (or even serialized) depending on locale
|
||||
|
||||
try
|
||||
{
|
||||
return s_converter.from_bytes( in );
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
return std::wstring();
|
||||
}
|
||||
}
|
||||
|
||||
std::wstring UTF8to16( const std::string & in ) { return UTF8to16( in.c_str() ); }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Format string to std::string converter
|
||||
//-----------------------------------------------------------------------------
|
||||
std::string Format( const char *pchFormat, ... )
|
||||
{
|
||||
static constexpr size_t k_ulMaxStackString = 4096;
|
||||
|
||||
va_list args;
|
||||
char pchBuffer[k_ulMaxStackString];
|
||||
|
||||
va_start( args, pchFormat );
|
||||
int unSize = vsnprintf( pchBuffer, sizeof( pchBuffer ), pchFormat, args );
|
||||
va_end( args );
|
||||
|
||||
// Something went fairly wrong
|
||||
if ( unSize < 0 )
|
||||
{
|
||||
//AssertMsg( false, "Format string parse failure" );
|
||||
return "";
|
||||
}
|
||||
|
||||
// Processing on the stack worked, success
|
||||
if ( unSize < k_ulMaxStackString )
|
||||
{
|
||||
return pchBuffer;
|
||||
}
|
||||
|
||||
// If processing on the stack failed, fallback to a dynamic allocation
|
||||
std::vector< char > vecChar{};
|
||||
vecChar.resize( unSize + 1 );
|
||||
|
||||
va_start( args, pchFormat );
|
||||
unSize = vsnprintf( vecChar.data(), vecChar.size(), pchFormat, args );
|
||||
va_end( args );
|
||||
|
||||
// Double check, just in case
|
||||
if ( unSize < 0 )
|
||||
{
|
||||
//AssertMsg( false, "Format string parse failure" );
|
||||
return "";
|
||||
}
|
||||
|
||||
return vecChar.data();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#if defined( _WIN32 )
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Convert LPSTR in the default CodePage to UTF8
|
||||
//-----------------------------------------------------------------------------
|
||||
std::string DefaultACPtoUTF8( const char *pszStr )
|
||||
{
|
||||
if ( GetACP() == CP_UTF8 )
|
||||
{
|
||||
return pszStr;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<wchar_t> vecBuf( strlen( pszStr ) + 1 ); // should be guaranteed to be enough
|
||||
MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, pszStr, -1, vecBuf.data(), (int) vecBuf.size() );
|
||||
return UTF16to8( vecBuf.data() );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// --------------------------------------------------------------------
|
||||
void strcpy_safe( char *pchBuffer, size_t unBufferSizeBytes, const char *pchSource )
|
||||
{
|
||||
strncpy( pchBuffer, pchSource, unBufferSizeBytes - 1 );
|
||||
pchBuffer[unBufferSizeBytes - 1] = '\0';
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Purpose: converts a string to upper case
|
||||
// --------------------------------------------------------------------
|
||||
std::string StringToUpper( const std::string & sString )
|
||||
{
|
||||
std::string sOut;
|
||||
sOut.reserve( sString.size() + 1 );
|
||||
for( std::string::const_iterator i = sString.begin(); i != sString.end(); i++ )
|
||||
{
|
||||
sOut.push_back( (char)toupper( *i ) );
|
||||
}
|
||||
|
||||
return sOut;
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Purpose: converts a string to lower case
|
||||
// --------------------------------------------------------------------
|
||||
std::string StringToLower( const std::string & sString )
|
||||
{
|
||||
std::string sOut;
|
||||
sOut.reserve( sString.size() + 1 );
|
||||
for( std::string::const_iterator i = sString.begin(); i != sString.end(); i++ )
|
||||
{
|
||||
sOut.push_back( (char)tolower( *i ) );
|
||||
}
|
||||
|
||||
return sOut;
|
||||
}
|
||||
|
||||
|
||||
uint32_t ReturnStdString( const std::string & sValue, char *pchBuffer, uint32_t unBufferLen )
|
||||
{
|
||||
uint32_t unLen = (uint32_t)sValue.length() + 1;
|
||||
if( !pchBuffer || !unBufferLen )
|
||||
return unLen;
|
||||
|
||||
if( unBufferLen < unLen )
|
||||
{
|
||||
pchBuffer[0] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy( pchBuffer, sValue.c_str(), unLen );
|
||||
}
|
||||
|
||||
return unLen;
|
||||
}
|
||||
|
||||
|
||||
/** Returns a std::string from a uint64_t */
|
||||
std::string Uint64ToString( uint64_t ulValue )
|
||||
{
|
||||
char buf[ 22 ];
|
||||
#if defined( _WIN32 )
|
||||
sprintf_s( buf, "%llu", ulValue );
|
||||
#else
|
||||
snprintf( buf, sizeof( buf ), "%llu", (long long unsigned int ) ulValue );
|
||||
#endif
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
/** returns a uint64_t from a string */
|
||||
uint64_t StringToUint64( const std::string & sValue )
|
||||
{
|
||||
return strtoull( sValue.c_str(), NULL, 0 );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Helper for converting a numeric value to a hex digit, value should be 0-15.
|
||||
//-----------------------------------------------------------------------------
|
||||
char cIntToHexDigit( int nValue )
|
||||
{
|
||||
//Assert( nValue >= 0 && nValue <= 15 );
|
||||
return "0123456789ABCDEF"[ nValue & 15 ];
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Helper for converting a hex char value to numeric, return -1 if the char
|
||||
// is not a valid hex digit.
|
||||
//-----------------------------------------------------------------------------
|
||||
int iHexCharToInt( char cValue )
|
||||
{
|
||||
int32_t iValue = cValue;
|
||||
if ( (uint32_t)( iValue - '0' ) < 10 )
|
||||
return iValue - '0';
|
||||
|
||||
iValue |= 0x20;
|
||||
if ( (uint32_t)( iValue - 'a' ) < 6 )
|
||||
return iValue - 'a' + 10;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: These define the set of characters to filter for components (which
|
||||
// need all the escaping we can muster) vs. paths (which don't want
|
||||
// / and : escaped so we don't break less compliant URL handling code.
|
||||
//-----------------------------------------------------------------------------
|
||||
static bool CharNeedsEscape_Component( const char c )
|
||||
{
|
||||
return (!(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z') && !(c >= '0' && c <= '9')
|
||||
&& c != '-' && c != '_' && c != '.');
|
||||
}
|
||||
static bool CharNeedsEscape_FullPath( const char c )
|
||||
{
|
||||
return (!(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z') && !(c >= '0' && c <= '9')
|
||||
&& c != '-' && c != '_' && c != '.' && c != '/' && c != ':' );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Internal implementation of encode, works in the strict RFC manner, or
|
||||
// with spaces turned to + like HTML form encoding.
|
||||
//-----------------------------------------------------------------------------
|
||||
void V_URLEncodeInternal( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen,
|
||||
bool bUsePlusForSpace, std::function< bool(const char)> fnNeedsEscape )
|
||||
{
|
||||
//AssertMsg( nDestLen > 3*nSourceLen, "Target buffer for V_URLEncode should be 3x source length, plus one for terminating null\n" );
|
||||
|
||||
int iDestPos = 0;
|
||||
for ( int i=0; i < nSourceLen; ++i )
|
||||
{
|
||||
// worst case we need 3 additional chars
|
||||
if( (iDestPos+3) > nDestLen )
|
||||
{
|
||||
pchDest[0] = '\0';
|
||||
// AssertMsg( false, "Target buffer too short\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
// We allow only a-z, A-Z, 0-9, period, underscore, and hyphen to pass through unescaped.
|
||||
// These are the characters allowed by both the original RFC 1738 and the latest RFC 3986.
|
||||
// Current specs also allow '~', but that is forbidden under original RFC 1738.
|
||||
if ( fnNeedsEscape( pchSource[i] ) )
|
||||
{
|
||||
if ( bUsePlusForSpace && pchSource[i] == ' ' )
|
||||
{
|
||||
pchDest[iDestPos++] = '+';
|
||||
}
|
||||
else
|
||||
{
|
||||
pchDest[iDestPos++] = '%';
|
||||
uint8_t iValue = pchSource[i];
|
||||
if ( iValue == 0 )
|
||||
{
|
||||
pchDest[iDestPos++] = '0';
|
||||
pchDest[iDestPos++] = '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
char cHexDigit1 = cIntToHexDigit( iValue % 16 );
|
||||
iValue /= 16;
|
||||
char cHexDigit2 = cIntToHexDigit( iValue );
|
||||
pchDest[iDestPos++] = cHexDigit2;
|
||||
pchDest[iDestPos++] = cHexDigit1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pchDest[iDestPos++] = pchSource[i];
|
||||
}
|
||||
}
|
||||
|
||||
if( (iDestPos+1) > nDestLen )
|
||||
{
|
||||
pchDest[0] = '\0';
|
||||
//AssertMsg( false, "Target buffer too short to terminate\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
// Null terminate
|
||||
pchDest[iDestPos++] = 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Internal implementation of decode, works in the strict RFC manner, or
|
||||
// with spaces turned to + like HTML form encoding.
|
||||
//
|
||||
// Returns the amount of space used in the output buffer.
|
||||
//-----------------------------------------------------------------------------
|
||||
size_t V_URLDecodeInternal( char *pchDecodeDest, int nDecodeDestLen, const char *pchEncodedSource, int nEncodedSourceLen, bool bUsePlusForSpace )
|
||||
{
|
||||
if ( nDecodeDestLen < nEncodedSourceLen )
|
||||
{
|
||||
//AssertMsg( false, "V_URLDecode needs a dest buffer at least as large as the source" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iDestPos = 0;
|
||||
for( int i=0; i < nEncodedSourceLen; ++i )
|
||||
{
|
||||
if ( bUsePlusForSpace && pchEncodedSource[i] == '+' )
|
||||
{
|
||||
pchDecodeDest[ iDestPos++ ] = ' ';
|
||||
}
|
||||
else if ( pchEncodedSource[i] == '%' )
|
||||
{
|
||||
// Percent signifies an encoded value, look ahead for the hex code, convert to numeric, and use that
|
||||
|
||||
// First make sure we have 2 more chars
|
||||
if ( i < nEncodedSourceLen - 2 )
|
||||
{
|
||||
char cHexDigit1 = pchEncodedSource[i+1];
|
||||
char cHexDigit2 = pchEncodedSource[i+2];
|
||||
|
||||
// Turn the chars into a hex value, if they are not valid, then we'll
|
||||
// just place the % and the following two chars direct into the string,
|
||||
// even though this really shouldn't happen, who knows what bad clients
|
||||
// may do with encoding.
|
||||
bool bValid = false;
|
||||
int iValue = iHexCharToInt( cHexDigit1 );
|
||||
if ( iValue != -1 )
|
||||
{
|
||||
iValue *= 16;
|
||||
int iValue2 = iHexCharToInt( cHexDigit2 );
|
||||
if ( iValue2 != -1 )
|
||||
{
|
||||
iValue += iValue2;
|
||||
pchDecodeDest[ iDestPos++ ] = (char)iValue;
|
||||
bValid = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !bValid )
|
||||
{
|
||||
pchDecodeDest[ iDestPos++ ] = '%';
|
||||
pchDecodeDest[ iDestPos++ ] = cHexDigit1;
|
||||
pchDecodeDest[ iDestPos++ ] = cHexDigit2;
|
||||
}
|
||||
}
|
||||
|
||||
// Skip ahead
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
pchDecodeDest[ iDestPos++ ] = pchEncodedSource[i];
|
||||
}
|
||||
}
|
||||
|
||||
// We may not have extra room to NULL terminate, since this can be used on raw data, but if we do
|
||||
// go ahead and do it as this can avoid bugs.
|
||||
if ( iDestPos < nDecodeDestLen )
|
||||
{
|
||||
pchDecodeDest[iDestPos] = 0;
|
||||
}
|
||||
|
||||
return (size_t)iDestPos;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Encodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2.
|
||||
// This version of the call isn't a strict RFC implementation, but uses + for space as is
|
||||
// the standard in HTML form encoding, despite it not being part of the RFC.
|
||||
//
|
||||
// Dest buffer should be at least as large as source buffer to guarantee room for decode.
|
||||
//-----------------------------------------------------------------------------
|
||||
void V_URLEncode( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen )
|
||||
{
|
||||
return V_URLEncodeInternal( pchDest, nDestLen, pchSource, nSourceLen, true, CharNeedsEscape_Component );
|
||||
}
|
||||
|
||||
|
||||
void V_URLEncodeNoPlusForSpace( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen )
|
||||
{
|
||||
return V_URLEncodeInternal( pchDest, nDestLen, pchSource, nSourceLen, false, CharNeedsEscape_Component );
|
||||
}
|
||||
|
||||
void V_URLEncodeFullPath( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen )
|
||||
{
|
||||
return V_URLEncodeInternal( pchDest, nDestLen, pchSource, nSourceLen, false, CharNeedsEscape_FullPath );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Decodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2.
|
||||
// This version of the call isn't a strict RFC implementation, but uses + for space as is
|
||||
// the standard in HTML form encoding, despite it not being part of the RFC.
|
||||
//
|
||||
// Dest buffer should be at least as large as source buffer to guarantee room for decode.
|
||||
// Dest buffer being the same as the source buffer (decode in-place) is explicitly allowed.
|
||||
//-----------------------------------------------------------------------------
|
||||
size_t V_URLDecode( char *pchDecodeDest, int nDecodeDestLen, const char *pchEncodedSource, int nEncodedSourceLen )
|
||||
{
|
||||
return V_URLDecodeInternal( pchDecodeDest, nDecodeDestLen, pchEncodedSource, nEncodedSourceLen, true );
|
||||
}
|
||||
|
||||
size_t V_URLDecodeNoPlusForSpace( char *pchDecodeDest, int nDecodeDestLen, const char *pchEncodedSource, int nEncodedSourceLen )
|
||||
{
|
||||
return V_URLDecodeInternal( pchDecodeDest, nDecodeDestLen, pchEncodedSource, nEncodedSourceLen, false );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void V_StripExtension( std::string &in )
|
||||
{
|
||||
// Find the last dot. If it's followed by a dot or a slash, then it's part of a
|
||||
// directory specifier like ../../somedir/./blah.
|
||||
std::string::size_type test = in.rfind( '.' );
|
||||
if ( test != std::string::npos )
|
||||
{
|
||||
// This handles things like ".\blah" or "c:\my@email.com\abc\def\geh"
|
||||
// Which would otherwise wind up with "" and "c:\my@email", respectively.
|
||||
if ( in.rfind( '\\' ) < test && in.rfind( '/' ) < test )
|
||||
{
|
||||
in.resize( test );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Tokenizes a string into a vector of strings
|
||||
//-----------------------------------------------------------------------------
|
||||
std::vector<std::string> TokenizeString( const std::string & sString, char cToken )
|
||||
{
|
||||
std::vector<std::string> vecStrings;
|
||||
std::istringstream stream( sString );
|
||||
std::string s;
|
||||
while ( std::getline( stream, s, cToken ) )
|
||||
{
|
||||
vecStrings.push_back( s );
|
||||
}
|
||||
|
||||
if ( !sString.empty() && sString.back() == cToken )
|
||||
{
|
||||
vecStrings.push_back( "" );
|
||||
}
|
||||
|
||||
return vecStrings;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Repairs a should-be-UTF-8 string to a for-sure-is-UTF-8 string, plus return boolean if we subbed in '?' somewhere
|
||||
//-----------------------------------------------------------------------------
|
||||
bool RepairUTF8( const char *pbegin, const char *pend, std::string & sOutputUtf8 )
|
||||
{
|
||||
typedef std::codecvt_utf8<char32_t> facet_type;
|
||||
facet_type myfacet;
|
||||
|
||||
std::mbstate_t mystate = std::mbstate_t();
|
||||
|
||||
sOutputUtf8.clear();
|
||||
sOutputUtf8.reserve( pend - pbegin );
|
||||
bool bSqueakyClean = true;
|
||||
|
||||
const char *pmid = pbegin;
|
||||
while ( pmid != pend )
|
||||
{
|
||||
bool bHasError = false;
|
||||
bool bHasValidData = false;
|
||||
|
||||
char32_t out = 0xdeadbeef, *pout;
|
||||
pbegin = pmid;
|
||||
switch ( myfacet.in( mystate, pbegin, pend, pmid, &out, &out + 1, pout ) )
|
||||
{
|
||||
case facet_type::ok:
|
||||
bHasValidData = true;
|
||||
break;
|
||||
|
||||
case facet_type::noconv:
|
||||
// unexpected! always converting type
|
||||
bSqueakyClean = false;
|
||||
break;
|
||||
|
||||
case facet_type::partial:
|
||||
bHasError = pbegin == pmid;
|
||||
if ( bHasError )
|
||||
{
|
||||
bSqueakyClean = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
bHasValidData = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case facet_type::error:
|
||||
bHasError = true;
|
||||
bSqueakyClean = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( bHasValidData )
|
||||
{
|
||||
// could convert back, but no need
|
||||
for ( const char *p = pbegin; p != pmid; ++p )
|
||||
{
|
||||
sOutputUtf8 += *p;
|
||||
}
|
||||
}
|
||||
|
||||
if ( bHasError )
|
||||
{
|
||||
sOutputUtf8 += '?';
|
||||
}
|
||||
|
||||
if ( pmid == pbegin )
|
||||
{
|
||||
pmid++;
|
||||
}
|
||||
}
|
||||
|
||||
return bSqueakyClean;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Repairs a should-be-UTF-8 string to a for-sure-is-UTF-8 string, plus return boolean if we subbed in '?' somewhere
|
||||
//-----------------------------------------------------------------------------
|
||||
bool RepairUTF8( const std::string & sInputUtf8, std::string & sOutputUtf8 )
|
||||
{
|
||||
return RepairUTF8( sInputUtf8.data(), sInputUtf8.data() + sInputUtf8.size(), sOutputUtf8 );
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
//========= Copyright Valve Corporation ============//
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <vector>
|
||||
|
||||
/** returns true if the string has the prefix */
|
||||
bool StringHasPrefix( const std::string & sString, const std::string & sPrefix );
|
||||
bool StringHasPrefixCaseSensitive( const std::string & sString, const std::string & sPrefix );
|
||||
|
||||
/** returns if the string has the suffix */
|
||||
bool StringHasSuffix( const std::string &sString, const std::string &sSuffix );
|
||||
bool StringHasSuffixCaseSensitive( const std::string &sString, const std::string &sSuffix );
|
||||
|
||||
/** converts a UTF-16 string to a UTF-8 string */
|
||||
std::string UTF16to8( const wchar_t * in );
|
||||
std::string UTF16to8( const std::wstring & in );
|
||||
|
||||
/** converts a UTF-8 string to a UTF-16 string */
|
||||
std::wstring UTF8to16(const char * in);
|
||||
std::wstring UTF8to16( const std::string & in );
|
||||
#define Utf16FromUtf8 UTF8to16
|
||||
|
||||
#if defined( _WIN32 )
|
||||
std::string DefaultACPtoUTF8( const char *pszStr );
|
||||
#endif
|
||||
|
||||
/** Repairs a should-be-UTF-8 string to a for-sure-is-UTF-8 string, plus return boolean if we subbed in '?' somewhere */
|
||||
bool RepairUTF8( const char *begin, const char *end, std::string & sOutputUtf8 );
|
||||
bool RepairUTF8( const std::string & sInputUtf8, std::string & sOutputUtf8 );
|
||||
|
||||
/** safely copy a string into a buffer */
|
||||
void strcpy_safe( char *pchBuffer, size_t unBufferSizeBytes, const char *pchSource );
|
||||
template< size_t bufferSize >
|
||||
void strcpy_safe( char (& buffer) [ bufferSize ], const char *pchSource )
|
||||
{
|
||||
strcpy_safe( buffer, bufferSize, pchSource );
|
||||
}
|
||||
|
||||
/** Turns printf-style format args into a std::string */
|
||||
std::string Format( const char *pchFormat, ... );
|
||||
|
||||
|
||||
/** converts a string to upper case */
|
||||
std::string StringToUpper( const std::string & sString );
|
||||
|
||||
/** converts a string to lower case */
|
||||
std::string StringToLower( const std::string & sString );
|
||||
|
||||
// we stricmp (from WIN) but it isn't POSIX - OSX/LINUX have strcasecmp so just inline bridge to it
|
||||
#if defined( OSX ) || defined( LINUX )
|
||||
int stricmp(const char *pStr1, const char *pStr2);
|
||||
#ifndef _stricmp
|
||||
#define _stricmp stricmp
|
||||
#endif
|
||||
int strnicmp( const char *pStr1, const char *pStr2, size_t unBufferLen );
|
||||
#ifndef _strnicmp
|
||||
#define _strnicmp strnicmp
|
||||
#endif
|
||||
|
||||
#ifndef _vsnprintf_s
|
||||
#define _vsnprintf_s vsnprintf
|
||||
#endif
|
||||
|
||||
#define _TRUNCATE ((size_t)-1)
|
||||
|
||||
#endif
|
||||
|
||||
#if defined( OSX )
|
||||
// behaviors ensure NULL-termination at least as well as _TRUNCATE does, but
|
||||
// wcsncpy_s/strncpy_s can non-NULL-terminate, wcslcpy/strlcpy can not.
|
||||
inline errno_t wcsncpy_s(wchar_t *strDest, size_t numberOfElements, const wchar_t *strSource, size_t count)
|
||||
{
|
||||
return wcslcpy(strDest, strSource, numberOfElements);
|
||||
}
|
||||
|
||||
inline errno_t strncpy_s(char *strDest, size_t numberOfElements, const char *strSource, size_t count)
|
||||
{
|
||||
return strlcpy(strDest, strSource, numberOfElements);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined( LINUX )
|
||||
// this implementation does not return whether or not the destination was
|
||||
// truncated, but that is straightforward to fix if anybody actually needs the
|
||||
// return code.
|
||||
#include "string.h"
|
||||
inline void wcsncpy_s(wchar_t *strDest, size_t numberOfElements, const wchar_t *strSource, size_t count)
|
||||
{
|
||||
wcsncpy(strDest, strSource, numberOfElements);
|
||||
strDest[numberOfElements-1] = '\0';
|
||||
}
|
||||
|
||||
inline void strncpy_s(char *strDest, size_t numberOfElements, const char *strSource, size_t count)
|
||||
{
|
||||
strncpy(strDest, strSource, numberOfElements);
|
||||
strDest[numberOfElements-1] = '\0';
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined( _WIN32 ) && _MSC_VER < 1800
|
||||
inline uint64_t strtoull(const char *str, char **endptr, int base) { return _strtoui64( str, endptr, base ); }
|
||||
#endif
|
||||
|
||||
/* Handles copying a std::string into a buffer as would be provided in an API */
|
||||
uint32_t ReturnStdString( const std::string & sValue, char *pchBuffer, uint32_t unBufferLen );
|
||||
|
||||
/** Returns a std::string from a uint64_t */
|
||||
std::string Uint64ToString( uint64_t ulValue );
|
||||
|
||||
/** returns a uint64_t from a string */
|
||||
uint64_t StringToUint64( const std::string & sValue );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Encodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2.
|
||||
// This version of the call isn't a strict RFC implementation, but uses + for space as is
|
||||
// the standard in HTML form encoding, despite it not being part of the RFC.
|
||||
//
|
||||
// Dest buffer should be at least as large as source buffer to guarantee room for decode.
|
||||
//-----------------------------------------------------------------------------
|
||||
void V_URLEncode( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen );
|
||||
|
||||
/** Same as V_URLEncode, but without plus for space. */
|
||||
void V_URLEncodeNoPlusForSpace( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen );
|
||||
|
||||
/** Same as V_URLEncodeNoPlusForSpace, but without escaping / and : */
|
||||
void V_URLEncodeFullPath( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen );
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Decodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2.
|
||||
// This version of the call isn't a strict RFC implementation, but uses + for space as is
|
||||
// the standard in HTML form encoding, despite it not being part of the RFC.
|
||||
//
|
||||
// Dest buffer should be at least as large as source buffer to guarantee room for decode.
|
||||
// Dest buffer being the same as the source buffer (decode in-place) is explicitly allowed.
|
||||
//-----------------------------------------------------------------------------
|
||||
size_t V_URLDecode( char *pchDecodeDest, int nDecodeDestLen, const char *pchEncodedSource, int nEncodedSourceLen );
|
||||
|
||||
/** Same as V_URLDecode, but without plus for space. */
|
||||
size_t V_URLDecodeNoPlusForSpace( char *pchDecodeDest, int nDecodeDestLen, const char *pchEncodedSource, int nEncodedSourceLen );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: strip extension from a path
|
||||
//-----------------------------------------------------------------------------
|
||||
void V_StripExtension( std::string &in );
|
||||
|
||||
|
||||
/** Tokenizes a string into a vector of strings */
|
||||
std::vector<std::string> TokenizeString( const std::string & sString, char cToken );
|
|
@ -0,0 +1,483 @@
|
|||
//========= Copyright Valve Corporation ============//
|
||||
|
||||
#include <vrcommon/vrpathregistry_public.h>
|
||||
#include <json/json.h>
|
||||
#include <vrcommon/pathtools_public.h>
|
||||
#include <vrcommon/envvartools_public.h>
|
||||
#include <vrcommon/strtools_public.h>
|
||||
#include <vrcommon/dirtools_public.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <shlobj.h>
|
||||
|
||||
#undef GetEnvironmentVariable
|
||||
#elif defined OSX
|
||||
#include <Foundation/Foundation.h>
|
||||
#include <AppKit/AppKit.h>
|
||||
#elif defined(LINUX)
|
||||
#include <dlfcn.h>
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
#ifndef VRLog
|
||||
#if defined( __MINGW32__ )
|
||||
#define VRLog(args...) fprintf(stderr, args)
|
||||
#elif defined( WIN32 )
|
||||
#define VRLog(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
|
||||
#else
|
||||
#define VRLog(args...) fprintf(stderr, args)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** Returns the root of the directory the system wants us to store user config data in */
|
||||
static std::string GetAppSettingsPath()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
WCHAR rwchPath[MAX_PATH];
|
||||
|
||||
if( !SUCCEEDED( SHGetFolderPathW( NULL, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, rwchPath ) ) )
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
// Convert the path to UTF-8 and store in the output
|
||||
std::string sUserPath = UTF16to8( rwchPath );
|
||||
|
||||
return sUserPath;
|
||||
#elif defined( OSX )
|
||||
std::string sSettingsDir;
|
||||
@autoreleasepool {
|
||||
// Search for the path
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains( NSApplicationSupportDirectory, NSUserDomainMask, YES );
|
||||
if ( [paths count] == 0 )
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
NSString *resolvedPath = [paths objectAtIndex:0];
|
||||
resolvedPath = [resolvedPath stringByAppendingPathComponent: @"OpenVR"];
|
||||
|
||||
if ( ![[NSFileManager defaultManager] createDirectoryAtPath: resolvedPath withIntermediateDirectories:YES attributes:nil error:nil] )
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
sSettingsDir.assign( [resolvedPath UTF8String] );
|
||||
}
|
||||
return sSettingsDir;
|
||||
#elif defined( LINUX )
|
||||
|
||||
// As defined by XDG Base Directory Specification
|
||||
// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
|
||||
|
||||
const char *pchHome = getenv("XDG_CONFIG_HOME");
|
||||
if ( ( pchHome != NULL) && ( pchHome[0] != '\0' ) )
|
||||
{
|
||||
return pchHome;
|
||||
}
|
||||
|
||||
//
|
||||
// XDG_CONFIG_HOME is not defined, use ~/.config instead
|
||||
//
|
||||
pchHome = getenv( "HOME" );
|
||||
if ( pchHome == NULL )
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string sUserPath( pchHome );
|
||||
sUserPath = Path_Join( sUserPath, ".config" );
|
||||
return sUserPath;
|
||||
#else
|
||||
#warning "Unsupported platform"
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Purpose: Constructor
|
||||
// ---------------------------------------------------------------------------
|
||||
CVRPathRegistry_Public::CVRPathRegistry_Public()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Purpose: Computes the registry filename
|
||||
// ---------------------------------------------------------------------------
|
||||
std::string CVRPathRegistry_Public::GetOpenVRConfigPath()
|
||||
{
|
||||
std::string sConfigPath = GetAppSettingsPath();
|
||||
if( sConfigPath.empty() )
|
||||
return "";
|
||||
|
||||
#if defined( _WIN32 ) || defined( LINUX )
|
||||
sConfigPath = Path_Join( sConfigPath, "openvr" );
|
||||
#elif defined ( OSX )
|
||||
sConfigPath = Path_Join( sConfigPath, ".openvr" );
|
||||
#else
|
||||
#warning "Unsupported platform"
|
||||
#endif
|
||||
sConfigPath = Path_FixSlashes( sConfigPath );
|
||||
return sConfigPath;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
std::string CVRPathRegistry_Public::GetVRPathRegistryFilename()
|
||||
{
|
||||
std::string sOverridePath = GetEnvironmentVariable( "VR_PATHREG_OVERRIDE" );
|
||||
if ( !sOverridePath.empty() )
|
||||
return sOverridePath;
|
||||
|
||||
std::string sPath = GetOpenVRConfigPath();
|
||||
if ( sPath.empty() )
|
||||
return "";
|
||||
|
||||
#if defined( _WIN32 )
|
||||
sPath = Path_Join( sPath, "openvrpaths.vrpath" );
|
||||
#elif defined ( POSIX )
|
||||
sPath = Path_Join( sPath, "openvrpaths.vrpath" );
|
||||
#else
|
||||
#error "Unsupported platform"
|
||||
#endif
|
||||
sPath = Path_FixSlashes( sPath );
|
||||
return sPath;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Purpose: Converts JSON to a history array
|
||||
// ---------------------------------------------------------------------------
|
||||
static void ParseStringListFromJson( std::vector< std::string > *pvecHistory, const Json::Value & root, const char *pchArrayName )
|
||||
{
|
||||
if( !root.isMember( pchArrayName ) )
|
||||
return;
|
||||
|
||||
const Json::Value & arrayNode = root[ pchArrayName ];
|
||||
if( !arrayNode )
|
||||
{
|
||||
VRLog( "VR Path Registry node %s is not an array\n", pchArrayName );
|
||||
return;
|
||||
}
|
||||
|
||||
pvecHistory->clear();
|
||||
pvecHistory->reserve( arrayNode.size() );
|
||||
for( uint32_t unIndex = 0; unIndex < arrayNode.size(); unIndex++ )
|
||||
{
|
||||
std::string sPath( arrayNode[ unIndex ].asString() );
|
||||
pvecHistory->push_back( sPath );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Purpose: Converts a history array to JSON
|
||||
// ---------------------------------------------------------------------------
|
||||
static void StringListToJson( const std::vector< std::string > & vecHistory, Json::Value & root, const char *pchArrayName )
|
||||
{
|
||||
Json::Value & arrayNode = root[ pchArrayName ];
|
||||
for( auto i = vecHistory.begin(); i != vecHistory.end(); i++ )
|
||||
{
|
||||
arrayNode.append( *i );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CVRPathRegistry_Public::ToJsonString( std::string &sJsonString )
|
||||
{
|
||||
std::string sRegPath = GetVRPathRegistryFilename();
|
||||
if( sRegPath.empty() )
|
||||
return false;
|
||||
|
||||
std::string sRegistryContents = Path_ReadTextFile( sRegPath );
|
||||
if( sRegistryContents.empty() )
|
||||
return false;
|
||||
|
||||
sJsonString = sRegistryContents;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Purpose: Loads the config file from its well known location
|
||||
// ---------------------------------------------------------------------------
|
||||
bool CVRPathRegistry_Public::BLoadFromFile( std::string *psLoadError )
|
||||
{
|
||||
std::string sRegPath = GetVRPathRegistryFilename();
|
||||
if( sRegPath.empty() )
|
||||
{
|
||||
if ( psLoadError )
|
||||
{
|
||||
*psLoadError = "Unable to determine VR Path Registry filename";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string sRegistryContents = Path_ReadTextFile( sRegPath );
|
||||
if( sRegistryContents.empty() )
|
||||
{
|
||||
if ( psLoadError )
|
||||
{
|
||||
*psLoadError = "Unable to read VR Path Registry from " + sRegPath;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Json::Value root;
|
||||
Json::CharReaderBuilder builder;
|
||||
std::istringstream istream( sRegistryContents );
|
||||
std::string sErrors;
|
||||
|
||||
try {
|
||||
if ( !parseFromStream( builder, istream, &root, &sErrors ) )
|
||||
{
|
||||
if ( psLoadError )
|
||||
{
|
||||
*psLoadError = "Unable to parse " + sRegPath + ": " + sErrors;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ParseStringListFromJson( &m_vecRuntimePath, root, "runtime" );
|
||||
ParseStringListFromJson( &m_vecConfigPath, root, "config" );
|
||||
ParseStringListFromJson( &m_vecLogPath, root, "log" );
|
||||
if ( root.isMember( "external_drivers" ) && root["external_drivers"].isArray() )
|
||||
{
|
||||
ParseStringListFromJson( &m_vecExternalDrivers, root, "external_drivers" );
|
||||
}
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
if ( psLoadError )
|
||||
{
|
||||
*psLoadError = "Unable to parse " + sRegPath + ": exception thrown in JSON library";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Purpose: Saves the config file to its well known location
|
||||
// ---------------------------------------------------------------------------
|
||||
bool CVRPathRegistry_Public::BSaveToFile() const
|
||||
{
|
||||
std::string sRegPath = GetVRPathRegistryFilename();
|
||||
if( sRegPath.empty() )
|
||||
return false;
|
||||
|
||||
Json::Value root;
|
||||
|
||||
root[ "version" ] = 1;
|
||||
root[ "jsonid" ] = "vrpathreg";
|
||||
|
||||
StringListToJson( m_vecRuntimePath, root, "runtime" );
|
||||
StringListToJson( m_vecConfigPath, root, "config" );
|
||||
StringListToJson( m_vecLogPath, root, "log" );
|
||||
StringListToJson( m_vecExternalDrivers, root, "external_drivers" );
|
||||
|
||||
Json::StreamWriterBuilder builder;
|
||||
std::string sRegistryContents = Json::writeString( builder, root );
|
||||
|
||||
// make sure the directory we're writing into actually exists
|
||||
std::string sRegDirectory = Path_StripFilename( sRegPath );
|
||||
if( !BCreateDirectoryRecursive( sRegDirectory.c_str() ) )
|
||||
{
|
||||
VRLog( "Unable to create path registry directory %s\n", sRegDirectory.c_str() );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !Path_WriteStringToTextFile( sRegPath, sRegistryContents.c_str() ) )
|
||||
{
|
||||
VRLog( "Unable to write VR path registry to %s\n", sRegPath.c_str() );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Purpose: Returns the current runtime path or NULL if no path is configured.
|
||||
// ---------------------------------------------------------------------------
|
||||
std::string CVRPathRegistry_Public::GetRuntimePath() const
|
||||
{
|
||||
if( m_vecRuntimePath.empty() )
|
||||
return "";
|
||||
else
|
||||
return m_vecRuntimePath.front().c_str();
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Purpose: Returns the current config path or NULL if no path is configured.
|
||||
// ---------------------------------------------------------------------------
|
||||
std::string CVRPathRegistry_Public::GetConfigPath() const
|
||||
{
|
||||
if( m_vecConfigPath.empty() )
|
||||
return "";
|
||||
else
|
||||
return m_vecConfigPath.front().c_str();
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Purpose: Returns the current log path or NULL if no path is configured.
|
||||
// ---------------------------------------------------------------------------
|
||||
std::string CVRPathRegistry_Public::GetLogPath() const
|
||||
{
|
||||
if( m_vecLogPath.empty() )
|
||||
return "";
|
||||
else
|
||||
return m_vecLogPath.front().c_str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Purpose: Returns paths using the path registry and the provided override
|
||||
// values. Pass NULL for any paths you don't care about.
|
||||
// ---------------------------------------------------------------------------
|
||||
bool CVRPathRegistry_Public::GetPaths( std::string *psRuntimePath, std::string *psConfigPath, std::string *psLogPath, const char *pchConfigPathOverride, const char *pchLogPathOverride, std::vector<std::string> *pvecExternalDrivers )
|
||||
{
|
||||
std::string sLoadError;
|
||||
CVRPathRegistry_Public pathReg;
|
||||
bool bLoadedRegistry = pathReg.BLoadFromFile( &sLoadError );
|
||||
int nCountEnvironmentVariables = 0;
|
||||
int nRequestedPaths = 0;
|
||||
|
||||
if( psRuntimePath )
|
||||
{
|
||||
nRequestedPaths++;
|
||||
if ( GetEnvironmentVariable( k_pchRuntimeOverrideVar ).length() != 0 )
|
||||
{
|
||||
*psRuntimePath = GetEnvironmentVariable( k_pchRuntimeOverrideVar );
|
||||
nCountEnvironmentVariables++;
|
||||
}
|
||||
else if( !pathReg.GetRuntimePath().empty() )
|
||||
{
|
||||
*psRuntimePath = pathReg.GetRuntimePath();
|
||||
}
|
||||
else
|
||||
{
|
||||
*psRuntimePath = "";
|
||||
}
|
||||
}
|
||||
|
||||
if( psConfigPath )
|
||||
{
|
||||
nRequestedPaths++;
|
||||
if ( GetEnvironmentVariable( k_pchConfigOverrideVar ).length() != 0 )
|
||||
{
|
||||
*psConfigPath = GetEnvironmentVariable( k_pchConfigOverrideVar );
|
||||
nCountEnvironmentVariables++;
|
||||
}
|
||||
else if( pchConfigPathOverride )
|
||||
{
|
||||
*psConfigPath = pchConfigPathOverride;
|
||||
}
|
||||
else if( !pathReg.GetConfigPath().empty() )
|
||||
{
|
||||
*psConfigPath = pathReg.GetConfigPath();
|
||||
}
|
||||
else
|
||||
{
|
||||
*psConfigPath = "";
|
||||
}
|
||||
}
|
||||
|
||||
if( psLogPath )
|
||||
{
|
||||
nRequestedPaths++;
|
||||
if ( GetEnvironmentVariable( k_pchLogOverrideVar ).length() != 0 )
|
||||
{
|
||||
*psLogPath = GetEnvironmentVariable( k_pchLogOverrideVar );
|
||||
nCountEnvironmentVariables++;
|
||||
}
|
||||
else if( pchLogPathOverride )
|
||||
{
|
||||
*psLogPath = pchLogPathOverride;
|
||||
}
|
||||
else if( !pathReg.GetLogPath().empty() )
|
||||
{
|
||||
*psLogPath = pathReg.GetLogPath();
|
||||
}
|
||||
else
|
||||
{
|
||||
*psLogPath = "";
|
||||
}
|
||||
}
|
||||
|
||||
if ( pvecExternalDrivers )
|
||||
{
|
||||
*pvecExternalDrivers = pathReg.m_vecExternalDrivers;
|
||||
}
|
||||
|
||||
if ( nCountEnvironmentVariables == nRequestedPaths )
|
||||
{
|
||||
// all three environment variables were set, so we don't need the physical file
|
||||
return true;
|
||||
}
|
||||
else if( !bLoadedRegistry )
|
||||
{
|
||||
VRLog( "%s\n", sLoadError.c_str() );
|
||||
}
|
||||
|
||||
return bLoadedRegistry;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
uint32_t CVRPathRegistry_Public::GetSteamAppId()
|
||||
{
|
||||
#if !defined( REL_BRANCH_ONLY )
|
||||
uint32_t nSteamAppId = k_unSteamVRMainAppId;
|
||||
#else
|
||||
uint32_t nSteamAppId = k_unSteamVRAppId;
|
||||
#endif
|
||||
|
||||
return nSteamAppId;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CVRPathRegistry_Public::IsSteamVRMain()
|
||||
{
|
||||
#if defined( REL_BRANCH_ONLY )
|
||||
return false;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
uint32_t CVRPathRegistry_Public::InitSteamAppId()
|
||||
{
|
||||
uint32_t nSteamAppId = CVRPathRegistry_Public::GetSteamAppId();
|
||||
|
||||
// Forcefully setting to what it should be before SteamAPI_Init() since SteamVR is more often
|
||||
// started as child processes of the game app and otherwise Steam then considers us as the
|
||||
// wrong app id.
|
||||
SetEnvironmentVariable( "SteamAppId", std::to_string( nSteamAppId ).c_str() );
|
||||
SetEnvironmentVariable( "SteamGameId", std::to_string( nSteamAppId ).c_str() );
|
||||
|
||||
return nSteamAppId;
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
//========= Copyright Valve Corporation ============//
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
|
||||
static const char *k_pchRuntimeOverrideVar = "VR_OVERRIDE";
|
||||
static const char *k_pchConfigOverrideVar = "VR_CONFIG_PATH";
|
||||
static const char *k_pchLogOverrideVar = "VR_LOG_PATH";
|
||||
|
||||
static const uint32_t k_unSteamVRAppId = 250820;
|
||||
static const uint32_t k_unSteamVRMainAppId = 330050;
|
||||
|
||||
|
||||
class CVRPathRegistry_Public
|
||||
{
|
||||
public:
|
||||
static std::string GetVRPathRegistryFilename();
|
||||
static std::string GetOpenVRConfigPath();
|
||||
static uint32_t GetSteamAppId();
|
||||
static bool IsSteamVRMain();
|
||||
static uint32_t InitSteamAppId();
|
||||
|
||||
public:
|
||||
CVRPathRegistry_Public();
|
||||
|
||||
/** Returns paths using the path registry and the provided override values. Pass NULL for any paths you don't care about.
|
||||
* Returns false if the path registry could not be read. Valid paths might still be returned based on environment variables. */
|
||||
static bool GetPaths( std::string *psRuntimePath, std::string *psConfigPath, std::string *psLogPath, const char *pchConfigPathOverride, const char *pchLogPathOverride, std::vector<std::string> *pvecExternalDrivers = NULL );
|
||||
|
||||
bool BLoadFromFile( std::string *psError = nullptr );
|
||||
bool BSaveToFile() const;
|
||||
|
||||
bool ToJsonString( std::string &sJsonString );
|
||||
|
||||
// methods to get the current values
|
||||
std::string GetRuntimePath() const;
|
||||
std::string GetConfigPath() const;
|
||||
std::string GetLogPath() const;
|
||||
|
||||
protected:
|
||||
typedef std::vector< std::string > StringVector_t;
|
||||
|
||||
// index 0 is the current setting
|
||||
StringVector_t m_vecRuntimePath;
|
||||
StringVector_t m_vecLogPath;
|
||||
StringVector_t m_vecConfigPath;
|
||||
|
||||
// full list of external drivers
|
||||
StringVector_t m_vecExternalDrivers;
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 9c0f555acb2531d818f2c405044418fc75379fb2
|
|
@ -0,0 +1,71 @@
|
|||
# Building WOWlet
|
||||
|
||||
Building for Linux and Windows via Docker is done in 3 steps:
|
||||
|
||||
1. Cloning this repository (+submodules)
|
||||
2. Creating a base Docker image
|
||||
3. Using the base image to compile a build
|
||||
|
||||
**important:** you only have to do step 2 (base docker image) once.
|
||||
|
||||
For Mac OS, scroll down.
|
||||
|
||||
# Linux
|
||||
|
||||
For more information, check the Dockerfile: `Dockerfile`.
|
||||
|
||||
### 1. Clone
|
||||
|
||||
```bash
|
||||
git clone --branch master --recursive https://git.wownero.com/wowlet/wowlet.git
|
||||
cd wowlet
|
||||
```
|
||||
|
||||
Replace `master` with the desired version tag (e.g. `v3.1.0`) to build the release binary.
|
||||
|
||||
### 2. Base image
|
||||
|
||||
```bash
|
||||
docker build --tag wowlet:linux --build-arg THREADS=6 .
|
||||
```
|
||||
|
||||
Building the base image takes a while. **You only need to build the base image once.**
|
||||
|
||||
### 3. Build
|
||||
|
||||
```bash
|
||||
docker run --rm -it -v $PWD:/wowlet -w /wowlet wowlet:linux sh -c 'make release-static -j6'
|
||||
```
|
||||
|
||||
If you're re-running a build make sure to `rm -rf build/` first.
|
||||
|
||||
The resulting binary can be found in `build/bin/wowlet`.
|
||||
|
||||
# Windows
|
||||
|
||||
### 1. Clone
|
||||
|
||||
```bash
|
||||
git clone --branch master --recursive https://git.wownero.com/wowlet/wowlet.git
|
||||
cd wowlet
|
||||
```
|
||||
|
||||
Replace `master` with the desired version tag (e.g. `v3.1.0`) to build the release binary.
|
||||
|
||||
### 2. Base image
|
||||
|
||||
```bash
|
||||
docker build -f Dockerfile.windows --tag wowlet:win --build-arg THREADS=6 .
|
||||
```
|
||||
|
||||
Building the base image takes a while. **You only need to build the base image once.**
|
||||
|
||||
### 3. Build
|
||||
|
||||
```bash
|
||||
docker run --rm -it -v $PWD:/wowlet -w /wowlet wowlet:win sh -c 'make windows root=/depends target=x86_64-w64-mingw32 tag=win-x64 -j6'
|
||||
```
|
||||
|
||||
If you're re-running a build make sure to `rm -rf build/` first.
|
||||
|
||||
The resulting binary can be found in `build/x86_64-w64-mingw32/release/bin/wowlet.exe`.
|
|
@ -0,0 +1,89 @@
|
|||
# Documentation for developers
|
||||
|
||||
WOWlet is developed primarily on Linux. It uses Qt 5.15.* and chances are that your
|
||||
distro's package manager has a lower version. It is therefore recommended that you install
|
||||
Qt manually using the online installer, which can be found here: https://www.qt.io/download
|
||||
(under open-source).
|
||||
|
||||
## Jetbrains Clion
|
||||
|
||||
WOWlet was developed using JetBrains Clion since it integrates nicely
|
||||
with CMake and comes with a built-in debugger. To pass CMake flags to CLion,
|
||||
go to `File->Settings->Build->CMake`, set Build Type to `Debug` and set your
|
||||
preferred CMake options/definitions.
|
||||
|
||||
## Man Page
|
||||
|
||||
There is a WOWlet's manual page, which can be accessed with: `man wowlet`
|
||||
|
||||
If a new option is introduced, please be sure to update the options section in
|
||||
`src/assets/wowlet.1.md`, the month and year in line 3, and "manify" the document
|
||||
by running this command: `pandoc wowlet.1.md -s -t man -o wowlet.1 && gzip wowlet.1`
|
||||
|
||||
## Requirements
|
||||
|
||||
(Possibly out-of-date)
|
||||
|
||||
### Ubuntu/Debian
|
||||
|
||||
```bash
|
||||
apt install -y git cmake libqrencode-dev build-essential cmake libboost-all-dev \
|
||||
miniupnpc libunbound-dev graphviz doxygen libunwind8-dev pkg-config libssl-dev \
|
||||
libzmq3-dev libsodium-dev libhidapi-dev libnorm-dev libusb-1.0-0-dev libpgm-dev \
|
||||
libprotobuf-dev protobuf-compiler libgcrypt20-dev libpng-dev
|
||||
```
|
||||
|
||||
## CMake
|
||||
|
||||
After installing Qt you might have a folder called `/home/$USER/Qt/`. You need to pass this to CMake
|
||||
via the `CMAKE_PREFIX_PATH` definition.
|
||||
|
||||
```
|
||||
-DCMAKE_PREFIX_PATH=/home/$USER/QtFooBar/5.15.0/gcc_64
|
||||
```
|
||||
|
||||
There are some Wownero/WOWlet related options/definitions that you may pass, see also `CMakeLists.txt`.
|
||||
|
||||
At a bare minimum, recommended:
|
||||
|
||||
`-DMANUAL_SUBMODULES=1 -DUSE_DEVICE_TREZOR=OFF -DUSE_SINGLE_BUILDDIR=ON -DDEV_MODE=ON`
|
||||
|
||||
If you have OpenSSL installed at a custom location, try:
|
||||
|
||||
```
|
||||
-DOPENSSL_INCLUDE_DIR=/usr/local/lib/openssl-1.1.1g/include
|
||||
-DOPENSSL_SSL_LIBRARY=/usr/local/lib/openssl-1.1.1g/libssl.so.1.1
|
||||
-DOPENSSL_CRYPTO_LIBRARY=/usr/local/lib/openssl-1.1.1g/libcrypto.so.1.1
|
||||
```
|
||||
|
||||
I prefer also enabling verbose makefiles, which may be useful in some situations.
|
||||
|
||||
```
|
||||
-DCMAKE_VERBOSE_MAKEFILE=ON
|
||||
```
|
||||
|
||||
Enable debugging symbols:
|
||||
|
||||
```bash
|
||||
-DCMAKE_BUILD_TYPE=Debug
|
||||
```
|
||||
|
||||
## Wowlet
|
||||
|
||||
It's best to install Tor locally as a service and start `wowlet` with `--use-local-tor`, this
|
||||
prevents the child process from starting up each time you launch WOWlet and thus saves time.
|
||||
|
||||
#### Ubuntu/Debian
|
||||
|
||||
```bash
|
||||
apt install -y tor
|
||||
sudo service tor start
|
||||
```
|
||||
|
||||
To skip the wizards and open a wallet directly use `--wallet-file`:
|
||||
|
||||
```bash
|
||||
./wowlet --use-local-tor --wallet-file /home/user/Wownero/wallets/bla.keys
|
||||
```
|
||||
|
||||
|
|
@ -11,6 +11,5 @@ The following keys may be used to communicate sensitive information to developer
|
|||
| Name | Fingerprint |
|
||||
|------|-------------|
|
||||
| dsc | 1BFD 40F9 B0E2 B40D C8C7 FD4A 521F 1E79 91AA 42DC |
|
||||
| tobtoht | C5AB E5C0 E50F A2B3 F14A B92D 1CAD D27F 41F4 5C3C |
|
||||
|
||||
Public keys can be found in `utils/pubkeys`.
|
1
monero
|
@ -1 +0,0 @@
|
|||
Subproject commit f611d5c9e32bc62f1735f6571b0bdb95cc020531
|
|
@ -2,19 +2,11 @@ set(CMAKE_AUTOMOC ON)
|
|||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
|
||||
# pthread
|
||||
find_package(Threads REQUIRED)
|
||||
find_package(ZLIB REQUIRED)
|
||||
find_package(PNG REQUIRED)
|
||||
|
||||
find_package(Qt5 REQUIRED COMPONENTS Core Widgets Gui Network Svg Xml WebSockets)
|
||||
|
||||
add_subdirectory(libwalletqt)
|
||||
add_subdirectory(model)
|
||||
add_subdirectory(utils)
|
||||
add_subdirectory(openpgp)
|
||||
|
||||
qt5_add_resources(RESOURCES assets.qrc)
|
||||
|
||||
# Compile source files (.h/.cpp)
|
||||
# Compile these source files (.h/.cpp)
|
||||
file(GLOB SOURCE_FILES
|
||||
"*.h"
|
||||
"*.cpp"
|
||||
|
@ -42,12 +34,43 @@ file(GLOB SOURCE_FILES
|
|||
"dialog/*.cpp"
|
||||
)
|
||||
|
||||
find_package(Qt5 REQUIRED COMPONENTS Core Widgets Gui Network Svg Xml WebSockets Quick QuickWidgets Qml QuickControls2 QuickCompiler QmlImportScanner Multimedia)
|
||||
|
||||
if(OPENVR)
|
||||
# include some extra files
|
||||
qt5_add_resources(RESOURCES vr/qml.qrc)
|
||||
file(GLOB SOURCE_FILES_QML
|
||||
"vr/*.h"
|
||||
"vr/*.cpp"
|
||||
"vr/utils/*.h"
|
||||
"vr/utils/*.cpp"
|
||||
)
|
||||
list(APPEND SOURCE_FILES ${SOURCE_FILES_QML})
|
||||
endif()
|
||||
|
||||
if(ANDROID OR ANDROID_DEBUG)
|
||||
qt5_add_resources(RESOURCES mobile/qml.qrc)
|
||||
file(GLOB SOURCE_FILES_QML
|
||||
"mobile/*.h"
|
||||
"mobile/*.cpp"
|
||||
)
|
||||
list(APPEND SOURCE_FILES ${SOURCE_FILES_QML})
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wno-deprecated-declarations") # @TODO: removeme
|
||||
|
||||
add_subdirectory(libwalletqt)
|
||||
add_subdirectory(model)
|
||||
add_subdirectory(utils)
|
||||
|
||||
if(WITH_SCANNER)
|
||||
add_subdirectory(QR-Code-scanner)
|
||||
endif()
|
||||
|
||||
qt5_add_resources(RESOURCES assets.qrc)
|
||||
|
||||
if(TOR_BIN)
|
||||
if(APPLE)
|
||||
set(ASSETS_TOR "assets_tor_macos.qrc")
|
||||
else()
|
||||
set(ASSETS_TOR "assets_tor.qrc")
|
||||
endif()
|
||||
set(ASSETS_TOR "assets_tor.qrc")
|
||||
endif()
|
||||
|
||||
set(EXECUTABLE_FLAG)
|
||||
|
@ -70,11 +93,16 @@ if(APPLE)
|
|||
list(APPEND RESOURCES ${ICON})
|
||||
endif()
|
||||
|
||||
add_executable(wowlet ${EXECUTABLE_FLAG} main.cpp
|
||||
${SOURCE_FILES}
|
||||
${RESOURCES}
|
||||
${ASSETS_TOR}
|
||||
)
|
||||
if(NOT ANDROID)
|
||||
add_executable(wowlet ${EXECUTABLE_FLAG} main.cpp
|
||||
${SOURCE_FILES}
|
||||
${RESOURCES}
|
||||
${ASSETS_TOR}
|
||||
)
|
||||
else()
|
||||
add_library(wowlet SHARED ${SOURCE_FILES} ${RESOURCES})
|
||||
set_target_properties(wowlet PROPERTIES COMPILE_DEFINITIONS "ANDROID")
|
||||
endif()
|
||||
|
||||
# mac os bundle
|
||||
set_target_properties(wowlet PROPERTIES
|
||||
|
@ -93,11 +121,11 @@ file(GLOB_RECURSE SRC_SOURCES *.cpp)
|
|||
file(GLOB_RECURSE SRC_HEADERS *.h)
|
||||
|
||||
target_include_directories(wowlet PUBLIC
|
||||
${CMAKE_BINARY_DIR}/src/feather_autogen/include
|
||||
${CMAKE_SOURCE_DIR}/monero/include
|
||||
${CMAKE_SOURCE_DIR}/monero/src
|
||||
${CMAKE_SOURCE_DIR}/monero/external/easylogging++
|
||||
${CMAKE_SOURCE_DIR}/monero/contrib/epee/include
|
||||
${CMAKE_BINARY_DIR}/src/wowlet_autogen/include
|
||||
${CMAKE_SOURCE_DIR}/wownero/include
|
||||
${CMAKE_SOURCE_DIR}/wownero/src
|
||||
${CMAKE_SOURCE_DIR}/wownero/external/easylogging++
|
||||
${CMAKE_SOURCE_DIR}/wownero/contrib/epee/include
|
||||
${CMAKE_SOURCE_DIR}/src
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/daemon
|
||||
|
@ -107,7 +135,9 @@ target_include_directories(wowlet PUBLIC
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/tor
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/qrcode
|
||||
${X11_INCLUDE_DIR}
|
||||
${QRENCODE_INCLUDE_DIR}
|
||||
${Boost_INCLUDE_DIRS}
|
||||
${Iconv_INCLUDE_DIRS}
|
||||
${OPENSSL_INCLUDE_DIR}
|
||||
${Qt5Core_INCLUDE_DIRS}
|
||||
${Qt5Widgets_INCLUDE_DIRS}
|
||||
|
@ -118,16 +148,32 @@ target_include_directories(wowlet PUBLIC
|
|||
${Qt5WebSockets_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
if(DONATE_BEG)
|
||||
target_compile_definitions(wowlet PRIVATE DONATE_BEG=1)
|
||||
if(LINUX_ACTIVATION)
|
||||
target_include_directories(wowlet PUBLIC
|
||||
${CAIRO_INCLUDE_DIRS}
|
||||
${XFIXES_INCLUDE_DIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
if(OPENVR)
|
||||
target_include_directories(wowlet PUBLIC ${CMAKE_SOURCE_DIR}/contrib/)
|
||||
endif()
|
||||
|
||||
if(TOR_BIN)
|
||||
target_compile_definitions(wowlet PRIVATE HAS_TOR_BIN=1)
|
||||
endif()
|
||||
|
||||
if(XMRIG)
|
||||
target_compile_definitions(wowlet PRIVATE HAS_XMRIG=1)
|
||||
if(ANDROID)
|
||||
target_compile_definitions(wowlet PRIVATE HAS_ANDROID=1)
|
||||
endif()
|
||||
|
||||
if(ANDROID_DEBUG)
|
||||
target_compile_definitions(wowlet PRIVATE HAS_ANDROID_DEBUG=1)
|
||||
endif()
|
||||
|
||||
if(OPENVR)
|
||||
target_compile_definitions(wowlet PRIVATE HAS_OPENVR=1)
|
||||
target_compile_definitions(wowlet PUBLIC VR_API_PUBLIC)
|
||||
endif()
|
||||
|
||||
if(HAVE_SYS_PRCTL_H)
|
||||
|
@ -138,8 +184,8 @@ if(STATIC)
|
|||
target_compile_definitions(wowlet PRIVATE STATIC=1)
|
||||
endif()
|
||||
|
||||
if(STATIC)
|
||||
target_compile_definitions(wowlet PRIVATE STATIC=1)
|
||||
if(LINUX_ACTIVATION)
|
||||
target_compile_definitions(wowlet PRIVATE LINUX_ACTIVATION=1)
|
||||
endif()
|
||||
|
||||
if("$ENV{DRONE}" STREQUAL "true")
|
||||
|
@ -150,6 +196,15 @@ if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
|
|||
target_compile_definitions(wowlet PRIVATE QT_NO_DEBUG=1)
|
||||
endif()
|
||||
|
||||
add_definitions(${QT_DEFINITIONS})
|
||||
if(NOT "${CMAKE_BUILD_TYPE}" EQUAL "Debug")
|
||||
add_definitions(-DQT_NO_DEBUG)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(wowlet PUBLIC VR_API_PUBLIC)
|
||||
|
||||
qt5_import_qml_plugins(${PROJECT_NAME})
|
||||
|
||||
target_compile_definitions(wowlet
|
||||
PUBLIC
|
||||
${Qt5Core_DEFINITIONS}
|
||||
|
@ -163,73 +218,181 @@ target_compile_definitions(wowlet
|
|||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
if(UNIX)
|
||||
# https://stackoverflow.com/questions/57766620/cmake-add-library-doesnt-initialize-static-global-variable
|
||||
# so that contrib/monero-seed/src/gf_elem.cpp properly initializes. A better solution is welcome.
|
||||
target_link_libraries(wowlet -Wl,--whole-archive monero-seed::monero-seed -Wl,--no-whole-archive)
|
||||
else()
|
||||
target_link_libraries(wowlet monero-seed::monero-seed)
|
||||
target_link_libraries(wowlet PUBLIC -Wl,--whole-archive wownero-seed::wownero-seed -Wl,--no-whole-archive)
|
||||
endif()
|
||||
|
||||
target_link_libraries(wowlet
|
||||
wallet_merged
|
||||
${LMDB_LIBRARY}
|
||||
if(ANDROID)
|
||||
# yolo some hardcoded paths
|
||||
target_include_directories(wowlet PUBLIC
|
||||
/opt/android/prefix/include/QtAndroidExtras/
|
||||
)
|
||||
endif()
|
||||
|
||||
# Link Wownero core libraries
|
||||
target_link_libraries(wowlet PUBLIC
|
||||
epee
|
||||
${UNBOUND_LIBRARY}
|
||||
${SODIUM_LIBRARY}
|
||||
wallet_api
|
||||
easylogging
|
||||
blockchain_db
|
||||
hardforks
|
||||
${Boost_LIBRARIES}
|
||||
${OPENSSL_LIBRARIES}
|
||||
${CMAKE_DL_LIBS}
|
||||
${EXTRA_LIBRARIES}
|
||||
${Iconv_LIBRARIES}
|
||||
${UNBOUND_LIBRARIES}
|
||||
# /usr/local/lib/libunbound.a
|
||||
${EXTRA_LIBRARIES})
|
||||
|
||||
# Link Qt libraries
|
||||
target_link_libraries(wowlet PUBLIC
|
||||
Qt5::Core
|
||||
Qt5::Widgets
|
||||
Qt5::Gui
|
||||
Qt5::Network
|
||||
Qt5::Svg
|
||||
Qt5::QSvgPlugin
|
||||
Qt5::QSvgIconPlugin
|
||||
Qt5::Xml
|
||||
Qt5::WebSockets
|
||||
${ICU_LIBRARIES}
|
||||
openpgp
|
||||
Qt5::Quick
|
||||
Qt5::Qml
|
||||
Qt5::QuickControls2
|
||||
Qt5::QuickWidgets)
|
||||
|
||||
if(ANDROID)
|
||||
# yolo some hardcoded paths
|
||||
target_link_libraries(wowlet PUBLIC
|
||||
/opt/android/prefix/lib/libQt5QuickTemplates2_arm64-v8a.so
|
||||
/opt/android/prefix/lib/libQt5Quick_arm64-v8a.so
|
||||
/opt/android/prefix/lib/libQt5QmlModels_arm64-v8a.so
|
||||
/opt/android/prefix/lib/libQt5Qml_arm64-v8a.so
|
||||
/opt/android/prefix/lib/libQt5Svg_arm64-v8a.so
|
||||
/opt/android/prefix/lib/libQt5Widgets_arm64-v8a.so
|
||||
/opt/android/prefix/lib/libQt5Gui_arm64-v8a.so
|
||||
/opt/android/prefix/lib/libQt5Xml_arm64-v8a.so
|
||||
/opt/android/prefix/lib/libQt5XmlPatterns_arm64-v8a.so
|
||||
/opt/android/prefix/lib/libQt5Network_arm64-v8a.so
|
||||
/opt/android/prefix/lib/libQt5Core_arm64-v8a.so
|
||||
/opt/android/prefix/lib/libQt5VirtualKeyboard_arm64-v8a.so
|
||||
/opt/android/prefix/lib/libQt5AndroidExtras_arm64-v8a.so
|
||||
/opt/android/prefix/plugins/bearer/libplugins_bearer_qandroidbearer_arm64-v8a.so
|
||||
GLESv2
|
||||
log
|
||||
z
|
||||
jnigraphics
|
||||
android
|
||||
EGL
|
||||
c++_shared
|
||||
)
|
||||
endif()
|
||||
|
||||
# Link random other stuff
|
||||
target_link_libraries(wowlet PUBLIC
|
||||
Threads::Threads
|
||||
${QRENCODE_LIBRARY}
|
||||
)
|
||||
|
||||
if(APPLE)
|
||||
target_link_libraries(wowlet
|
||||
KDMacTouchBar
|
||||
# Link Cairo and Xfixes
|
||||
if(LINUX_ACTIVATION)
|
||||
target_link_libraries(wowlet PUBLIC
|
||||
${CAIRO_LIBRARIES}
|
||||
${XFIXES_LIBRARY}
|
||||
${X11_Xinerama_LIB}
|
||||
)
|
||||
target_include_directories(wowlet
|
||||
PUBLIC ../contrib/KDMacTouchBar)
|
||||
endif()
|
||||
|
||||
if(NOT APPLE)
|
||||
target_link_libraries(wowlet
|
||||
Qt5::QSvgIconPlugin
|
||||
Qt5::QSvgPlugin
|
||||
)
|
||||
# Link scanner
|
||||
if(WITH_SCANNER)
|
||||
target_link_libraries(wowlet PUBLIC qrdecoder qrscanner)
|
||||
if(LINUX AND NOT ANDROID)
|
||||
target_link_libraries(wowlet PUBLIC
|
||||
jpeg
|
||||
v4l2
|
||||
v4lconvert
|
||||
rt
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Link OpenVR
|
||||
if(OPENVR)
|
||||
if(MINGW)
|
||||
target_link_libraries(wowlet PUBLIC
|
||||
openvr_api64
|
||||
gcc stdc++ winpthread ssp glu32 opengl32 glmf32 -dynamic)
|
||||
else()
|
||||
target_link_libraries(wowlet PUBLIC openvr_api)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_link_libraries(wowlet PUBLIC
|
||||
Qt5::QSvgIconPlugin
|
||||
Qt5::QSvgPlugin
|
||||
)
|
||||
|
||||
if(STATIC)
|
||||
target_link_libraries(wowlet
|
||||
target_link_libraries(wowlet PUBLIC
|
||||
Qt5::QSvgIconPlugin
|
||||
Qt5::QSvgPlugin)
|
||||
if(UNIX AND NOT APPLE)
|
||||
target_link_libraries(wowlet
|
||||
Qt5::QXcbIntegrationPlugin)
|
||||
if(UNIX)
|
||||
target_link_libraries(wowlet PUBLIC
|
||||
Qt5::QXcbIntegrationPlugin)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(X11_FOUND)
|
||||
target_link_libraries(wowlet ${X11_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
include(Deploy)
|
||||
target_link_libraries(wowlet PUBLIC ${X11_LIBRARIES})
|
||||
endif()
|
||||
|
||||
install(TARGETS wowlet
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}
|
||||
)
|
||||
|
||||
|
||||
message(STATUS "\n====================================== SUMMARY")
|
||||
if(GIT_FOUND)
|
||||
execute_process(COMMAND git rev-parse "HEAD" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/wownero OUTPUT_VARIABLE _WOWNERO_HEAD OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(NOT _WOWNERO_HEAD STREQUAL WOWNERO_HEAD)
|
||||
message(STATUS "[+] WOWNERO HEAD: ${_WOWNERO_HEAD} ... while CMake requested ${WOWNERO_HEAD}")
|
||||
else()
|
||||
message(STATUS "[+] WOWNERO HEAD: ${WOWNERO_HEAD}")
|
||||
endif()
|
||||
endif()
|
||||
message(STATUS "[+] VERSION: ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}-${VERSION}")
|
||||
message(STATUS "[+] STATIC: ${STATIC}")
|
||||
message(STATUS "[+] Include Valve's OpenVR library: ${OPENVR}")
|
||||
message(STATUS "[+] This build is for Android: ${ANDROID}")
|
||||
message(STATUS "[+] This build is for testing the Android app on desktop: ${ANDROID_DEBUG}")
|
||||
message(STATUS "[+] TOR_BIN: ${TOR_BIN}")
|
||||
message(STATUS "[+] LINUX_ACTIVATION: ${LINUX_ACTIVATION}")
|
||||
|
||||
message(STATUS "[+] OpenSSL")
|
||||
message(STATUS " - version: ${OPENSSL_VERSION}")
|
||||
message(STATUS " - dirs: ${OPENSSL_INCLUDE_DIR}")
|
||||
message(STATUS " - libs: ${OPENSSL_LIBRARIES} ${OPENSSL_SSL_LIBRARIES}")
|
||||
|
||||
if(CAIRO_FOUND)
|
||||
message(STATUS "[+] Cairo")
|
||||
message(STATUS " - version: ${CAIRO_VERSION}")
|
||||
message(STATUS " - dirs: ${CAIRO_INCLUDE_DIRS}")
|
||||
message(STATUS " - libs: ${CAIRO_LIBRARIES}")
|
||||
endif()
|
||||
|
||||
if(XFIXES_FOUND)
|
||||
message(STATUS "[+] Xfixes")
|
||||
message(STATUS " - dirs: ${XFIXES_INCLUDE_DIR}")
|
||||
message(STATUS " - libs: ${XFIXES_LIBRARY}")
|
||||
endif()
|
||||
|
||||
message(STATUS "[+] Boost")
|
||||
message(STATUS " - version: ${Boost_VERSION}")
|
||||
message(STATUS " - dirs: ${Boost_INCLUDE_DIRS}")
|
||||
message(STATUS " - libs: ${Boost_LIBRARIES}")
|
||||
|
||||
if(Iconv_FOUND)
|
||||
message(STATUS "[+] Iconv")
|
||||
message(STATUS " - version: ${Iconv_VERSION}")
|
||||
message(STATUS " - libs: ${Iconv_LIBRARIES}")
|
||||
message(STATUS " - dirs: ${Iconv_INCLUDE_DIRS}")
|
||||
endif()
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
add_library(qrdecoder STATIC
|
||||
Decoder.cpp
|
||||
)
|
||||
target_link_libraries(qrdecoder
|
||||
PUBLIC
|
||||
Qt5::Gui
|
||||
PNG::PNG
|
||||
PRIVATE
|
||||
quirc
|
||||
)
|
||||
|
||||
if(WITH_SCANNER)
|
||||
add_library(qrscanner
|
||||
QrCodeScanner.cpp
|
||||
QrScanThread.cpp
|
||||
)
|
||||
target_link_libraries(qrscanner
|
||||
PUBLIC
|
||||
Qt5::Multimedia
|
||||
qrdecoder
|
||||
)
|
||||
endif()
|
|
@ -0,0 +1,359 @@
|
|||
// Copyright (c) 2020, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits>
|
||||
#include <QDebug>
|
||||
#include <QString>
|
||||
#include "Decoder.h"
|
||||
#include "quirc.h"
|
||||
|
||||
|
||||
QrDecoder::QrDecoder()
|
||||
: m_qr(quirc_new())
|
||||
{
|
||||
if (m_qr == nullptr)
|
||||
{
|
||||
throw std::runtime_error("QUIRC: failed to allocate memory");
|
||||
}
|
||||
}
|
||||
|
||||
QrDecoder::~QrDecoder()
|
||||
{
|
||||
quirc_destroy(m_qr);
|
||||
}
|
||||
|
||||
std::vector<std::string> QrDecoder::decode(const QImage &image)
|
||||
{
|
||||
if (image.format() == QImage::Format_Grayscale8)
|
||||
{
|
||||
return decodeGrayscale8(image);
|
||||
}
|
||||
return decodeGrayscale8(image.convertToFormat(QImage::Format_Grayscale8));
|
||||
}
|
||||
|
||||
std::vector<std::string> QrDecoder::decodePNG(QString pngPath) {
|
||||
struct quirc *q;
|
||||
std::vector<std::string> result;
|
||||
auto pngPathStd = pngPath.toStdString();
|
||||
auto pngPathCstr = pngPathStd.c_str();
|
||||
|
||||
q = quirc_new();
|
||||
if (!q) {
|
||||
qWarning() << "can't create quirc object";
|
||||
return result;
|
||||
}
|
||||
|
||||
int status = -1;
|
||||
if (check_if_png(pngPathCstr)) {
|
||||
status = load_png(q, pngPathCstr);
|
||||
} else {
|
||||
qWarning() << QString("Image is not a PNG: %1").arg(pngPath);
|
||||
return result;
|
||||
}
|
||||
if (status < 0) {
|
||||
quirc_destroy(q);
|
||||
return result;
|
||||
}
|
||||
|
||||
quirc_end(q);
|
||||
auto count = quirc_count(q);
|
||||
result.reserve(static_cast<size_t>(count));
|
||||
|
||||
for (int index = 0; index < count; ++index)
|
||||
{
|
||||
quirc_code code;
|
||||
quirc_extract(q, index, &code);
|
||||
|
||||
quirc_data data;
|
||||
const quirc_decode_error_t err = quirc_decode(&code, &data);
|
||||
if (err == QUIRC_SUCCESS)
|
||||
{
|
||||
result.emplace_back(&data.payload[0], &data.payload[data.payload_len]);
|
||||
}
|
||||
}
|
||||
|
||||
quirc_destroy(q);
|
||||
return result;
|
||||
}
|
||||
|
||||
// I can't seem to get this function to work, we'll use dgbutil.h instead
|
||||
std::vector<std::string> QrDecoder::decodeGrayscale8(const QImage &image)
|
||||
{
|
||||
if (quirc_resize(m_qr, image.width(), image.height()) < 0)
|
||||
{
|
||||
throw std::runtime_error("QUIRC: failed to allocate video memory");
|
||||
}
|
||||
|
||||
uint8_t *rawImage = quirc_begin(m_qr, nullptr, nullptr);
|
||||
if (rawImage == nullptr)
|
||||
{
|
||||
throw std::runtime_error("QUIRC: failed to get image buffer");
|
||||
}
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
|
||||
std::copy(image.constBits(), image.constBits() + image.sizeInBytes(), rawImage);
|
||||
#else
|
||||
std::copy(image.constBits(), image.constBits() + image.byteCount(), rawImage);
|
||||
#endif
|
||||
quirc_end(m_qr);
|
||||
|
||||
const int count = quirc_count(m_qr);
|
||||
if (count < 0)
|
||||
{
|
||||
throw std::runtime_error("QUIRC: failed to get the number of recognized QR-codes");
|
||||
}
|
||||
|
||||
std::vector<std::string> result;
|
||||
result.reserve(static_cast<size_t>(count));
|
||||
for (int index = 0; index < count; ++index)
|
||||
{
|
||||
quirc_code code;
|
||||
quirc_extract(m_qr, index, &code);
|
||||
|
||||
quirc_data data;
|
||||
const quirc_decode_error_t err = quirc_decode(&code, &data);
|
||||
if (err == QUIRC_SUCCESS)
|
||||
{
|
||||
result.emplace_back(&data.payload[0], &data.payload[data.payload_len]);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* quirc -- QR-code recognition library
|
||||
* Copyright (C) 2010-2012 Daniel Beer <dlbeer@gmail.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
static const char *data_type_str(int dt)
|
||||
{
|
||||
switch (dt) {
|
||||
case QUIRC_DATA_TYPE_NUMERIC: return "NUMERIC";
|
||||
case QUIRC_DATA_TYPE_ALPHA: return "ALPHA";
|
||||
case QUIRC_DATA_TYPE_BYTE: return "BYTE";
|
||||
case QUIRC_DATA_TYPE_KANJI: return "KANJI";
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
void QrDecoder::dump_data(const struct quirc_data *data)
|
||||
{
|
||||
printf(" Version: %d\n", data->version);
|
||||
printf(" ECC level: %c\n", "MLHQ"[data->ecc_level]);
|
||||
printf(" Mask: %d\n", data->mask);
|
||||
printf(" Data type: %d (%s)\n",
|
||||
data->data_type, data_type_str(data->data_type));
|
||||
printf(" Length: %d\n", data->payload_len);
|
||||
printf(" Payload: %s\n", data->payload);
|
||||
|
||||
if (data->eci)
|
||||
printf(" ECI: %d\n", data->eci);
|
||||
}
|
||||
|
||||
void QrDecoder::dump_cells(const struct quirc_code *code)
|
||||
{
|
||||
int u, v;
|
||||
|
||||
printf(" %d cells, corners:", code->size);
|
||||
for (u = 0; u < 4; u++)
|
||||
printf(" (%d,%d)", code->corners[u].x,
|
||||
code->corners[u].y);
|
||||
printf("\n");
|
||||
|
||||
for (v = 0; v < code->size; v++) {
|
||||
printf(" ");
|
||||
for (u = 0; u < code->size; u++) {
|
||||
int p = v * code->size + u;
|
||||
|
||||
if (code->cell_bitmap[p >> 3] & (1 << (p & 7)))
|
||||
printf("[]");
|
||||
else
|
||||
printf(" ");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* hacked from https://dev.w3.org/Amaya/libpng/example.c
|
||||
*
|
||||
* Check if a file is a PNG image using png_sig_cmp(). Returns 1 if the given
|
||||
* file is a PNG and 0 otherwise.
|
||||
*/
|
||||
#define PNG_BYTES_TO_CHECK 4
|
||||
int QrDecoder::check_if_png(const char *filename)
|
||||
{
|
||||
int ret = 0;
|
||||
FILE *infile = NULL;
|
||||
unsigned char buf[PNG_BYTES_TO_CHECK];
|
||||
|
||||
/* Open the prospective PNG file. */
|
||||
if ((infile = fopen(filename, "rb")) == NULL)
|
||||
goto out;
|
||||
|
||||
/* Read in some of the signature bytes */
|
||||
if (fread(buf, 1, PNG_BYTES_TO_CHECK, infile) != PNG_BYTES_TO_CHECK)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Compare the first PNG_BYTES_TO_CHECK bytes of the signature.
|
||||
* png_sig_cmp() returns zero if the image is a PNG and nonzero if it
|
||||
* isn't a PNG.
|
||||
*/
|
||||
if (png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK) == 0)
|
||||
ret = 1;
|
||||
|
||||
/* FALLTHROUGH */
|
||||
out:
|
||||
if (infile)
|
||||
fclose(infile);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int QrDecoder::load_png(struct quirc *q, const char *filename)
|
||||
{
|
||||
int width, height, rowbytes, interlace_type, number_passes = 1;
|
||||
png_uint_32 trns;
|
||||
png_byte color_type, bit_depth;
|
||||
png_structp png_ptr = NULL;
|
||||
png_infop info_ptr = NULL;
|
||||
FILE *infile = NULL;
|
||||
uint8_t *image;
|
||||
int ret = -1;
|
||||
int pass;
|
||||
|
||||
if ((infile = fopen(filename, "rb")) == NULL)
|
||||
goto out;
|
||||
|
||||
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if (!png_ptr)
|
||||
goto out;
|
||||
|
||||
info_ptr = png_create_info_struct(png_ptr);
|
||||
if (!info_ptr)
|
||||
goto out;
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr)))
|
||||
goto out;
|
||||
|
||||
png_init_io(png_ptr, infile);
|
||||
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
|
||||
color_type = png_get_color_type(png_ptr, info_ptr);
|
||||
bit_depth = png_get_bit_depth(png_ptr, info_ptr);
|
||||
interlace_type = png_get_interlace_type(png_ptr, info_ptr);
|
||||
|
||||
// Read any color_type into 8bit depth, Grayscale format.
|
||||
// See http://www.libpng.org/pub/png/libpng-manual.txt
|
||||
|
||||
// PNG_COLOR_TYPE_GRAY_ALPHA is always 8 or 16bit depth.
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
|
||||
png_set_expand_gray_1_2_4_to_8(png_ptr);
|
||||
|
||||
if ((trns = png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)))
|
||||
png_set_tRNS_to_alpha(png_ptr);
|
||||
|
||||
if (bit_depth == 16)
|
||||
#if PNG_LIBPNG_VER >= 10504
|
||||
png_set_scale_16(png_ptr);
|
||||
#else
|
||||
png_set_strip_16(png_ptr);
|
||||
#endif
|
||||
|
||||
if ((trns) || color_type & PNG_COLOR_MASK_ALPHA)
|
||||
png_set_strip_alpha(png_ptr);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_PALETTE)
|
||||
png_set_palette_to_rgb(png_ptr);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_PALETTE ||
|
||||
color_type == PNG_COLOR_TYPE_RGB ||
|
||||
color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
|
||||
png_set_rgb_to_gray_fixed(png_ptr, 1, -1, -1);
|
||||
}
|
||||
|
||||
if (interlace_type != PNG_INTERLACE_NONE)
|
||||
number_passes = png_set_interlace_handling(png_ptr);
|
||||
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
|
||||
width = png_get_image_width(png_ptr, info_ptr);
|
||||
height = png_get_image_height(png_ptr, info_ptr);
|
||||
rowbytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||
if (rowbytes != width) {
|
||||
fprintf(stderr,
|
||||
"load_png: expected rowbytes to be %u but got %u\n",
|
||||
width, rowbytes);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (quirc_resize(q, width, height) < 0)
|
||||
goto out;
|
||||
|
||||
image = quirc_begin(q, NULL, NULL);
|
||||
|
||||
for (pass = 0; pass < number_passes; pass++) {
|
||||
int y;
|
||||
|
||||
for (y = 0; y < height; y++) {
|
||||
png_bytep row_pointer = image + y * width;
|
||||
png_read_rows(png_ptr, &row_pointer, NULL, 1);
|
||||
}
|
||||
}
|
||||
|
||||
png_read_end(png_ptr, info_ptr);
|
||||
|
||||
ret = 0;
|
||||
/* FALLTHROUGH */
|
||||
out:
|
||||
/* cleanup */
|
||||
if (png_ptr) {
|
||||
if (info_ptr)
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
|
||||
else
|
||||
png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
|
||||
}
|
||||
if (infile)
|
||||
fclose(infile);
|
||||
return (ret);
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2020-2021, The Monero Project
|
||||
// Copyright (c) 2020, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
|
@ -26,63 +26,47 @@
|
|||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#pragma once
|
||||
#include <QImage>
|
||||
|
||||
#include <vector>
|
||||
#include <png.h>
|
||||
|
||||
#include <span.h>
|
||||
struct quirc;
|
||||
|
||||
#include "serialization.h"
|
||||
|
||||
namespace openpgp
|
||||
{
|
||||
|
||||
class packet_stream
|
||||
class QrDecoder
|
||||
{
|
||||
public:
|
||||
packet_stream(const epee::span<const uint8_t> buffer)
|
||||
: packet_stream(deserializer<epee::span<const uint8_t>>(buffer))
|
||||
{
|
||||
}
|
||||
QrDecoder(const QrDecoder &) = delete;
|
||||
QrDecoder &operator=(const QrDecoder &) = delete;
|
||||
|
||||
template <
|
||||
typename byte_container,
|
||||
typename = typename std::enable_if<(sizeof(typename byte_container::value_type) == 1)>::type>
|
||||
packet_stream(deserializer<byte_container> buffer)
|
||||
{
|
||||
while (!buffer.empty())
|
||||
{
|
||||
packet_tag tag = buffer.read_packet_tag();
|
||||
packets.push_back({std::move(tag), buffer.read(tag.length)});
|
||||
}
|
||||
}
|
||||
QrDecoder();
|
||||
~QrDecoder();
|
||||
|
||||
const std::vector<uint8_t> *find_first(packet_tag::type type) const
|
||||
{
|
||||
for (const auto &packet : packets)
|
||||
{
|
||||
if (packet.first.packet_type == type)
|
||||
{
|
||||
return &packet.second;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename Callback>
|
||||
void for_each(packet_tag::type type, Callback &callback) const
|
||||
{
|
||||
for (const auto &packet : packets)
|
||||
{
|
||||
if (packet.first.packet_type == type)
|
||||
{
|
||||
callback(packet.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::vector<std::string> decode(const QImage &image);
|
||||
std::vector<std::string> decodePNG(QString pngPath);
|
||||
|
||||
private:
|
||||
std::vector<std::pair<packet_tag, std::vector<uint8_t>>> packets;
|
||||
};
|
||||
/* Dump decoded information on stdout. */
|
||||
void dump_data(const struct quirc_data *data);
|
||||
|
||||
} // namespace openpgp
|
||||
/* Dump a grid cell map on stdout. */
|
||||
void dump_cells(const struct quirc_code *code);
|
||||
|
||||
/* Check if a file is a PNG image.
|
||||
*
|
||||
* returns 1 if the given file is a PNG and 0 otherwise.
|
||||
*/
|
||||
int check_if_png(const char *filename);
|
||||
|
||||
/* Read a PNG image into the decoder.
|
||||
*
|
||||
* Note that you must call quirc_end() if the function returns
|
||||
* successfully (0).
|
||||
*/
|
||||
int load_png(struct quirc *q, const char *filename);
|
||||
|
||||
private:
|
||||
std::vector<std::string> decodeGrayscale8(const QImage &image);
|
||||
|
||||
private:
|
||||
quirc *m_qr;
|
||||
};
|
|
@ -0,0 +1,92 @@
|
|||
// Copyright (c) 2014-2019, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "QrCodeScanner.h"
|
||||
#include <QVideoProbe>
|
||||
#include <QCamera>
|
||||
|
||||
QrCodeScanner::QrCodeScanner(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_processTimerId(-1)
|
||||
, m_processInterval(750)
|
||||
, m_enabled(true)
|
||||
{
|
||||
m_probe = new QVideoProbe(this);
|
||||
m_thread = new QrScanThread(this);
|
||||
m_thread->start();
|
||||
QObject::connect(m_thread, SIGNAL(decoded(QString)), this, SIGNAL(decoded(QString)));
|
||||
QObject::connect(m_thread, SIGNAL(notifyError(const QString &, bool)), this, SIGNAL(notifyError(const QString &, bool)));
|
||||
connect(m_probe, SIGNAL(videoFrameProbed(QVideoFrame)), this, SLOT(processFrame(QVideoFrame)));
|
||||
}
|
||||
void QrCodeScanner::setSource(QCamera *camera)
|
||||
{
|
||||
m_probe->setSource(camera);
|
||||
}
|
||||
void QrCodeScanner::processFrame(QVideoFrame frame)
|
||||
{
|
||||
if(frame.isValid()){
|
||||
m_curFrame = frame;
|
||||
}
|
||||
}
|
||||
bool QrCodeScanner::enabled() const
|
||||
{
|
||||
return m_enabled;
|
||||
}
|
||||
void QrCodeScanner::setEnabled(bool enabled)
|
||||
{
|
||||
m_enabled = enabled;
|
||||
if(!enabled && (m_processTimerId != -1) )
|
||||
{
|
||||
this->killTimer(m_processTimerId);
|
||||
m_processTimerId = -1;
|
||||
}
|
||||
else if (enabled && (m_processTimerId == -1) )
|
||||
{
|
||||
m_processTimerId = this->startTimer(m_processInterval);
|
||||
}
|
||||
emit enabledChanged();
|
||||
}
|
||||
void QrCodeScanner::timerEvent(QTimerEvent *event)
|
||||
{
|
||||
if( (event->timerId() == m_processTimerId) ){
|
||||
m_thread->addFrame(m_curFrame);
|
||||
}
|
||||
}
|
||||
|
||||
QrCodeScanner::~QrCodeScanner()
|
||||
{
|
||||
m_thread->stop();
|
||||
m_thread->quit();
|
||||
if(!m_thread->wait(5000))
|
||||
{
|
||||
m_thread->terminate();
|
||||
m_thread->wait();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2020-2021, The Monero Project
|
||||
// Copyright (c) 2014-2019, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
|
@ -26,53 +26,48 @@
|
|||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#pragma once
|
||||
#ifndef QRCODESCANNER_H_
|
||||
#define QRCODESCANNER_H_
|
||||
|
||||
#include <gcrypt.h>
|
||||
#include <QImage>
|
||||
#include <QVideoFrame>
|
||||
#include "QrScanThread.h"
|
||||
|
||||
namespace openpgp
|
||||
class QVideoProbe;
|
||||
class QCamera;
|
||||
|
||||
class QrCodeScanner : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
|
||||
|
||||
class mpi
|
||||
{
|
||||
public:
|
||||
mpi(const mpi &) = delete;
|
||||
mpi &operator=(const mpi &) = delete;
|
||||
QrCodeScanner(QObject *parent = Q_NULLPTR);
|
||||
~QrCodeScanner();
|
||||
void setSource(QCamera*);
|
||||
|
||||
mpi(mpi &&other)
|
||||
: data(other.data)
|
||||
{
|
||||
other.data = nullptr;
|
||||
}
|
||||
bool enabled() const;
|
||||
void setEnabled(bool enabled);
|
||||
|
||||
template <
|
||||
typename byte_container,
|
||||
typename = typename std::enable_if<(sizeof(typename byte_container::value_type) == 1)>::type>
|
||||
mpi(const byte_container &buffer, gcry_mpi_format format = GCRYMPI_FMT_USG)
|
||||
: mpi(&buffer[0], buffer.size(), format)
|
||||
{
|
||||
}
|
||||
public Q_SLOTS:
|
||||
void processFrame(QVideoFrame);
|
||||
|
||||
mpi(const void *buffer, size_t size, gcry_mpi_format format = GCRYMPI_FMT_USG)
|
||||
{
|
||||
if (gcry_mpi_scan(&data, format, buffer, size, nullptr) != GPG_ERR_NO_ERROR)
|
||||
{
|
||||
throw std::runtime_error("failed to read mpi from buffer");
|
||||
}
|
||||
}
|
||||
Q_SIGNALS:
|
||||
void enabledChanged();
|
||||
|
||||
~mpi()
|
||||
{
|
||||
gcry_mpi_release(data);
|
||||
}
|
||||
void decoded(const QString &data);
|
||||
void notifyError(const QString &error, bool warning = false);
|
||||
|
||||
const gcry_mpi_t &get() const
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
private:
|
||||
gcry_mpi_t data;
|
||||
protected:
|
||||
void timerEvent(QTimerEvent *);
|
||||
QrScanThread *m_thread;
|
||||
int m_processTimerId;
|
||||
int m_processInterval;
|
||||
int m_enabled;
|
||||
QVideoFrame m_curFrame;
|
||||
QVideoProbe *m_probe;
|
||||
};
|
||||
|
||||
} // namespace openpgp
|
||||
#endif
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2020-2021, The Monero Project
|
||||
// Copyright (c) 2014-2019, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
|
@ -26,82 +26,65 @@
|
|||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#pragma once
|
||||
#include "QrScanThread.h"
|
||||
#include <QtGlobal>
|
||||
#include <QDebug>
|
||||
|
||||
#include <vector>
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
|
||||
extern QImage qt_imageFromVideoFrame(const QVideoFrame &f);
|
||||
#endif
|
||||
|
||||
#include <gcrypt.h>
|
||||
#include <span.h>
|
||||
|
||||
namespace openpgp
|
||||
QrScanThread::QrScanThread(QObject *parent)
|
||||
: QThread(parent)
|
||||
,m_running(true)
|
||||
{
|
||||
|
||||
class hash
|
||||
{
|
||||
public:
|
||||
enum algorithm : uint8_t
|
||||
{
|
||||
sha256 = 8,
|
||||
};
|
||||
|
||||
hash(const hash &) = delete;
|
||||
hash &operator=(const hash &) = delete;
|
||||
|
||||
hash(uint8_t algorithm)
|
||||
: algo(algorithm)
|
||||
, consumed(0)
|
||||
{
|
||||
if (gcry_md_open(&md, algo, 0) != GPG_ERR_NO_ERROR)
|
||||
{
|
||||
throw std::runtime_error("failed to create message digest object");
|
||||
}
|
||||
}
|
||||
|
||||
~hash()
|
||||
{
|
||||
gcry_md_close(md);
|
||||
}
|
||||
|
||||
hash &operator<<(uint8_t byte)
|
||||
{
|
||||
gcry_md_putc(md, byte);
|
||||
++consumed;
|
||||
return *this;
|
||||
}
|
||||
|
||||
hash &operator<<(const epee::span<const uint8_t> &bytes)
|
||||
{
|
||||
gcry_md_write(md, &bytes[0], bytes.size());
|
||||
consumed += bytes.size();
|
||||
return *this;
|
||||
}
|
||||
|
||||
hash &operator<<(const std::vector<uint8_t> &bytes)
|
||||
{
|
||||
return *this << epee::to_span(bytes);
|
||||
}
|
||||
|
||||
std::vector<uint8_t> finish() const
|
||||
{
|
||||
std::vector<uint8_t> result(gcry_md_get_algo_dlen(algo));
|
||||
const void *digest = gcry_md_read(md, algo);
|
||||
if (digest == nullptr)
|
||||
{
|
||||
throw std::runtime_error("failed to read the digest");
|
||||
}
|
||||
memcpy(&result[0], digest, result.size());
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t consumed_bytes() const
|
||||
{
|
||||
return consumed;
|
||||
}
|
||||
|
||||
private:
|
||||
const uint8_t algo;
|
||||
gcry_md_hd_t md;
|
||||
size_t consumed;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void QrScanThread::processQImage(const QImage &qimg)
|
||||
{
|
||||
try {
|
||||
for (const std::string &code : m_decoder.decode(qimg))
|
||||
{
|
||||
emit decoded(QString::fromStdString(code));
|
||||
}
|
||||
}
|
||||
catch(std::exception &e) {
|
||||
qDebug() << "ERROR: " << e.what();
|
||||
emit notifyError(e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void QrScanThread::processVideoFrame(const QVideoFrame &frame)
|
||||
{
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
|
||||
processQImage( qt_imageFromVideoFrame(frame) );
|
||||
#else
|
||||
processQImage(frame.image());
|
||||
#endif
|
||||
}
|
||||
|
||||
void QrScanThread::stop()
|
||||
{
|
||||
m_running = false;
|
||||
m_waitCondition.wakeOne();
|
||||
}
|
||||
|
||||
void QrScanThread::addFrame(const QVideoFrame &frame)
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
m_queue.append(frame);
|
||||
m_waitCondition.wakeOne();
|
||||
}
|
||||
|
||||
void QrScanThread::run()
|
||||
{
|
||||
QVideoFrame frame;
|
||||
while(m_running) {
|
||||
QMutexLocker locker(&m_mutex);
|
||||
while(m_queue.isEmpty() && m_running)
|
||||
m_waitCondition.wait(&m_mutex);
|
||||
if(!m_queue.isEmpty())
|
||||
processVideoFrame(m_queue.takeFirst());
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2020-2021, The Monero Project
|
||||
// Copyright (c) 2014-2019, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
|
@ -26,53 +26,41 @@
|
|||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#pragma once
|
||||
#ifndef _QRSCANTHREAD_H_
|
||||
#define _QRSCANTHREAD_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <QThread>
|
||||
#include <QMutex>
|
||||
#include <QWaitCondition>
|
||||
#include <QEvent>
|
||||
#include <QVideoFrame>
|
||||
#include <QCamera>
|
||||
|
||||
#include <gcrypt.h>
|
||||
#include "Decoder.h"
|
||||
|
||||
namespace openpgp
|
||||
class QrScanThread : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class s_expression
|
||||
{
|
||||
public:
|
||||
s_expression(const s_expression &) = delete;
|
||||
s_expression &operator=(const s_expression &) = delete;
|
||||
QrScanThread(QObject *parent = Q_NULLPTR);
|
||||
void addFrame(const QVideoFrame &frame);
|
||||
virtual void stop();
|
||||
|
||||
template <typename... Args>
|
||||
s_expression(Args... args)
|
||||
{
|
||||
if (gcry_sexp_build(&data, nullptr, args...) != GPG_ERR_NO_ERROR)
|
||||
{
|
||||
throw std::runtime_error("failed to build S-expression");
|
||||
}
|
||||
}
|
||||
Q_SIGNALS:
|
||||
void decoded(const QString &data);
|
||||
void notifyError(const QString &error, bool warning = false);
|
||||
|
||||
s_expression(s_expression &&other)
|
||||
{
|
||||
std::swap(data, other.data);
|
||||
}
|
||||
|
||||
s_expression(gcry_sexp_t data)
|
||||
: data(data)
|
||||
{
|
||||
}
|
||||
|
||||
~s_expression()
|
||||
{
|
||||
gcry_sexp_release(data);
|
||||
}
|
||||
|
||||
const gcry_sexp_t &get() const
|
||||
{
|
||||
return data;
|
||||
}
|
||||
protected:
|
||||
virtual void run();
|
||||
void processVideoFrame(const QVideoFrame &);
|
||||
void processQImage(const QImage &);
|
||||
|
||||
private:
|
||||
gcry_sexp_t data = nullptr;
|
||||
QrDecoder m_decoder;
|
||||
bool m_running;
|
||||
QMutex m_mutex;
|
||||
QWaitCondition m_waitCondition;
|
||||
QList<QVideoFrame> m_queue;
|
||||
};
|
||||
|
||||
} // namespace openpgp
|
||||
#endif
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "appcontext.h"
|
||||
#include "globals.h"
|
||||
#include "config-wowlet.h"
|
||||
|
||||
// libwalletqt
|
||||
#include "libwalletqt/TransactionHistory.h"
|
||||
|
@ -21,91 +22,102 @@ TxFiatHistory *AppContext::txFiatHistory = nullptr;
|
|||
double AppContext::balance = 0;
|
||||
QMap<QString, QString> AppContext::txDescriptionCache;
|
||||
QMap<QString, QString> AppContext::txCache;
|
||||
bool AppContext::isQML = false;
|
||||
|
||||
AppContext::AppContext(QCommandLineParser *cmdargs) {
|
||||
this->m_walletKeysFilesModel = new WalletKeysFilesModel(this, this);
|
||||
this->network = new QNetworkAccessManager();
|
||||
this->networkClearnet = new QNetworkAccessManager();
|
||||
this->cmdargs = cmdargs;
|
||||
AppContext::isQML = false;
|
||||
|
||||
// OS & env
|
||||
#if defined(Q_OS_MAC)
|
||||
this->isMac = true;
|
||||
this->isTorSocks = qgetenv("DYLD_INSERT_LIBRARIES").indexOf("libtorsocks") >= 0;
|
||||
#elif __ANDROID__
|
||||
this->isAndroid = true;
|
||||
#elif defined(Q_OS_LINUX)
|
||||
this->isLinux = true;
|
||||
this->isTorSocks = qgetenv("LD_PRELOAD").indexOf("libtorsocks") >= 0;
|
||||
#elif defined(Q_OS_WIN)
|
||||
this->isTorSocks = false;
|
||||
#endif
|
||||
|
||||
this->isTails = TailsOS::detect();
|
||||
this->isWhonix = WhonixOS::detect();
|
||||
#elif defined(Q_OS_WIN)
|
||||
this->isWindows = true;
|
||||
this->isTorSocks = false;
|
||||
#endif
|
||||
this->androidDebug = cmdargs->isSet("android-debug");
|
||||
|
||||
//Paths
|
||||
// Paths
|
||||
this->pathGenericData = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation);
|
||||
this->configRoot = QDir::homePath();
|
||||
if (isTails) { // #if defined(PORTABLE)
|
||||
QString portablePath = []{
|
||||
QString appImagePath = qgetenv("APPIMAGE");
|
||||
if (appImagePath.isEmpty()) {
|
||||
qDebug() << "Not an appimage, using currentPath()";
|
||||
return QDir::currentPath() + "/.wowlet";
|
||||
}
|
||||
|
||||
QFileInfo appImageDir(appImagePath);
|
||||
return appImageDir.absoluteDir().path() + "/.wowlet";
|
||||
}();
|
||||
|
||||
|
||||
if (QDir().mkpath(portablePath)) {
|
||||
this->configRoot = portablePath;
|
||||
} else {
|
||||
qCritical() << "Unable to create portable directory: " << portablePath;
|
||||
}
|
||||
}
|
||||
|
||||
this->accountName = Utils::getUnixAccountName();
|
||||
this->homeDir = QDir::homePath();
|
||||
|
||||
this->configDirectory = QString("%1/.config/wowlet/").arg(this->configRoot);
|
||||
this->configDirectoryVR = QString("%1%2").arg(this->configDirectory, "vr");
|
||||
|
||||
if (isTails) this->setupPathsTails();
|
||||
|
||||
QString walletDir = config()->get(Config::walletDirectory).toString();
|
||||
if (walletDir.isEmpty()) {
|
||||
#if defined(Q_OS_LINUX) or defined(Q_OS_MAC)
|
||||
this->defaultWalletDir = QString("%1/Wownero/wallets").arg(this->configRoot);
|
||||
this->defaultWalletDirRoot = QString("%1/Wownero").arg(this->configRoot);
|
||||
#elif defined(Q_OS_WIN)
|
||||
this->defaultWalletDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + "/Wownero";
|
||||
this->defaultWalletDirRoot = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
|
||||
#endif
|
||||
if(walletDir.isEmpty()) {
|
||||
if (isAndroid && !androidDebug) setupPathsAndroid();
|
||||
else if (isWindows) setupPathsWindows();
|
||||
else if (isLinux || isMac) setupPathsUnix();
|
||||
} else {
|
||||
this->defaultWalletDir = walletDir;
|
||||
this->defaultWalletDirRoot = walletDir;
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
// can haz disk I/O?
|
||||
QVector<QString> perms = {
|
||||
"android.permission.WRITE_EXTERNAL_STORAGE",
|
||||
"android.permission.READ_EXTERNAL_STORAGE"
|
||||
};
|
||||
Utils::androidAskPermissions(perms);
|
||||
#endif
|
||||
|
||||
// Create wallet dirs
|
||||
qDebug() << "creating " << defaultWalletDir;
|
||||
if (!QDir().mkpath(defaultWalletDir))
|
||||
qCritical() << "Unable to create dir: " << defaultWalletDir;
|
||||
|
||||
this->configDirectory = QString("%1/.config/wowlet/").arg(this->configRoot);
|
||||
#if defined(Q_OS_UNIX)
|
||||
if(!this->configDirectory.endsWith('/'))
|
||||
this->configDirectory = QString("%1/").arg(this->configDirectory);
|
||||
#endif
|
||||
|
||||
// Config
|
||||
// Create some directories
|
||||
createConfigDirectory(this->configDirectory);
|
||||
|
||||
// if(this->cmdargs->isSet("stagenet"))
|
||||
// this->networkType = NetworkType::STAGENET;
|
||||
// else if(this->cmdargs->isSet("testnet"))
|
||||
// this->networkType = NetworkType::TESTNET;
|
||||
// else
|
||||
this->networkType = NetworkType::MAINNET;
|
||||
|
||||
qDebug() << "configRoot: " << this->configRoot;
|
||||
qDebug() << "homeDir: " << this->homeDir;
|
||||
qDebug() << "customWalletDir: " << walletDir;
|
||||
qDebug() << "defaultWalletDir: " << this->defaultWalletDir;
|
||||
qDebug() << "defaultWalletDirRoot: " << this->defaultWalletDirRoot;
|
||||
qDebug() << "configDirectory: " << this->configDirectory;
|
||||
|
||||
// auto nodeSourceUInt = config()->get(Config::nodeSource).toUInt();
|
||||
// AppContext::nodeSource = static_cast<NodeSource>(nodeSourceUInt);
|
||||
this->nodes = new Nodes(this, this->networkClearnet);
|
||||
connect(this, &AppContext::nodeSourceChanged, this->nodes, &Nodes::onNodeSourceChanged);
|
||||
connect(this, &AppContext::setCustomNodes, this->nodes, &Nodes::setCustomNodes);
|
||||
|
||||
// Tor & socks proxy
|
||||
this->ws = new WSClient(this, m_wsUrl);
|
||||
// init backend URLs
|
||||
if(cmdargs->isSet("backend-host"))
|
||||
this->backendHost = cmdargs->value("backend-host");
|
||||
if(cmdargs->isSet("backend-host"))
|
||||
this->backendPort = cmdargs->value("backend-port").toUInt();
|
||||
if(cmdargs->isSet("backend-tls"))
|
||||
this->backendTLS = true;
|
||||
|
||||
backendWSUrl = this->backendTLS ? "wss://" : "ws://";
|
||||
backendWSUrl += QString("%1:%2").arg(this->backendHost).arg(this->backendPort);
|
||||
backendHTTPUrl = this->backendTLS ? "https://" : "http://";
|
||||
backendHTTPUrl += QString("%1:%2").arg(this->backendHost).arg(this->backendPort);
|
||||
|
||||
// init websocket client
|
||||
this->ws = new WSClient(this);
|
||||
connect(this->ws, &WSClient::WSMessage, this, &AppContext::onWSMessage);
|
||||
connect(this->ws, &WSClient::connectionEstablished, this, &AppContext::wsConnected);
|
||||
connect(this->ws, &WSClient::closed, this, &AppContext::wsDisconnected);
|
||||
|
||||
// Store the wallet every 2 minutes
|
||||
m_storeTimer.start(2 * 60 * 1000);
|
||||
|
@ -113,6 +125,24 @@ AppContext::AppContext(QCommandLineParser *cmdargs) {
|
|||
this->storeWallet();
|
||||
});
|
||||
|
||||
// If system clock skewed for >= 300 seconds, assume a wake-up from hibernate and reload the websocket connection
|
||||
if(!this->isAndroid)
|
||||
m_hibernateTimer.start(3 * 1000);
|
||||
|
||||
m_hibernatePreviousTime = std::chrono::steady_clock::now();
|
||||
connect(&m_hibernateTimer, &QTimer::timeout, [this]() {
|
||||
const auto now = std::chrono::steady_clock::now();
|
||||
const auto elapsed = now - m_hibernatePreviousTime;
|
||||
|
||||
if(elapsed >= m_hibernateDetectInterval) {
|
||||
qCritical() << "Clock skew detected, resetting websocket connection";
|
||||
this->ws->webSocket.abort();
|
||||
this->ws->start();
|
||||
}
|
||||
|
||||
m_hibernatePreviousTime = now;
|
||||
});
|
||||
|
||||
// restore height lookup
|
||||
this->initRestoreHeights();
|
||||
|
||||
|
@ -133,15 +163,13 @@ AppContext::AppContext(QCommandLineParser *cmdargs) {
|
|||
AppContext::prices = new Prices();
|
||||
|
||||
// XMRig
|
||||
#ifdef HAS_XMRIG
|
||||
this->XMRig = new XmRig(this->configDirectory, this);
|
||||
this->XMRig->prepare();
|
||||
#endif
|
||||
|
||||
this->walletManager = WalletManager::instance();
|
||||
QString logPath = QString("%1/daemon.log").arg(configDirectory);
|
||||
Monero::Utils::onStartup();
|
||||
Monero::Wallet::init("", "feather", logPath.toStdString(), true);
|
||||
Monero::Wallet::init("", "wowlet", logPath.toStdString(), true);
|
||||
|
||||
bool logLevelFromEnv;
|
||||
int logLevel = qEnvironmentVariableIntValue("MONERO_LOG_LEVEL", &logLevelFromEnv);
|
||||
|
@ -154,18 +182,25 @@ AppContext::AppContext(QCommandLineParser *cmdargs) {
|
|||
|
||||
// libwallet connects
|
||||
connect(this->walletManager, &WalletManager::walletOpened, this, &AppContext::onWalletOpened);
|
||||
|
||||
// hideOnClose
|
||||
auto hideOnClose = config()->get(Config::hideOnClose).toBool();
|
||||
if(hideOnClose)
|
||||
QApplication::setQuitOnLastWindowClosed(false);
|
||||
}
|
||||
|
||||
void AppContext::initTor() {
|
||||
this->tor = new Tor(this, this);
|
||||
this->tor->start();
|
||||
|
||||
if (!(isWhonix)) {
|
||||
this->networkProxy = new QNetworkProxy(QNetworkProxy::Socks5Proxy, Tor::torHost, Tor::torPort);
|
||||
this->network->setProxy(*networkProxy);
|
||||
if (m_wsUrl.host().endsWith(".onion"))
|
||||
this->ws->webSocket.setProxy(*networkProxy);
|
||||
if (!isWhonix && !backendHost.contains(".onion")) {
|
||||
qDebug() << "'backend-host' did not contain '.onion' - running without Tor proxy.";
|
||||
return;
|
||||
}
|
||||
|
||||
this->networkProxy = new QNetworkProxy(QNetworkProxy::Socks5Proxy, Tor::torHost, Tor::torPort);
|
||||
this->network->setProxy(*networkProxy);
|
||||
this->ws->webSocket.setProxy(*networkProxy);
|
||||
}
|
||||
|
||||
void AppContext::initWS() {
|
||||
|
@ -193,7 +228,7 @@ void AppContext::onSweepOutput(const QString &keyImage, QString address, bool ch
|
|||
this->currentWallet->createTransactionSingleAsync(keyImage, address, outputs, this->tx_priority);
|
||||
}
|
||||
|
||||
void AppContext::onCreateTransaction(const QString &address, quint64 amount, const QString &description, bool all) {
|
||||
void AppContext::onCreateTransaction(QString address, quint64 amount, QString description, bool all) {
|
||||
// tx creation
|
||||
this->tmpTxDescription = description;
|
||||
|
||||
|
@ -299,6 +334,7 @@ void AppContext::onPreferredFiatCurrencyChanged(const QString &symbol) {
|
|||
auto *model = this->currentWallet->transactionHistoryModel();
|
||||
if(model != nullptr) {
|
||||
model->preferredFiatSymbol = symbol;
|
||||
this->currentWallet->transactionHistoryModel()->transactionHistory()->calcFiatInfo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -329,6 +365,8 @@ void AppContext::onWalletOpened(Wallet *wallet) {
|
|||
this->refreshed = false;
|
||||
this->currentWallet = wallet;
|
||||
this->walletPath = this->currentWallet->path() + ".keys";
|
||||
QFileInfo fileInfo(this->currentWallet->path());
|
||||
this->walletName = fileInfo.fileName();
|
||||
this->walletViewOnly = this->currentWallet->viewOnly();
|
||||
config()->set(Config::walletPath, this->walletPath);
|
||||
|
||||
|
@ -342,7 +380,14 @@ void AppContext::onWalletOpened(Wallet *wallet) {
|
|||
connect(this->currentWallet, &Wallet::heightRefreshed, this, &AppContext::onHeightRefreshed);
|
||||
connect(this->currentWallet, &Wallet::transactionCreated, this, &AppContext::onTransactionCreated);
|
||||
|
||||
emit walletOpened();
|
||||
this->currentWallet->historyModel(); // load historyModel
|
||||
auto *txHistory = this->currentWallet->history();
|
||||
txHistory->refresh(this->currentWallet->currentSubaddressAccount());
|
||||
|
||||
connect(AppContext::prices, &Prices::fiatPricesUpdated, txHistory, &TransactionHistory::calcFiatInfo);
|
||||
connect(AppContext::prices, &Prices::cryptoPricesUpdated, txHistory, &TransactionHistory::calcFiatInfo);
|
||||
|
||||
emit walletOpened(wallet);
|
||||
|
||||
connect(this->currentWallet, &Wallet::connectionStatusChanged, [this]{
|
||||
this->nodes->autoConnect();
|
||||
|
@ -350,10 +395,6 @@ void AppContext::onWalletOpened(Wallet *wallet) {
|
|||
this->nodes->connectToNode();
|
||||
this->updateBalance();
|
||||
|
||||
#ifdef DONATE_BEG
|
||||
this->donateBeg();
|
||||
#endif
|
||||
|
||||
// force trigger preferredFiat signal for history model
|
||||
this->onPreferredFiatCurrencyChanged(config()->get(Config::preferredFiatCurrency).toString());
|
||||
this->setWindowTitle();
|
||||
|
@ -403,20 +444,23 @@ void AppContext::onWSMessage(const QJsonObject &msg) {
|
|||
if(changed)
|
||||
emit blockHeightWSUpdated(this->heights);
|
||||
}
|
||||
|
||||
else if(cmd == "nodes") {
|
||||
else if(cmd == "yellwow") {
|
||||
this->yellowPagesData = msg.value("data").toArray();
|
||||
emit yellowUpdated();
|
||||
}
|
||||
else if(cmd == "rpc_nodes") {
|
||||
this->onWSNodes(msg.value("data").toArray());
|
||||
}
|
||||
#if defined(HAS_XMRIG)
|
||||
else if(cmd == "xmrig") {
|
||||
this->XMRigDownloads(msg.value("data").toObject());
|
||||
}
|
||||
#endif
|
||||
else if(cmd == "wownerod_releases") {
|
||||
emit WownerodDownloads(msg.value("data").toObject());
|
||||
}
|
||||
else if(cmd == "crypto_rates") {
|
||||
QJsonArray crypto_rates = msg.value("data").toArray();
|
||||
AppContext::prices->cryptoPricesReceived(crypto_rates);
|
||||
}
|
||||
|
||||
else if(cmd == "fiat_rates") {
|
||||
QJsonObject fiat_rates = msg.value("data").toObject();
|
||||
AppContext::prices->fiatPricesReceived(fiat_rates);
|
||||
|
@ -425,25 +469,56 @@ void AppContext::onWSMessage(const QJsonObject &msg) {
|
|||
QJsonArray reddit_data = msg.value("data").toArray();
|
||||
this->onWSReddit(reddit_data);
|
||||
}
|
||||
|
||||
else if(cmd == "wfs") {
|
||||
else if(cmd == "forum") {
|
||||
QJsonArray forum_data = msg.value("data").toArray();
|
||||
this->onWSForum(forum_data);
|
||||
}
|
||||
else if(cmd == "funding_proposals") {
|
||||
auto ccs_data = msg.value("data").toArray();
|
||||
this->onWSCCS(ccs_data);
|
||||
}
|
||||
|
||||
else if(cmd == "suchwow") {
|
||||
QJsonArray such_data = msg.value("data").toArray();
|
||||
emit suchWowUpdated(such_data);
|
||||
}
|
||||
|
||||
else if(cmd == "txFiatHistory") {
|
||||
auto txFiatHistory_data = msg.value("data").toObject();
|
||||
AppContext::txFiatHistory->onWSData(txFiatHistory_data);
|
||||
}
|
||||
else if(cmd == "wowlet_releases") {
|
||||
versionPending = msg.value("data").toObject();
|
||||
auto version_str = versionPending.value("version").toString();
|
||||
|
||||
if(Utils::versionOutdated(WOWLET_VERSION_SEMVER, version_str))
|
||||
emit versionOutdated(version_str, versionPending);
|
||||
}
|
||||
else if(cmd == "kill") {
|
||||
// used *only* in dire emergencies
|
||||
auto killme = msg.value("data").toBool();
|
||||
if(killme)
|
||||
QCoreApplication::quit();
|
||||
}
|
||||
#if defined(HAS_OPENVR)
|
||||
else if(cmd == "requestPIN") {
|
||||
auto pin = msg.value("data").toString();
|
||||
emit pinReceived(pin);
|
||||
}
|
||||
|
||||
else if(cmd == "lookupPIN") {
|
||||
auto lookup_data = msg.value("data").toObject();
|
||||
auto address = lookup_data.value("address").toString();
|
||||
auto pin = lookup_data.value("PIN").toString();
|
||||
|
||||
if(address.isEmpty())
|
||||
emit pinLookupErrorReceived();
|
||||
else
|
||||
emit pinLookupReceived(address, pin);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void AppContext::onWSNodes(const QJsonArray &nodes) {
|
||||
QList<QSharedPointer<FeatherNode>> l;
|
||||
QList<QSharedPointer<WowletNode>> l;
|
||||
for (auto &&entry: nodes) {
|
||||
auto obj = entry.toObject();
|
||||
auto nettype = obj.value("nettype");
|
||||
|
@ -462,17 +537,34 @@ void AppContext::onWSNodes(const QJsonArray &nodes) {
|
|||
if(type == "tor" && (!(this->isTails || this->isWhonix || this->isTorSocks)))
|
||||
continue;
|
||||
|
||||
auto node = new FeatherNode(
|
||||
auto node = new WowletNode(
|
||||
obj.value("address").toString(),
|
||||
obj.value("height").toInt(),
|
||||
obj.value("target_height").toInt(),
|
||||
obj.value("online").toBool());
|
||||
QSharedPointer<FeatherNode> r = QSharedPointer<FeatherNode>(node);
|
||||
QSharedPointer<WowletNode> r = QSharedPointer<WowletNode>(node);
|
||||
l.append(r);
|
||||
}
|
||||
this->nodes->onWSNodesReceived(l);
|
||||
}
|
||||
|
||||
void AppContext::onWSForum(const QJsonArray& forum_data) {
|
||||
QList<QSharedPointer<ForumPost>> l;
|
||||
|
||||
for (auto &&entry: forum_data) {
|
||||
auto obj = entry.toObject();
|
||||
auto forumPost = new ForumPost(
|
||||
obj.value("thread").toString(),
|
||||
obj.value("member_name").toString(),
|
||||
obj.value("permalink").toString(),
|
||||
obj.value("member_name").toString());
|
||||
QSharedPointer<ForumPost> r = QSharedPointer<ForumPost>(forumPost);
|
||||
l.append(r);
|
||||
}
|
||||
|
||||
emit forumUpdated(l);
|
||||
}
|
||||
|
||||
void AppContext::onWSReddit(const QJsonArray& reddit_data) {
|
||||
QList<QSharedPointer<RedditPost>> l;
|
||||
|
||||
|
@ -522,8 +614,8 @@ void AppContext::onWSCCS(const QJsonArray &ccs_data) {
|
|||
}
|
||||
|
||||
void AppContext::createConfigDirectory(const QString &dir) {
|
||||
QString config_dir_tor = QString("%1%2").arg(dir).arg("tor");
|
||||
QString config_dir_tordata = QString("%1%2").arg(dir).arg("tor/data");
|
||||
auto config_dir_tor = QString("%1%2").arg(dir).arg("tor");
|
||||
auto config_dir_tordata = QString("%1%2").arg(dir).arg("tor/data");
|
||||
|
||||
QStringList createDirs({dir, config_dir_tor, config_dir_tordata});
|
||||
for(const auto &d: createDirs) {
|
||||
|
@ -533,9 +625,24 @@ void AppContext::createConfigDirectory(const QString &dir) {
|
|||
throw std::runtime_error("Could not create directory " + d.toStdString());
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAS_OPENVR
|
||||
auto config_dir_vr = QString("%1%2").arg(dir, "vr");
|
||||
if(!Utils::dirExists(config_dir_vr)) {
|
||||
qDebug() << QString("Creating directory: %1").arg(config_dir_vr);
|
||||
if (!QDir().mkpath(config_dir_vr))
|
||||
throw std::runtime_error("Could not create directory " + config_dir_vr.toStdString());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void AppContext::createWallet(FeatherSeed seed, const QString &path, const QString &password) {
|
||||
void AppContext::createWalletWithoutSpecifyingSeed(const QString &name, const QString &password) {
|
||||
WowletSeed seed = WowletSeed(this->restoreHeights[this->networkType], this->coinName, this->seedLanguage);
|
||||
auto path = QDir(this->defaultWalletDir).filePath(name);
|
||||
this->createWallet(seed, path, password);
|
||||
}
|
||||
|
||||
void AppContext::createWallet(WowletSeed seed, const QString &path, const QString &password) {
|
||||
if(Utils::fileExists(path)) {
|
||||
auto err = QString("Failed to write wallet to path: \"%1\"; file already exists.").arg(path);
|
||||
qCritical() << err;
|
||||
|
@ -551,9 +658,9 @@ void AppContext::createWallet(FeatherSeed seed, const QString &path, const QStri
|
|||
Wallet *wallet = nullptr;
|
||||
if (seed.seedType == SeedType::TEVADOR) {
|
||||
wallet = this->walletManager->createDeterministicWalletFromSpendKey(path, password, seed.language, this->networkType, seed.spendKey, seed.restoreHeight, this->kdfRounds);
|
||||
wallet->setCacheAttribute("feather.seed", seed.mnemonic.join(" "));
|
||||
wallet->setCacheAttribute("wowlet.seed", seed.mnemonic.join(" "));
|
||||
}
|
||||
if (seed.seedType == SeedType::MONERO) {
|
||||
if (seed.seedType == SeedType::WOWNERO) {
|
||||
wallet = this->walletManager->recoveryWallet(path, password, seed.mnemonic.join(" "), "", this->networkType, seed.restoreHeight, this->kdfRounds);
|
||||
}
|
||||
|
||||
|
@ -604,6 +711,9 @@ void AppContext::createWalletFinish(const QString &password) {
|
|||
this->currentWallet->store();
|
||||
this->walletPassword = password;
|
||||
emit walletCreated(this->currentWallet);
|
||||
|
||||
// emit signal on behalf of walletManager, open wallet
|
||||
this->walletManager->walletOpened(this->currentWallet);
|
||||
}
|
||||
|
||||
void AppContext::initRestoreHeights() {
|
||||
|
@ -613,7 +723,7 @@ void AppContext::initRestoreHeights() {
|
|||
}
|
||||
|
||||
void AppContext::onSetRestoreHeight(quint64 height){
|
||||
auto seed = this->currentWallet->getCacheAttribute("feather.seed");
|
||||
auto seed = this->currentWallet->getCacheAttribute("wowlet.seed");
|
||||
if(!seed.isEmpty()) {
|
||||
const auto msg = "This wallet has a 14 word mnemonic seed which has the restore height embedded.";
|
||||
emit setRestoreHeightError(msg);
|
||||
|
@ -672,21 +782,6 @@ void AppContext::onOpenAliasResolve(const QString &openAlias) {
|
|||
emit openAliasResolveError(msg);
|
||||
}
|
||||
|
||||
void AppContext::donateBeg() {
|
||||
if(this->currentWallet == nullptr) return;
|
||||
if(this->networkType != NetworkType::Type::MAINNET) return;
|
||||
if(this->currentWallet->viewOnly()) return;
|
||||
|
||||
auto donationCounter = config()->get(Config::donateBeg).toInt();
|
||||
if(donationCounter == -1)
|
||||
return; // previously donated
|
||||
|
||||
donationCounter += 1;
|
||||
if (donationCounter % m_donationBoundary == 0)
|
||||
emit donationNag();
|
||||
config()->set(Config::donateBeg, donationCounter);
|
||||
}
|
||||
|
||||
AppContext::~AppContext() {}
|
||||
|
||||
// ############################################## LIBWALLET QT #########################################################
|
||||
|
@ -761,17 +856,83 @@ void AppContext::onHeightRefreshed(quint64 walletHeight, quint64 daemonHeight, q
|
|||
}
|
||||
|
||||
void AppContext::onTransactionCreated(PendingTransaction *tx, const QVector<QString> &address) {
|
||||
for (auto &addr : address) {
|
||||
if (addr == this->donationAddress) {
|
||||
this->donationSending = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Let UI know that the transaction was constructed
|
||||
emit endTransaction();
|
||||
|
||||
// Some validation
|
||||
auto tx_status = tx->status();
|
||||
auto err = QString("Can't create transaction: ");
|
||||
|
||||
if(tx_status != PendingTransaction::Status_Ok){
|
||||
auto tx_err = tx->errorString();
|
||||
qCritical() << tx_err;
|
||||
|
||||
if (this->currentWallet->connectionStatus() == Wallet::ConnectionStatus_WrongVersion)
|
||||
err = QString("%1 Wrong daemon version: %2").arg(err).arg(tx_err);
|
||||
else
|
||||
err = QString("%1 %2").arg(err).arg(tx_err);
|
||||
|
||||
qDebug() << Q_FUNC_INFO << err;
|
||||
emit createTransactionError(err);
|
||||
this->currentWallet->disposeTransaction(tx);
|
||||
return;
|
||||
} else if (tx->txCount() == 0) {
|
||||
err = QString("%1 %2").arg(err).arg("No unmixable outputs to sweep.");
|
||||
qDebug() << Q_FUNC_INFO << err;
|
||||
emit createTransactionError(err);
|
||||
this->currentWallet->disposeTransaction(tx);
|
||||
return;
|
||||
}
|
||||
|
||||
// tx created, but not sent yet. ask user to verify first.
|
||||
emit createTransactionSuccess(tx, address);
|
||||
|
||||
if(this->autoCommitTx) {
|
||||
this->currentWallet->commitTransactionAsync(tx);
|
||||
}
|
||||
}
|
||||
|
||||
QString AppContext::getAddress(quint32 accountIndex, quint32 addressIndex) {
|
||||
return this->currentWallet->address(accountIndex, addressIndex);
|
||||
}
|
||||
|
||||
void AppContext::onAskReceivingPIN() {
|
||||
// request new receiving PIN from wowlet-backend
|
||||
if(this->currentWallet == nullptr)
|
||||
return;
|
||||
|
||||
auto address = this->currentWallet->address(0, 1);
|
||||
QString signature = this->currentWallet->signMessage(address, false, address);
|
||||
|
||||
QJsonObject data;
|
||||
data["signature"] = signature;
|
||||
data["address"] = address;
|
||||
|
||||
QJsonObject obj;
|
||||
obj["cmd"] = "requestPIN";
|
||||
obj["data"] = data;
|
||||
|
||||
QJsonDocument doc = QJsonDocument(obj);
|
||||
this->ws->sendMsg(doc.toJson(QJsonDocument::Compact));
|
||||
}
|
||||
|
||||
void AppContext::onLookupReceivingPIN(QString pin) {
|
||||
// lookup PIN -> address
|
||||
if(this->currentWallet == nullptr)
|
||||
return;
|
||||
|
||||
auto address = this->currentWallet->address(0, 1);
|
||||
QString signature = this->currentWallet->signMessage(address, false, address);
|
||||
|
||||
QJsonObject data;
|
||||
data["PIN"] = pin;
|
||||
|
||||
QJsonObject obj;
|
||||
obj["cmd"] = "lookupPIN";
|
||||
obj["data"] = data;
|
||||
|
||||
QJsonDocument doc = QJsonDocument(obj);
|
||||
this->ws->sendMsg(doc.toJson(QJsonDocument::Compact));
|
||||
}
|
||||
|
||||
void AppContext::onTransactionCommitted(bool status, PendingTransaction *tx, const QStringList& txid){
|
||||
|
@ -784,12 +945,6 @@ void AppContext::onTransactionCommitted(bool status, PendingTransaction *tx, con
|
|||
this->updateBalance();
|
||||
|
||||
emit transactionCommitted(status, tx, txid);
|
||||
|
||||
// this tx was a donation to Feather, stop our nagging
|
||||
if(this->donationSending) {
|
||||
this->donationSending = false;
|
||||
config()->set(Config::donateBeg, -1);
|
||||
}
|
||||
}
|
||||
|
||||
void AppContext::storeWallet() {
|
||||
|
@ -809,7 +964,13 @@ void AppContext::updateBalance() {
|
|||
AppContext::balance = balance_u / globals::cdiv;
|
||||
double spendable = this->currentWallet->unlockedBalance();
|
||||
|
||||
// formatted
|
||||
QString fmt_str = QString("Balance: %1 WOW").arg(Utils::balanceFormat(spendable));
|
||||
if (balance > spendable)
|
||||
fmt_str += QString(" (+%1 WOW unconfirmed)").arg(Utils::balanceFormat(balance - spendable));
|
||||
|
||||
emit balanceUpdated(balance_u, spendable);
|
||||
emit balanceUpdatedFormatted(fmt_str);
|
||||
}
|
||||
|
||||
void AppContext::syncStatusUpdated(quint64 height, quint64 target) {
|
||||
|
@ -831,3 +992,38 @@ void AppContext::refreshModels() {
|
|||
this->currentWallet->coins()->refresh(this->currentWallet->currentSubaddressAccount());
|
||||
// Todo: set timer for refreshes
|
||||
}
|
||||
|
||||
void AppContext::setupPathsUnix() {
|
||||
this->defaultWalletDir = QString("%1/Wownero/wallets").arg(this->configRoot);
|
||||
this->defaultWalletDirRoot = QString("%1/Wownero").arg(this->configRoot);
|
||||
}
|
||||
|
||||
void AppContext::setupPathsWindows() {
|
||||
this->defaultWalletDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + "/Wownero";
|
||||
this->defaultWalletDirRoot = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
|
||||
}
|
||||
|
||||
void AppContext::setupPathsAndroid() {
|
||||
this->defaultWalletDir = QString("%1/Wownero/wallets").arg(this->pathGenericData);
|
||||
this->defaultWalletDirRoot = QString("%1/Wownero").arg(this->pathGenericData);
|
||||
}
|
||||
|
||||
void AppContext::setupPathsTails() {
|
||||
QString portablePath = []{
|
||||
QString appImagePath = qgetenv("APPIMAGE");
|
||||
if (appImagePath.isEmpty()) {
|
||||
qDebug() << "Not an appimage, using currentPath()";
|
||||
return QDir::currentPath() + "/.wowlet";
|
||||
}
|
||||
|
||||
QFileInfo appImageDir(appImagePath);
|
||||
return appImageDir.absoluteDir().path() + "/.wowlet";
|
||||
}();
|
||||
|
||||
if (QDir().mkpath(portablePath)) {
|
||||
this->configRoot = portablePath;
|
||||
} else {
|
||||
qCritical() << "Unable to create portable directory: " << portablePath;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
// Copyright (c) 2020-2021, The Monero Project.
|
||||
|
||||
#ifndef FEATHER_APPCONTEXT_H
|
||||
#define FEATHER_APPCONTEXT_H
|
||||
#ifndef WOWLET_APPCONTEXT_H
|
||||
#define WOWLET_APPCONTEXT_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QProcess>
|
||||
|
@ -17,8 +17,9 @@
|
|||
#include "utils/xmrig.h"
|
||||
#include "utils/wsclient.h"
|
||||
#include "utils/txfiathistory.h"
|
||||
#include "utils/FeatherSeed.h"
|
||||
#include "utils/WowletSeed.h"
|
||||
#include "widgets/RedditPost.h"
|
||||
#include "widgets/ForumPost.h"
|
||||
#include "widgets/CCSEntry.h"
|
||||
#include "utils/RestoreHeightLookup.h"
|
||||
#include "utils/nodes.h"
|
||||
|
@ -39,30 +40,47 @@ public:
|
|||
~AppContext() override;
|
||||
bool isTails = false;
|
||||
bool isWhonix = false;
|
||||
bool isAndroid = false;
|
||||
bool isLinux = false;
|
||||
bool isMac = false;
|
||||
bool isWindows = false;
|
||||
bool isDebug = false;
|
||||
static bool isQML;
|
||||
bool androidDebug = false;
|
||||
|
||||
// Donation config
|
||||
const QString donationAddress = "Wo3MWeKwtA918DU4c69hVSNgejdWFCRCuWjShRY66mJkU2Hv58eygJWDJS1MNa2Ge5M1WjUkGHuLqHkweDxwZZU42d16v94mP";
|
||||
const int donationAmount = 25; // euro
|
||||
bool donationSending = false;
|
||||
|
||||
QCommandLineParser *cmdargs;
|
||||
|
||||
QString coinName = "wownero";
|
||||
bool isTorSocks = false;
|
||||
QString pathGenericData;
|
||||
QString homeDir;
|
||||
QString accountName;
|
||||
QString configRoot;
|
||||
QString configDirectory;
|
||||
QString configDirectoryVR;
|
||||
QString defaultWalletDir;
|
||||
QString defaultWalletDirRoot;
|
||||
QString tmpTxDescription;
|
||||
|
||||
// https://git.wownero.com/wowlet/wowlet-backend/
|
||||
QString backendHost = "l3hkasj5nnrh24yzj4acj5dgqlscq56o5xjvvqsftj55fkonqly5aiid.onion";
|
||||
unsigned int backendPort = 80;
|
||||
bool backendTLS = false;
|
||||
QString backendWSUrl;
|
||||
QString backendHTTPUrl;
|
||||
|
||||
QString walletPath;
|
||||
QString walletPassword = "";
|
||||
QString walletName;
|
||||
bool walletViewOnly = false;
|
||||
NetworkType::Type networkType;
|
||||
|
||||
Q_PROPERTY(QString walletName MEMBER walletName);
|
||||
|
||||
QString applicationPath;
|
||||
|
||||
static void createConfigDirectory(const QString &dir) ;
|
||||
|
@ -73,6 +91,11 @@ public:
|
|||
PendingTransaction::Priority tx_priority = PendingTransaction::Priority::Priority_Low;
|
||||
quint32 tx_mixin = static_cast<const quint32 &>(10);
|
||||
QString seedLanguage = "English"; // 14 word `monero-seed` only has English
|
||||
// turn this on if you want to auto commit tx's after they have
|
||||
// been created. Caution while using this setting is advised. This
|
||||
// probably also breaks the default QtWidgets GUI. It is meant for
|
||||
// alternative users of AppContext.
|
||||
bool autoCommitTx = false;
|
||||
|
||||
QNetworkAccessManager *network;
|
||||
QNetworkAccessManager *networkClearnet;
|
||||
|
@ -88,30 +111,46 @@ public:
|
|||
static QMap<QString, QString> txDescriptionCache;
|
||||
static QMap<QString, QString> txCache;
|
||||
static TxFiatHistory *txFiatHistory;
|
||||
QJsonArray yellowPagesData;
|
||||
QJsonObject versionPending;
|
||||
|
||||
// libwalletqt
|
||||
bool refreshed = false;
|
||||
|
||||
WalletManager *walletManager;
|
||||
Wallet *currentWallet = nullptr;
|
||||
void createWallet(FeatherSeed seed, const QString &path, const QString &password);
|
||||
void createWallet(WowletSeed seed, const QString &path, const QString &password);
|
||||
Q_INVOKABLE void createWalletWithoutSpecifyingSeed(const QString &name, const QString &password);
|
||||
void createWalletViewOnly(const QString &path, const QString &password, const QString &address, const QString &viewkey, const QString &spendkey, quint64 restoreHeight);
|
||||
void createWalletFinish(const QString &password);
|
||||
void syncStatusUpdated(quint64 height, quint64 target);
|
||||
void updateBalance();
|
||||
void initTor();
|
||||
Q_INVOKABLE void initTor();
|
||||
Q_INVOKABLE void initWS();
|
||||
void initRestoreHeights();
|
||||
void initWS();
|
||||
void donateBeg();
|
||||
void refreshModels();
|
||||
void setWindowTitle(bool mining = false);
|
||||
|
||||
// Closes the currently opened wallet
|
||||
void closeWallet(bool emitClosedSignal = true, bool storeWallet = false);
|
||||
Q_INVOKABLE void closeWallet(bool emitClosedSignal = true, bool storeWallet = false);
|
||||
void storeWallet();
|
||||
|
||||
Q_INVOKABLE QVariantList listWallets() {
|
||||
m_walletKeysFilesModel->refresh();
|
||||
|
||||
QVariantList list;
|
||||
for(const WalletKeysFiles &wallet: m_walletKeysFilesModel->listWallets())
|
||||
list << wallet.toVariant();
|
||||
return list;
|
||||
}
|
||||
|
||||
Q_INVOKABLE QString displayAmount(quint64 amount) {
|
||||
return Utils::balanceFormat(amount);
|
||||
}
|
||||
|
||||
public slots:
|
||||
void onOpenWallet(const QString& path, const QString &password);
|
||||
void onCreateTransaction(const QString &address, quint64 amount, const QString &description, bool all);
|
||||
Q_INVOKABLE void onOpenWallet(const QString& path, const QString &password);
|
||||
void onCreateTransaction(QString address, quint64 amount, const QString description, bool all);
|
||||
void onCreateTransactionMultiDest(const QVector<QString> &addresses, const QVector<quint64> &amounts, const QString &description);
|
||||
void onCancelTransaction(PendingTransaction *tx, const QVector<QString> &address);
|
||||
void onSweepOutput(const QString &keyImage, QString address, bool churn, int outputs) const;
|
||||
|
@ -119,12 +158,16 @@ public slots:
|
|||
void onOpenAliasResolve(const QString &openAlias);
|
||||
void onSetRestoreHeight(quint64 height);
|
||||
void onPreferredFiatCurrencyChanged(const QString &symbol);
|
||||
Q_INVOKABLE void onAskReceivingPIN();
|
||||
Q_INVOKABLE void onLookupReceivingPIN(QString pin);
|
||||
Q_INVOKABLE QString getAddress(quint32 accountIndex, quint32 addressIndex);
|
||||
|
||||
private slots:
|
||||
void onWSNodes(const QJsonArray &nodes);
|
||||
void onWSMessage(const QJsonObject& msg);
|
||||
void onWSCCS(const QJsonArray &ccs_data);
|
||||
void onWSReddit(const QJsonArray& reddit_data);
|
||||
void onWSForum(const QJsonArray& forum_data);
|
||||
|
||||
void onMoneySpent(const QString &txId, quint64 amount);
|
||||
void onMoneyReceived(const QString &txId, quint64 amount);
|
||||
|
@ -145,12 +188,13 @@ signals:
|
|||
void walletClosed();
|
||||
|
||||
void balanceUpdated(quint64 balance, quint64 spendable);
|
||||
void balanceUpdatedFormatted(QString fmt);
|
||||
void blockchainSync(int height, int target);
|
||||
void refreshSync(int height, int target);
|
||||
void synchronized();
|
||||
void blockHeightWSUpdated(QMap<QString, int> heights);
|
||||
void walletRefreshed();
|
||||
void walletOpened();
|
||||
void walletOpened(Wallet *wallet);
|
||||
void walletCreatedError(const QString &msg);
|
||||
void walletCreated(Wallet *wallet);
|
||||
void walletOpenedError(QString msg);
|
||||
|
@ -159,13 +203,21 @@ signals:
|
|||
void createTransactionError(QString message);
|
||||
void createTransactionCancelled(const QVector<QString> &address, double amount);
|
||||
void createTransactionSuccess(PendingTransaction *tx, const QVector<QString> &address);
|
||||
void wsConnected();
|
||||
void wsDisconnected();
|
||||
void redditUpdated(QList<QSharedPointer<RedditPost>> &posts);
|
||||
void nodesUpdated(QList<QSharedPointer<FeatherNode>> &nodes);
|
||||
void forumUpdated(QList<QSharedPointer<ForumPost>> &posts);
|
||||
void nodesUpdated(QList<QSharedPointer<WowletNode>> &nodes);
|
||||
void ccsUpdated(QList<QSharedPointer<CCSEntry>> &entries);
|
||||
void suchWowUpdated(const QJsonArray &such_data);
|
||||
void yellowUpdated();
|
||||
void nodeSourceChanged(NodeSource nodeSource);
|
||||
void XMRigDownloads(const QJsonObject &data);
|
||||
void setCustomNodes(QList<FeatherNode> nodes);
|
||||
void WownerodDownloads(const QJsonObject &data);
|
||||
void pinLookupReceived(QString address, QString pin);
|
||||
void pinLookupErrorReceived();
|
||||
void pinReceived(QString pin);
|
||||
void setCustomNodes(QList<WowletNode> nodes);
|
||||
void openAliasResolveError(const QString &msg);
|
||||
void openAliasResolved(const QString &address, const QString &openAlias);
|
||||
void setRestoreHeightError(const QString &msg);
|
||||
|
@ -175,11 +227,20 @@ signals:
|
|||
void initiateTransaction();
|
||||
void endTransaction();
|
||||
void setTitle(const QString &title); // set window title
|
||||
void versionOutdated(QString version_string, QJsonObject data);
|
||||
|
||||
private:
|
||||
WalletKeysFilesModel *m_walletKeysFilesModel;
|
||||
const int m_donationBoundary = 15;
|
||||
QTimer m_storeTimer;
|
||||
QUrl m_wsUrl = QUrl(QStringLiteral("ws://feathercitimllbmdktu6cmjo3fizgmyfrntntqzu6xguqa2rlq5cgid.onion/ws"));
|
||||
QTimer m_hibernateTimer;
|
||||
std::chrono::seconds m_hibernateDetectInterval{300};
|
||||
std::chrono::time_point<std::chrono::steady_clock> m_hibernatePreviousTime;
|
||||
|
||||
void setupPathsUnix();
|
||||
void setupPathsWindows();
|
||||
void setupPathsAndroid();
|
||||
void setupPathsTails();
|
||||
};
|
||||
|
||||
#endif //FEATHER_APPCONTEXT_H
|
||||
#endif //WOWLET_APPCONTEXT_H
|
||||
|
|
210
src/assets.qrc
|
@ -3,7 +3,7 @@
|
|||
<file>assets/about.txt</file>
|
||||
<file>assets/ack.txt</file>
|
||||
<file>assets/contributors.txt</file>
|
||||
<file>assets/wowlet.desktop</file>
|
||||
<file>assets/org.wowlet.wowlet.desktop</file>
|
||||
<file>assets/nodes.json</file>
|
||||
<file>assets/images/appicons/32x32.png</file>
|
||||
<file>assets/images/appicons/48x48.png</file>
|
||||
|
@ -12,7 +12,6 @@
|
|||
<file>assets/images/appicons/128x128.png</file>
|
||||
<file>assets/images/appicons/256x256.png</file>
|
||||
<file>assets/images/arrow.svg</file>
|
||||
<file>assets/images/banners/1.png</file>
|
||||
<file>assets/images/bitcoin.png</file>
|
||||
<file>assets/images/camera_dark.png</file>
|
||||
<file>assets/images/camera_white.png</file>
|
||||
|
@ -29,7 +28,8 @@
|
|||
<file>assets/images/confirmed.svg</file>
|
||||
<file>assets/images/connect.svg</file>
|
||||
<file>assets/images/copy.png</file>
|
||||
<file>assets/images/cutexmrfox.png</file>
|
||||
<file>assets/images/dog_running.gif</file>
|
||||
<file>assets/images/dog_sitting.gif</file>
|
||||
<file>assets/images/edit.png</file>
|
||||
<file>assets/images/exchange.png</file>
|
||||
<file>assets/images/exchange_white.png</file>
|
||||
|
@ -39,6 +39,7 @@
|
|||
<file>assets/images/eye_blind.png</file>
|
||||
<file>assets/images/wowlet.png</file>
|
||||
<file>assets/images/file.png</file>
|
||||
<file>assets/images/fire.png</file>
|
||||
<file>assets/images/gnome-calc.png</file>
|
||||
<file>assets/images/history.png</file>
|
||||
<file>assets/images/info.png</file>
|
||||
|
@ -54,56 +55,133 @@
|
|||
<file>assets/images/network.png</file>
|
||||
<file>assets/images/offline_tx.png</file>
|
||||
<file>assets/images/person.svg</file>
|
||||
<file>assets/images/photos/illiterate_illuminati.png</file>
|
||||
<file>assets/images/photos/wow1.png</file>
|
||||
<file>assets/images/photos/wow2.png</file>
|
||||
<file>assets/images/photos/wow3.png</file>
|
||||
<file>assets/images/photos/wow4.png</file>
|
||||
<file>assets/images/photos/wow5.png</file>
|
||||
<file>assets/images/photos/wow6.png</file>
|
||||
<file>assets/images/photos/wow7.png</file>
|
||||
<file>assets/images/photos/wow8.png</file>
|
||||
<file>assets/images/photos/wow9.png</file>
|
||||
<file>assets/images/photos/wow10.png</file>
|
||||
<file>assets/images/photos/wow11.png</file>
|
||||
<file>assets/images/photos/wow12.png</file>
|
||||
<file>assets/images/photos/wow13.png</file>
|
||||
<file>assets/images/photos/wow14.png</file>
|
||||
<file>assets/images/photos/wow15.png</file>
|
||||
<file>assets/images/photos/wow16.png</file>
|
||||
<file>assets/images/photos/wow17.png</file>
|
||||
<file>assets/images/photos/wow18.png</file>
|
||||
<file>assets/images/photos/wow19.png</file>
|
||||
<file>assets/images/photos/wow20.png</file>
|
||||
<file>assets/images/photos/wow21.png</file>
|
||||
<file>assets/images/photos/wow22.png</file>
|
||||
<file>assets/images/photos/wow23.png</file>
|
||||
<file>assets/images/photos/wow24.png</file>
|
||||
<file>assets/images/photos/wow25.png</file>
|
||||
<file>assets/images/photos/wow26.png</file>
|
||||
<file>assets/images/photos/wow27.png</file>
|
||||
<file>assets/images/photos/wow28.png</file>
|
||||
<file>assets/images/photos/wow29.png</file>
|
||||
<file>assets/images/photos/wow30.png</file>
|
||||
<file>assets/images/photos/wow31.png</file>
|
||||
<file>assets/images/photos/wow32.png</file>
|
||||
<file>assets/images/photos/wow33.png</file>
|
||||
<file>assets/images/photos/wow34.png</file>
|
||||
<file>assets/images/photos/wow35.png</file>
|
||||
<file>assets/images/photos/wow36.png</file>
|
||||
<file>assets/images/photos/wow37.png</file>
|
||||
<file>assets/images/photos/wow38.png</file>
|
||||
<file>assets/images/photos/wow39.png</file>
|
||||
<file>assets/images/photos/wow40.png</file>
|
||||
<file>assets/images/photos/wow41.png</file>
|
||||
<file>assets/images/photos/wow42.png</file>
|
||||
<file>assets/images/photos/wow43.png</file>
|
||||
<file>assets/images/photos/wow44.png</file>
|
||||
<file>assets/images/photos/wow45.png</file>
|
||||
<file>assets/images/photos/wow46.png</file>
|
||||
<file>assets/images/photos/wow47.png</file>
|
||||
<file>assets/images/illiterate_illuminati.png</file>
|
||||
<file>assets/images/welcome/wow1.png</file>
|
||||
<file>assets/images/welcome/wow2.png</file>
|
||||
<file>assets/images/welcome/wow3.png</file>
|
||||
<file>assets/images/welcome/wow4.png</file>
|
||||
<file>assets/images/welcome/wow5.png</file>
|
||||
<file>assets/images/welcome/wow6.png</file>
|
||||
<file>assets/images/welcome/wow7.png</file>
|
||||
<file>assets/images/welcome/wow8.png</file>
|
||||
<file>assets/images/welcome/wow9.png</file>
|
||||
<file>assets/images/welcome/wow10.png</file>
|
||||
<file>assets/images/welcome/wow11.png</file>
|
||||
<file>assets/images/welcome/wow12.png</file>
|
||||
<file>assets/images/welcome/wow13.png</file>
|
||||
<file>assets/images/welcome/wow14.png</file>
|
||||
<file>assets/images/welcome/wow15.png</file>
|
||||
<file>assets/images/welcome/wow16.png</file>
|
||||
<file>assets/images/welcome/wow17.png</file>
|
||||
<file>assets/images/welcome/wow18.png</file>
|
||||
<file>assets/images/welcome/wow19.png</file>
|
||||
<file>assets/images/welcome/wow20.png</file>
|
||||
<file>assets/images/welcome/wow21.png</file>
|
||||
<file>assets/images/welcome/wow22.png</file>
|
||||
<file>assets/images/welcome/wow23.png</file>
|
||||
<file>assets/images/welcome/wow24.png</file>
|
||||
<file>assets/images/welcome/wow25.png</file>
|
||||
<file>assets/images/welcome/wow26.png</file>
|
||||
<file>assets/images/welcome/wow27.png</file>
|
||||
<file>assets/images/welcome/wow28.png</file>
|
||||
<file>assets/images/welcome/wow29.png</file>
|
||||
<file>assets/images/welcome/wow30.png</file>
|
||||
<file>assets/images/welcome/wow31.png</file>
|
||||
<file>assets/images/welcome/wow32.png</file>
|
||||
<file>assets/images/welcome/wow33.png</file>
|
||||
<file>assets/images/welcome/wow34.png</file>
|
||||
<file>assets/images/welcome/wow35.png</file>
|
||||
<file>assets/images/welcome/wow36.png</file>
|
||||
<file>assets/images/welcome/wow37.png</file>
|
||||
<file>assets/images/welcome/wow38.png</file>
|
||||
<file>assets/images/welcome/wow39.png</file>
|
||||
<file>assets/images/welcome/wow40.png</file>
|
||||
<file>assets/images/welcome/wow41.png</file>
|
||||
<file>assets/images/welcome/wow42.png</file>
|
||||
<file>assets/images/welcome/wow43.png</file>
|
||||
<file>assets/images/welcome/wow44.png</file>
|
||||
<file>assets/images/welcome/wow45.png</file>
|
||||
<file>assets/images/welcome/wow46.png</file>
|
||||
<file>assets/images/welcome/wow47.png</file>
|
||||
<file>assets/images/welcome/wow48.png</file>
|
||||
<file>assets/images/welcome/wow49.png</file>
|
||||
<file>assets/images/welcome/wow50.png</file>
|
||||
<file>assets/images/welcome/wow51.png</file>
|
||||
<file>assets/images/welcome/wow52.png</file>
|
||||
<file>assets/images/welcome/wow53.png</file>
|
||||
<file>assets/images/welcome/wow54.png</file>
|
||||
<file>assets/images/welcome/wow55.png</file>
|
||||
<file>assets/images/welcome/wow56.png</file>
|
||||
<file>assets/images/welcome/wow57.png</file>
|
||||
<file>assets/images/welcome/wow58.png</file>
|
||||
<file>assets/images/welcome/wow59.png</file>
|
||||
<file>assets/images/welcome/wow60.png</file>
|
||||
<file>assets/images/welcome/wow61.png</file>
|
||||
<file>assets/images/welcome/wow62.png</file>
|
||||
<file>assets/images/welcome/wow63.png</file>
|
||||
<file>assets/images/welcome/wow64.png</file>
|
||||
<file>assets/images/welcome/wow65.png</file>
|
||||
<file>assets/images/welcome/wow66.png</file>
|
||||
<file>assets/images/welcome/wow67.png</file>
|
||||
<file>assets/images/welcome/wow68.png</file>
|
||||
<file>assets/images/welcome/wow69.png</file>
|
||||
<file>assets/images/welcome/wow70.png</file>
|
||||
<file>assets/images/welcome/wow71.png</file>
|
||||
<file>assets/images/welcome/wow72.png</file>
|
||||
<file>assets/images/welcome/wow73.png</file>
|
||||
<file>assets/images/welcome/wow74.png</file>
|
||||
<file>assets/images/welcome/wow75.png</file>
|
||||
<file>assets/images/welcome/wow76.png</file>
|
||||
<file>assets/images/welcome/wow77.png</file>
|
||||
<file>assets/images/welcome/wow78.png</file>
|
||||
<file>assets/images/welcome/wow79.png</file>
|
||||
<file>assets/images/welcome/wow80.png</file>
|
||||
<file>assets/images/welcome/wow81.png</file>
|
||||
<file>assets/images/welcome/wow82.png</file>
|
||||
<file>assets/images/welcome/wow83.png</file>
|
||||
<file>assets/images/welcome/wow84.png</file>
|
||||
<file>assets/images/welcome/wow85.png</file>
|
||||
<file>assets/images/welcome/wow86.png</file>
|
||||
<file>assets/images/welcome/wow87.png</file>
|
||||
<file>assets/images/welcome/wow88.png</file>
|
||||
<file>assets/images/welcome/wow89.png</file>
|
||||
<file>assets/images/welcome/wow90.png</file>
|
||||
<file>assets/images/welcome/wow91.png</file>
|
||||
<file>assets/images/welcome/wow92.png</file>
|
||||
<file>assets/images/welcome/wow93.png</file>
|
||||
<file>assets/images/welcome/wow94.png</file>
|
||||
<file>assets/images/welcome/wow95.png</file>
|
||||
<file>assets/images/welcome/wow96.png</file>
|
||||
<file>assets/images/welcome/wow97.png</file>
|
||||
<file>assets/images/welcome/wow98.png</file>
|
||||
<file>assets/images/welcome/wow99.png</file>
|
||||
<file>assets/images/welcome/wow100.png</file>
|
||||
<file>assets/images/welcome/wow101.png</file>
|
||||
<file>assets/images/welcome/wow102.png</file>
|
||||
<file>assets/images/welcome/wow103.png</file>
|
||||
<file>assets/images/welcome/wow104.png</file>
|
||||
<file>assets/images/welcome/wow105.png</file>
|
||||
<file>assets/images/welcome/wow106.png</file>
|
||||
<file>assets/images/welcome/wow107.png</file>
|
||||
<file>assets/images/welcome/wow108.png</file>
|
||||
<file>assets/images/welcome/wow109.png</file>
|
||||
<file>assets/images/welcome/wow110.png</file>
|
||||
<file>assets/images/welcome/wow111.png</file>
|
||||
<file>assets/images/welcome/wow112.png</file>
|
||||
<file>assets/images/welcome/wow113.png</file>
|
||||
<file>assets/images/welcome/wow114.png</file>
|
||||
<file>assets/images/welcome/wow115.png</file>
|
||||
<file>assets/images/welcome/wow116.png</file>
|
||||
<file>assets/images/welcome/wow117.png</file>
|
||||
<file>assets/images/welcome/wow118.png</file>
|
||||
<file>assets/images/welcome/wow119.png</file>
|
||||
<file>assets/images/welcome/wow120.png</file>
|
||||
<file>assets/images/welcome/wow121.png</file>
|
||||
<file>assets/images/welcome/wow122.png</file>
|
||||
<file>assets/images/welcome/wow123.png</file>
|
||||
<file>assets/images/preferences.png</file>
|
||||
<file>assets/images/preferences.svg</file>
|
||||
<file>assets/images/credits.jpg</file>
|
||||
<file>assets/images/qrcode.png</file>
|
||||
<file>assets/images/qrcode_white.png</file>
|
||||
<file>assets/images/revealer_c.png</file>
|
||||
|
@ -111,6 +189,7 @@
|
|||
<file>assets/images/seal.png</file>
|
||||
<file>assets/images/seed.png</file>
|
||||
<file>assets/images/speaker.png</file>
|
||||
<file>assets/images/pls_update.jpg</file>
|
||||
<file>assets/images/status_connected_fork.png</file>
|
||||
<file>assets/images/status_connected.png</file>
|
||||
<file>assets/images/status_connected_proxy_fork.png</file>
|
||||
|
@ -149,5 +228,34 @@
|
|||
<file>assets/images/zoom.png</file>
|
||||
<file>assets/mnemonic_25_english.txt</file>
|
||||
<file>assets/restore_heights_wownero_mainnet.txt</file>
|
||||
|
||||
<file alias="mining/bottom_center_console.png">assets/images/mining/bottom_center_console.png</file>
|
||||
<file alias="mining/intel.png">assets/images/mining/intel.png</file>
|
||||
<file alias="mining/amd.png">assets/images/mining/amd.png</file>
|
||||
<file alias="mining/overlay.png">assets/images/mining/overlay.png</file>
|
||||
<file alias="mining/mining_gradient.png">assets/images/mining/mining_gradient.png</file>
|
||||
<file alias="mining/bg1.gif">assets/images/mining/bg1.gif</file>
|
||||
<file alias="mining/lowerleft_circle.png">assets/images/mining/lowerleft_circle.png</file>
|
||||
<file alias="mining/lowerleft.png">assets/images/mining/lowerleft.png</file>
|
||||
<file alias="mining/lower_repeat.png">assets/images/mining/lower_repeat.png</file>
|
||||
<file alias="mining/lowerright.png">assets/images/mining/lowerright.png</file>
|
||||
<file alias="mining/r_bottom.png">assets/images/mining/r_bottom.png</file>
|
||||
<file alias="mining/r_left.png">assets/images/mining/r_left.png</file>
|
||||
<file alias="mining/r_right.png">assets/images/mining/r_right.png</file>
|
||||
<file alias="mining/topleft.png">assets/images/mining/topleft.png</file>
|
||||
<file alias="mining/topright_bar.png">assets/images/mining/topright_bar.png</file>
|
||||
<file alias="mining/topright_left.png">assets/images/mining/topright_left.png</file>
|
||||
<file alias="mining/topright_middle.png">assets/images/mining/topright_middle.png</file>
|
||||
<file alias="mining/topright_right.png">assets/images/mining/topright_right.png</file>
|
||||
<file alias="mining/warning.png">assets/images/mining/warning.png</file>
|
||||
<file alias="mining/axe.png">assets/images/mining/axe.png</file>
|
||||
<file alias="mining/lowerleft_btn.png">assets/images/mining/lowerleft_btn.png</file>
|
||||
<file alias="mining/elmo.gif">assets/images/mining/elmo.gif</file>
|
||||
<file alias="mining/bubble.png">assets/images/mining/bubble.png</file>
|
||||
<file alias="mining/mining.webp">assets/images/mining/mining.webp</file>
|
||||
|
||||
<file alias="fonts/ComicMono.ttf">assets/fonts/ComicMono.ttf</file>
|
||||
<file alias="fonts/ComicMono-Bold.ttf">assets/fonts/ComicMono-Bold.ttf</file>
|
||||
<file alias="mining.qml">ui/qml/mining.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
WOWlet <feather_version> (<feather_git_head>)
|
||||
WOWlet <wowlet_version> (<wowlet_git_head>)
|
||||
|
||||
Website: https://wownero.org
|
||||
E-mail: dev@wownero.org
|
||||
|
|
After Width: | Height: | Size: 98 KiB |
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 801 B After Width: | Height: | Size: 941 B |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 412 B |
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 103 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 3.9 KiB |
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1"
|
||||
id="svg24" inkscape:version="1.0 (4035a4fb49, 2020-05-01)" sodipodi:docname="wownero.svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 600 600"
|
||||
style="enable-background:new 0 0 600 600;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FF2AD4;}
|
||||
.st1{fill:#FFCC00;}
|
||||
.st2{fill:#FFFFFF;}
|
||||
</style>
|
||||
<g id="Identity" transform="matrix(0.92248086,0,0,0.92248086,-442.13585,-627.93272)">
|
||||
<g id="g10">
|
||||
<path id="path6" class="st0" d="M1103.8,879.4c-16.4-38.7-39.8-73.4-69.6-103.3c-29.9-29.9-64.5-53.2-103.3-69.6
|
||||
c-40.1-17-82.6-25.6-126.5-25.6s-86.4,8.6-126.5,25.6c-38.7,16.4-73.4,39.8-103.3,69.6c-29.9,29.9-53.2,64.5-69.6,103.3
|
||||
c-17,40.1-25.6,82.6-25.6,126.5s8.6,86.4,25.6,126.5c16.4,38.7,39.8,73.4,69.6,103.3c29.9,29.9,64.5,53.2,103.3,69.6
|
||||
c40.1,17,82.6,25.6,126.5,25.6s86.4-8.6,126.5-25.6c38.7-16.4,73.4-39.8,103.3-69.6c29.9-29.9,53.2-64.5,69.6-103.3
|
||||
c17-40.1,25.6-82.6,25.6-126.5S1120.7,919.5,1103.8,879.4L1103.8,879.4z"/>
|
||||
<path id="path4" class="st1" d="M661,902.2l10.6,186.7l132.8-147.3L937,1089.2c0,0,9.6-157.9,11.3-186.7c47,0,98.1,0,150.8,0
|
||||
c-42.7-121.8-158.5-208.9-294.7-208.9c-135.8,0-251.7,87.2-294.6,208.6C529.8,902.4,661,902.2,661,902.2z"/>
|
||||
<path id="path8" class="st2" d="M1103.1,913.8H958.8l-11.7,203.9c-15-17.4-135-149.6-142.9-158.9
|
||||
c-4.7,5.3-142.7,158.5-142.7,158.5l-11.6-203.5h-144c-8.9,29-13.7,59.7-13.7,91.5c0,172.2,140,312.3,312.3,312.3
|
||||
s312.3-140.1,312.3-312.3C1116.8,973.7,1111.9,942.6,1103.1,913.8L1103.1,913.8z M804.5,1296c-158.5,0-287.1-128.6-287.1-287.1
|
||||
c0-24.8,3-48.5,8.9-71.4h101.3c0.6,10.3,13.8,240.1,13.8,240.1l163.3-180.4l164.1,181.1c0,0,0,0.1,14-240.8h100.3
|
||||
c5.8,22.8,8.5,46.8,8.5,71.4C1091.6,1167.4,963,1296,804.5,1296L804.5,1296z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.2 KiB |