Merge branch 'daleglass/opus-plugin' into opus-plugin

This commit is contained in:
Marcus Llewellyn 2020-01-12 18:18:14 -06:00
commit 2b8c0ffbdc
47 changed files with 760 additions and 185 deletions

View file

@ -32,7 +32,7 @@ These are not placed in your normal build tree when doing an out of source build
#### CMake
Hifi uses CMake to generate build files and project files for your platform.
Athena uses CMake to generate build files and project files for your platform.
#### Qt
CMake will download Qt 5.12.3 using vcpkg.
@ -47,7 +47,7 @@ This can either be entered directly into your shell session before you build or
#### Vcpkg
Hifi uses vcpkg to download and build dependencies.
Athena uses vcpkg to download and build dependencies.
You do not need to install vcpkg.
Building the dependencies can be lengthy and the resulting files will be stored in your OS temp directory.

View file

@ -62,7 +62,7 @@ The above code to suppress modules is not necessary, but will speed up the build
### Clone the repository
`git clone https://github.com/highfidelity/hifi.git `
`git clone https://github.com/kasenvr/project-athena.git`
# Building & Running

View file

@ -76,7 +76,7 @@ sudo apt-get install nodejs
Clone this repository:
```bash
git clone https://github.com/highfidelity/hifi.git
git clone https://github.com/kasenvr/project-athena.git
```
To compile a RELEASE version checkout the tag you need getting a list of all tags:

View file

