Merge branch 'master' of https://github.com/highfidelity/hifi into metavoxels

This commit is contained in:
Andrzej Kapolka 2014-07-07 11:09:17 -07:00
commit fb64d22171
39 changed files with 630 additions and 114 deletions

4
.gitignore vendored
View file

@ -50,5 +50,9 @@ interface/external/faceplus/*
interface/external/priovr/*
!interface/external/priovr/readme.txt
# Ignore RtMidi
interface/external/rtmidi/*
!interface/external/rtmidi/readme.txt
# Ignore interfaceCache for Linux users
interface/interfaceCache/

View file

@ -210,12 +210,12 @@ void Agent::run() {
NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkReply *reply = networkAccessManager.get(QNetworkRequest(scriptURL));
QNetworkDiskCache* cache = new QNetworkDiskCache(&networkAccessManager);
QNetworkDiskCache* cache = new QNetworkDiskCache();
QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
cache->setCacheDirectory(!cachePath.isEmpty() ? cachePath : "agentCache");
QMetaObject::invokeMethod(&networkAccessManager, "setCache",
Qt::BlockingQueuedConnection,
Q_ARG(QAbstractNetworkCache*, cache));
cache->moveToThread(networkAccessManager.thread());
networkAccessManager.setCache(cache);
qDebug() << "Downloading script at" << scriptURL.toString();
@ -270,4 +270,5 @@ void Agent::run() {
void Agent::aboutToFinish() {
_scriptEngine.stop();
NetworkAccessManager::getInstance().clearAccessCache();
}

View file

@ -89,6 +89,10 @@ AudioMixer::~AudioMixer() {
delete _listenerUnattenuatedZone;
}
const float ATTENUATION_BEGINS_AT_DISTANCE = 1.0f;
const float ATTENUATION_AMOUNT_PER_DOUBLING_IN_DISTANCE = 0.18f;
const float ATTENUATION_EPSILON_DISTANCE = 0.1f;
void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuffer* bufferToAdd,
AvatarAudioRingBuffer* listeningNodeBuffer) {
float bearingRelativeAngleToSource = 0.0f;
@ -104,7 +108,7 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf
glm::vec3 relativePosition = bufferToAdd->getPosition() - listeningNodeBuffer->getPosition();
float distanceBetween = glm::length(relativePosition);
if (distanceBetween < EPSILON) {
distanceBetween = EPSILON;
}
@ -121,6 +125,12 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf
shouldAttenuate = !bufferToAdd->getListenerUnattenuatedZone()->contains(listeningNodeBuffer->getPosition());
}
if (bufferToAdd->getType() == PositionalAudioRingBuffer::Injector) {
attenuationCoefficient *= reinterpret_cast<InjectedAudioRingBuffer*>(bufferToAdd)->getAttenuationRatio();
}
shouldAttenuate = shouldAttenuate && distanceBetween > ATTENUATION_EPSILON_DISTANCE;
if (shouldAttenuate) {
glm::quat inverseOrientation = glm::inverse(listeningNodeBuffer->getOrientation());
@ -128,9 +138,7 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf
float radius = 0.0f;
if (bufferToAdd->getType() == PositionalAudioRingBuffer::Injector) {
InjectedAudioRingBuffer* injectedBuffer = (InjectedAudioRingBuffer*) bufferToAdd;
radius = injectedBuffer->getRadius();
attenuationCoefficient *= injectedBuffer->getAttenuationRatio();
radius = reinterpret_cast<InjectedAudioRingBuffer*>(bufferToAdd)->getRadius();
}
if (radius == 0 || (distanceSquareToSource > radius * radius)) {
@ -155,7 +163,7 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf
const float OFF_AXIS_ATTENUATION_FORMULA_STEP = (1 - MAX_OFF_AXIS_ATTENUATION) / 2.0f;
float offAxisCoefficient = MAX_OFF_AXIS_ATTENUATION +
(OFF_AXIS_ATTENUATION_FORMULA_STEP * (angleOfDelivery / PI_OVER_TWO));
(OFF_AXIS_ATTENUATION_FORMULA_STEP * (angleOfDelivery / PI_OVER_TWO));
// multiply the current attenuation coefficient by the calculated off axis coefficient
attenuationCoefficient *= offAxisCoefficient;
@ -163,19 +171,18 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf
glm::vec3 rotatedSourcePosition = inverseOrientation * relativePosition;
const float DISTANCE_SCALE = 2.5f;
const float GEOMETRIC_AMPLITUDE_SCALAR = 0.3f;
const float DISTANCE_LOG_BASE = 2.5f;
const float DISTANCE_SCALE_LOG = logf(DISTANCE_SCALE) / logf(DISTANCE_LOG_BASE);
// calculate the distance coefficient using the distance to this node
float distanceCoefficient = powf(GEOMETRIC_AMPLITUDE_SCALAR,
DISTANCE_SCALE_LOG +
(0.5f * logf(distanceSquareToSource) / logf(DISTANCE_LOG_BASE)) - 1);
distanceCoefficient = std::min(1.0f, distanceCoefficient);
// multiply the current attenuation coefficient by the distance coefficient
attenuationCoefficient *= distanceCoefficient;
if (distanceBetween >= ATTENUATION_BEGINS_AT_DISTANCE) {
// calculate the distance coefficient using the distance to this node
float distanceCoefficient = 1 - (logf(distanceBetween / ATTENUATION_BEGINS_AT_DISTANCE) / logf(2.0f)
* ATTENUATION_AMOUNT_PER_DOUBLING_IN_DISTANCE);
if (distanceCoefficient < 0) {
distanceCoefficient = 0;
}
// multiply the current attenuation coefficient by the distance coefficient
attenuationCoefficient *= distanceCoefficient;
}
// project the rotated source position vector onto the XZ plane
rotatedSourcePosition.y = 0.0f;

View file

@ -101,8 +101,7 @@ int AudioMixerClientData::parseData(const QByteArray& packet) {
if (!matchingInjectedRingBuffer) {
// we don't have a matching injected audio ring buffer, so add it
matchingInjectedRingBuffer = new InjectedAudioRingBuffer(streamIdentifier,
AudioMixer::getUseDynamicJitterBuffers());
matchingInjectedRingBuffer = new InjectedAudioRingBuffer(streamIdentifier, AudioMixer::getUseDynamicJitterBuffers());
_ringBuffers.push_back(matchingInjectedRingBuffer);
}

View file

@ -216,9 +216,13 @@ int OctreeInboundPacketProcessor::sendNackPackets() {
}
const SharedNodePointer& destinationNode = NodeList::getInstance()->getNodeHash().value(nodeUUID);
const QSet<unsigned short int>& missingSequenceNumbers = nodeStats.getIncomingEditSequenceNumberStats().getMissingSet();
// retrieve sequence number stats of node, prune its missing set
SequenceNumberStats& sequenceNumberStats = nodeStats.getIncomingEditSequenceNumberStats();
sequenceNumberStats.pruneMissingSet();
// construct nack packet(s) for this node
const QSet<unsigned short int>& missingSequenceNumbers = sequenceNumberStats.getMissingSet();
int numSequenceNumbersAvailable = missingSequenceNumbers.size();
QSet<unsigned short int>::const_iterator missingSequenceNumberIterator = missingSequenceNumbers.constBegin();
while (numSequenceNumbersAvailable > 0) {

View file

@ -35,6 +35,7 @@ public:
{ return _totalElementsInPacket == 0 ? 0 : _totalLockWaitTime / _totalElementsInPacket; }
const SequenceNumberStats& getIncomingEditSequenceNumberStats() const { return _incomingEditSequenceNumberStats; }
SequenceNumberStats& getIncomingEditSequenceNumberStats() { return _incomingEditSequenceNumberStats; }
void trackInboundPacket(unsigned short int incomingSequence, quint64 transitTime,
int editsInPacket, quint64 processTime, quint64 lockWaitTime);

View file

@ -42,7 +42,7 @@ OctreeQueryNode::OctreeQueryNode() :
_lastRootTimestamp(0),
_myPacketType(PacketTypeUnknown),
_isShuttingDown(false),
_sentPacketHistory(1000)
_sentPacketHistory()
{
}

View file

@ -0,0 +1,33 @@
#
# FindRtMidd.cmake
#
# Try to find the RtMidi library
#
# You can provide a RTMIDI_ROOT_DIR which contains lib and include directories
#
# Once done this will define
#
# RTMIDI_FOUND - system found RtMidi
# RTMIDI_INCLUDE_DIRS - the RtMidi include directory
# RTMIDI_CPP - Include this with src to use RtMidi
#
# Created on 6/30/2014 by Stephen Birarda
# Copyright 2014 High Fidelity, Inc.
#
# Distributed under the Apache License, Version 2.0.
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
#
if (RTMIDI_LIBRARIES AND RTMIDI_INCLUDE_DIRS)
# in cache already
set(RTMIDI_FOUND TRUE)
else ()
set(RTMIDI_SEARCH_DIRS "${RTMIDI_ROOT_DIR}" "$ENV{HIFI_LIB_DIR}/rtmidi")
find_path(RTMIDI_INCLUDE_DIR RtMidi.h PATH_SUFFIXES include HINTS ${RTMIDI_SEARCH_DIRS})
find_file(RTMIDI_CPP NAMES RtMidi.cpp PATH_SUFFIXES src HINTS ${RTMIDI_SEARCH_DIRS})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(RTMIDI DEFAULT_MSG RTMIDI_INCLUDE_DIR RTMIDI_CPP)
endif ()

View file

@ -0,0 +1,32 @@
//
// animationStateExample.js
// examples
//
// Created by Brad Hefta-Gaub on 7/3/14.
// Copyright 2014 High Fidelity, Inc.
//
// This is an example script that runs in a loop and displays a counter to the log
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
//
var count = 0;
function displayAnimationDetails(deltaTime) {
print("count =" + count + " deltaTime=" + deltaTime);
count++;
var animationDetails = MyAvatar.getAnimationDetailsByRole("idle");
print("animationDetails.frameIndex=" + animationDetails.frameIndex);
}
function scriptEnding() {
print("SCRIPT ENDNG!!!\n");
}
// register the call back so it fires before each data send
Script.update.connect(displayAnimationDetails);
// register our scriptEnding callback
Script.scriptEnding.connect(scriptEnding);

View file

@ -18,6 +18,7 @@ set(LIBOVR_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/oculus")
set(PRIOVR_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/priovr")
set(SIXENSE_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/Sixense")
set(VISAGE_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/visage")
set(RTMIDI_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/rtmidi")
find_package(Qt5LinguistTools REQUIRED)
find_package(Qt5LinguistToolsMacros)
@ -110,6 +111,16 @@ if (APPLE)
SET(INTERFACE_SRCS ${INTERFACE_SRCS} "${CMAKE_CURRENT_SOURCE_DIR}/interface.icns")
endif()
# RtMidi for scripted MIDI control
find_package(RtMidi)
if (RTMIDI_FOUND AND NOT DISABLE_RTMIDI)
add_definitions(-DHAVE_RTMIDI)
include_directories(SYSTEM ${RTMIDI_INCLUDE_DIR})
set(INTERFACE_SRCS ${INTERFACE_SRCS} "${RTMIDI_CPP}")
endif ()
# create the executable, make it a bundle on OS X
add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS} ${QM})
@ -143,75 +154,82 @@ find_package(Qxmpp)
# include the Sixense library for Razer Hydra if available
if (SIXENSE_FOUND AND NOT DISABLE_SIXENSE)
add_definitions(-DHAVE_SIXENSE)
include_directories(SYSTEM "${SIXENSE_INCLUDE_DIRS}")
if (APPLE OR UNIX)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${SIXENSE_INCLUDE_DIRS}")
endif (APPLE OR UNIX)
target_link_libraries(${TARGET_NAME} "${SIXENSE_LIBRARIES}")
add_definitions(-DHAVE_SIXENSE)
include_directories(SYSTEM "${SIXENSE_INCLUDE_DIRS}")
if (APPLE OR UNIX)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${SIXENSE_INCLUDE_DIRS}")
endif (APPLE OR UNIX)
target_link_libraries(${TARGET_NAME} "${SIXENSE_LIBRARIES}")
endif (SIXENSE_FOUND AND NOT DISABLE_SIXENSE)
# likewise with Visage library for webcam feature tracking
if (VISAGE_FOUND AND NOT DISABLE_VISAGE)
add_definitions(-DHAVE_VISAGE -DVISAGE_STATIC)
include_directories(SYSTEM "${VISAGE_INCLUDE_DIRS}")
if (APPLE)
add_definitions(-DMAC_OS_X)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-comment")
include_directories(SYSTEM "${VISAGE_INCLUDE_DIRS}")
find_library(AVFoundation AVFoundation)
find_library(CoreMedia CoreMedia)
find_library(NEW_STD_LIBRARY libc++.dylib /usr/lib/)
target_link_libraries(${TARGET_NAME} ${AVFoundation} ${CoreMedia} ${NEW_STD_LIBRARY})
endif (APPLE)
target_link_libraries(${TARGET_NAME} "${VISAGE_LIBRARIES}")
add_definitions(-DHAVE_VISAGE -DVISAGE_STATIC)
include_directories(SYSTEM "${VISAGE_INCLUDE_DIRS}")
if (APPLE)
add_definitions(-DMAC_OS_X)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-comment")
include_directories(SYSTEM "${VISAGE_INCLUDE_DIRS}")
find_library(AVFoundation AVFoundation)
find_library(CoreMedia CoreMedia)
find_library(NEW_STD_LIBRARY libc++.dylib /usr/lib/)
target_link_libraries(${TARGET_NAME} ${AVFoundation} ${CoreMedia} ${NEW_STD_LIBRARY})
endif (APPLE)
target_link_libraries(${TARGET_NAME} "${VISAGE_LIBRARIES}")
endif (VISAGE_FOUND AND NOT DISABLE_VISAGE)
# and with Faceplus library, also for webcam feature tracking
if (FACEPLUS_FOUND AND NOT DISABLE_FACEPLUS)
add_definitions(-DHAVE_FACEPLUS)
include_directories(SYSTEM "${FACEPLUS_INCLUDE_DIRS}")
target_link_libraries(${TARGET_NAME} "${FACEPLUS_LIBRARIES}")
add_definitions(-DHAVE_FACEPLUS)
include_directories(SYSTEM "${FACEPLUS_INCLUDE_DIRS}")
target_link_libraries(${TARGET_NAME} "${FACEPLUS_LIBRARIES}")
endif (FACEPLUS_FOUND AND NOT DISABLE_FACEPLUS)
# and with LibOVR for Oculus Rift
if (LIBOVR_FOUND AND NOT DISABLE_LIBOVR)
add_definitions(-DHAVE_LIBOVR)
include_directories(SYSTEM "${LIBOVR_INCLUDE_DIRS}")
add_definitions(-DHAVE_LIBOVR)
include_directories(SYSTEM "${LIBOVR_INCLUDE_DIRS}")
if (APPLE OR UNIX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${LIBOVR_INCLUDE_DIRS}")
endif ()
if (APPLE OR UNIX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${LIBOVR_INCLUDE_DIRS}")
endif ()
if (WIN32)
target_link_libraries(${TARGET_NAME} optimized "${LIBOVR_RELEASE_LIBRARIES}" debug "${LIBOVR_DEBUG_LIBRARIES}")
else()
target_link_libraries(${TARGET_NAME} "${LIBOVR_LIBRARIES}")
endif()
if (WIN32)
target_link_libraries(${TARGET_NAME} optimized "${LIBOVR_RELEASE_LIBRARIES}" debug "${LIBOVR_DEBUG_LIBRARIES}")
else ()
target_link_libraries(${TARGET_NAME} "${LIBOVR_LIBRARIES}")
endif ()
endif (LIBOVR_FOUND AND NOT DISABLE_LIBOVR)
# and with PrioVR library
if (PRIOVR_FOUND AND NOT DISABLE_PRIOVR)
add_definitions(-DHAVE_PRIOVR)
include_directories(SYSTEM "${PRIOVR_INCLUDE_DIRS}")
target_link_libraries(${TARGET_NAME} "${PRIOVR_LIBRARIES}")
add_definitions(-DHAVE_PRIOVR)
include_directories(SYSTEM "${PRIOVR_INCLUDE_DIRS}")
target_link_libraries(${TARGET_NAME} "${PRIOVR_LIBRARIES}")
endif (PRIOVR_FOUND AND NOT DISABLE_PRIOVR)
# and with SDL for joysticks
if (SDL_FOUND AND NOT DISABLE_SDL)
add_definitions(-DHAVE_SDL)
include_directories(SYSTEM "${SDL_INCLUDE_DIR}")
target_link_libraries(${TARGET_NAME} "${SDL_LIBRARY}")
add_definitions(-DHAVE_SDL)
include_directories(SYSTEM "${SDL_INCLUDE_DIR}")
target_link_libraries(${TARGET_NAME} "${SDL_LIBRARY}")
endif (SDL_FOUND AND NOT DISABLE_SDL)
# and with qxmpp for chat
if (QXMPP_FOUND AND NOT DISABLE_QXMPP)
add_definitions(-DHAVE_QXMPP -DQXMPP_STATIC)
include_directories(SYSTEM ${QXMPP_INCLUDE_DIR})
add_definitions(-DHAVE_QXMPP -DQXMPP_STATIC)
include_directories(SYSTEM ${QXMPP_INCLUDE_DIR})
target_link_libraries(${TARGET_NAME} "${QXMPP_LIBRARY}")
target_link_libraries(${TARGET_NAME} "${QXMPP_LIBRARY}")
endif (QXMPP_FOUND AND NOT DISABLE_QXMPP)
# link CoreMIDI if we're using RtMidi
if (RTMIDI_FOUND AND APPLE)
find_library(CoreMIDI CoreMIDI)
add_definitions(-D__MACOSX_CORE__)
target_link_libraries(${TARGET_NAME} ${CoreMIDI})
endif()
# include headers for interface and InterfaceConfig.
include_directories("${PROJECT_SOURCE_DIR}/src" "${PROJECT_BINARY_DIR}/includes")

41
interface/external/rtmidi/readme.txt vendored Normal file
View file

@ -0,0 +1,41 @@
Instructions for adding the RtMidi library to Interface
Stephen Birarda, June 30, 2014
1. Download the RtMidi tarball from High Fidelity S3.
http://highfidelity-public.s3.amazonaws.com/dependencies/rtmidi-2.1.0.tar.gz
2. Copy RtMidi.h to externals/rtmidi/include.
3. Copy RtMidi.cpp to externals/rtmidi/src
4. Delete your build directory, run cmake and build, and you should be all set.
=========================
RtMidi: realtime MIDI i/o C++ classes<BR>
Copyright (c) 2003-2014 Gary P. Scavone
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
Any person wishing to distribute modifications to the Software is
asked to send the modifications to the original developer so that
they can be incorporated into the canonical version. This is,
however, not a binding provision of this license.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -70,6 +70,7 @@
#include "Menu.h"
#include "ModelUploader.h"
#include "Util.h"
#include "devices/MIDIManager.h"
#include "devices/OculusManager.h"
#include "devices/TV3DManager.h"
#include "renderer/ProgramObject.h"
@ -315,11 +316,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkDiskCache* cache = new QNetworkDiskCache(&networkAccessManager);
// Make sure cache on same thread than its parent (NetworkAccessManager)
QNetworkDiskCache* cache = new QNetworkDiskCache();
cache->moveToThread(networkAccessManager.thread());
cache->setParent(&networkAccessManager);
cache->setCacheDirectory(!cachePath.isEmpty() ? cachePath : "interfaceCache");
QMetaObject::invokeMethod(&networkAccessManager, "setCache",
Qt::BlockingQueuedConnection,
Q_ARG(QAbstractNetworkCache*, cache));
networkAccessManager.setCache(cache);
ResourceCache::setRequestLimit(3);
@ -396,6 +400,12 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
OAuthWebViewHandler::addHighFidelityRootCAToSSLConfig();
_trayIcon->show();
#ifdef HAVE_RTMIDI
// setup the MIDIManager
MIDIManager& midiManagerInstance = MIDIManager::getInstance();
midiManagerInstance.openDefaultPort();
#endif
}
Application::~Application() {
@ -2184,11 +2194,11 @@ int Application::sendNackPackets() {
_octreeSceneStatsLock.unlock();
continue;
}
OctreeSceneStats& stats = _octreeServerSceneStats[nodeUUID];
// make copy of missing sequence numbers from stats
const QSet<OCTREE_PACKET_SEQUENCE> missingSequenceNumbers =
stats.getIncomingOctreeSequenceNumberStats().getMissingSet();
// get sequence number stats of node, prune its missing set, and make a copy of the missing set
SequenceNumberStats& sequenceNumberStats = _octreeServerSceneStats[nodeUUID].getIncomingOctreeSequenceNumberStats();
sequenceNumberStats.pruneMissingSet();
const QSet<OCTREE_PACKET_SEQUENCE> missingSequenceNumbers = sequenceNumberStats.getMissingSet();
_octreeSceneStatsLock.unlock();
@ -3625,6 +3635,10 @@ ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScript
scriptEngine->registerGlobalObject("AnimationCache", &_animationCache);
scriptEngine->registerGlobalObject("AudioReflector", &_audioReflector);
scriptEngine->registerGlobalObject("Account", AccountScriptingInterface::getInstance());
#ifdef HAVE_RTMIDI
scriptEngine->registerGlobalObject("MIDI", &MIDIManager::getInstance());
#endif
QThread* workerThread = new QThread(this);

View file

@ -67,7 +67,7 @@ Audio::Audio(int16_t initialJitterBufferSamples, QObject* parent) :
_proceduralAudioOutput(NULL),
_proceduralOutputDevice(NULL),
_inputRingBuffer(0),
_ringBuffer(NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL),
_ringBuffer(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO),
_isStereoInput(false),
_averagedLatency(0.0),
_measuredJitter(0),
@ -93,7 +93,7 @@ Audio::Audio(int16_t initialJitterBufferSamples, QObject* parent) :
_processSpatialAudio(false),
_spatialAudioStart(0),
_spatialAudioFinish(0),
_spatialAudioRingBuffer(NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL, true), // random access mode
_spatialAudioRingBuffer(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO, true), // random access mode
_scopeEnabled(false),
_scopeEnabledPause(false),
_scopeInputOffset(0),

View file

@ -149,13 +149,19 @@ void DatagramProcessor::processDatagrams() {
break;
}
case PacketTypeVoxelEditNack:
application->_voxelEditSender.processNackPacket(incomingPacket);
if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableNackPackets)) {
application->_voxelEditSender.processNackPacket(incomingPacket);
}
break;
case PacketTypeParticleEditNack:
application->_particleEditSender.processNackPacket(incomingPacket);
if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableNackPackets)) {
application->_particleEditSender.processNackPacket(incomingPacket);
}
break;
case PacketTypeModelEditNack:
application->_modelEditSender.processNackPacket(incomingPacket);
if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableNackPackets)) {
application->_modelEditSender.processNackPacket(incomingPacket);
}
break;
default:
nodeList->processNodeData(senderSockAddr, incomingPacket);

View file

@ -551,6 +551,40 @@ void MyAvatar::stopAnimation(const QString& url) {
}
}
AnimationDetails MyAvatar::getAnimationDetailsByRole(const QString& role) {
AnimationDetails result;
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "getAnimationDetailsByRole", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(AnimationDetails, result),
Q_ARG(const QString&, role));
return result;
}
foreach (const AnimationHandlePointer& handle, _skeletonModel.getRunningAnimations()) {
if (handle->getRole() == role) {
result = handle->getAnimationDetails();
break;
}
}
return result;
}
AnimationDetails MyAvatar::getAnimationDetails(const QString& url) {
AnimationDetails result;
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "getAnimationDetails", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(AnimationDetails, result),
Q_ARG(const QString&, url));
return result;
}
foreach (const AnimationHandlePointer& handle, _skeletonModel.getRunningAnimations()) {
if (handle->getURL() == url) {
result = handle->getAnimationDetails();
break;
}
}
return result;
}
void MyAvatar::saveData(QSettings* settings) {
settings->beginGroup("Avatar");

View file

@ -83,6 +83,9 @@ public:
/// Stops an animation identified by its role.
Q_INVOKABLE void stopAnimationByRole(const QString& role);
Q_INVOKABLE AnimationDetails getAnimationDetailsByRole(const QString& role);
Q_INVOKABLE AnimationDetails getAnimationDetails(const QString& url);
// get/set avatar data
void saveData(QSettings* settings);

View file

@ -0,0 +1,68 @@
//
// MIDIManager.cpp
//
//
// Created by Stephen Birarda on 2014-06-30.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QtCore/QDebug>
#include "MIDIManager.h"
#ifdef HAVE_RTMIDI
MIDIManager& MIDIManager::getInstance() {
static MIDIManager sharedInstance;
return sharedInstance;
}
void MIDIManager::midiCallback(double deltaTime, std::vector<unsigned char>* message, void* userData) {
MIDIEvent callbackEvent;
callbackEvent.deltaTime = deltaTime;
callbackEvent.type = message->at(0);
if (message->size() > 1) {
callbackEvent.data1 = message->at(1);
}
if (message->size() > 2) {
callbackEvent.data2 = message->at(2);
}
emit getInstance().midiEvent(callbackEvent);
}
MIDIManager::~MIDIManager() {
delete _midiInput;
}
const int DEFAULT_MIDI_PORT = 0;
void MIDIManager::openDefaultPort() {
if (!_midiInput) {
_midiInput = new RtMidiIn();
if (_midiInput->getPortCount() > 0) {
qDebug() << "MIDIManager opening port" << DEFAULT_MIDI_PORT;
_midiInput->openPort(DEFAULT_MIDI_PORT);
// don't ignore sysex, timing, or active sensing messages
_midiInput->ignoreTypes(false, false, false);
_midiInput->setCallback(&MIDIManager::midiCallback);
} else {
qDebug() << "MIDIManager openDefaultPort called but there are no ports available.";
delete _midiInput;
_midiInput = NULL;
}
}
}
#endif

View file

@ -0,0 +1,56 @@
//
// MIDIManager.h
// interface/src/devices
//
// Created by Stephen Birarda on 2014-06-30.
// Copyright 2014 High Fidelity, Inc.
//
// 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_MIDIManager_h
#define hifi_MIDIManager_h
#ifdef HAVE_RTMIDI
#include <QtCore/QObject>
#include <QtScript/QScriptEngine>
#include <MIDIEvent.h>
#include <RtMidi.h>
class MIDIManager : public QObject {
Q_OBJECT
Q_PROPERTY(unsigned int NoteOn READ NoteOn)
Q_PROPERTY(unsigned int NoteOff READ NoteOff)
Q_PROPERTY(unsigned int ModWheel READ ModWheel)
Q_PROPERTY(unsigned int PitchWheel READ PitchWheel)
public:
static MIDIManager& getInstance();
static void midiCallback(double deltaTime, std::vector<unsigned char>* message, void* userData);
~MIDIManager();
void openDefaultPort();
bool hasDevice() const { return !!_midiInput; }
public slots:
unsigned int NoteOn() const { return 144; }
unsigned int NoteOff() const { return 128; }
unsigned int ModWheel() const { return 176; }
unsigned int PitchWheel() const { return 224; }
signals:
void midiEvent(const MIDIEvent& event);
private:
RtMidiIn* _midiInput;
};
#endif
#endif // hifi_MIDIManager_h

View file

@ -71,6 +71,16 @@ void SixenseManager::setFilter(bool filter) {
void SixenseManager::update(float deltaTime) {
#ifdef HAVE_SIXENSE
// if the controllers haven't been moved in a while, disable
const unsigned int MOVEMENT_DISABLE_SECONDS = 3;
if (usecTimestampNow() - _lastMovement > (MOVEMENT_DISABLE_SECONDS * USECS_PER_SECOND)) {
Hand* hand = Application::getInstance()->getAvatar()->getHand();
for (std::vector<PalmData>::iterator it = hand->getPalms().begin(); it != hand->getPalms().end(); it++) {
it->setActive(false);
}
_lastMovement = usecTimestampNow();
}
if (sixenseGetNumActiveControllers() == 0) {
_hydrasConnected = false;
return;
@ -154,6 +164,11 @@ void SixenseManager::update(float deltaTime) {
// no latency.
float velocityFilter = glm::clamp(1.0f - glm::length(rawVelocity), 0.0f, 1.0f);
palm->setRawPosition(palm->getRawPosition() * velocityFilter + position * (1.0f - velocityFilter));
// adjustment for hydra controllers fit into hands
float sign = (i == 0) ? -1.0f : 1.0f;
rotation *= glm::angleAxis(sign * PI/4.0f, glm::vec3(0.0f, 0.0f, 1.0f));
palm->setRawRotation(safeMix(palm->getRawRotation(), rotation, 1.0f - velocityFilter));
// use the velocity to determine whether there's any movement (if the hand isn't new)
@ -180,14 +195,6 @@ void SixenseManager::update(float deltaTime) {
if (numActiveControllers == 2) {
updateCalibration(controllers);
}
// if the controllers haven't been moved in a while, disable
const unsigned int MOVEMENT_DISABLE_SECONDS = 3;
if (usecTimestampNow() - _lastMovement > (MOVEMENT_DISABLE_SECONDS * USECS_PER_SECOND)) {
for (std::vector<PalmData>::iterator it = hand->getPalms().begin(); it != hand->getPalms().end(); it++) {
it->setActive(false);
}
}
#endif // HAVE_SIXENSE
}

View file

@ -1701,6 +1701,13 @@ AnimationHandle::AnimationHandle(Model* model) :
_running(false) {
}
AnimationDetails AnimationHandle::getAnimationDetails() const {
AnimationDetails details(_role, _url, _fps, _priority, _loop, _hold,
_startAutomatically, _firstFrame, _lastFrame, _running, _frameIndex);
return details;
}
void AnimationHandle::simulate(float deltaTime) {
_frameIndex += deltaTime * _fps;

View file

@ -354,6 +354,11 @@ public:
void setRunning(bool running);
bool isRunning() const { return _running; }
void setFrameIndex(float frameIndex) { _frameIndex = glm::clamp(_frameIndex, _firstFrame, _lastFrame); }
float getFrameIndex() const { return _frameIndex; }
AnimationDetails getAnimationDetails() const;
signals:
void runningChanged(bool running);

View file

@ -102,3 +102,39 @@ void Animation::downloadFinished(QNetworkReply* reply) {
QThreadPool::globalInstance()->start(new AnimationReader(_self, reply));
}
AnimationDetails::AnimationDetails() :
role(), url(), fps(0.0f), priority(0.0f), loop(false), hold(false),
startAutomatically(false), firstFrame(0.0f), lastFrame(0.0f), running(false), frameIndex(0.0f)
{
}
AnimationDetails::AnimationDetails(QString role, QUrl url, float fps, float priority, bool loop,
bool hold, bool startAutomatically, float firstFrame, float lastFrame, bool running, float frameIndex) :
role(role), url(url), fps(fps), priority(priority), loop(loop), hold(hold),
startAutomatically(startAutomatically), firstFrame(firstFrame), lastFrame(lastFrame),
running(running), frameIndex(frameIndex)
{
}
QScriptValue animationDetailsToScriptValue(QScriptEngine* engine, const AnimationDetails& details) {
QScriptValue obj = engine->newObject();
obj.setProperty("role", details.role);
obj.setProperty("url", details.url.toString());
obj.setProperty("fps", details.fps);
obj.setProperty("priority", details.priority);
obj.setProperty("loop", details.loop);
obj.setProperty("hold", details.hold);
obj.setProperty("startAutomatically", details.startAutomatically);
obj.setProperty("firstFrame", details.firstFrame);
obj.setProperty("lastFrame", details.lastFrame);
obj.setProperty("running", details.running);
obj.setProperty("frameIndex", details.frameIndex);
return obj;
}
void animationDetailsFromScriptValue(const QScriptValue& object, AnimationDetails& details) {
// nothing for now...
}

View file

@ -12,6 +12,9 @@
#ifndef hifi_AnimationCache_h
#define hifi_AnimationCache_h
#include <QScriptEngine>
#include <QScriptValue>
#include <ResourceCache.h>
#include <FBXReader.h>
@ -68,4 +71,28 @@ private:
bool _isValid;
};
class AnimationDetails {
public:
AnimationDetails();
AnimationDetails(QString role, QUrl url, float fps, float priority, bool loop,
bool hold, bool startAutomatically, float firstFrame, float lastFrame, bool running, float frameIndex);
QString role;
QUrl url;
float fps;
float priority;
bool loop;
bool hold;
bool startAutomatically;
float firstFrame;
float lastFrame;
bool running;
float frameIndex;
};
Q_DECLARE_METATYPE(AnimationDetails);
QScriptValue animationDetailsToScriptValue(QScriptEngine* engine, const AnimationDetails& event);
void animationDetailsFromScriptValue(const QScriptValue& object, AnimationDetails& event);
#endif // hifi_AnimationCache_h

View file

@ -19,10 +19,11 @@
#include "AudioRingBuffer.h"
AudioRingBuffer::AudioRingBuffer(int numFrameSamples, bool randomAccessMode) :
AudioRingBuffer::AudioRingBuffer(int numFrameSamples, bool randomAccessMode, int numFramesCapacity) :
NodeData(),
_overflowCount(0),
_sampleCapacity(numFrameSamples * RING_BUFFER_LENGTH_FRAMES),
_frameCapacity(numFramesCapacity),
_sampleCapacity(numFrameSamples * numFramesCapacity),
_isFull(false),
_numFrameSamples(numFrameSamples),
_isStarved(true),
@ -48,6 +49,8 @@ AudioRingBuffer::~AudioRingBuffer() {
}
void AudioRingBuffer::reset() {
_overflowCount = 0;
_isFull = false;
_endOfLastWrite = _buffer;
_nextOutput = _buffer;
_isStarved = true;
@ -55,13 +58,13 @@ void AudioRingBuffer::reset() {
void AudioRingBuffer::resizeForFrameSize(int numFrameSamples) {
delete[] _buffer;
_sampleCapacity = numFrameSamples * RING_BUFFER_LENGTH_FRAMES;
_sampleCapacity = numFrameSamples * _frameCapacity;
_numFrameSamples = numFrameSamples;
_buffer = new int16_t[_sampleCapacity];
if (_randomAccessMode) {
memset(_buffer, 0, _sampleCapacity * sizeof(int16_t));
}
_nextOutput = _buffer;
_endOfLastWrite = _buffer;
reset();
}
int AudioRingBuffer::parseData(const QByteArray& packet) {

View file

@ -31,15 +31,15 @@ const int NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL = NETWORK_BUFFER_LENGTH_BYTE
const unsigned int BUFFER_SEND_INTERVAL_USECS = floorf((NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL
/ (float) SAMPLE_RATE) * 1000 * 1000);
const short RING_BUFFER_LENGTH_FRAMES = 10;
const int MAX_SAMPLE_VALUE = std::numeric_limits<int16_t>::max();
const int MIN_SAMPLE_VALUE = std::numeric_limits<int16_t>::min();
const int DEFAULT_RING_BUFFER_FRAME_CAPACITY = 10;
class AudioRingBuffer : public NodeData {
Q_OBJECT
public:
AudioRingBuffer(int numFrameSamples, bool randomAccessMode = false);
AudioRingBuffer(int numFrameSamples, bool randomAccessMode = false, int numFramesCapacity = DEFAULT_RING_BUFFER_FRAME_CAPACITY);
~AudioRingBuffer();
void reset();
@ -84,6 +84,7 @@ protected:
int _overflowCount; /// how many times has the ring buffer has overwritten old data
int _frameCapacity;
int _sampleCapacity;
bool _isFull;
int _numFrameSamples;

View file

@ -20,7 +20,7 @@
#include "InjectedAudioRingBuffer.h"
InjectedAudioRingBuffer::InjectedAudioRingBuffer(const QUuid& streamIdentifier, bool dynamicJitterBuffer) :
PositionalAudioRingBuffer(PositionalAudioRingBuffer::Injector, /* isStereo=*/ false , dynamicJitterBuffer),
PositionalAudioRingBuffer(PositionalAudioRingBuffer::Injector, false, dynamicJitterBuffer),
_streamIdentifier(streamIdentifier),
_radius(0.0f),
_attenuationRatio(0)

