Merge branch 'kasen/core' into fix/http-serverless

This commit is contained in:
David Rowe 2020-02-07 11:32:38 +13:00
commit e6c54faaf2
28 changed files with 904 additions and 101 deletions

View file

@ -1,6 +1,4 @@
The project embraces distributed development and if you'd like to help, we'll pay you -- find out more at [Worklist.net](https://worklist.net). If you find a small bug and have a fix, pull requests are welcome. If you'd like to get paid for your work, make sure you report the bug via a job on Worklist.net. The project embraces distributed development and if you'd like to help, it would be greatly appreciated. Just open a pull request with the revisions.
We're hiring! We're looking for skilled developers; send your resume to hiring@highfidelity.io
Contributing Contributing
=== ===
@ -8,7 +6,7 @@ Contributing
2. Clone your fork of the repository locally 2. Clone your fork of the repository locally
``` ```
git clone git://github.com/USERNAME/hifi.git git clone git://github.com/USERNAME/project-athena.git
``` ```
3. Create a new branch 3. Create a new branch
@ -22,15 +20,16 @@ Contributing
6. Update your branch 6. Update your branch
``` ```
git remote add upstream https://github.com/highfidelity/hifi git remote add upstream https://github.com/kasenvr/project-athena
git pull upstream master git pull upstream kasen/core
``` ```
Resolve any conflicts that arise with this step. Resolve any conflicts that arise with this step.
7. Push to your fork 7. Push to your fork
``` ```
git push origin master git push origin kasen/core
``` ```
8. Submit a pull request 8. Submit a pull request
@ -39,10 +38,10 @@ Contributing
Reporting Bugs Reporting Bugs
=== ===
1. Always update to the latest code on master, we make many merges every day and it is possible the bug has already been fixed! 1. Always update to the latest code on master, we make many merges every day and it is possible the bug has already been fixed!
2. Search jobs [on Worklist](https://worklist.net) to make sure that somebody has not already reported the same bug. 2. Search [issues](https://github.com/kasenvr/project-athena/issues) to make sure that somebody has not already reported the same bug.
3. Add a [job on Worklist](https://worklist.net/job/add) including information about your system and how to reproduce the bug. 3. [Add](https://github.com/kasenvr/project-athena/issues/new) your report to the issues list!
Requesting a feature Requesting a Feature
=== ===
1. Search the [the Worklist](https://worklist.net) to make sure that somebody has not already requested the same feature. If you find a matching request, feel free to add any additional comments to the existing issue. 1. Search [issues](https://github.com/kasenvr/project-athena/issues) to make sure that somebody has not already requested the same feature.
2. Add a [job on Worklist](https://worklist.net/job/add) that is labeled as a Feature (and select any other appropriate Labels) and includes a detailed description of your request. 2. [Add](https://github.com/kasenvr/project-athena/issues/new) your request to the issues list!

View file

@ -0,0 +1,13 @@
#
# Created by Michael Bailey on 12/20/2019
# Copyright 2019 Michael Bailey
#
# 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)
find_library(OPUS_LIBRARY_RELEASE NAMES opus PATHS ${VCPKG_INSTALL_ROOT}/lib)
find_library(OPUS_LIBRARY_DEBUG NAMES opus PATHS ${VCPKG_INSTALL_ROOT}/debug/lib)
select_library_configurations(OPUS)
target_link_libraries(${TARGET_NAME} ${OPUS_LIBRARY})
endmacro()

View file

@ -1,4 +1,4 @@
Source: hifi-deps Source: hifi-deps
Version: 0.3 Version: 0.4
Description: Collected dependencies for High Fidelity applications Description: Collected dependencies for High Fidelity applications
Build-Depends: bullet3, draco, etc2comp, glm, nvtt, openexr (!android), openssl (windows), tbb (!android&!osx), zlib, webrtc (!android) Build-Depends: bullet3, draco, etc2comp, glm, nvtt, openexr (!android), openssl (windows), opus, tbb (!android&!osx), zlib, webrtc (!android)

3
cmake/ports/opus/CONTROL Normal file
View file

@ -0,0 +1,3 @@
Source: opus
Version: 1.3.1
Description: Totally open, royalty-free, highly versatile audio codec

View file

@ -0,0 +1,28 @@
include(vcpkg_common_functions)
vcpkg_from_github(
OUT_SOURCE_PATH
SOURCE_PATH
REPO
xiph/opus
REF
e85ed7726db5d677c9c0677298ea0cb9c65bdd23
SHA512
a8c7e5bf383c06f1fdffd44d9b5f658f31eb4800cb59d12da95ddaeb5646f7a7b03025f4663362b888b1374d4cc69154f006ba07b5840ec61ddc1a1af01d6c54
HEAD_REF
master)
vcpkg_configure_cmake(SOURCE_PATH ${SOURCE_PATH} PREFER_NINJA)
vcpkg_install_cmake()
vcpkg_fixup_cmake_targets(CONFIG_PATH lib/cmake/Opus)
vcpkg_copy_pdbs()
file(INSTALL
${SOURCE_PATH}/COPYING
DESTINATION
${CURRENT_PACKAGES_DIR}/share/opus
RENAME copyright)
file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/lib/cmake
${CURRENT_PACKAGES_DIR}/lib/cmake
${CURRENT_PACKAGES_DIR}/debug/include)

View file

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

View file

@ -6,7 +6,7 @@ import controlsUit 1.0
WebView { WebView {
id: webview id: webview
url: "https://highfidelity.com/" url: "https://projectathena.io/"
profile: FileTypeProfile; profile: FileTypeProfile;
property var parentRoot: null property var parentRoot: null

View file

@ -3156,7 +3156,7 @@ void Application::showLoginScreen() {
QJsonObject loginData = {}; QJsonObject loginData = {};
loginData["action"] = "login dialog popped up"; loginData["action"] = "login dialog popped up";
UserActivityLogger::getInstance().logAction("encourageLoginDialog", loginData); UserActivityLogger::getInstance().logAction("encourageLoginDialog", loginData);
_window->setWindowTitle("High Fidelity"); _window->setWindowTitle("Project Athena");
} else { } else {
resumeAfterLoginDialogActionTaken(); resumeAfterLoginDialogActionTaken();
} }

View file

@ -1366,7 +1366,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
* var METERS_TO_INCHES = 39.3701; * var METERS_TO_INCHES = 39.3701;
* var entity = Entities.addEntity({ * var entity = Entities.addEntity({
* type: "Web", * type: "Web",
* sourceUrl: "https://highfidelity.com/", * sourceUrl: "https://projectathena.io/",
* position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0.75, z: -4 })), * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0.75, z: -4 })),
* rotation: MyAvatar.orientation, * rotation: MyAvatar.orientation,
* dimensions: { * dimensions: {

View file

@ -105,7 +105,7 @@ public:
* @returns {TabletProxy} The tablet instance. * @returns {TabletProxy} The tablet instance.
* @example <caption>Display the High Fidelity home page on the system tablet.</caption> * @example <caption>Display the High Fidelity home page on the system tablet.</caption>
* var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); * var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
* tablet.gotoWebScreen("https://highfidelity.com/"); * tablet.gotoWebScreen("https://projectathena.io/");
*/ */
Q_INVOKABLE TabletProxy* getTablet(const QString& tabletId); Q_INVOKABLE TabletProxy* getTablet(const QString& tabletId);

View file

@ -43,6 +43,8 @@ set(DIR "pcmCodec")
add_subdirectory(${DIR}) add_subdirectory(${DIR})
set(DIR "hifiCodec") set(DIR "hifiCodec")
add_subdirectory(${DIR}) add_subdirectory(${DIR})
set(DIR "opusCodec")
add_subdirectory(${DIR})
# example plugins # example plugins
set(DIR "KasenAPIExample") set(DIR "KasenAPIExample")

View file

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

View file

@ -13,6 +13,7 @@
#include <AudioCodec.h> #include <AudioCodec.h>
#include <AudioConstants.h> #include <AudioConstants.h>
#include <PerfStat.h>
const char* HiFiCodec::NAME { "hifiAC" }; const char* HiFiCodec::NAME { "hifiAC" };
@ -44,6 +45,8 @@ public:
} }
virtual void encode(const QByteArray& decodedBuffer, QByteArray& encodedBuffer) override { virtual void encode(const QByteArray& decodedBuffer, QByteArray& encodedBuffer) override {
PerformanceTimer perfTimer("HiFiEncoder::encode");
encodedBuffer.resize(_encodedSize); encodedBuffer.resize(_encodedSize);
AudioEncoder::process((const int16_t*)decodedBuffer.constData(), (int16_t*)encodedBuffer.data(), AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL); AudioEncoder::process((const int16_t*)decodedBuffer.constData(), (int16_t*)encodedBuffer.data(), AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL);
} }
@ -58,11 +61,15 @@ public:
} }
virtual void decode(const QByteArray& encodedBuffer, QByteArray& decodedBuffer) override { virtual void decode(const QByteArray& encodedBuffer, QByteArray& decodedBuffer) override {
PerformanceTimer perfTimer("HiFiEncoder::decode");
decodedBuffer.resize(_decodedSize); decodedBuffer.resize(_decodedSize);
AudioDecoder::process((const int16_t*)encodedBuffer.constData(), (int16_t*)decodedBuffer.data(), AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL, true); AudioDecoder::process((const int16_t*)encodedBuffer.constData(), (int16_t*)decodedBuffer.data(), AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL, true);
} }
virtual void lostFrame(QByteArray& decodedBuffer) override { virtual void lostFrame(QByteArray& decodedBuffer) override {
PerformanceTimer perfTimer("HiFiEncoder::lostFrame");
decodedBuffer.resize(_decodedSize); decodedBuffer.resize(_decodedSize);
// this performs packet loss interpolation // this performs packet loss interpolation
AudioDecoder::process(nullptr, (int16_t*)decodedBuffer.data(), AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL, false); AudioDecoder::process(nullptr, (int16_t*)decodedBuffer.data(), AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL, false);

View file

@ -0,0 +1,16 @@
#
# Created by Michael Bailey on 12/20/2019
# Copyright 2019 Michael Bailey
#
# Distributed under the Apache License, Version 2.0.
# See the accompanying file LICENSE or http:#www.apache.org/licenses/LICENSE-2.0.html
#
set(TARGET_NAME opusCodec)
setup_hifi_client_server_plugin()
link_hifi_libraries(shared audio plugins)
target_opus()
if (BUILD_SERVER)
install_beside_console()
endif ()

View file

@ -0,0 +1,58 @@
//
// opusCodec.cpp
// plugins/opusCodec/src
//
// Created by Michael Bailey on 12/20/2019
// Copyright 2019 Michael Bailey
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "OpusCodecManager.h"
#include <QtCore/QCoreApplication>
#include <PerfStat.h>
#include "OpusEncoder.h"
#include "OpusDecoder.h"
const char* AthenaOpusCodec::NAME { "opus" };
void AthenaOpusCodec::init() {
}
void AthenaOpusCodec::deinit() {
}
bool AthenaOpusCodec::activate() {
CodecPlugin::activate();
return true;
}
void AthenaOpusCodec::deactivate() {
CodecPlugin::deactivate();
}
bool AthenaOpusCodec::isSupported() const {
return true;
}
Encoder* AthenaOpusCodec::createEncoder(int sampleRate, int numChannels) {
return new AthenaOpusEncoder(sampleRate, numChannels);
}
Decoder* AthenaOpusCodec::createDecoder(int sampleRate, int numChannels) {
return new AthenaOpusDecoder(sampleRate, numChannels);
}
void AthenaOpusCodec::releaseEncoder(Encoder* encoder) {
delete encoder;
}
void AthenaOpusCodec::releaseDecoder(Decoder* decoder) {
delete decoder;
}

View file

@ -0,0 +1,42 @@
//
// OpusCodecManager.h
// plugins/opusCodec/src
//
// Created by Michael Bailey on 12/20/2019
// Copyright 2019 Michael Bailey
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi__OpusCodecManager_h
#define hifi__OpusCodecManager_h
#include <plugins/CodecPlugin.h>
class AthenaOpusCodec : public CodecPlugin {
Q_OBJECT
public:
// Plugin functions
bool isSupported() const override;
const QString getName() const override { return NAME; }
void init() override;
void deinit() override;
/// Called when a plugin is being activated for use. May be called multiple times.
bool activate() override;
/// Called when a plugin is no longer being used. May be called multiple times.
void deactivate() override;
virtual Encoder* createEncoder(int sampleRate, int numChannels) override;
virtual Decoder* createDecoder(int sampleRate, int numChannels) override;
virtual void releaseEncoder(Encoder* encoder) override;
virtual void releaseDecoder(Decoder* decoder) override;
private:
static const char* NAME;
};
#endif // hifi__opusCodecManager_h

View file

@ -0,0 +1,45 @@
//
// Created by Michael Bailey on 12/20/2019
// Copyright 2019 Michael Bailey
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <mutex>
#include <QtCore/QObject>
#include <QtCore/QtPlugin>
#include <QtCore/QStringList>
#include <plugins/RuntimePlugin.h>
#include <plugins/CodecPlugin.h>
#include "OpusCodecManager.h"
class AthenaOpusCodecProvider : public QObject, public CodecProvider {
Q_OBJECT
Q_PLUGIN_METADATA(IID CodecProvider_iid FILE "plugin.json")
Q_INTERFACES(CodecProvider)
public:
AthenaOpusCodecProvider(QObject* parent = nullptr) : QObject(parent) {}
virtual ~AthenaOpusCodecProvider() {}
virtual CodecPluginList getCodecPlugins() override {
static std::once_flag once;
std::call_once(once, [&] {
CodecPluginPointer opusCodec(new AthenaOpusCodec());
if (opusCodec->isSupported()) {
_codecPlugins.push_back(opusCodec);
}
});
return _codecPlugins;
}
private:
CodecPluginList _codecPlugins;
};
#include "OpusCodecProvider.moc"

View file

@ -0,0 +1,131 @@
//
// OpusCodecManager.h
// plugins/opusCodec/src
//
// Copyright 2020 Dale Glass
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#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;
_opusSampleRate = sampleRate;
_opusNumChannels = 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 bufferSize = AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL * static_cast<int>(sizeof(int16_t))
* _opusNumChannels;
decodedBuffer.resize(bufferSize);
int bufferFrames = decodedBuffer.size() / _opusNumChannels / static_cast<int>(sizeof(opus_int16));
int decoded_frames = opus_decode(_decoder, reinterpret_cast<const unsigned char*>(encodedBuffer.data()),
encodedBuffer.length(), reinterpret_cast<opus_int16*>(decodedBuffer.data()), bufferFrames, 0);
if (decoded_frames >= 0) {
if (decoded_frames < bufferFrames) {
qCWarning(decoder) << "Opus decoder returned " << decoded_frames << ", but " << bufferFrames
<< " were expected!";
int start = decoded_frames * static_cast<int>(sizeof(int16_t)) * _opusNumChannels;
memset( &decodedBuffer.data()[start], 0, static_cast<size_t>(decodedBuffer.length() - start));
} else if (decoded_frames > bufferFrames) {
// This should never happen
qCCritical(decoder) << "Opus decoder returned " << decoded_frames << ", but only " << bufferFrames
<< " 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 bufferSize = AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL * static_cast<int>(sizeof(int16_t))
* _opusNumChannels;
decodedBuffer.resize(bufferSize);
int bufferFrames = decodedBuffer.size() / _opusNumChannels / static_cast<int>(sizeof(opus_int16));
int decoded_frames = opus_decode(_decoder, nullptr, 0, reinterpret_cast<opus_int16*>(decodedBuffer.data()),
bufferFrames, 1);
if (decoded_frames >= 0) {
if ( decoded_frames < bufferFrames ) {
qCWarning(decoder) << "Opus decoder returned " << decoded_frames << ", but " << bufferFrames
<< " were expected!";
int start = decoded_frames * static_cast<int>(sizeof(int16_t)) * _opusNumChannels;
memset( &decodedBuffer.data()[start], 0, static_cast<size_t>(decodedBuffer.length() - start));
} else if (decoded_frames > bufferFrames) {
// This should never happen
qCCritical(decoder) << "Opus decoder returned " << decoded_frames << ", but only " << bufferFrames
<< " 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,39 @@
//
// OpusCodecManager.h
// plugins/opusCodec/src
//
// Copyright 2020 Dale Glass
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#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 _opusSampleRate = 0;
int _opusNumChannels = 0;
int _decodedSize = 0;
};
#endif // OPUSDECODER_H

View file

@ -0,0 +1,273 @@
//
// OpusCodecManager.h
// plugins/opusCodec/src
//
// Copyright 2020 Dale Glass
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <PerfStat.h>
#include <QtCore/QLoggingCategory>
#include <opus/opus.h>
#include "OpusEncoder.h"
static QLoggingCategory encoder("AthenaOpusEncoder");
static QString errorToString(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) {
_opusSampleRate = sampleRate;
_opusChannels = numChannels;
int error;
_encoder = opus_encoder_create(sampleRate, numChannels, DEFAULT_APPLICATION, &error);
if (error != OPUS_OK) {
qCCritical(encoder) << "Failed to initialize Opus encoder: " << errorToString(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 frameSize = decodedBuffer.length() / _opusChannels / static_cast<int>(sizeof(opus_int16));
int bytes = opus_encode(_encoder, reinterpret_cast<const opus_int16*>(decodedBuffer.constData()), frameSize,
reinterpret_cast<unsigned char*>(encodedBuffer.data()), encodedBuffer.size() );
if (bytes >= 0) {
encodedBuffer.resize(bytes);
} else {
encodedBuffer.resize(0);
qCWarning(encoder) << "Error when encoding " << decodedBuffer.length() << " bytes of audio: "
<< errorToString(bytes);
}
}
int AthenaOpusEncoder::getComplexity() const {
assert(_encoder);
int returnValue;
opus_encoder_ctl(_encoder, OPUS_GET_COMPLEXITY(&returnValue));
return returnValue;
}
void AthenaOpusEncoder::setComplexity(int complexity) {
assert(_encoder);
int returnValue = opus_encoder_ctl(_encoder, OPUS_SET_COMPLEXITY(complexity));
if (returnValue != OPUS_OK) {
qCWarning(encoder) << "Error when setting complexity to " << complexity << ": " << errorToString(returnValue);
}
}
int AthenaOpusEncoder::getBitrate() const {
assert(_encoder);
int returnValue;
opus_encoder_ctl(_encoder, OPUS_GET_BITRATE(&returnValue));
return returnValue;
}
void AthenaOpusEncoder::setBitrate(int bitrate) {
assert(_encoder);
int errorCode = opus_encoder_ctl(_encoder, OPUS_SET_BITRATE(bitrate));
if (errorCode != OPUS_OK) {
qCWarning(encoder) << "Error when setting bitrate to " << bitrate << ": " << errorToString(errorCode);
}
}
int AthenaOpusEncoder::getVBR() const {
assert(_encoder);
int returnValue;
opus_encoder_ctl(_encoder, OPUS_GET_VBR(&returnValue));
return returnValue;
}
void AthenaOpusEncoder::setVBR(int vbr) {
assert(_encoder);
int errorCode = opus_encoder_ctl(_encoder, OPUS_SET_VBR(vbr));
if (errorCode != OPUS_OK) {
qCWarning(encoder) << "Error when setting VBR to " << vbr << ": " << errorToString(errorCode);
}
}
int AthenaOpusEncoder::getVBRConstraint() const {
assert(_encoder);
int returnValue;
opus_encoder_ctl(_encoder, OPUS_GET_VBR_CONSTRAINT(&returnValue));
return returnValue;
}
void AthenaOpusEncoder::setVBRConstraint(int vbr_const) {
assert(_encoder);
int errorCode = opus_encoder_ctl(_encoder, OPUS_SET_VBR_CONSTRAINT(vbr_const));
if (errorCode != OPUS_OK) {
qCWarning(encoder) << "Error when setting VBR constraint to " << vbr_const << ": " << errorToString(errorCode);
}
}
int AthenaOpusEncoder::getMaxBandwidth() const {
assert(_encoder);
int returnValue;
opus_encoder_ctl(_encoder, OPUS_GET_MAX_BANDWIDTH(&returnValue));
return returnValue;
}
void AthenaOpusEncoder::setMaxBandwidth(int maxBandwidth) {
assert(_encoder);
int errorCode = opus_encoder_ctl(_encoder, OPUS_SET_MAX_BANDWIDTH(maxBandwidth));
if (errorCode != OPUS_OK) {
qCWarning(encoder) << "Error when setting max bandwidth to " << maxBandwidth << ": " << errorToString(errorCode);
}
}
int AthenaOpusEncoder::getBandwidth() const {
assert(_encoder);
int bandwidth;
opus_encoder_ctl(_encoder, OPUS_GET_BANDWIDTH(&bandwidth));
return bandwidth;
}
void AthenaOpusEncoder::setBandwidth(int bandwidth) {
assert(_encoder);
int errorCode = opus_encoder_ctl(_encoder, OPUS_SET_BANDWIDTH(bandwidth));
if (errorCode != OPUS_OK) {
qCWarning(encoder) << "Error when setting bandwidth to " << bandwidth << ": " << errorToString(errorCode);
}
}
int AthenaOpusEncoder::getSignal() const {
assert(_encoder);
int signal;
opus_encoder_ctl(_encoder, OPUS_GET_SIGNAL(&signal));
return signal;
}
void AthenaOpusEncoder::setSignal(int signal) {
assert(_encoder);
int errorCode = opus_encoder_ctl(_encoder, OPUS_SET_SIGNAL(signal));
if (errorCode != OPUS_OK) {
qCWarning(encoder) << "Error when setting signal to " << signal << ": " << errorToString(errorCode);
}
}
int AthenaOpusEncoder::getApplication() const {
assert(_encoder);
int applicationValue;
opus_encoder_ctl(_encoder, OPUS_GET_APPLICATION(&applicationValue));
return applicationValue;
}
void AthenaOpusEncoder::setApplication(int application) {
assert(_encoder);
int errorCode = opus_encoder_ctl(_encoder, OPUS_SET_APPLICATION(application));
if (errorCode != OPUS_OK) {
qCWarning(encoder) << "Error when setting application to " << application << ": " << errorToString(errorCode);
}
}
int AthenaOpusEncoder::getLookahead() const {
assert(_encoder);
int lookAhead;
opus_encoder_ctl(_encoder, OPUS_GET_LOOKAHEAD(&lookAhead));
return lookAhead;
}
int AthenaOpusEncoder::getInbandFEC() const {
assert(_encoder);
int fec;
opus_encoder_ctl(_encoder, OPUS_GET_INBAND_FEC(&fec));
return fec;
}
void AthenaOpusEncoder::setInbandFEC(int inBandFEC) {
assert(_encoder);
int errorCode = opus_encoder_ctl(_encoder, OPUS_SET_INBAND_FEC(inBandFEC));
if (errorCode != OPUS_OK) {
qCWarning(encoder) << "Error when setting inband FEC to " << inBandFEC << ": " << errorToString(errorCode);
}
}
int AthenaOpusEncoder::getExpectedPacketLossPercentage() const {
assert(_encoder);
int lossPercentage;
opus_encoder_ctl(_encoder, OPUS_GET_PACKET_LOSS_PERC(&lossPercentage));
return lossPercentage;
}
void AthenaOpusEncoder::setExpectedPacketLossPercentage(int percentage) {
assert(_encoder);
int errorCode = opus_encoder_ctl(_encoder, OPUS_SET_PACKET_LOSS_PERC(percentage));
if (errorCode != OPUS_OK) {
qCWarning(encoder) << "Error when setting loss percent to " << percentage << ": " << errorToString(errorCode);
}
}
int AthenaOpusEncoder::getDTX() const {
assert(_encoder);
int dtx;
opus_encoder_ctl(_encoder, OPUS_GET_DTX(&dtx));
return dtx;
}
void AthenaOpusEncoder::setDTX(int dtx) {
assert(_encoder);
int errorCode = opus_encoder_ctl(_encoder, OPUS_SET_DTX(dtx));
if (errorCode != OPUS_OK) {
qCWarning(encoder) << "Error when setting DTX to " << dtx << ": " << errorToString(errorCode);
}
}

View file

@ -0,0 +1,78 @@
//
// OpusCodecManager.h
// plugins/opusCodec/src
//
// Copyright 2020 Dale Glass
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef OPUSENCODER_H
#define OPUSENCODER_H
#include <plugins/CodecPlugin.h>
#include <opus/opus.h>
class AthenaOpusEncoder : public Encoder {
public:
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 vbrConstraint);
int getMaxBandwidth() const;
void setMaxBandwidth(int maxBandwidth);
int getBandwidth() const;
void setBandwidth(int bandwidth);
int getSignal() const;
void setSignal(int signal);
int getApplication() const;
void setApplication(int application);
int getLookahead() const;
int getInbandFEC() const;
void setInbandFEC(int inBandFEC);
int getExpectedPacketLossPercentage() const;
void setExpectedPacketLossPercentage(int percentage);
int getDTX() const;
void setDTX(int dtx);
private:
const int DEFAULT_BITRATE = 128000;
const int DEFAULT_COMPLEXITY = 10;
const int DEFAULT_APPLICATION = OPUS_APPLICATION_VOIP;
const int DEFAULT_SIGNAL = OPUS_AUTO;
int _opusSampleRate = 0;
int _opusChannels = 0;
int _opusExpectedLoss = 0;
OpusEncoder* _encoder = nullptr;
};
#endif // OPUSENCODER_H

View file

@ -0,0 +1,4 @@
{
"name": "Opus Codec",
"version": 1
}

View file

@ -114,7 +114,7 @@ Script.setInterval(function () {
if (isModel) { if (isModel) {
properties.modelURL = type; properties.modelURL = type;
} else if (type === 'Web') { } else if (type === 'Web') {
properties.sourceUrl = 'https://highfidelity.com'; properties.sourceUrl = 'https://projectathena.io';
} else { } else {
properties.color = { red: x / ROWS_X * 255, green: y / ROWS_Y * 255, blue: z / ROWS_Z * 255 }; properties.color = { red: x / ROWS_X * 255, green: y / ROWS_Y * 255, blue: z / ROWS_Z * 255 };
if (type === 'ParticleEffect') { if (type === 'ParticleEffect') {

View file

@ -39,7 +39,7 @@ var DEFAULT_SCRIPTS_COMBINED = [
var DEFAULT_SCRIPTS_SEPARATE = [ var DEFAULT_SCRIPTS_SEPARATE = [
"system/controllers/controllerScripts.js", "system/controllers/controllerScripts.js",
"communityModules/notificationCore/notificationCore.js", "communityModules/notificationCore/notificationCore.js",
"communityModules/chat/FloofChat.js" {"stable": "communityModules/chat/FloofChat.js", "beta": "https://content.fluffy.ws/scripts/chat/FloofChat.js"}
//"system/chat.js" //"system/chat.js"
]; ];
@ -53,7 +53,9 @@ var MENU_CATEGORY = "Developer > Scripting";
var MENU_ITEM = "Debug defaultScripts.js"; var MENU_ITEM = "Debug defaultScripts.js";
var SETTINGS_KEY = '_debugDefaultScriptsIsChecked'; var SETTINGS_KEY = '_debugDefaultScriptsIsChecked';
var previousSetting = Settings.getValue(SETTINGS_KEY); var SETTINGS_KEY_BETA = '_betaDefaultScriptsIsChecked';
var previousSetting = Settings.getValue(SETTINGS_KEY, false);
var previousSettingBeta = Settings.getValue(SETTINGS_KEY_BETA, false);
if (previousSetting === '' || previousSetting === false || previousSetting === 'false') { if (previousSetting === '' || previousSetting === false || previousSetting === 'false') {
previousSetting = false; previousSetting = false;
@ -77,17 +79,30 @@ function loadSeparateDefaults() {
for (var i in DEFAULT_SCRIPTS_SEPARATE) { for (var i in DEFAULT_SCRIPTS_SEPARATE) {
var shouldLoadCurrentDefaultScript = true; var shouldLoadCurrentDefaultScript = true;
var scriptItem = DEFAULT_SCRIPTS_SEPARATE[i];
if (typeof scriptItem === "object") {
if (previousSettingBeta) {
console.log("Loading Beta item " + scriptItem.beta);
scriptItem = scriptItem.beta;
} else {
scriptItem = scriptItem.stable;
}
}
for (var j = 0; j < currentlyRunningScripts.length; j++) { for (var j = 0; j < currentlyRunningScripts.length; j++) {
var currentRunningScriptObject = currentlyRunningScripts[j]; var currentRunningScriptObject = currentlyRunningScripts[j];
var currentDefaultScriptName = DEFAULT_SCRIPTS_SEPARATE[i].substr((DEFAULT_SCRIPTS_SEPARATE[i].lastIndexOf("/") + 1), DEFAULT_SCRIPTS_SEPARATE[i].length); var currentDefaultScriptName = scriptItem.substr((scriptItem.lastIndexOf("/") + 1), scriptItem.length);
if (currentDefaultScriptName === currentRunningScriptObject.name) { if (currentDefaultScriptName === currentRunningScriptObject.name) {
if (currentRunningScriptObject.url !== scriptItem) {
ScriptDiscoveryService.stopScript(currentRunningScriptObject.url);
} else {
shouldLoadCurrentDefaultScript = false; shouldLoadCurrentDefaultScript = false;
} }
} }
}
if (shouldLoadCurrentDefaultScript) { if (shouldLoadCurrentDefaultScript) {
Script.load(DEFAULT_SCRIPTS_SEPARATE[i]); Script.load(scriptItem);
} }
} }
} }

View file

@ -427,7 +427,7 @@ const DEFAULT_ENTITY_PROPERTIES = {
y: 0.9, y: 0.9,
z: 0.01 z: 0.01
}, },
sourceUrl: "https://highfidelity.com/", sourceUrl: "https://projectathena.io/",
dpi: 30, dpi: 30,
}, },
ParticleEffect: { ParticleEffect: {

View file

@ -0,0 +1,17 @@
.nav-header {
display: none;
}
nav {
display: none !important;
}
section {
margin-right: 0px !important;
}
#main {
margin-left: 15px !important;
margin-right: 15px !important;
overflow: auto;
}

View file

@ -16,6 +16,8 @@
<link type="text/css" rel="stylesheet" href="styles/prettify.css"> <link type="text/css" rel="stylesheet" href="styles/prettify.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
<link type="text/css" rel="stylesheet" href="styles/night.css"> <link type="text/css" rel="stylesheet" href="styles/night.css">
<link type="text/css" rel="stylesheet" href="styles/responsive.css">
<link type="text/css" rel="stylesheet" href="styles/main.css">
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Material+Icons|Material+Icons+Outlined|Material+Icons+Two+Tone|Material+Icons+Round|Material+Icons+Sharp" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Material+Icons|Material+Icons+Outlined|Material+Icons+Two+Tone|Material+Icons+Round|Material+Icons+Sharp" rel="stylesheet">
<link href="styles/materialdesignicons.min.css" rel="stylesheet"> <link href="styles/materialdesignicons.min.css" rel="stylesheet">
@ -32,38 +34,61 @@
</style> </style>
<script> <script>
//We are running the check here to preload the theme because it may load the incorrect one first for a split second. //We are running the check here to preload the theme because it may load the incorrect one first for a split second.
var darkDisabled = JSON.parse(localStorage.getItem('darkDisabled')); var isLocalStorageSupported = false;
if (darkDisabled == null) { try { // Edge browsing files on local file system doesn't support localStorage.
localStorage.setItem('darkDisabled', JSON.stringify(false)); if (localStorage) {
isLocalStorageSupported = true;
}
} catch (e) {
// nop
}
var defaultDarkDisabled = false;
var darkDisabled = isLocalStorageSupported ? JSON.parse(localStorage.getItem('darkDisabled')) : defaultDarkDisabled;
if (darkDisabled === null) {
localStorage.setItem('darkDisabled', JSON.stringify(defaultDarkDisabled));
} else { } else {
var nightSheet = document.querySelector('[href="styles/night.css"]'); var nightSheet = document.querySelector('[href="styles/night.css"]');
nightSheet.disabled = darkDisabled; nightSheet.disabled = darkDisabled;
} }
var defaultResponsiveDisabled = true;
var responsiveDisabled =
isLocalStorageSupported ? JSON.parse(localStorage.getItem('responsiveDisabled')) : defaultResponsiveDisabled;
if (responsiveDisabled === null) {
localStorage.setItem('responsiveDisabled', JSON.stringify(defaultResponsiveDisabled));
} else {
var responsiveSheet = document.querySelector('[href="styles/responsive.css"]');
responsiveSheet.disabled = responsiveDisabled;
}
</script> </script>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui"> <!-- <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui"> -->
<link href="images/fav-icon.ico" rel="shortcut icon"> <link href="images/fav-icon.ico" rel="shortcut icon">
</head> </head>
<body> <body>
<v-app dark>
<div id="vue-menu">
<template>
<v-btn @click="toggleResponsive" fab large dark style="position: fixed; right: 15px; top: 15px;">
<v-icon class="ml-4">mdi-backburger</v-icon>
</v-btn>
<div class="nav-header"> <div class="nav-header">
<p><a href="https://projectathena.io"><img src="images/project-athena-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) { ?> <?js if (env.conf.docdash.search) { ?>
<input type="text" class="search-input" id="nav-search" placeholder="Search API Docs ..." /> <input type="text" class="search-input" id="nav-search" placeholder="Search API Docs ..." />
<?js } ?> <?js } ?>
<p><a href="https://docs.projectathena.dev">Looking for <strong>Project Athena</strong><br /> Documentation?</a></p> <p><a href="https://docs.projectathena.dev">Looking for <strong>Project Athena</strong><br /> Documentation?</a></p>
<div id="app">
<v-app dark>
<v-btn @click="toggleNightMode" text dark> <v-btn @click="toggleNightMode" text dark>
Toggle <span>Toggle</span>
<v-icon class="ml-2">mdi-theme-light-dark</v-icon> <v-icon style="margin-left: 5px;">mdi-theme-light-dark</v-icon>
</v-btn> </v-btn>
</v-app>
</div> </div>
</div>
<nav> <nav>
<?js= this.nav ?> <?js= this.nav ?>
</nav> </nav>
</template>
</div>
</v-app>
<div id="main"> <div id="main">
<h1 class="page-title"><?js= title ?></h1> <h1 class="page-title"><?js= title ?></h1>
@ -110,7 +135,7 @@
<script> <script>
new Vue({ new Vue({
el: '#app', el: '#vue-menu',
vuetify: new Vuetify({ vuetify: new Vuetify({
theme: { theme: {
dark: true, dark: true,
@ -130,6 +155,14 @@
var nightSheet = document.querySelector('[href="styles/night.css"]'); var nightSheet = document.querySelector('[href="styles/night.css"]');
nightSheet.disabled = darkDisabled; nightSheet.disabled = darkDisabled;
},
toggleResponsive: function() {
var responsiveDisabled = JSON.parse(localStorage.getItem('responsiveDisabled'));
localStorage.setItem('responsiveDisabled', JSON.stringify(!responsiveDisabled));
responsiveDisabled = !responsiveDisabled;
var responsiveSheet = document.querySelector('[href="styles/responsive.css"]');
responsiveSheet.disabled = responsiveDisabled;
} }
}, },
}) })