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.
We're hiring! We're looking for skilled developers; send your resume to hiring@highfidelity.io
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.
Contributing
===
@ -8,7 +6,7 @@ Contributing
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
@ -22,15 +20,16 @@ Contributing
6. Update your branch
```
git remote add upstream https://github.com/highfidelity/hifi
git pull upstream master
git remote add upstream https://github.com/kasenvr/project-athena
git pull upstream kasen/core
```
Resolve any conflicts that arise with this step.
7. Push to your fork
```
git push origin master
git push origin kasen/core
```
8. Submit a pull request
@ -39,10 +38,10 @@ Contributing
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!
2. Search jobs [on Worklist](https://worklist.net) 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.
2. Search [issues](https://github.com/kasenvr/project-athena/issues) to make sure that somebody has not already reported the same 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.
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.
1. Search [issues](https://github.com/kasenvr/project-athena/issues) to make sure that somebody has not already requested the same feature.
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
Version: 0.3
Version: 0.4
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",
"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

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

View file

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

View file

@ -1366,7 +1366,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
* var METERS_TO_INCHES = 39.3701;
* var entity = Entities.addEntity({
* 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 })),
* rotation: MyAvatar.orientation,
* dimensions: {

View file

@ -105,7 +105,7 @@ public:
* @returns {TabletProxy} The tablet instance.
* @example <caption>Display the High Fidelity home page on the system tablet.</caption>
* 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);

View file

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

View file

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

View file

@ -13,6 +13,7 @@
#include <AudioCodec.h>
#include <AudioConstants.h>
#include <PerfStat.h>
const char* HiFiCodec::NAME { "hifiAC" };
@ -44,6 +45,8 @@ public:
}
virtual void encode(const QByteArray& decodedBuffer, QByteArray& encodedBuffer) override {
PerformanceTimer perfTimer("HiFiEncoder::encode");
encodedBuffer.resize(_encodedSize);
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 {
PerformanceTimer perfTimer("HiFiEncoder::decode");
decodedBuffer.resize(_decodedSize);
AudioDecoder::process((const int16_t*)encodedBuffer.constData(), (int16_t*)decodedBuffer.data(), AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL, true);
}
virtual void lostFrame(QByteArray& decodedBuffer) override {
PerformanceTimer perfTimer("HiFiEncoder::lostFrame");
decodedBuffer.resize(_decodedSize);
// this performs packet loss interpolation
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) {
properties.modelURL = type;
} else if (type === 'Web') {
properties.sourceUrl = 'https://highfidelity.com';
properties.sourceUrl = 'https://projectathena.io';
} else {
properties.color = { red: x / ROWS_X * 255, green: y / ROWS_Y * 255, blue: z / ROWS_Z * 255 };
if (type === 'ParticleEffect') {

View file

@ -39,7 +39,7 @@ var DEFAULT_SCRIPTS_COMBINED = [
var DEFAULT_SCRIPTS_SEPARATE = [
"system/controllers/controllerScripts.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"
];
@ -53,7 +53,9 @@ var MENU_CATEGORY = "Developer > Scripting";
var MENU_ITEM = "Debug defaultScripts.js";
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') {
previousSetting = false;
@ -77,17 +79,30 @@ function loadSeparateDefaults() {
for (var i in DEFAULT_SCRIPTS_SEPARATE) {
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++) {
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) {
shouldLoadCurrentDefaultScript = false;
if (currentRunningScriptObject.url !== scriptItem) {
ScriptDiscoveryService.stopScript(currentRunningScriptObject.url);
} else {
shouldLoadCurrentDefaultScript = false;
}
}
}
if (shouldLoadCurrentDefaultScript) {
Script.load(DEFAULT_SCRIPTS_SEPARATE[i]);
Script.load(scriptItem);
}
}
}
@ -161,7 +176,7 @@ function removeMenuItem() {
}
}
Script.scriptEnding.connect(function() {
Script.scriptEnding.connect(function () {
removeMenuItem();
});

View file

@ -427,7 +427,7 @@ const DEFAULT_ENTITY_PROPERTIES = {
y: 0.9,
z: 0.01
},
sourceUrl: "https://highfidelity.com/",
sourceUrl: "https://projectathena.io/",
dpi: 30,
},
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

@ -4,10 +4,10 @@
<?js if (!env.conf.docdash) { env.conf.docdash = {};} ?>
<meta charset="utf-8">
<title><?js= title ?></title>
<script src="scripts/vue.min.js"></script>
<script src="scripts/vuetify.js"></script>
<script src="scripts/vue.min.js"></script>
<script src="scripts/vuetify.js"></script>
<script src="scripts/prettify/prettify.js"></script>
<script src="scripts/prettify/lang-css.js"></script>
<!--[if lt IE 9]>
@ -15,55 +15,80 @@
<![endif]-->
<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/night.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=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/vuetify.css" rel="stylesheet">
<style>
.v-application--wrap {
min-height: 0 !important;
}
/** Override Vue CSS. */
.theme--dark.v-application {
background: #27343b !important;
}
</style>
<script>
//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'));
if (darkDisabled == null) {
localStorage.setItem('darkDisabled', JSON.stringify(false));
} else {
var nightSheet = document.querySelector('[href="styles/night.css"]');
nightSheet.disabled = darkDisabled;
}
</script>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
<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=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/vuetify.css" rel="stylesheet">
<style>
.v-application--wrap {
min-height: 0 !important;
}
/** Override Vue CSS. */
.theme--dark.v-application {
background: #27343b !important;
}
</style>
<script>
//We are running the check here to preload the theme because it may load the incorrect one first for a split second.
var isLocalStorageSupported = false;
try { // Edge browsing files on local file system doesn't support localStorage.
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 {
var nightSheet = document.querySelector('[href="styles/night.css"]');
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>
<!-- <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">
</head>
<body>
<div class="nav-header">
<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.projectathena.dev">Looking for <strong>Project Athena</strong><br /> Documentation?</a></p>
<div id="app">
<v-app dark>
<v-btn @click="toggleNightMode" text dark>
Toggle
<v-icon class="ml-2">mdi-theme-light-dark</v-icon>
</v-btn>
</v-app>
<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">
<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.projectathena.dev">Looking for <strong>Project Athena</strong><br /> Documentation?</a></p>
<v-btn @click="toggleNightMode" text dark>
<span>Toggle</span>
<v-icon style="margin-left: 5px;">mdi-theme-light-dark</v-icon>
</v-btn>
</div>
<nav>
<?js= this.nav ?>
</nav>
</template>
</div>
</div>
<nav>
<?js= this.nav ?>
</nav>
</v-app>
<div id="main">
<h1 class="page-title"><?js= title ?></h1>
@ -109,30 +134,38 @@
<?js } ?>
<script>
new Vue({
el: '#app',
vuetify: new Vuetify({
theme: {
dark: true,
},
}),
data: () => ({
new Vue({
el: '#vue-menu',
vuetify: new Vuetify({
theme: {
dark: true,
},
}),
data: () => ({
}),
created: function () {
},
methods: {
toggleNightMode: function() {
var darkDisabled = JSON.parse(localStorage.getItem('darkDisabled'));
localStorage.setItem('darkDisabled', JSON.stringify(!darkDisabled));
darkDisabled = !darkDisabled;
var nightSheet = document.querySelector('[href="styles/night.css"]');
nightSheet.disabled = darkDisabled;
}
},
})
}),
created: function () {
},
methods: {
toggleNightMode: function() {
var darkDisabled = JSON.parse(localStorage.getItem('darkDisabled'));
localStorage.setItem('darkDisabled', JSON.stringify(!darkDisabled));
darkDisabled = !darkDisabled;
var nightSheet = document.querySelector('[href="styles/night.css"]');
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;
}
},
})
</script>
<!-- Start Google Analytics Tag -->