View file

@ -85,10 +85,10 @@ quint64 InterframeTimeGapStats::getWindowMaxGap() {
}
PositionalAudioRingBuffer::PositionalAudioRingBuffer(PositionalAudioRingBuffer::Type type,
bool isStereo, bool dynamicJitterBuffers) :
PositionalAudioRingBuffer::PositionalAudioRingBuffer(PositionalAudioRingBuffer::Type type, bool isStereo, bool dynamicJitterBuffers) :
AudioRingBuffer(isStereo ? NETWORK_BUFFER_LENGTH_SAMPLES_STEREO : NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL),
AudioRingBuffer(isStereo ? NETWORK_BUFFER_LENGTH_SAMPLES_STEREO : NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL,
false, AUDIOMIXER_INBOUND_RING_BUFFER_FRAME_CAPACITY),
_type(type),
_position(0.0f, 0.0f, 0.0f),
_orientation(0.0f, 0.0f, 0.0f, 0.0f),
@ -98,7 +98,7 @@ PositionalAudioRingBuffer::PositionalAudioRingBuffer(PositionalAudioRingBuffer::
_isStereo(isStereo),
_listenerUnattenuatedZone(NULL),
_desiredJitterBufferFrames(1),
_currentJitterBufferFrames(0),
_currentJitterBufferFrames(-1),
_dynamicJitterBuffers(dynamicJitterBuffers)
{
}
@ -216,8 +216,8 @@ bool PositionalAudioRingBuffer::shouldBeAddedToMix() {
// if the buffer doesn't have a full frame of samples to take for mixing, it is starved
_isStarved = true;
// set to 0 to indicate the jitter buffer is starved
_currentJitterBufferFrames = 0;
// set to -1 to indicate the jitter buffer is starved
_currentJitterBufferFrames = -1;
// reset our _shouldOutputStarveDebug to true so the next is printed
_shouldOutputStarveDebug = true;
@ -261,7 +261,7 @@ void PositionalAudioRingBuffer::updateDesiredJitterBufferFrames() {
if (_desiredJitterBufferFrames < 1) {
_desiredJitterBufferFrames = 1;
}
const int maxDesired = RING_BUFFER_LENGTH_FRAMES - 1;
const int maxDesired = _frameCapacity - 1;
if (_desiredJitterBufferFrames > maxDesired) {
_desiredJitterBufferFrames = maxDesired;
}

View file

@ -43,6 +43,8 @@ private:
bool _newWindowMaxGapAvailable;
};
const int AUDIOMIXER_INBOUND_RING_BUFFER_FRAME_CAPACITY = 100;
class PositionalAudioRingBuffer : public AudioRingBuffer {
public:
enum Type {
@ -103,6 +105,11 @@ protected:
int _desiredJitterBufferFrames;
int _currentJitterBufferFrames;
bool _dynamicJitterBuffers;
// extra stats
int _starveCount;
int _silentFramesDropped;
};
#endif // hifi_PositionalAudioRingBuffer_h

View file

@ -10,6 +10,7 @@
//
#include <QMetaObject>
#include <QAbstractNetworkCache>
#include <QThread>
#include "NetworkAccessManager.h"
@ -20,6 +21,7 @@ NetworkAccessManager& NetworkAccessManager::getInstance() {
}
NetworkAccessManager::NetworkAccessManager() {
qRegisterMetaType<QAbstractNetworkCache*>();
}
QNetworkReply* NetworkAccessManager::get(const QNetworkRequest& request) {
@ -146,4 +148,14 @@ QNetworkReply* NetworkAccessManager::sendCustomRequest(const QNetworkRequest& re
return result;
}
return QNetworkAccessManager::sendCustomRequest(request, verb, data);
}
void NetworkAccessManager::setCache(QAbstractNetworkCache* cache) {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this,
"setCache",
Qt::BlockingQueuedConnection,
Q_ARG(QAbstractNetworkCache*, cache));
}
QNetworkAccessManager::setCache(cache);
}

View file

@ -18,7 +18,9 @@
/// Wrapper around QNetworkAccessManager wo that we only use one instance
/// For any other method you should need, make sure to be on the right thread
/// or call the method using QMetaObject::invokeMethod()
/// or if it is not but is a slot, use QMetaObject::invokeMethod()
/// In the case what you want to call isn't a slot and you aren't on the same thread,
/// then add then method to the method to the wrapper with the Q_INVKABLE flag
class NetworkAccessManager : public QNetworkAccessManager {
Q_OBJECT
public:
@ -33,6 +35,7 @@ public:
Q_INVOKABLE QNetworkReply* put(const QNetworkRequest& request, QHttpMultiPart* multiPart);
Q_INVOKABLE QNetworkReply* put(const QNetworkRequest& request, const QByteArray& data);
Q_INVOKABLE QNetworkReply* sendCustomRequest(const QNetworkRequest& request, const QByteArray& verb, QIODevice* data = 0);
Q_INVOKABLE void setCache(QAbstractNetworkCache* cache);
private:
NetworkAccessManager();

View file

@ -15,10 +15,12 @@
#include <qbytearray.h>
#include <qvector.h>
#include "SequenceNumberStats.h"
class SentPacketHistory {
public:
SentPacketHistory(int size = 1000);
SentPacketHistory(int size = MAX_REASONABLE_SEQUENCE_GAP);
void packetSent(uint16_t sequenceNumber, const QByteArray& packet);
const QByteArray* getPacket(uint16_t sequenceNumber) const;

View file

@ -39,7 +39,6 @@ void SequenceNumberStats::reset() {
}
static const int UINT16_RANGE = std::numeric_limits<uint16_t>::max() + 1;
static const int MAX_REASONABLE_SEQUENCE_GAP = 1000; // this must be less than UINT16_RANGE / 2 for rollover handling to work
void SequenceNumberStats::sequenceNumberReceived(quint16 incoming, QUuid senderUUID, const bool wantExtraDebugging) {
@ -95,6 +94,7 @@ void SequenceNumberStats::sequenceNumberReceived(quint16 incoming, QUuid senderU
_numEarly++;
_numLost += (incomingInt - expectedInt);
_lastReceived = incoming;
// add all sequence numbers that were skipped to the missing sequence numbers list
for (int missingInt = expectedInt; missingInt < incomingInt; missingInt++) {
@ -106,14 +106,14 @@ void SequenceNumberStats::sequenceNumberReceived(quint16 incoming, QUuid senderU
if (_missingSet.size() > MAX_REASONABLE_SEQUENCE_GAP) {
pruneMissingSet(wantExtraDebugging);
}
_lastReceived = incoming;
} else { // late
if (wantExtraDebugging) {
qDebug() << "this packet is later than expected...";
}
_numLate++;
// do not update _lastReceived; it shouldn't become smaller
// remove this from missing sequence number if it's in there
if (_missingSet.remove(incoming)) {
if (wantExtraDebugging) {
@ -127,8 +127,6 @@ void SequenceNumberStats::sequenceNumberReceived(quint16 incoming, QUuid senderU
}
_numDuplicate++;
}
// do not update _incomingLastSequence; it shouldn't become smaller
}
}
}

View file

@ -15,13 +15,15 @@
#include "SharedUtil.h"
#include <quuid.h>
const int MAX_REASONABLE_SEQUENCE_GAP = 1000;
class SequenceNumberStats {
public:
SequenceNumberStats();
void reset();
void sequenceNumberReceived(quint16 incoming, QUuid senderUUID = QUuid(), const bool wantExtraDebugging = false);
void pruneMissingSet(const bool wantExtraDebugging = false);
quint32 getNumReceived() const { return _numReceived; }
quint32 getNumUnreasonable() const { return _numUnreasonable; }
@ -34,8 +36,6 @@ public:
const QSet<quint16>& getMissingSet() const { return _missingSet; }
private:
void pruneMissingSet(const bool wantExtraDebugging);
quint16 _lastReceived;
QSet<quint16> _missingSet;

View file

@ -168,6 +168,7 @@ public:
float getIncomingFlightTimeAverage() { return _incomingFlightTimeAverage.getAverage(); }
const SequenceNumberStats& getIncomingOctreeSequenceNumberStats() const { return _incomingOctreeSequenceNumberStats; }
SequenceNumberStats& getIncomingOctreeSequenceNumberStats() { return _incomingOctreeSequenceNumberStats; }
private:

View file

@ -0,0 +1,37 @@
//
// MIDIEvent.cpp
// libraries/script-engine/src
//
// Created by Stephen Birarda on 2014-06-30.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "MIDIEvent.h"
void registerMIDIMetaTypes(QScriptEngine* engine) {
qScriptRegisterMetaType(engine, midiEventToScriptValue, midiEventFromScriptValue);
}
const QString MIDI_DELTA_TIME_PROP_NAME = "deltaTime";
const QString MIDI_EVENT_TYPE_PROP_NAME = "type";
const QString MIDI_DATA_1_PROP_NAME = "data1";
const QString MIDI_DATA_2_PROP_NAME = "data2";
QScriptValue midiEventToScriptValue(QScriptEngine* engine, const MIDIEvent& event) {
QScriptValue obj = engine->newObject();
obj.setProperty(MIDI_DELTA_TIME_PROP_NAME, event.deltaTime);
obj.setProperty(MIDI_EVENT_TYPE_PROP_NAME, event.type);
obj.setProperty(MIDI_DATA_1_PROP_NAME, event.data1);
obj.setProperty(MIDI_DATA_2_PROP_NAME, event.data2);
return obj;
}
void midiEventFromScriptValue(const QScriptValue &object, MIDIEvent& event) {
event.deltaTime = object.property(MIDI_DELTA_TIME_PROP_NAME).toVariant().toDouble();
event.type = object.property(MIDI_EVENT_TYPE_PROP_NAME).toVariant().toUInt();
event.data1 = object.property(MIDI_DATA_1_PROP_NAME).toVariant().toUInt();
event.data2 = object.property(MIDI_DATA_2_PROP_NAME).toVariant().toUInt();
}

View file

@ -0,0 +1,32 @@
//
// MIDIEvent.h
// libraries/script-engine/src
//
// Created by Stephen Birarda on 2014-06-30.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QtScript/QScriptEngine>
#ifndef hifi_MIDIEvent_h
#define hifi_MIDIEvent_h
class MIDIEvent {
public:
double deltaTime;
unsigned int type;
unsigned int data1;
unsigned int data2;
};
Q_DECLARE_METATYPE(MIDIEvent)
void registerMIDIMetaTypes(QScriptEngine* engine);
QScriptValue midiEventToScriptValue(QScriptEngine* engine, const MIDIEvent& event);
void midiEventFromScriptValue(const QScriptValue &object, MIDIEvent& event);
#endif // hifi_MIDIEvent_h

View file

@ -33,6 +33,7 @@
#include "AnimationObject.h"
#include "MenuItemProperties.h"
#include "MIDIEvent.h"
#include "LocalVoxels.h"
#include "ScriptEngine.h"
#include "XMLHttpRequestClass.h"
@ -217,6 +218,7 @@ void ScriptEngine::init() {
// register various meta-types
registerMetaTypes(&_engine);
registerMIDIMetaTypes(&_engine);
registerVoxelMetaTypes(&_engine);
registerEventTypes(&_engine);
registerMenuItemProperties(&_engine);
@ -254,6 +256,8 @@ void ScriptEngine::init() {
qScriptRegisterMetaType(&_engine, injectorToScriptValue, injectorFromScriptValue);
qScriptRegisterMetaType(&_engine, animationDetailsToScriptValue, animationDetailsFromScriptValue);
registerGlobalObject("Script", this);
registerGlobalObject("Audio", &_audioScriptingInterface);
registerGlobalObject("Controller", _controllerScriptingInterface);

View file

@ -29,7 +29,7 @@ void AudioRingBufferTests::runAllTests() {
int readIndexAt;
AudioRingBuffer ringBuffer(10); // makes buffer of 100 int16_t samples
AudioRingBuffer ringBuffer(10, false, 10); // makes buffer of 100 int16_t samples
for (int T = 0; T < 300; T++) {
writeIndexAt = 0;

View file

@ -115,6 +115,11 @@ void SequenceNumberStatsTests::earlyLateTest() {
}
}
stats.reset();
numSent = 0;
numEarly = 0;
numLate = 0;
numLost = 0;
numRecovered = 0;
}
}
@ -203,6 +208,11 @@ void SequenceNumberStatsTests::duplicateTest() {
}
}
stats.reset();
numSent = 0;
numDuplicate = 0;
numEarly = 0;
numLate = 0;
numLost = 0;
}
}
@ -263,5 +273,8 @@ void SequenceNumberStatsTests::pruneTest() {
}
}
stats.reset();
numSent = 0;
numEarly = 0;
numLost = 0;
}
}