@ -1,5 +1,5 @@
This is a stand-alone guide for creating your first High Fidelity build for Windows 64-bit.
## Building High Fidelity
This is a stand-alone guide for creating your first Project Athena build for Windows 64-bit.
## Building Project Athena
Note: We are now using Visual Studio 2017 or 2019 and Qt 5.12.3.
If you are upgrading from previous versions, do a clean uninstall of those versions before going through this guide.
@ -37,7 +37,7 @@ Download and install the latest version of CMake 3.15.
Download the file named win64-x64 Installer from the [CMake Website](https://cmake.org/download/). You can access the installer on this [3.15 Version page](https://cmake.org/files/v3.15/). During installation, make sure to check "Add CMake to system PATH for all users" when prompted.
### Step 3. Create VCPKG environment variable
In the next step, you will use CMake to build High Fidelity. By default, the CMake process builds dependency files in Windows' `%TEMP%` directory, which is periodically cleared by the operating system. To prevent you from having to re-build the dependencies in the event that Windows clears that directory, we recommend that you create a `HIFI_VCPKG_BASE` environment variable linked to a directory somewhere on your machine. That directory will contain all dependency files until you manually remove them.
In the next step, you will use CMake to build Project Athena. By default, the CMake process builds dependency files in Windows' `%TEMP%` directory, which is periodically cleared by the operating system. To prevent you from having to re-build the dependencies in the event that Windows clears that directory, we recommend that you create a `HIFI_VCPKG_BASE` environment variable linked to a directory somewhere on your machine. That directory will contain all dependency files until you manually remove them.
To create this variable:
* Naviagte to 'Edit the System Environment Variables' Through the start menu.
@ -72,7 +72,7 @@ Where `%HIFI_DIR%` is the directory for the highfidelity repository.
### Step 5. Making a Build
Open `%HIFI_DIR%\build\hifi.sln` using Visual Studio.
Open `%HIFI_DIR%\build\athena.sln` using Visual Studio.
Change the Solution Configuration (menu ribbon under the menu bar, next to the green play button) from "Debug" to "Release" for best performance.
@ -88,7 +88,7 @@ Restart Visual Studio again.
In Visual Studio, right+click "interface" under the Apps folder in Solution Explorer and select "Set as Startup Project". Run from the menu bar `Debug > Start Debugging`.
Now, you should have a full build of High Fidelity and be able to run the Interface using Visual Studio. Please check our [Docs](https://wiki.highfidelity.com/wiki/Main_Page) for more information regarding the programming workflow.
Now, you should have a full build of Project Athena and be able to run the Interface using Visual Studio. Please check our [Docs](https://wiki.highfidelity.com/wiki/Main_Page) for more information regarding the programming workflow.
Note: You can also run Interface by launching it from command line or File Explorer from `%HIFI_DIR%\build\interface\Release\interface.exe`
@ -97,7 +97,7 @@ Note: You can also run Interface by launching it from command line or File Explo
For any problems after Step #6, first try this:
* Delete your locally cloned copy of the highfidelity repository
* Restart your computer
* Redownload the [repository](https://github.com/kasenvr/hificommunity)
* Redownload the [repository](https://github.com/kasenvr/project-athena)
* Restart directions from Step #6
#### CMake gives you the same error message repeatedly after the build fails

View file

@ -1,10 +1,10 @@
# HiFi Community Edition
# Project Athena
### [Download v0.86.0 K1 (Windows 64-bit, .zip)](https://realities.dev/cdn/hifi-community/v0860-kasen-VS-release+freshstart/Packaged_Release.zip)
### [Download ALPHA-DEV v0.86.0 K1 (Windows 64-bit, .zip)](https://realities.dev/cdn/hifi-community/v0860-kasen-VS-release+freshstart/Packaged_Release.zip)
#### Changes for **v0.86.0** consist of:
This build has been tested on Windows 10 Pro 64-bit w/ Nvidia graphics drivers.
#### Added in K1 (12/3/19)
#### v0.86.0 K1 (12/3/19)
* Audio Buffer choppy audio bugfix by increasing the buffer size.
* User Activity Logger disabled, option in code to log the reports to console.
@ -13,15 +13,10 @@
* Entity Script Whitelist, no scripts are whitelisted by default.
* Background CMD outputs full log, instant close of application on closing of the CMD-line.
#### Added in K2 (TBD)
#### v0.86.0 K2 (TBD)
* QML Interface to access and save whitelist live to interface.json.
* Add "VideoDecodeStats" to .gitignore.
* Fix VCPKG SDL2 to port files from 2.0.8 to 2.0.10 to fix CMake build issues.
* Added Github link to "About High Fidelity".
* Removed environment variable requirement for "procedural shader materials".
This build has been tested on Windows 10 Pro 64-bit w/ Nvidia graphics drivers.
##### Features, Bugs, and Housekeeping
Check out the releases page for more information!
### Whitelist Instructions
@ -31,15 +26,7 @@ The Interface has the whitelist settings under "**Settings -> Entity Script Whit
Do not use spaces or commas in the whitelist interface, you will only separate by commas and not new lines in the environment variables.
It is recommended that you add High Fidelity's CDN URLs ahead of time to ensure general content works right off the bat:
```
http://mpassets.highfidelity.com/
https://raw.githubusercontent.com/highfidelity/
https://hifi-content.s3.amazonaws.com/
```
You can also set the Windows environment variable "**EXTRA_WHITELIST**" with your whitelisted domains comma separated like so: "**https://kasen.io/,http://kasen.io/,https://exampledomain.com/scriptFolder/**"
You can also set the Windows environment variable "**EXTRA_WHITELIST**" with your whitelisted domains comma separated like so: "**http://mpassets.highfidelity.com/,https://raw.githubusercontent.com/highfidelity/,https://hifi-content.s3.amazonaws.com/**"
Alternatively you can make a batch file placed in the same folder as interface.exe that sets the whitelist environment variable temporarily:
@ -50,7 +37,8 @@ interface.exe
### How to build interface.exe
[For Windows](https://github.com/kasenvr/hifi-community/blob/kasen/core/BUILD_WIN.md)
[For Windows](https://github.com/kasenvr/project-athena/blob/kasen/core/BUILD_WIN.md)
[For Linux](https://github.com/kasenvr/project-athena/blob/kasen/core/BUILD_LINUX.md)
### Boot to Metaverse: The Goal
@ -58,7 +46,7 @@ Too many of us have our own personal combinations of High Fidelity from C++ modi
The goal of this repo is to give a common area to PR the very best of our findings and creations so that we may effectively take each necessary step towards our common goal of living in a true metaverse.
### Why High Fidelity?
### Why High Fidelity's Engine?
Because of all the options, it is the only starting point that is open-source, cross-platform, fully VR integrated + fully desktop integrated with an aim for quality visuals and performance. It also does us the service of providing a foundation to start from such as entity management, full body IK, etc.
@ -68,6 +56,8 @@ Platforms like NeosVR or VRChat are unusable from go due to their fundamental cl
So the necessary desire is to use High Fidelity as our foundation as a community of one, of all to build a metaverse worth living in.
### Contributors
### Contribution
A special thanks to the contributors of the community edition.
A special thanks to the contributors of the Project Athena.
[Contribution](CONTRIBUTING.md)

View file

@ -5,7 +5,7 @@
# Distributed under the Apache License, Version 2.0.
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
#
macro(TARGET_opus)
macro(TARGET_OPUS)
if (ANDROID)
# no idea if this is correct
target_link_libraries(${TARGET_NAME})

View file

@ -19,7 +19,7 @@ include(vcpkg_common_functions)
vcpkg_from_github(
OUT_SOURCE_PATH SOURCE_PATH
REPO highfidelity/etc2comp
REPO kasenvr/etc2comp
REF 7f1843bf07825c21cab711360c1ddbad04641036
SHA512 d747076acda8537d39585858c793a35c3dcc9ef283d723619a47f8c81ec1454c95b3340ad35f0655a939eae5b8271c801c48a9a7568311a01903a344c44af25b
HEAD_REF master

View file

@ -3,7 +3,7 @@ include(vcpkg_common_functions)
vcpkg_from_github(
OUT_SOURCE_PATH SOURCE_PATH
REPO highfidelity/scribe
REPO kasenvr/scribe
REF 1bd638a36ca771e5a68d01985b6389b71835cbd2
SHA512 dbe241d86df3912e544f6b9839873f9875df54efc93822b145e7b13243eaf2e3d690bc8a28b1e52d05bdcd7e68fca6b0b2f5c43ffd0f56a9b7a50d54dcf9e31e
HEAD_REF master

View file

@ -9,7 +9,7 @@ include(vcpkg_common_functions)
vcpkg_from_github(
OUT_SOURCE_PATH SOURCE_PATH
REPO highfidelity/nvidia-texture-tools
REPO kasenvr/nvidia-texture-tools
REF 330c4d56274a0f602a5c70596e2eb670a4ed56c2
SHA512 4c0bc2f369120d696cc27710b6d33086b27eef55f537ec66b9a5c8b1839bc2426c0413670b0f65be52c5d353468f0126dfe024be1f0690611d4d7e33ac530127
HEAD_REF master

View file

@ -1227,8 +1227,8 @@
"name": "codec_preference_order",
"label": "Audio Codec Preference Order",
"help": "List of codec names in order of preferred usage",
"placeholder": "hifiAC, zlib, pcm",
"default": "hifiAC,zlib,pcm",
"placeholder": "opus, hifiAC, zlib, pcm",
"default": "opus,hifiAC,zlib,pcm",
"advanced": true
}
]

View file

@ -164,7 +164,7 @@ endif()
if downloadVcpkg:
if "HIFI_VCPKG_BOOTSTRAP" in os.environ:
print("Cloning vcpkg from github to {}".format(self.path))
hifi_utils.executeSubprocess(['git', 'clone', 'git@github.com:microsoft/vcpkg.git', self.path])
hifi_utils.executeSubprocess(['git', 'clone', 'https://github.com/microsoft/vcpkg', self.path])
print("Bootstrapping vcpkg")
hifi_utils.executeSubprocess([self.bootstrapCmd], folder=self.path)
else:

View file

@ -15,9 +15,9 @@ set(CUSTOM_INTERFACE_QRC_PATHS "")
find_npm()
#if (BUILD_TOOLS AND NPM_EXECUTABLE)
# add_custom_qrc_path(CUSTOM_INTERFACE_QRC_PATHS "${CMAKE_SOURCE_DIR}/tools/jsdoc/out/hifiJSDoc.json" "auto-complete/hifiJSDoc.json")
#endif ()
if (BUILD_TOOLS AND NPM_EXECUTABLE)
add_custom_qrc_path(CUSTOM_INTERFACE_QRC_PATHS "${CMAKE_SOURCE_DIR}/tools/jsdoc/out/hifiJSDoc.json" "auto-complete/hifiJSDoc.json")
endif ()
set(RESOURCES_QRC ${CMAKE_CURRENT_BINARY_DIR}/resources.qrc)
set(RESOURCES_RCC ${CMAKE_CURRENT_SOURCE_DIR}/compiledResources/resources.rcc)
@ -161,9 +161,9 @@ elseif (WIN32)
configure_file("${HF_CMAKE_DIR}/templates/VersionInfo.rc.in" ${CONFIGURE_VERSION_INFO_RC_OUTPUT})
# add an executable that also has the icon itself and the configured rc file as resources
#add_executable(${TARGET_NAME} WIN32 ${INTERFACE_SRCS} ${QM} ${CONFIGURE_ICON_RC_OUTPUT} ${CONFIGURE_VERSION_INFO_RC_OUTPUT})
add_executable(${TARGET_NAME} WIN32 ${INTERFACE_SRCS} ${QM} ${CONFIGURE_ICON_RC_OUTPUT} ${CONFIGURE_VERSION_INFO_RC_OUTPUT})
##^^^^^ creates native Win32 app w/o cmd console vvvvvv forces cmd console for logging
add_executable(${TARGET_NAME} ${INTERFACE_SRCS} ${QM} ${CONFIGURE_ICON_RC_OUTPUT} ${CONFIGURE_VERSION_INFO_RC_OUTPUT})
# add_executable(${TARGET_NAME} ${INTERFACE_SRCS} ${QM} ${CONFIGURE_ICON_RC_OUTPUT} ${CONFIGURE_VERSION_INFO_RC_OUTPUT})
if (NOT DEV_BUILD)
add_custom_command(
@ -182,10 +182,10 @@ else ()
endif ()
#if (BUILD_TOOLS AND NPM_EXECUTABLE)
if (BUILD_TOOLS AND NPM_EXECUTABLE)
# require JSDoc to be build before interface is deployed
# add_dependencies(resources jsdoc)
#endif()
add_dependencies(resources jsdoc)
endif()
add_dependencies(${TARGET_NAME} resources)
@ -326,9 +326,9 @@ if (APPLE)
"${CMAKE_SOURCE_DIR}/scripts"
"${RESOURCES_DEV_DIR}/scripts"
# copy JSDoc files beside the executable
#COMMAND "${CMAKE_COMMAND}" -E copy_directory
# "${CMAKE_SOURCE_DIR}/tools/jsdoc/out"
# "${RESOURCES_DEV_DIR}/jsdoc"
COMMAND "${CMAKE_COMMAND}" -E copy_directory
"${CMAKE_SOURCE_DIR}/tools/jsdoc/out"
"${RESOURCES_DEV_DIR}/jsdoc"
# copy the resources files beside the executable
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
"${RESOURCES_RCC}"
@ -381,9 +381,9 @@ else()
"${PROJECT_SOURCE_DIR}/resources/serverless/redirect.json"
"${RESOURCES_DEV_DIR}/serverless/redirect.json"
# copy JSDoc files beside the executable
#COMMAND "${CMAKE_COMMAND}" -E copy_directory
# "${CMAKE_SOURCE_DIR}/tools/jsdoc/out"
# "${INTERFACE_EXEC_DIR}/jsdoc"
COMMAND "${CMAKE_COMMAND}" -E copy_directory
"${CMAKE_SOURCE_DIR}/tools/jsdoc/out"
"${INTERFACE_EXEC_DIR}/jsdoc"
)
# link target to external libraries

View file

@ -40,7 +40,7 @@ Controls.WebView {
userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ]
function onWebEventReceived(event) {
if (event.slice(0, 17) === "CLARA.IO DOWNLOAD") {
if (typeof event === "string" && event.slice(0, 17) === "CLARA.IO DOWNLOAD") {
ApplicationInterface.addAssetToWorldFromURL(event.slice(18));
}
}

View file

@ -229,7 +229,7 @@ Item {
}
function openDocs() {
Qt.openUrlExternally("https://docs.highfidelity.com/create/avatars/package-avatar.html");
Qt.openUrlExternally("https://docs.projectathena.dev/create/avatars/package-avatar.html");
}
function openVideo() {

View file

@ -128,6 +128,8 @@ ShadowRectangle {
}
}
// FIXME: Link to a Project Athena version of the video.
/*
RalewayButton {
id: video
visible: false
@ -141,6 +143,12 @@ ShadowRectangle {
onClicked: videoButtonClicked()
}
*/
// Temporary placeholder for video button.
Rectangle {
id: video
visible: false
}
RalewayButton {
id: docs

View file

@ -44,7 +44,11 @@ Item {
HifiControls.Button {
id: uploadButton
// FIXME: Re-enable if ability to upload to hosted location is added.
/*
visible: AvatarPackagerCore.currentAvatarProject && !AvatarPackagerCore.currentAvatarProject.fst.hasMarketplaceID && !root.hasSuccessfullyUploaded
*/
visible: false
enabled: Account.loggedIn
anchors.verticalCenter: parent.verticalCenter
@ -62,7 +66,11 @@ Item {
HifiControls.Button {
id: updateButton
// FIXME: Re-enable if ability to upload to hosted location is added.
/*
visible: AvatarPackagerCore.currentAvatarProject && AvatarPackagerCore.currentAvatarProject.fst.hasMarketplaceID && !root.hasSuccessfullyUploaded
*/
visible: false
enabled: Account.loggedIn
anchors.verticalCenter: parent.verticalCenter
@ -79,7 +87,12 @@ Item {
}
Item {
anchors.fill: parent
// FIXME: Re-enable if ability to upload to hosted location is added.
/*
visible: root.hasSuccessfullyUploaded
*/
visible: false;
HifiControls.Button {
enabled: Account.loggedIn
@ -115,6 +128,22 @@ Item {
onClicked: AvatarPackagerCore.currentAvatarProject.openInInventory()
}
}
// FIXME: Remove if "Upload" button is reinstated.
HifiControls.Button {
id: openDirectoryButton
visible: AvatarPackagerCore.currentAvatarProject
enabled: true
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
text: qsTr("Open Project Folder")
color: hifi.buttons.blue
colorScheme: root.colorScheme
width: 200
height: 40
onClicked: {
fileDialogHelper.openDirectory(fileDialogHelper.pathToUrl(AvatarPackagerCore.currentAvatarProject.projectFolderPath));
}
}
}
Rectangle {
@ -263,13 +292,58 @@ Item {
color: 'white'
size: 20
anchors.left: parent.left
anchors.right: parent.right
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: errorsGlyph.bottom
wrapMode: Text.Wrap
}
RalewayRegular {
id: notForSaleMessage
visible: root.hasSuccessfullyUploaded
color: 'white'
linkColor: '#00B4EF'
size: 20
anchors.left: parent.left
anchors.right: parent.right
anchors.top: doctorStatusMessage.bottom
anchors.topMargin: 10
anchors.bottomMargin: 24
wrapMode: Text.Wrap
text: "This item is not for sale yet, <a href='#'>learn more</a>."
onLinkActivated: {
Qt.openUrlExternally("https://docs.projectathena.dev/sell/add-item/upload-avatar.html");
}
}
RalewayRegular {
id: showErrorsLink
color: 'white'
linkColor: '#00B4EF'
visible: AvatarPackagerCore.currentAvatarProject && AvatarPackagerCore.currentAvatarProject.hasErrors
anchors {
top: notForSaleMessage.bottom
horizontalCenter: parent.horizontalCenter
}
size: 28
text: "<a href='toggle'>View all errors</a>"
onLinkActivated: {
avatarPackager.state = AvatarPackagerState.avatarDoctorErrorReport;
}
}
RalewayRegular {
id: infoMessage
@ -297,60 +371,14 @@ Item {
anchors.left: parent.left
anchors.right: parent.right
anchors.top: doctorStatusMessage.bottom
anchors.bottom: showFilesText.top
anchors.bottomMargin: 24
wrapMode: Text.Wrap
text: "You can upload your files to our servers to always access them, and to make your avatar visible to other users."
}
RalewayRegular {
id: notForSaleMessage
visible: root.hasSuccessfullyUploaded
color: 'white'
linkColor: '#00B4EF'
size: 20
anchors.left: parent.left
anchors.right: parent.right
anchors.top: infoMessage.bottom
anchors.topMargin: 10
anchors.bottomMargin: 24
wrapMode: Text.Wrap
text: "This item is not for sale yet, <a href='#'>learn more</a>."
onLinkActivated: {
Qt.openUrlExternally("https://docs.highfidelity.com/sell/add-item/upload-avatar.html");
}
}
RalewayRegular {
id: showErrorsLink
color: 'white'
linkColor: '#00B4EF'
visible: AvatarPackagerCore.currentAvatarProject && AvatarPackagerCore.currentAvatarProject.hasErrors
anchors {
top: notForSaleMessage.visible ? notForSaleMessage.bottom : infoMessage .bottom
bottom: showFilesText.top
horizontalCenter: parent.horizontalCenter
}
size: 28
text: "<a href='toggle'>View all errors</a>"
onLinkActivated: {
avatarPackager.state = AvatarPackagerState.avatarDoctorErrorReport;
}
// FIXME: Restore original text if ability to upload to hosted location is added.
//text: "You can upload your files to our servers to always access them, and to make your avatar visible to other users."
text: "Your files are ready to be uploaded to a server to make your avatar visible to other users."
}
HifiControls.Button {
@ -389,8 +417,13 @@ Item {
Rectangle {
id: loginRequiredMessage
// FIXME: Re-enable if ability to upload to hosted location is added.
/*
visible: !Account.loggedIn
height: !Account.loggedIn ? loginRequiredTextRow.height + 20 : 0
*/
visible: false
height: 0
anchors {
bottom: parent.bottom

View file

@ -53,18 +53,7 @@ Rectangle {
textFormat: Text.StyledText
linkColor: "#00B4EF"
color: "white"
text: "<a href=\"https:/www.highfidelity.com\">www.highfidelity.com</a>."
size: 20
onLinkActivated: {
HiFiAbout.openUrl("https:/www.highfidelity.com");
}
}
RalewayRegular {
textFormat: Text.StyledText
linkColor: "#00B4EF"
color: "white"
text: "<a href=\"https:/github.com/kasenvr/hifi-community\">HiFi Community Github</a>."
text: "<a href=\"https:/github.com/kasenvr/hifi-community\">Project Athena Github</a>."
size: 20
onLinkActivated: {
HiFiAbout.openUrl("https:/github.com/kasenvr/hifi-community");

View file

@ -1,5 +1,5 @@
//
// ScriptWhitelist.qml
// EntityScriptQMLWhitelist.qml
// interface/resources/qml/hifi/dialogs/security
//
// Created by Kasen IO on 2019.12.05 | realities.dev | kasenvr@gmail.com
@ -145,7 +145,9 @@ Rectangle {
https://google.com/
https://bing.com/
https://mydomain.here/
\nEnsure there are no spaces or whitespace."
\nEnsure there are no spaces or whitespace.
\nFor QML files, you can only whitelist each file individually
ending with '.qml'."
// Text size
size: 16;
// Style

View file

@ -200,7 +200,7 @@ Rectangle {
id: eventBridgeConnection
target: eventBridge
onWebEventReceived: {
if (message.slice(0, 17) === "CLARA.IO DOWNLOAD") {
if (typeof message === "string" && message.slice(0, 17) === "CLARA.IO DOWNLOAD") {
ApplicationInterface.addAssetToWorldFromURL(message.slice(18));
}
}

View file

@ -118,7 +118,7 @@ Windows.ScrollingWindow {
id: eventBridgeConnection
target: eventBridge
onWebEventReceived: {
if (message.slice(0, 17) === "CLARA.IO DOWNLOAD") {
if (typeof message === "string" && message.slice(0, 17) === "CLARA.IO DOWNLOAD") {
ApplicationInterface.addAssetToWorldFromURL(message.slice(18));
}
}

View file

@ -1158,7 +1158,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
QFontDatabase::addApplicationFont(PathUtils::resourcesPath() + "fonts/Graphik-SemiBold.ttf");
QFontDatabase::addApplicationFont(PathUtils::resourcesPath() + "fonts/Graphik-Regular.ttf");
QFontDatabase::addApplicationFont(PathUtils::resourcesPath() + "fonts/Graphik-Medium.ttf");
_window->setWindowTitle("High Fidelity");
_window->setWindowTitle("Project Athena");
Model::setAbstractViewStateInterface(this); // The model class will sometimes need to know view state details from us
@ -3202,10 +3202,30 @@ void Application::initializeUi() {
// Allow remote QML content from trusted sources ONLY
{
auto defaultUrlValidator = OffscreenQmlSurface::getUrlValidator();
auto newValidator = [=](const QUrl& url)->bool {
if (AUTHORIZED_EXTERNAL_QML_SOURCE.isParentOf(url)) {
return true;
auto newValidator = [=](const QUrl& url) -> bool {
QString whitelistPrefix = "[WHITELIST ENTITY SCRIPTS]";
QList<QString> safeURLS = { "" };
safeURLS += qEnvironmentVariable("EXTRA_WHITELIST").trimmed().split(QRegExp("\\s*,\\s*"), QString::SkipEmptyParts);
// PULL SAFEURLS FROM INTERFACE.JSON Settings
QVariant raw = Setting::Handle<QVariant>("private/settingsSafeURLS").get();
QStringList settingsSafeURLS = raw.toString().trimmed().split(QRegExp("\\s*[,\r\n]+\\s*"), QString::SkipEmptyParts);
safeURLS += settingsSafeURLS;
// END PULL SAFEURLS FROM INTERFACE.JSON Settings
bool isInWhitelist = false; // assume unsafe
for (const auto& str : safeURLS) {
if (!str.isEmpty() && str.endsWith(".qml") && url.toString().endsWith(".qml") &&
url.toString().startsWith(str)) {
qCDebug(interfaceapp) << "Found matching url!" << url.host();
isInWhitelist = true;
return true;
}
}
qCDebug(interfaceapp) << "No matching url" << url.host();
return defaultUrlValidator(url);
};
OffscreenQmlSurface::setUrlValidator(newValidator);
@ -7046,7 +7066,7 @@ void Application::updateWindowTitle() const {
auto accountManager = DependencyManager::get<AccountManager>();
auto isInErrorState = nodeList->getDomainHandler().isInErrorState();
QString buildVersion = " - Kasen Community Edition v0.86.0 K2 - "
QString buildVersion = " - Project Athena v0.86.0 K2 - "
+ (BuildInfo::BUILD_TYPE == BuildInfo::BuildType::Stable ? QString("Version") : QString("Build"))
+ " " + applicationVersion();

View file

@ -288,13 +288,12 @@ Menu::Menu() {
});
// Settings > Entity Script Whitelist
action = addActionToQMenuAndActionHash(settingsMenu, "Entity Script Whitelist");
action = addActionToQMenuAndActionHash(settingsMenu, "Entity Script / QML Whitelist");
connect(action, &QAction::triggered, [] {
auto tablet = DependencyManager::get<TabletScriptingInterface>()->getTablet("com.highfidelity.interface.tablet.system");
auto hmd = DependencyManager::get<HMDScriptingInterface>();
DependencyManager::get<OffscreenUi>()->clearCache();
tablet->pushOntoStack("hifi/dialogs/security/EntityScriptWhitelist.qml");
tablet->pushOntoStack("hifi/dialogs/security/EntityScriptQMLWhitelist.qml");
if (!hmd->getShouldShowTablet()) {
hmd->toggleShouldShowTablet();
@ -808,7 +807,7 @@ Menu::Menu() {
// Help > Report a Bug!
action = addActionToQMenuAndActionHash(helpMenu, "Report a Bug!");
connect(action, &QAction::triggered, qApp, [] {
QDesktopServices::openUrl(QUrl("mailto:support@highfidelity.com"));
QDesktopServices::openUrl(QUrl("https://github.com/kasenvr/hifi-community/issues"));
});
}

View file

@ -181,7 +181,7 @@ namespace MenuOption {
const QString RunningScripts = "Running Scripts...";
const QString RunTimingTests = "Run Timing Tests";
const QString ScriptedMotorControl = "Enable Scripted Motor Control";
const QString EntityScriptWhitelist = "Entity Script Whitelist";
const QString EntityScriptQMLWhitelist = "Entity Script / QML Whitelist";
const QString ShowTrackedObjects = "Show Tracked Objects";
const QString SelfieCamera = "Selfie";
const QString SendWrongDSConnectVersion = "Send wrong DS connect version";

View file

@ -55,7 +55,7 @@ static QStringList HAND_MAPPING_SUFFIXES = {
"HandThumb1",
};
const QUrl PACKAGE_AVATAR_DOCS_BASE_URL = QUrl("https://docs.highfidelity.com/create/avatars/package-avatar.html");
const QUrl PACKAGE_AVATAR_DOCS_BASE_URL = QUrl("https://docs.projectathena.dev/create/avatars/package-avatar.html");
AvatarDoctor::AvatarDoctor(const QUrl& avatarFSTFileUrl) :
_avatarFSTFileUrl(avatarFSTFileUrl) {

View file

@ -95,7 +95,7 @@ public:
static bool isValidNewProjectName(const QString& projectPath, const QString& projectName);
static QString getDefaultProjectsPath() {
return QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + "/High Fidelity Projects";
return QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + "/Project Athena Projects";
}
signals:

View file

@ -3825,7 +3825,7 @@ void MyAvatar::updateActionMotor(float deltaTime) {
}
_actionMotorVelocity = motorSpeed * direction;
} else {
_actionMotorVelocity = direction;
_actionMotorVelocity = sensorToWorldScale * direction;
}
float previousBoomLength = _boomLength;

View file

@ -130,6 +130,10 @@ void FetchSpatialTree::configure(const Config& config) {
}
void FetchSpatialTree::run(const RenderContextPointer& renderContext, const Inputs& inputs, ItemSpatialTree::ItemSelection& outSelection) {
if (!renderContext){
return;
}
// start fresh
outSelection.clear();
@ -142,6 +146,10 @@ void FetchSpatialTree::run(const RenderContextPointer& renderContext, const Inpu
RenderArgs* args = renderContext->args;
auto& scene = renderContext->_scene;
if (!args) {
return;
}
auto queryFrustum = args->getViewFrustum();
// Eventually use a frozen frustum
if (_freezeFrustum) {

View file

@ -16,6 +16,8 @@
#include "ScriptEngine.h"
#include "ScriptEngineLogging.h"
WebSocketClass::WebSocketClass(QScriptEngine* engine, QString url) :
_webSocket(new QWebSocket()),
_engine(engine)
@ -34,10 +36,11 @@ WebSocketClass::WebSocketClass(QScriptEngine* engine, QWebSocket* qWebSocket) :
void WebSocketClass::initialize() {
connect(_webSocket, &QWebSocket::disconnected, this, &WebSocketClass::handleOnClose);
connect(_webSocket, &QWebSocket::textMessageReceived, this, &WebSocketClass::handleOnMessage);
connect(_webSocket, &QWebSocket::binaryMessageReceived, this, &WebSocketClass::handleOnBinaryMessage);
connect(_webSocket, &QWebSocket::connected, this, &WebSocketClass::handleOnOpen);
connect(_webSocket, static_cast<void(QWebSocket::*)(QAbstractSocket::SocketError)>(&QWebSocket::error), this,
&WebSocketClass::handleOnError);
_binaryType = QStringLiteral("blob");
_binaryType = QStringLiteral("arraybuffer");
}
QScriptValue WebSocketClass::constructor(QScriptContext* context, QScriptEngine* engine) {
@ -53,7 +56,12 @@ WebSocketClass::~WebSocketClass() {
}
void WebSocketClass::send(QScriptValue message) {
_webSocket->sendTextMessage(message.toString());
if (message.isObject()) {
QByteArray ba = qscriptvalue_cast<QByteArray>(message);
_webSocket->sendBinaryMessage(ba);
} else {
_webSocket->sendTextMessage(message.toString());
}
}
void WebSocketClass::close() {
@ -97,6 +105,25 @@ void WebSocketClass::handleOnMessage(const QString& message) {
}
}
void WebSocketClass::handleOnBinaryMessage(const QByteArray& message) {
if (_onMessageEvent.isFunction()) {
QScriptValueList args;
QScriptValue arg = _engine->newObject();
QScriptValue data = _engine->newVariant(QVariant::fromValue(message));
QScriptValue ctor = _engine->globalObject().property("ArrayBuffer");
auto array = qscriptvalue_cast<ArrayBufferClass*>(ctor.data());
QScriptValue arrayBuffer;
if (!array) {
qCWarning(scriptengine) << "WebSocketClass::handleOnBinaryMessage !ArrayBuffer";
} else {
arrayBuffer = _engine->newObject(array, data);
}
arg.setProperty("data", arrayBuffer);
args << arg;
_onMessageEvent.call(QScriptValue(), args);
}
}
void WebSocketClass::handleOnOpen() {
if (_onOpenEvent.isFunction()) {
_onOpenEvent.call();

View file

@ -123,6 +123,7 @@ private slots:
void handleOnClose();
void handleOnError(QAbstractSocket::SocketError error);
void handleOnMessage(const QString& message);
void handleOnBinaryMessage(const QByteArray& message);
void handleOnOpen();
};

View file

@ -269,7 +269,11 @@ void VrMenu::insertAction(QAction* before, QAction* action) {
Q_ASSERT(invokeResult);
QObject* result = reinterpret_cast<QObject*>(returnedValue); // returnedValue.value<QObject*>();
Q_ASSERT(result);
bindActionToQmlAction(result, action, _rootMenu);
if ( result ) {
bindActionToQmlAction(result, action, _rootMenu);
} else {
qWarning() << "Failed to find addItem() method in object " << menu << ". Not inserting action " << action;
}
}
class QQuickMenuBase;

View file

@ -39,9 +39,11 @@ if (NOT SERVER_ONLY AND NOT ANDROID)
endif()
# server-side plugins
set(DIR "pcmCodec")
add_subdirectory(${DIR})
set(DIR "hifiCodec")
# set(DIR "pcmCodec")
# add_subdirectory(${DIR})
# set(DIR "hifiCodec")
# add_subdirectory(${DIR})
set(DIR "opusCodec")
add_subdirectory(${DIR})
set(DIR "opusCodec")
add_subdirectory(${DIR})

View file

@ -108,9 +108,11 @@ QString getVrSettingString(const char* section, const char* setting) {
return result;
}
bool isHMDInErrorState = false;
vr::IVRSystem* acquireOpenVrSystem() {
bool hmdPresent = vr::VR_IsHmdPresent();
if (hmdPresent) {
if (hmdPresent && !isHMDInErrorState) {
Lock lock(mutex);
if (!activeHmd) {
#if DEV_BUILD
@ -122,6 +124,14 @@ vr::IVRSystem* acquireOpenVrSystem() {
#if DEV_BUILD
qCDebug(displayplugins) << "OpenVR display: HMD is " << activeHmd << " error is " << eError;
#endif
if (eError == vr::VRInitError_Init_HmdNotFound) {
isHMDInErrorState = true;
activeHmd = nullptr;
#if DEV_BUILD
qCDebug(displayplugins) << "OpenVR: No HMD connected, setting nullptr!";
#endif
}
}
if (activeHmd) {
#if DEV_BUILD

View file

@ -8,7 +8,8 @@
set(TARGET_NAME opusCodec)
setup_hifi_client_server_plugin()
link_hifi_libraries(shared plugins)
link_hifi_libraries(shared audio plugins)
target_opus()
if (BUILD_SERVER)
install_beside_console()

View file

@ -22,6 +22,9 @@
#include <opus/opus_multistream.h>
#include <opus/opus_projection.h>
#include "OpusEncoder.h"
#include "OpusDecoder.h"
#define FRAME_SIZE 960
#define SAMPLE_RATE 48000
#define CHANNELS 2
@ -31,56 +34,41 @@
#define MAX_FRAME_SIZE 6*FRAME_SIZE
#define MAX_PACKET_SIZE 3*1276
const char* OpusCodec::NAME { "opus" };
const char* AthenaOpusCodec::NAME { "opus" };
void OpusCodec::init() {
void AthenaOpusCodec::init() {
}
void OpusCodec::deinit() {
void AthenaOpusCodec::deinit() {
}
bool OpusCodec::activate() {
bool AthenaOpusCodec::activate() {
CodecPlugin::activate();
return true;
}
void OpusCodec::deactivate() {
void AthenaOpusCodec::deactivate() {
CodecPlugin::deactivate();
}
bool OpusCodec::isSupported() const {
bool AthenaOpusCodec::isSupported() const {
return true;
}
class OpusEncoder : public Encoder {
public:
OpusEncoder(int sampleRate, int numChannels) {
}
virtual void encode(const QByteArray& decodedBuffer, QByteArray& encodedBuffer) override {
encodedBuffer.resize(_encodedSize);
}
private:
int _encodedSize;
};
Encoder* OpusCodec::createEncoder(int sampleRate, int numChannels) {
return new OpusEncoder(sampleRate, numChannels);
Encoder* AthenaOpusCodec::createEncoder(int sampleRate, int numChannels) {
return new AthenaOpusEncoder(sampleRate, numChannels);
}
Decoder* OpusCodec::createDecoder(int sampleRate, int numChannels) {
return this;
Decoder* AthenaOpusCodec::createDecoder(int sampleRate, int numChannels) {
return new AthenaOpusDecoder(sampleRate, numChannels);
}
void OpusCodec::releaseEncoder(Encoder* encoder) {
void AthenaOpusCodec::releaseEncoder(Encoder* encoder) {
delete encoder;
}
void OpusCodec::releaseDecoder(Decoder* decoder) {
void AthenaOpusCodec::releaseDecoder(Decoder* decoder) {
delete decoder;
}
}

View file

@ -14,7 +14,7 @@
#include <plugins/CodecPlugin.h>
class OpusCodec : public CodecPlugin, public Encoder, public Decoder {
class AthenaOpusCodec : public CodecPlugin {
Q_OBJECT
public:

View file

@ -17,20 +17,20 @@
#include "OpusCodecManager.h"
class OpusCodecProvider : public QObject, public CodecProvider {
class AthenaOpusCodecProvider : public QObject, public CodecProvider {
Q_OBJECT
Q_PLUGIN_METADATA(IID CodecProvider_iid FILE "plugin.json")
Q_INTERFACES(CodecProvider)
public:
OpusCodecProvider(QObject* parent = nullptr) : QObject(parent) {}
virtual ~OpusCodecProvider() {}
AthenaOpusCodecProvider(QObject* parent = nullptr) : QObject(parent) {}
virtual ~AthenaOpusCodecProvider() {}
virtual CodecPluginList getCodecPlugins() override {
static std::once_flag once;
std::call_once(once, [&] {
CodecPluginPointer opusCodec(new OpusCodec());
CodecPluginPointer opusCodec(new AthenaOpusCodec());
if (opusCodec->isSupported()) {
_codecPlugins.push_back(opusCodec);
}

View file

@ -0,0 +1,123 @@
#include <PerfStat.h>
#include <QtCore/QLoggingCategory>
#include <AudioConstants.h>
#include "OpusDecoder.h"
static QLoggingCategory decoder("AthenaOpusDecoder");
static QString error_to_string(int error) {
switch (error) {
case OPUS_OK:
return "OK";
case OPUS_BAD_ARG:
return "One or more invalid/out of range arguments.";
case OPUS_BUFFER_TOO_SMALL:
return "The mode struct passed is invalid.";
case OPUS_INTERNAL_ERROR:
return "An internal error was detected.";
case OPUS_INVALID_PACKET:
return "The compressed data passed is corrupted.";
case OPUS_UNIMPLEMENTED:
return "Invalid/unsupported request number.";
case OPUS_INVALID_STATE:
return "An encoder or decoder structure is invalid or already freed.";
default:
return QString("Unknown error code: %i").arg(error);
}
}
AthenaOpusDecoder::AthenaOpusDecoder(int sampleRate, int numChannels)
{
int error;
_opus_sample_rate = sampleRate;
_opus_num_channels = numChannels;
_decoder = opus_decoder_create(sampleRate, numChannels, &error);
if ( error != OPUS_OK ) {
qCCritical(decoder) << "Failed to initialize Opus encoder: " << error_to_string(error);
_decoder = nullptr;
return;
}
qCDebug(decoder) << "Opus decoder initialized, sampleRate = " << sampleRate << "; numChannels = " << numChannels;
}
AthenaOpusDecoder::~AthenaOpusDecoder()
{
if ( _decoder )
opus_decoder_destroy(_decoder);
}
void AthenaOpusDecoder::decode(const QByteArray &encodedBuffer, QByteArray &decodedBuffer)
{
assert(_decoder);
PerformanceTimer perfTimer("AthenaOpusDecoder::decode");
// The audio system encodes and decodes always in fixed size chunks
int buffer_size = AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL * static_cast<int>(sizeof(int16_t)) * _opus_num_channels;
decodedBuffer.resize( buffer_size );
int buffer_frames = decodedBuffer.size() / _opus_num_channels / static_cast<int>(sizeof( opus_int16 ));
qCDebug(decoder) << "Opus decode: encodedBytes = " << encodedBuffer.length() << "; decodedBufferBytes = " << decodedBuffer.size() << "; frameCount = " << buffer_frames;
int decoded_frames = opus_decode( _decoder, reinterpret_cast<const unsigned char*>(encodedBuffer.data()), encodedBuffer.length(), reinterpret_cast<opus_int16*>(decodedBuffer.data()), buffer_frames, 0 );
if ( decoded_frames >= 0 ) {
//qCDebug(decoder) << "Decoded " << decoded_frames << " Opus frames, " << buffer_frames << " expected";
if ( decoded_frames < buffer_frames ) {
qCWarning(decoder) << "Opus decoder returned " << decoded_frames << ", but " << buffer_frames << " were expected!";
int start = decoded_frames * static_cast<int>(sizeof(int16_t)) * _opus_num_channels;
memset( &decodedBuffer.data()[start], 0, static_cast<size_t>(decodedBuffer.length() - start));
} else if ( decoded_frames > buffer_frames ) {
// This should never happen
qCCritical(decoder) << "Opus decoder returned " << decoded_frames << ", but only " << buffer_frames << " were expected! Buffer overflow!?";
}
} else {
qCCritical(decoder) << "Failed to decode audio: " << error_to_string(decoded_frames);
decodedBuffer.fill('\0');
}
}
void AthenaOpusDecoder::lostFrame(QByteArray &decodedBuffer)
{
assert(_decoder);
PerformanceTimer perfTimer("AthenaOpusDecoder::lostFrame");
int buffer_size = AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL * static_cast<int>(sizeof(int16_t)) * _opus_num_channels;
decodedBuffer.resize( buffer_size );
int buffer_frames = decodedBuffer.size() / _opus_num_channels / static_cast<int>(sizeof( opus_int16 ));
int decoded_frames = opus_decode( _decoder, nullptr, 0, reinterpret_cast<opus_int16*>(decodedBuffer.data()), buffer_frames, 1 );
if ( decoded_frames >= 0 ) {
//qCDebug(decoder) << "Produced " << decoded_frames << " opus frames from a lost frame, " << buffer_frames << " expected";
if ( decoded_frames < buffer_frames ) {
qCWarning(decoder) << "Opus decoder returned " << decoded_frames << ", but " << buffer_frames << " were expected!";
int start = decoded_frames * static_cast<int>(sizeof(int16_t)) * _opus_num_channels;
memset( &decodedBuffer.data()[start], 0, static_cast<size_t>(decodedBuffer.length() - start));
} else if ( decoded_frames > buffer_frames ) {
// This should never happen
qCCritical(decoder) << "Opus decoder returned " << decoded_frames << ", but only " << buffer_frames << " were expected! Buffer overflow!?";
}
} else {
qCCritical(decoder) << "Failed to decode lost frame: " << error_to_string(decoded_frames);
decodedBuffer.fill('\0');
}
}

View file

@ -0,0 +1,29 @@
#ifndef OPUSDECODER_H
#define OPUSDECODER_H
#include <plugins/CodecPlugin.h>
#include "opus/opus.h"
class AthenaOpusDecoder : public Decoder {
public:
AthenaOpusDecoder(int sampleRate, int numChannels);
~AthenaOpusDecoder() override;
virtual void decode(const QByteArray& encodedBuffer, QByteArray& decodedBuffer) override;
virtual void lostFrame( QByteArray &decodedBuffer) override;
private:
int _encodedSize;
OpusDecoder *_decoder = nullptr;
int _opus_sample_rate = 0;
int _opus_num_channels = 0;
int _decoded_size = 0;
};
#endif // OPUSDECODER_H

View file

@ -0,0 +1,270 @@
#include <PerfStat.h>
#include <QtCore/QLoggingCategory>
#include "OpusEncoder.h"
#include "OpusWrapper.h"
#include "opus/opus.h"
static QLoggingCategory encoder("AthenaOpusEncoder");
static QString error_to_string(int error) {
switch (error) {
case OPUS_OK:
return "OK";
case OPUS_BAD_ARG:
return "One or more invalid/out of range arguments.";
case OPUS_BUFFER_TOO_SMALL:
return "The mode struct passed is invalid.";
case OPUS_INTERNAL_ERROR:
return "An internal error was detected.";
case OPUS_INVALID_PACKET:
return "The compressed data passed is corrupted.";
case OPUS_UNIMPLEMENTED:
return "Invalid/unsupported request number.";
case OPUS_INVALID_STATE:
return "An encoder or decoder structure is invalid or already freed.";
default:
return QString("Unknown error code: %i").arg(error);
}
}
AthenaOpusEncoder::AthenaOpusEncoder(int sampleRate, int numChannels)
{
_opus_sample_rate = sampleRate;
_opus_channels = numChannels;
int error;
_encoder = opus_encoder_create(sampleRate, numChannels, DEFAULT_APPLICATION, &error);
if ( error != OPUS_OK ) {
qCCritical(encoder) << "Failed to initialize Opus encoder: " << error_to_string(error);
_encoder = nullptr;
return;
}
setBitrate(DEFAULT_BITRATE);
setComplexity(DEFAULT_COMPLEXITY);
setApplication(DEFAULT_APPLICATION);
setSignal(DEFAULT_SIGNAL);
qCDebug(encoder) << "Opus encoder initialized, sampleRate = " << sampleRate << "; numChannels = " << numChannels;
}
AthenaOpusEncoder::~AthenaOpusEncoder()
{
opus_encoder_destroy(_encoder);
}
void AthenaOpusEncoder::encode(const QByteArray& decodedBuffer, QByteArray& encodedBuffer) {
PerformanceTimer perfTimer("AthenaOpusEncoder::encode");
assert(_encoder);
encodedBuffer.resize( decodedBuffer.size() );
int frame_size = decodedBuffer.length()/ _opus_channels / static_cast<int>(sizeof(opus_int16));
int bytes = opus_encode(_encoder, reinterpret_cast<const opus_int16*>(decodedBuffer.constData()), frame_size, reinterpret_cast<unsigned char*>(encodedBuffer.data()), encodedBuffer.size() );
if ( bytes >= 0 ) {
//qCDebug(encoder) << "Encoded " << decodedBuffer.length() << " bytes into " << bytes << " opus bytes";
encodedBuffer.resize(bytes);
} else {
encodedBuffer.resize(0);
qCWarning(encoder) << "Error when encoding " << decodedBuffer.length() << " bytes of audio: " << error_to_string(bytes);
}
}
int AthenaOpusEncoder::getComplexity() const
{
assert(_encoder);
int ret;
opus_encoder_ctl(_encoder, OPUS_GET_COMPLEXITY(&ret));
return ret;
}
void AthenaOpusEncoder::setComplexity(int complexity)
{
assert(_encoder);
int ret = opus_encoder_ctl(_encoder, OPUS_SET_COMPLEXITY(complexity));
if ( ret != OPUS_OK )
qCWarning(encoder) << "Error when setting complexity to " << complexity << ": " << error_to_string(ret);
}
int AthenaOpusEncoder::getBitrate() const
{
assert(_encoder);
int ret;
opus_encoder_ctl(_encoder, OPUS_GET_BITRATE(&ret));
return ret;
}
void AthenaOpusEncoder::setBitrate(int bitrate)
{
assert(_encoder);
int ret = opus_encoder_ctl(_encoder, OPUS_SET_BITRATE(bitrate));
if ( ret != OPUS_OK )
qCWarning(encoder) << "Error when setting bitrate to " << bitrate << ": " << error_to_string(ret);
}
int AthenaOpusEncoder::getVBR() const
{
assert(_encoder);
int ret;
opus_encoder_ctl(_encoder, OPUS_GET_VBR(&ret));
return ret;
}
void AthenaOpusEncoder::setVBR(int vbr)
{
assert(_encoder);
int ret = opus_encoder_ctl(_encoder, OPUS_SET_VBR(vbr));
if ( ret != OPUS_OK )
qCWarning(encoder) << "Error when setting VBR to " << vbr << ": " << error_to_string(ret);
}
int AthenaOpusEncoder::getVBRConstraint() const
{
assert(_encoder);
int ret;
opus_encoder_ctl(_encoder, OPUS_GET_VBR_CONSTRAINT(&ret));
return ret;
}
void AthenaOpusEncoder::setVBRConstraint(int vbr_const)
{
assert(_encoder);
int ret = opus_encoder_ctl(_encoder, OPUS_SET_VBR_CONSTRAINT(vbr_const));
if ( ret != OPUS_OK )
qCWarning(encoder) << "Error when setting VBR constraint to " << vbr_const << ": " << error_to_string(ret);
}
int AthenaOpusEncoder::getMaxBandwidth() const
{
assert(_encoder);
int ret;
opus_encoder_ctl(_encoder, OPUS_GET_MAX_BANDWIDTH(&ret));
return ret;
}
void AthenaOpusEncoder::setMaxBandwidth(int maxbw)
{
assert(_encoder);
int ret = opus_encoder_ctl(_encoder, OPUS_SET_MAX_BANDWIDTH(maxbw));
if ( ret != OPUS_OK )
qCWarning(encoder) << "Error when setting max bandwidth to " << maxbw << ": " << error_to_string(ret);
}
int AthenaOpusEncoder::getBandwidth() const
{
assert(_encoder);
int ret;
opus_encoder_ctl(_encoder, OPUS_GET_BANDWIDTH(&ret));
return ret;
}
void AthenaOpusEncoder::setBandwidth(int bw)
{
assert(_encoder);
int ret = opus_encoder_ctl(_encoder, OPUS_SET_BANDWIDTH(bw));
if ( ret != OPUS_OK )
qCWarning(encoder) << "Error when setting bandwidth to " << bw << ": " << error_to_string(ret);
}
int AthenaOpusEncoder::getSignal() const
{
assert(_encoder);
int ret;
opus_encoder_ctl(_encoder, OPUS_GET_SIGNAL(&ret));
return ret;
}
void AthenaOpusEncoder::setSignal(int signal)
{
assert(_encoder);
int ret = opus_encoder_ctl(_encoder, OPUS_SET_SIGNAL(signal));
if ( ret != OPUS_OK )
qCWarning(encoder) << "Error when setting signal to " << signal << ": " << error_to_string(ret);
}
int AthenaOpusEncoder::getApplication() const
{
assert(_encoder);
int ret;
opus_encoder_ctl(_encoder, OPUS_GET_APPLICATION(&ret));
return ret;
}
void AthenaOpusEncoder::setApplication(int app)
{
assert(_encoder);
int ret = opus_encoder_ctl(_encoder, OPUS_SET_APPLICATION(app));
if ( ret != OPUS_OK )
qCWarning(encoder) << "Error when setting application to " << app << ": " << error_to_string(ret);
}
int AthenaOpusEncoder::getLookahead() const
{
assert(_encoder);
int ret;
opus_encoder_ctl(_encoder, OPUS_GET_LOOKAHEAD(&ret));
return ret;
}
int AthenaOpusEncoder::getInbandFEC() const
{
assert(_encoder);
int ret;
opus_encoder_ctl(_encoder, OPUS_GET_INBAND_FEC(&ret));
return ret;
}
void AthenaOpusEncoder::setInbandFEC(int fec)
{
assert(_encoder);
int ret = opus_encoder_ctl(_encoder, OPUS_SET_INBAND_FEC(fec));
if ( ret != OPUS_OK )
qCWarning(encoder) << "Error when setting inband FEC to " << fec << ": " << error_to_string(ret);
}
int AthenaOpusEncoder::getExpectedPacketLossPercent() const
{
assert(_encoder);
int ret;
opus_encoder_ctl(_encoder, OPUS_GET_PACKET_LOSS_PERC(&ret));
return ret;
}
void AthenaOpusEncoder::setExpectedPacketLossPercent(int perc)
{
assert(_encoder);
int ret = opus_encoder_ctl(_encoder, OPUS_SET_PACKET_LOSS_PERC(perc));
if ( ret != OPUS_OK )
qCWarning(encoder) << "Error when setting loss percent to " << perc << ": " << error_to_string(ret);
}
int AthenaOpusEncoder::getDTX() const
{
assert(_encoder);
int ret;
opus_encoder_ctl(_encoder, OPUS_GET_DTX(&ret));
return ret;
}
void AthenaOpusEncoder::setDTX(int dtx)
{
assert(_encoder);
int ret = opus_encoder_ctl(_encoder, OPUS_SET_DTX(dtx));
if ( ret != OPUS_OK )
qCWarning(encoder) << "Error when setting DTX to " << dtx << ": " << error_to_string(ret);
}

View file

@ -0,0 +1,69 @@
#ifndef OPUSENCODER_H
#define OPUSENCODER_H
#include <plugins/CodecPlugin.h>
#include "OpusWrapper.h"
#include "opus/opus.h"
class AthenaOpusEncoder : public Encoder {
public:
const int DEFAULT_BITRATE = 128000;
const int DEFAULT_COMPLEXITY = 10;
const int DEFAULT_APPLICATION = OPUS_APPLICATION_VOIP;
const int DEFAULT_SIGNAL = OPUS_AUTO;
AthenaOpusEncoder(int sampleRate, int numChannels);
~AthenaOpusEncoder() override;
virtual void encode(const QByteArray& decodedBuffer, QByteArray& encodedBuffer) override;
int getComplexity() const;
void setComplexity(int complexity);
int getBitrate() const;
void setBitrate(int bitrate);
int getVBR() const;
void setVBR(int vbr);
int getVBRConstraint() const;
void setVBRConstraint(int vbr_const);
int getMaxBandwidth() const;
void setMaxBandwidth(int maxbw);
int getBandwidth() const;
void setBandwidth(int bw);
int getSignal() const;
void setSignal(int signal);
int getApplication() const;
void setApplication(int app);
int getLookahead() const;
int getInbandFEC() const;
void setInbandFEC(int fec);
int getExpectedPacketLossPercent() const;
void setExpectedPacketLossPercent(int perc);
int getDTX() const;
void setDTX(int dtx);
private:
int _opus_sample_rate = 0;
int _opus_channels = 0;
int _opus_expected_loss = 0;
OpusEncoder *_encoder = nullptr;
};
#endif // OPUSENCODER_H

View file

@ -1,4 +1,4 @@
The High Fidelity JavaScript API lets content creators and developers create new experiences and transform virtual worlds within the High Fidelity metaverse. With it, you can build great content, customize avatars, play audio and so much more.
The Project Athena JavaScript API lets content creators and developers create new experiences and transform virtual worlds within the High Fidelity metaverse. With it, you can build great content, customize avatars, play audio and so much more.
You are most likely to interact with these APIs:
@ -6,4 +6,4 @@ You are most likely to interact with these APIs:
* The **[AvatarList](AvatarList.html)**, **[MyAvatar](MyAvatar.html)**, and **[Avatar](Avatar.html)** namespaces affect your personal avatars, and lets you get information on other people's avatars.
* The **[Script](Script.html)** namespace lets you to connect callbacks from your client to script, such as functionality that is dependent on time (`Script.update`, `Script.setTimeout`, `Script.setInterval`, etc), connect paths relatively to assets (`Script.resolvePath`), refer to other scripts (`Script.require`, `Script.include`), or connect functions to events which occur when the script is turned off (`Script.scriptEnding`).
To learn more about using High Fidelity and exploring the metaverse, visit the [High Fidelity Documentation](https://docs.highfidelity.com).
To learn more about using High Fidelity and exploring the metaverse, visit the [Project Athena Documentation](https://docs.projectathena.dev).

View file

@ -697,7 +697,7 @@ exports.publish = function(taffyData, opts, tutorials) {
var files = find({kind: 'file'});
var packages = find({kind: 'package'});
generate('', 'High Fidelity API Reference',
generate('', 'Project Athena API Reference',
packages.concat(
[{kind: 'mainpage', readme: opts.readme, longname: (opts.mainpagetitle) ? opts.mainpagetitle : 'Main Page'}]
).concat(files),

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

View file

@ -67,6 +67,7 @@ h1
font-size: 3.25rem;
text-align: center;
margin: 50px 25px 25px;
line-height: 100%;
}
h2

View file

@ -12,15 +12,16 @@
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
<link href="images/fav-icon.ico" rel="shortcut icon">
</head>
<body>
<div class="nav-header">
<p><a href="https://www.highfidelity.com"><img src="images/white-logo.png" width="214px" /></a></p>
<p><a href="https://projectathena.io"><img src="images/project-athena-logo.png" width="214px" /></a></p>
<?js if (env.conf.docdash.search) { ?>
<input type="text" class="search-input" id="nav-search" placeholder="Search API Docs ..." />
<?js } ?>
<p><a href="https://docs.highfidelity.com">Looking for <strong>High Fidelity</strong><br /> Documentation?</a></p>
<p><a href="https://docs.projectathena.dev">Looking for <strong>Project Athena</strong><br /> Documentation?</a></p>
</div>
<nav>