diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index f7953cdf41..9e7cf53e2f 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -67,7 +67,11 @@ void attachNewBufferToNode(Node *newNode) { AudioMixer::AudioMixer(const QByteArray& packet) : ThreadedAssignment(packet), _trailingSleepRatio(1.0f), - _minAudibilityThreshold(LOUDNESS_TO_DISTANCE_RATIO / 2.0f) + _minAudibilityThreshold(LOUDNESS_TO_DISTANCE_RATIO / 2.0f), + _performanceThrottling(0.0f), + _numStatFrames(0), + _sumListeners(0), + _sumMixes(0) { } @@ -95,6 +99,8 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf return; } + ++_sumMixes; + glm::quat inverseOrientation = glm::inverse(listeningNodeBuffer->getOrientation()); float distanceSquareToSource = glm::dot(relativePosition, relativePosition); @@ -352,8 +358,21 @@ void AudioMixer::readPendingDatagrams() { void AudioMixer::sendStatsPacket() { static QJsonObject statsObject; - statsObject["trailing_sleep"] = _trailingSleepRatio; - statsObject["min_audability_threshold"] = _minAudibilityThreshold; + statsObject["trailing_sleep_percentage"] = _trailingSleepRatio * 100.0f; + statsObject["performance_throttling"] = _performanceThrottling; + + statsObject["average_listeners_per_frame"] = _sumListeners / (float) _numStatFrames; + + if (_sumListeners > 0) { + statsObject["average_mixes_per_listener"] = _sumMixes / (float) _sumListeners; + } else { + statsObject["average_mixes_per_listener"] = 0.0; + } + + + _sumListeners = 0; + _sumMixes = 0; + _numStatFrames = 0; NodeList::getInstance()->sendStatsToDomainServer(statsObject); } @@ -382,7 +401,6 @@ void AudioMixer::run() { + numBytesForPacketHeaderGivenPacketType(PacketTypeMixedAudio)]; int usecToSleep = BUFFER_SEND_INTERVAL_USECS; - float audabilityCutoffRatio = 0; const int TRAILING_AVERAGE_FRAMES = 100; int framesSinceCutoffEvent = TRAILING_AVERAGE_FRAMES; @@ -410,7 +428,7 @@ void AudioMixer::run() { _trailingSleepRatio = (PREVIOUS_FRAMES_RATIO * _trailingSleepRatio) + (usecToSleep * CURRENT_FRAME_RATIO / (float) BUFFER_SEND_INTERVAL_USECS); - float lastCutoffRatio = audabilityCutoffRatio; + float lastCutoffRatio = _performanceThrottling; bool hasRatioChanged = false; if (framesSinceCutoffEvent >= TRAILING_AVERAGE_FRAMES) { @@ -420,27 +438,27 @@ void AudioMixer::run() { if (_trailingSleepRatio <= STRUGGLE_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD) { // we're struggling - change our min required loudness to reduce some load - audabilityCutoffRatio = audabilityCutoffRatio + (0.5f * (1.0f - audabilityCutoffRatio)); + _performanceThrottling = _performanceThrottling + (0.5f * (1.0f - _performanceThrottling)); qDebug() << "Mixer is struggling, sleeping" << _trailingSleepRatio * 100 << "% of frame time. Old cutoff was" - << lastCutoffRatio << "and is now" << audabilityCutoffRatio; + << lastCutoffRatio << "and is now" << _performanceThrottling; hasRatioChanged = true; - } else if (_trailingSleepRatio >= BACK_OFF_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD && audabilityCutoffRatio != 0) { + } else if (_trailingSleepRatio >= BACK_OFF_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD && _performanceThrottling != 0) { // we've recovered and can back off the required loudness - audabilityCutoffRatio = audabilityCutoffRatio - RATIO_BACK_OFF; + _performanceThrottling = _performanceThrottling - RATIO_BACK_OFF; - if (audabilityCutoffRatio < 0) { - audabilityCutoffRatio = 0; + if (_performanceThrottling < 0) { + _performanceThrottling = 0; } qDebug() << "Mixer is recovering, sleeping" << _trailingSleepRatio * 100 << "% of frame time. Old cutoff was" - << lastCutoffRatio << "and is now" << audabilityCutoffRatio; + << lastCutoffRatio << "and is now" << _performanceThrottling; hasRatioChanged = true; } if (hasRatioChanged) { // set out min audability threshold from the new ratio - _minAudibilityThreshold = LOUDNESS_TO_DISTANCE_RATIO / (2.0f * (1.0f - audabilityCutoffRatio)); + _minAudibilityThreshold = LOUDNESS_TO_DISTANCE_RATIO / (2.0f * (1.0f - _performanceThrottling)); qDebug() << "Minimum audability required to be mixed is now" << _minAudibilityThreshold; framesSinceCutoffEvent = 0; @@ -460,6 +478,8 @@ void AudioMixer::run() { memcpy(clientMixBuffer + numBytesPacketHeader, _clientSamples, NETWORK_BUFFER_LENGTH_BYTES_STEREO); nodeList->writeDatagram(clientMixBuffer, NETWORK_BUFFER_LENGTH_BYTES_STEREO + numBytesPacketHeader, node); + + ++_sumListeners; } } @@ -470,6 +490,8 @@ void AudioMixer::run() { } } + ++_numStatFrames; + QCoreApplication::processEvents(); if (_isFinished) { diff --git a/assignment-client/src/audio/AudioMixer.h b/assignment-client/src/audio/AudioMixer.h index 0f88701303..0b1de6f069 100644 --- a/assignment-client/src/audio/AudioMixer.h +++ b/assignment-client/src/audio/AudioMixer.h @@ -44,6 +44,10 @@ private: float _trailingSleepRatio; float _minAudibilityThreshold; + float _performanceThrottling; + int _numStatFrames; + int _sumListeners; + int _sumMixes; }; #endif /* defined(__hifi__AudioMixer__) */ diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index d4dfa80724..4990de2b55 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -236,7 +236,7 @@ void OctreeServer::initHTTPManager(int port) { _httpManager = new HTTPManager(port, documentRoot, this, this); } -bool OctreeServer::handleHTTPRequest(HTTPConnection* connection, const QString& path) { +bool OctreeServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url) { #ifdef FORCE_CRASH if (connection->requestOperation() == QNetworkAccessManager::GetOperation @@ -259,9 +259,9 @@ bool OctreeServer::handleHTTPRequest(HTTPConnection* connection, const QString& bool showStats = false; if (connection->requestOperation() == QNetworkAccessManager::GetOperation) { - if (path == "/") { + if (url.path() == "/") { showStats = true; - } else if (path == "/resetStats") { + } else if (url.path() == "/resetStats") { _octreeInboundPacketProcessor->resetStats(); resetSendingStats(); showStats = true; diff --git a/assignment-client/src/octree/OctreeServer.h b/assignment-client/src/octree/OctreeServer.h index 12091170d9..2664499b6a 100644 --- a/assignment-client/src/octree/OctreeServer.h +++ b/assignment-client/src/octree/OctreeServer.h @@ -97,7 +97,7 @@ public: static void trackPacketSendingTime(float time); static float getAveragePacketSendingTime() { return _averagePacketSendingTime.getAverage(); } - bool handleHTTPRequest(HTTPConnection* connection, const QString& path); + bool handleHTTPRequest(HTTPConnection* connection, const QUrl& url); virtual void aboutToFinish(); diff --git a/domain-server/resources/web/footer.html b/domain-server/resources/web/footer.html index 08ea9fba66..d1a3fc29e8 100644 --- a/domain-server/resources/web/footer.html +++ b/domain-server/resources/web/footer.html @@ -1,3 +1,3 @@ - - \ No newline at end of file + + \ No newline at end of file diff --git a/domain-server/resources/web/header.html b/domain-server/resources/web/header.html index 83d7ae5c23..2be603b00e 100644 --- a/domain-server/resources/web/header.html +++ b/domain-server/resources/web/header.html @@ -4,8 +4,8 @@ domain-server - - + +
\ No newline at end of file diff --git a/domain-server/resources/web/js/tables.js b/domain-server/resources/web/js/tables.js index e32f78a63e..ae5095592b 100644 --- a/domain-server/resources/web/js/tables.js +++ b/domain-server/resources/web/js/tables.js @@ -7,7 +7,7 @@ $(document).ready(function(){ $.each(json.nodes, function (uuid, data) { nodesTableBody += ""; nodesTableBody += "" + data.type + ""; - nodesTableBody += "" + uuid + ""; + nodesTableBody += "" + uuid + ""; nodesTableBody += "" + (data.pool ? data.pool : "") + ""; nodesTableBody += "" + data.public.ip + ":" + data.public.port + ""; nodesTableBody += "" + data.local.ip + ":" + data.local.port + ""; diff --git a/domain-server/resources/web/stats/index.shtml b/domain-server/resources/web/stats/index.shtml new file mode 100644 index 0000000000..62115d18fe --- /dev/null +++ b/domain-server/resources/web/stats/index.shtml @@ -0,0 +1,6 @@ + +

Stats

+
+ + + \ No newline at end of file diff --git a/domain-server/resources/web/stats/js/stats.js b/domain-server/resources/web/stats/js/stats.js new file mode 100644 index 0000000000..e82668ea9e --- /dev/null +++ b/domain-server/resources/web/stats/js/stats.js @@ -0,0 +1,31 @@ +function qs(key) { + key = key.replace(/[*+?^$.\[\]{}()|\\\/]/g, "\\$&"); // escape RegEx meta chars + var match = location.search.match(new RegExp("[?&]"+key+"=([^&]+)(&|$)")); + return match && decodeURIComponent(match[1].replace(/\+/g, " ")); +} + +$(document).ready(function(){ + // setup a function to grab the nodeStats + function getNodeStats() { + + var uuid = qs("uuid"); + + var statsTableBody = ""; + + $.getJSON("/nodes/" + uuid + ".json", function(json){ + $.each(json, function (key, value) { + statsTableBody += ""; + statsTableBody += "" + key + ""; + statsTableBody += "" + value + ""; + statsTableBody += ""; + }); + + $('#stats-table tbody').html(statsTableBody); + }); + } + + // do the first GET on page load + getNodeStats(); + // grab the new assignments JSON every second + var getNodeStatsInterval = setInterval(getNodeStats, 1000); +}); diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 1b867501d2..0a8b70a673 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -651,14 +651,14 @@ QJsonObject DomainServer::jsonObjectForNode(const SharedNodePointer& node) { return nodeJson; } -bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QString& path) { +bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url) { const QString JSON_MIME_TYPE = "application/json"; const QString URI_ASSIGNMENT = "/assignment"; const QString URI_NODES = "/nodes"; if (connection->requestOperation() == QNetworkAccessManager::GetOperation) { - if (path == "/assignments.json") { + if (url.path() == "/assignments.json") { // user is asking for json list of assignments // setup the JSON @@ -702,7 +702,7 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QString& // we've processed this request return true; - } else if (path == QString("%1.json").arg(URI_NODES)) { + } else if (url.path() == QString("%1.json").arg(URI_NODES)) { // setup the JSON QJsonObject rootJSON; QJsonObject nodesJSON; @@ -727,10 +727,10 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QString& return true; } else { const QString NODE_REGEX_STRING = - QString("\\%1\\/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\\/?$").arg(URI_NODES); + QString("\\%1\\/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}).json\\/?$").arg(URI_NODES); QRegExp nodeShowRegex(NODE_REGEX_STRING); - if (nodeShowRegex.indexIn(path) != -1) { + if (nodeShowRegex.indexIn(url.path()) != -1) { QUuid matchingUUID = QUuid(nodeShowRegex.cap(1)); // see if we have a node that matches this ID @@ -740,7 +740,7 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QString& QJsonDocument statsDocument(reinterpret_cast(matchingNode->getLinkedData()) ->getStatsJSONObject()); - // send the resposne + // send the response connection->respond(HTTPConnection::StatusCode200, statsDocument.toJson(), qPrintable(JSON_MIME_TYPE)); // tell the caller we processed the request @@ -749,7 +749,7 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QString& } } } else if (connection->requestOperation() == QNetworkAccessManager::PostOperation) { - if (path == URI_ASSIGNMENT) { + if (url.path() == URI_ASSIGNMENT) { // this is a script upload - ask the HTTPConnection to parse the form data QList formData = connection->parseFormData(); @@ -796,11 +796,11 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QString& return true; } } else if (connection->requestOperation() == QNetworkAccessManager::DeleteOperation) { - if (path.startsWith(URI_NODES)) { + if (url.path().startsWith(URI_NODES)) { // this is a request to DELETE a node by UUID // pull the UUID from the url - QUuid deleteUUID = QUuid(path.mid(URI_NODES.size() + sizeof('/'))); + QUuid deleteUUID = QUuid(url.path().mid(URI_NODES.size() + sizeof('/'))); if (!deleteUUID.isNull()) { SharedNodePointer nodeToKill = NodeList::getInstance()->nodeWithUUID(deleteUUID); diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 2d253cc41c..597be7f50d 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -30,7 +30,7 @@ public: bool requiresAuthentication() const { return !_nodeAuthenticationURL.isEmpty(); } - bool handleHTTPRequest(HTTPConnection* connection, const QString& path); + bool handleHTTPRequest(HTTPConnection* connection, const QUrl& url); void exit(int retCode = 0); diff --git a/examples/audioDeviceExample.js b/examples/audioDeviceExample.js new file mode 100644 index 0000000000..1ee00a1582 --- /dev/null +++ b/examples/audioDeviceExample.js @@ -0,0 +1,52 @@ +// +// audioDeviceExample.js +// hifi +// +// Created by Brad Hefta-Gaub on 3/22/14 +// Copyright (c) 2013 HighFidelity, Inc. All rights reserved. +// +// This is an example script that demonstrates use of the Menu object +// + + +var outputDevices = AudioDevice.getOutputDevices(); +var defaultOutputDevice = AudioDevice.getDefaultOutputDevice(); +var selectOutputDevice = outputDevices[0]; +print("Output Devices:"); +for(var i = 0; i < outputDevices.length; i++) { + if (outputDevices[i] == defaultOutputDevice) { + print(" " + outputDevices[i] + " << default"); + } else { + print(" " + outputDevices[i]); + } +} + +print("Default Output Device:" + defaultOutputDevice); +print("Selected Output Device:" + selectOutputDevice); +print("Current Audio Output Device: " + AudioDevice.getOutputDevice()); +AudioDevice.setOutputDevice(selectOutputDevice); +print("Audio Output Device: " + AudioDevice.getOutputDevice()); + +var inputDevices = AudioDevice.getInputDevices(); +var selectInputDevice = inputDevices[0]; +var defaultInputDevice = AudioDevice.getDefaultInputDevice(); +print("Input Devices:"); +for(var i = 0; i < inputDevices.length; i++) { + if (inputDevices[i] == defaultInputDevice) { + print(" " + inputDevices[i] + " << default"); + } else { + print(" " + inputDevices[i]); + } +} + +print("Default Input Device:" + defaultInputDevice); +print("Selected Input Device:" + selectInputDevice); +print("Current Audio Input Device: " + AudioDevice.getInputDevice()); +AudioDevice.setInputDevice(selectInputDevice); +print("Audio Input Device: " + AudioDevice.getInputDevice()); + +print("Audio Input Device Level: " + AudioDevice.getInputVolume()); +AudioDevice.setInputVolume(AudioDevice.getInputVolume() * 2); // twice as loud! +print("Audio Input Device Level: " + AudioDevice.getInputVolume()); + +Script.stop(); \ No newline at end of file diff --git a/examples/settingsExample.js b/examples/settingsExample.js new file mode 100644 index 0000000000..0dcc5482b6 --- /dev/null +++ b/examples/settingsExample.js @@ -0,0 +1,18 @@ +// +// settingsExample.js +// hifi +// +// Created by Brad Hefta-Gaub on 3/22/14 +// Copyright (c) 2013 HighFidelity, Inc. All rights reserved. +// +// This is an example script that demonstrates use of the Menu object +// + + + + +print("mySetting: " + Settings.getValue("mySetting")); +Settings.setValue("mySetting", "spam"); +print("mySetting: " + Settings.getValue("mySetting")); + +Script.stop(); \ No newline at end of file diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 7126e8929f..f991212a6e 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -48,7 +48,7 @@ configure_file(InterfaceVersion.h.in "${PROJECT_BINARY_DIR}/includes/InterfaceVe # grab the implementation and header files from src dirs file(GLOB INTERFACE_SRCS src/*.cpp src/*.h) -foreach(SUBDIR avatar devices renderer ui starfield location) +foreach(SUBDIR avatar devices renderer ui starfield location scripting voxels) file(GLOB_RECURSE SUBDIR_SRCS src/${SUBDIR}/*.cpp src/${SUBDIR}/*.h) set(INTERFACE_SRCS ${INTERFACE_SRCS} "${SUBDIR_SRCS}") endforeach(SUBDIR) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e896160b65..c36e9a77db 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -65,17 +65,21 @@ #include #include "Application.h" -#include "ClipboardScriptingInterface.h" #include "InterfaceVersion.h" #include "Menu.h" -#include "MenuScriptingInterface.h" #include "Util.h" #include "devices/OculusManager.h" #include "devices/TV3DManager.h" #include "renderer/ProgramObject.h" -#include "ui/TextRenderer.h" -#include "InfoView.h" + +#include "scripting/AudioDeviceScriptingInterface.h" +#include "scripting/ClipboardScriptingInterface.h" +#include "scripting/MenuScriptingInterface.h" +#include "scripting/SettingsScriptingInterface.h" + +#include "ui/InfoView.h" #include "ui/Snapshot.h" +#include "ui/TextRenderer.h" using namespace std; @@ -3559,6 +3563,8 @@ void Application::loadScript(const QString& fileNameString) { scriptEngine->registerGlobalObject("Overlays", &_overlays); scriptEngine->registerGlobalObject("Menu", MenuScriptingInterface::getInstance()); + scriptEngine->registerGlobalObject("Settings", SettingsScriptingInterface::getInstance()); + scriptEngine->registerGlobalObject("AudioDevice", AudioDeviceScriptingInterface::getInstance()); QThread* workerThread = new QThread(this); diff --git a/interface/src/Application.h b/interface/src/Application.h index 93a5044124..caeea529af 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -29,12 +29,12 @@ #include #include #include +#include +#include #include "Audio.h" -#include "BandwidthMeter.h" #include "BuckyBalls.h" #include "Camera.h" -#include "ControllerScriptingInterface.h" #include "DatagramProcessor.h" #include "Environment.h" #include "FileLogger.h" @@ -44,13 +44,6 @@ #include "PacketHeaders.h" #include "ParticleTreeRenderer.h" #include "Stars.h" -#include "ViewFrustum.h" -#include "VoxelFade.h" -#include "VoxelEditPacketSender.h" -#include "VoxelHideShowThread.h" -#include "VoxelPacketProcessor.h" -#include "VoxelSystem.h" -#include "VoxelImporter.h" #include "avatar/Avatar.h" #include "avatar/AvatarManager.h" #include "avatar/MyAvatar.h" @@ -63,13 +56,20 @@ #include "renderer/PointShader.h" #include "renderer/TextureCache.h" #include "renderer/VoxelShader.h" +#include "scripting/ControllerScriptingInterface.h" #include "ui/BandwidthDialog.h" +#include "ui/BandwidthMeter.h" #include "ui/OctreeStatsDialog.h" #include "ui/RearMirrorTools.h" #include "ui/LodToolsDialog.h" #include "ui/LogDialog.h" #include "ui/UpdateDialog.h" -#include "ui/Overlays.h" +#include "ui/overlays/Overlays.h" +#include "voxels/VoxelFade.h" +#include "voxels/VoxelHideShowThread.h" +#include "voxels/VoxelImporter.h" +#include "voxels/VoxelPacketProcessor.h" +#include "voxels/VoxelSystem.h" class QAction; @@ -172,7 +172,11 @@ public: Visage* getVisage() { return &_visage; } SixenseManager* getSixenseManager() { return &_sixenseManager; } BandwidthMeter* getBandwidthMeter() { return &_bandwidthMeter; } - QSettings* getSettings() { return _settings; } + + /// if you need to access the application settings, use lockSettings()/unlockSettings() + QSettings* lockSettings() { _settingsMutex.lock(); return _settings; } + void unlockSettings() { _settingsMutex.unlock(); } + QMainWindow* getWindow() { return _window; } NodeToOctreeSceneStats* getOcteeSceneStats() { return &_octreeServerSceneStats; } void lockOctreeSceneStats() { _octreeSceneStatsLock.lockForRead(); } @@ -353,6 +357,7 @@ private: DatagramProcessor _datagramProcessor; QNetworkAccessManager* _networkAccessManager; + QMutex _settingsMutex; QSettings* _settings; glm::vec3 _gravity; diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index b684cec46e..734b5345fb 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -92,6 +92,16 @@ void Audio::reset() { _ringBuffer.reset(); } +QAudioDeviceInfo getNamedAudioDeviceForMode(QAudio::Mode mode, const QString& deviceName) { + QAudioDeviceInfo result; + foreach(QAudioDeviceInfo audioDevice, QAudioDeviceInfo::availableDevices(mode)) { + if (audioDevice.deviceName().trimmed() == deviceName.trimmed()) { + result = audioDevice; + } + } + return result; +} + QAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) { #ifdef __APPLE__ if (QAudioDeviceInfo::availableDevices(mode).size() > 1) { @@ -249,27 +259,105 @@ void Audio::start() { _desiredOutputFormat.setChannelCount(2); QAudioDeviceInfo inputDeviceInfo = defaultAudioDeviceForMode(QAudio::AudioInput); - qDebug() << "The audio input device is" << inputDeviceInfo.deviceName(); + qDebug() << "The default audio input device is" << inputDeviceInfo.deviceName(); + bool inputFormatSupported = switchInputToAudioDevice(inputDeviceInfo.deviceName()); + + QAudioDeviceInfo outputDeviceInfo = defaultAudioDeviceForMode(QAudio::AudioOutput); + qDebug() << "The default audio output device is" << outputDeviceInfo.deviceName(); + bool outputFormatSupported = switchOutputToAudioDevice(outputDeviceInfo.deviceName()); - if (adjustedFormatForAudioDevice(inputDeviceInfo, _desiredInputFormat, _inputFormat)) { - qDebug() << "The format to be used for audio input is" << _inputFormat; + if (!inputFormatSupported || !outputFormatSupported) { + qDebug() << "Unable to set up audio I/O because of a problem with input or output formats."; + } +} + +QString Audio::getDefaultDeviceName(QAudio::Mode mode) { + QAudioDeviceInfo deviceInfo = defaultAudioDeviceForMode(mode); + return deviceInfo.deviceName(); +} + +QVector Audio::getDeviceNames(QAudio::Mode mode) { + QVector deviceNames; + foreach(QAudioDeviceInfo audioDevice, QAudioDeviceInfo::availableDevices(mode)) { + deviceNames << audioDevice.deviceName().trimmed(); + } + return deviceNames; +} + +bool Audio::switchInputToAudioDevice(const QString& inputDeviceName) { + bool supportedFormat = false; + + // cleanup any previously initialized device + if (_audioInput) { + _audioInput->stop(); + disconnect(_inputDevice, 0, 0, 0); + _inputDevice = NULL; + + delete _audioInput; + _audioInput = NULL; + _numInputCallbackBytes = 0; + + _inputAudioDeviceName = ""; + } + + QAudioDeviceInfo inputDeviceInfo = getNamedAudioDeviceForMode(QAudio::AudioInput, inputDeviceName); + + if (!inputDeviceInfo.isNull()) { + qDebug() << "The audio input device " << inputDeviceInfo.deviceName() << "is available."; + _inputAudioDeviceName = inputDeviceInfo.deviceName().trimmed(); + + if (adjustedFormatForAudioDevice(inputDeviceInfo, _desiredInputFormat, _inputFormat)) { + qDebug() << "The format to be used for audio input is" << _inputFormat; - _audioInput = new QAudioInput(inputDeviceInfo, _inputFormat, this); - _numInputCallbackBytes = NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL * _inputFormat.channelCount() - * (_inputFormat.sampleRate() / SAMPLE_RATE) - / CALLBACK_ACCELERATOR_RATIO; - _audioInput->setBufferSize(_numInputCallbackBytes); + _audioInput = new QAudioInput(inputDeviceInfo, _inputFormat, this); + _numInputCallbackBytes = NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL * _inputFormat.channelCount() + * (_inputFormat.sampleRate() / SAMPLE_RATE) + / CALLBACK_ACCELERATOR_RATIO; + _audioInput->setBufferSize(_numInputCallbackBytes); - QAudioDeviceInfo outputDeviceInfo = defaultAudioDeviceForMode(QAudio::AudioOutput); - qDebug() << "The audio output device is" << outputDeviceInfo.deviceName(); - - if (adjustedFormatForAudioDevice(outputDeviceInfo, _desiredOutputFormat, _outputFormat)) { - qDebug() << "The format to be used for audio output is" << _outputFormat; - + // how do we want to handle input working, but output not working? _inputRingBuffer.resizeForFrameSize(_numInputCallbackBytes * CALLBACK_ACCELERATOR_RATIO / sizeof(int16_t)); _inputDevice = _audioInput->start(); connect(_inputDevice, SIGNAL(readyRead()), this, SLOT(handleAudioInput())); + supportedFormat = true; + } + } + return supportedFormat; +} + +bool Audio::switchOutputToAudioDevice(const QString& outputDeviceName) { + bool supportedFormat = false; + + // cleanup any previously initialized device + if (_audioOutput) { + _audioOutput->stop(); + disconnect(_outputDevice, 0, 0, 0); + _outputDevice = NULL; + + delete _audioOutput; + _audioOutput = NULL; + _numInputCallbackBytes = 0; + + _loopbackOutputDevice = NULL; + delete _loopbackAudioOutput; + _loopbackAudioOutput = NULL; + + _proceduralOutputDevice = NULL; + delete _proceduralAudioOutput; + _proceduralAudioOutput = NULL; + _outputAudioDeviceName = ""; + } + + QAudioDeviceInfo outputDeviceInfo = getNamedAudioDeviceForMode(QAudio::AudioOutput, outputDeviceName); + + if (!outputDeviceInfo.isNull()) { + qDebug() << "The audio output device " << outputDeviceInfo.deviceName() << "is available."; + _outputAudioDeviceName = outputDeviceInfo.deviceName().trimmed(); + + if (adjustedFormatForAudioDevice(outputDeviceInfo, _desiredOutputFormat, _outputFormat)) { + qDebug() << "The format to be used for audio output is" << _outputFormat; + // setup our general output device for audio-mixer audio _audioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this); _audioOutput->setBufferSize(_ringBuffer.getSampleCapacity() * sizeof(int16_t)); @@ -278,17 +366,15 @@ void Audio::start() { // setup a loopback audio output device _loopbackAudioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this); - + // setup a procedural audio output device _proceduralAudioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this); gettimeofday(&_lastReceiveTime, NULL); + supportedFormat = true; } - - return; } - - qDebug() << "Unable to set up audio I/O because of a problem with input or output formats."; + return supportedFormat; } void Audio::handleAudioInput() { @@ -309,13 +395,15 @@ void Audio::handleAudioInput() { if (Menu::getInstance()->isOptionChecked(MenuOption::EchoLocalAudio) && !_muted) { // if this person wants local loopback add that to the locally injected audio - if (!_loopbackOutputDevice) { + if (!_loopbackOutputDevice && _loopbackAudioOutput) { // we didn't have the loopback output device going so set that up now _loopbackOutputDevice = _loopbackAudioOutput->start(); } if (_inputFormat == _outputFormat) { - _loopbackOutputDevice->write(inputByteArray); + if (_loopbackOutputDevice) { + _loopbackOutputDevice->write(inputByteArray); + } } else { static float loopbackOutputToInputRatio = (_outputFormat.sampleRate() / (float) _inputFormat.sampleRate()) * (_outputFormat.channelCount() / _inputFormat.channelCount()); @@ -326,7 +414,9 @@ void Audio::handleAudioInput() { inputByteArray.size() / sizeof(int16_t), loopBackByteArray.size() / sizeof(int16_t), _inputFormat, _outputFormat); - _loopbackOutputDevice->write(loopBackByteArray); + if (_loopbackOutputDevice) { + _loopbackOutputDevice->write(loopBackByteArray); + } } } @@ -455,7 +545,7 @@ void Audio::handleAudioInput() { addProceduralSounds(monoAudioSamples, NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL); - if (!_proceduralOutputDevice) { + if (!_proceduralOutputDevice && _proceduralAudioOutput) { _proceduralOutputDevice = _proceduralAudioOutput->start(); } @@ -469,7 +559,9 @@ void Audio::handleAudioInput() { NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL * 4, _desiredInputFormat, _outputFormat); - _proceduralOutputDevice->write(proceduralOutput); + if (_proceduralOutputDevice) { + _proceduralOutputDevice->write(proceduralOutput); + } NodeList* nodeList = NodeList::getInstance(); SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer); @@ -553,7 +645,7 @@ void Audio::addReceivedAudioToBuffer(const QByteArray& audioByteArray) { static float networkOutputToOutputRatio = (_desiredOutputFormat.sampleRate() / (float) _outputFormat.sampleRate()) * (_desiredOutputFormat.channelCount() / (float) _outputFormat.channelCount()); - if (!_ringBuffer.isStarved() && _audioOutput->bytesFree() == _audioOutput->bufferSize()) { + if (!_ringBuffer.isStarved() && _audioOutput && _audioOutput->bytesFree() == _audioOutput->bufferSize()) { // we don't have any audio data left in the output buffer // we just starved //qDebug() << "Audio output just starved."; diff --git a/interface/src/Audio.h b/interface/src/Audio.h index 880391d7f3..7aa1ef5afe 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -19,17 +19,20 @@ #include "InterfaceConfig.h" +#include +#include +#include #include #include #include +#include #include #include #include -#include "Oscilloscope.h" +#include "ui/Oscilloscope.h" -#include static const int NUM_AUDIO_CHANNELS = 2; @@ -72,7 +75,7 @@ public: int getNetworkSampleRate() { return SAMPLE_RATE; } int getNetworkBufferLengthSamplesPerChannel() { return NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; } - + public slots: void start(); void addReceivedAudioToBuffer(const QByteArray& audioByteArray); @@ -83,10 +86,21 @@ public slots: virtual void handleAudioByteArray(const QByteArray& audioByteArray); + bool switchInputToAudioDevice(const QString& inputDeviceName); + bool switchOutputToAudioDevice(const QString& outputDeviceName); + QString getDeviceName(QAudio::Mode mode) const { return (mode == QAudio::AudioInput) ? + _inputAudioDeviceName : _outputAudioDeviceName; } + QString getDefaultDeviceName(QAudio::Mode mode); + QVector getDeviceNames(QAudio::Mode mode); + + float getInputVolume() const { return (_audioInput) ? _audioInput->volume() : 0.0f; } + void setInputVolume(float volume) { if (_audioInput) _audioInput->setVolume(volume); } + signals: bool muteToggled(); private: + QByteArray firstInputFrame; QAudioInput* _audioInput; QAudioFormat _desiredInputFormat; @@ -105,6 +119,9 @@ private: QIODevice* _proceduralOutputDevice; AudioRingBuffer _inputRingBuffer; AudioRingBuffer _ringBuffer; + + QString _inputAudioDeviceName; + QString _outputAudioDeviceName; Oscilloscope* _scope; StDev _stdev; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index e62c7e1102..6eb03021b3 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -33,11 +33,11 @@ #include "Application.h" #include "Menu.h" -#include "MenuScriptingInterface.h" +#include "scripting/MenuScriptingInterface.h" #include "Util.h" -#include "InfoView.h" +#include "ui/InfoView.h" #include "ui/MetavoxelEditor.h" -#include "ModelBrowser.h" +#include "ui/ModelBrowser.h" Menu* Menu::_instance = NULL; @@ -374,8 +374,10 @@ Menu::~Menu() { } void Menu::loadSettings(QSettings* settings) { + bool lockedSettings = false; if (!settings) { - settings = Application::getInstance()->getSettings(); + settings = Application::getInstance()->lockSettings(); + lockedSettings = true; } _audioJitterBufferSamples = loadSetting(settings, "audioJitterBufferSamples", 0); @@ -404,11 +406,17 @@ void Menu::loadSettings(QSettings* settings) { // TODO: cache more settings in MyAvatar that are checked with very high frequency. MyAvatar* myAvatar = Application::getInstance()->getAvatar(); myAvatar->updateCollisionFlags(); + + if (lockedSettings) { + Application::getInstance()->unlockSettings(); + } } void Menu::saveSettings(QSettings* settings) { + bool lockedSettings = false; if (!settings) { - settings = Application::getInstance()->getSettings(); + settings = Application::getInstance()->lockSettings(); + lockedSettings = true; } settings->setValue("audioJitterBufferSamples", _audioJitterBufferSamples); @@ -430,6 +438,9 @@ void Menu::saveSettings(QSettings* settings) { Application::getInstance()->getAvatar()->saveData(settings); NodeList::getInstance()->saveData(settings); + if (lockedSettings) { + Application::getInstance()->unlockSettings(); + } } void Menu::importSettings() { diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 43a1787d13..77586dd7ae 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -27,10 +27,7 @@ Hand::Hand(Avatar* owningAvatar) : HandData((AvatarData*)owningAvatar), _owningAvatar(owningAvatar), - _renderAlpha(1.0), - _collisionCenter(0,0,0), - _collisionAge(0), - _collisionDuration(0) + _renderAlpha(1.0) { } @@ -42,10 +39,6 @@ void Hand::reset() { void Hand::simulate(float deltaTime, bool isMine) { - if (_collisionAge > 0.f) { - _collisionAge += deltaTime; - } - calculateGeometry(); if (isMine) { @@ -222,26 +215,6 @@ void Hand::collideAgainstOurself() { } } -void Hand::handleVoxelCollision(PalmData* palm, const glm::vec3& fingerTipPosition, VoxelTreeElement* voxel, float deltaTime) { - // Collision between finger and a voxel plays sound - const float LOWEST_FREQUENCY = 100.f; - const float HERTZ_PER_RGB = 3.f; - const float DECAY_PER_SAMPLE = 0.0005f; - const float DURATION_MAX = 2.0f; - const float MIN_VOLUME = 0.1f; - float volume = MIN_VOLUME + glm::clamp(glm::length(palm->getRawVelocity()), 0.f, (1.f - MIN_VOLUME)); - float duration = volume; - _collisionCenter = fingerTipPosition; - _collisionAge = deltaTime; - _collisionDuration = duration; - int voxelBrightness = voxel->getColor()[0] + voxel->getColor()[1] + voxel->getColor()[2]; - float frequency = LOWEST_FREQUENCY + (voxelBrightness * HERTZ_PER_RGB); - Application::getInstance()->getAudio()->startDrumSound(volume, - frequency, - DURATION_MAX, - DECAY_PER_SAMPLE); -} - void Hand::calculateGeometry() { // generate finger tip balls.... _leapFingerTipBalls.clear(); @@ -312,21 +285,6 @@ void Hand::render(bool isMine) { renderLeapHands(isMine); } - if (isMine) { - // If hand/voxel collision has happened, render a little expanding sphere - if (_collisionAge > 0.f) { - float opacity = glm::clamp(1.f - (_collisionAge / _collisionDuration), 0.f, 1.f); - glColor4f(1, 0, 0, 0.5 * opacity); - glPushMatrix(); - glTranslatef(_collisionCenter.x, _collisionCenter.y, _collisionCenter.z); - glutSolidSphere(_collisionAge * 0.25f, 20, 20); - glPopMatrix(); - if (_collisionAge > _collisionDuration) { - _collisionAge = 0.f; - } - } - } - glEnable(GL_DEPTH_TEST); glEnable(GL_RESCALE_NORMAL); diff --git a/interface/src/avatar/Hand.h b/interface/src/avatar/Hand.h index a1b1875424..f6ee5b281f 100755 --- a/interface/src/avatar/Hand.h +++ b/interface/src/avatar/Hand.h @@ -22,7 +22,6 @@ #include "InterfaceConfig.h" #include "world.h" -#include "VoxelSystem.h" class Avatar; @@ -72,13 +71,6 @@ private: std::vector _leapFingerTipBalls; std::vector _leapFingerRootBalls; - glm::vec3 _lastFingerAddVoxel, _lastFingerDeleteVoxel; - VoxelDetail _collidingVoxel; - - glm::vec3 _collisionCenter; - float _collisionAge; - float _collisionDuration; - // private methods void setLeapHands(const std::vector& handPositions, const std::vector& handNormals); @@ -88,8 +80,6 @@ private: void calculateGeometry(); - void handleVoxelCollision(PalmData* palm, const glm::vec3& fingerTipPosition, VoxelTreeElement* voxel, float deltaTime); - void playSlaps(PalmData& palm, Avatar* avatar); }; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 711e1d32c3..19d15fb803 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -26,7 +26,6 @@ #include "Menu.h" #include "MyAvatar.h" #include "Physics.h" -#include "VoxelSystem.h" #include "devices/Faceshift.h" #include "devices/OculusManager.h" #include "ui/TextRenderer.h" diff --git a/interface/src/scripting/AudioDeviceScriptingInterface.cpp b/interface/src/scripting/AudioDeviceScriptingInterface.cpp new file mode 100644 index 0000000000..a184e8a2f6 --- /dev/null +++ b/interface/src/scripting/AudioDeviceScriptingInterface.cpp @@ -0,0 +1,69 @@ +// +// AudioDeviceScriptingInterface.cpp +// hifi +// +// Created by Brad Hefta-Gaub on 3/23/14 +// Copyright (c) 2014 HighFidelity, Inc. All rights reserved. +// + +#include "Application.h" +#include "AudioDeviceScriptingInterface.h" + + +AudioDeviceScriptingInterface* AudioDeviceScriptingInterface::getInstance() { + static AudioDeviceScriptingInterface sharedInstance; + return &sharedInstance; +} + +bool AudioDeviceScriptingInterface::setInputDevice(const QString& deviceName) { + bool result; + QMetaObject::invokeMethod(Application::getInstance()->getAudio(), "switchInputToAudioDevice", + Qt::BlockingQueuedConnection, + Q_RETURN_ARG(bool, result), + Q_ARG(const QString&, deviceName)); + + return result; +} + +bool AudioDeviceScriptingInterface::setOutputDevice(const QString& deviceName) { + bool result; + QMetaObject::invokeMethod(Application::getInstance()->getAudio(), "switchOutputToAudioDevice", + Qt::BlockingQueuedConnection, + Q_RETURN_ARG(bool, result), + Q_ARG(const QString&, deviceName)); + + return result; +} + +QString AudioDeviceScriptingInterface::getInputDevice() { + return Application::getInstance()->getAudio()->getDeviceName(QAudio::AudioInput); +} + +QString AudioDeviceScriptingInterface::getOutputDevice() { + return Application::getInstance()->getAudio()->getDeviceName(QAudio::AudioOutput); +} + +QString AudioDeviceScriptingInterface::getDefaultInputDevice() { + return Application::getInstance()->getAudio()->getDefaultDeviceName(QAudio::AudioInput); +} + +QString AudioDeviceScriptingInterface::getDefaultOutputDevice() { + return Application::getInstance()->getAudio()->getDefaultDeviceName(QAudio::AudioOutput); +} + +QVector AudioDeviceScriptingInterface::getInputDevices() { + return Application::getInstance()->getAudio()->getDeviceNames(QAudio::AudioInput); +} + +QVector AudioDeviceScriptingInterface::getOutputDevices() { + return Application::getInstance()->getAudio()->getDeviceNames(QAudio::AudioOutput); +} + + +float AudioDeviceScriptingInterface::getInputVolume() { + return Application::getInstance()->getAudio()->getInputVolume(); +} + +void AudioDeviceScriptingInterface::setInputVolume(float volume) { + Application::getInstance()->getAudio()->setInputVolume(volume); +} diff --git a/interface/src/scripting/AudioDeviceScriptingInterface.h b/interface/src/scripting/AudioDeviceScriptingInterface.h new file mode 100644 index 0000000000..adc86cb15c --- /dev/null +++ b/interface/src/scripting/AudioDeviceScriptingInterface.h @@ -0,0 +1,41 @@ +// +// AudioDeviceScriptingInterface.h +// hifi +// +// Created by Brad Hefta-Gaub on 3/22/14 +// Copyright (c) 2014 HighFidelity, Inc. All rights reserved. +// + +#ifndef __hifi__AudioDeviceScriptingInterface__ +#define __hifi__AudioDeviceScriptingInterface__ + +#include +#include +#include + +#include "Application.h" + +class AudioDeviceScriptingInterface : public QObject { + Q_OBJECT + AudioDeviceScriptingInterface() { }; +public: + static AudioDeviceScriptingInterface* getInstance(); + +public slots: + bool setInputDevice(const QString& deviceName); + bool setOutputDevice(const QString& deviceName); + + QString getInputDevice(); + QString getOutputDevice(); + + QString getDefaultInputDevice(); + QString getDefaultOutputDevice(); + + QVector getInputDevices(); + QVector getOutputDevices(); + + float getInputVolume(); + void setInputVolume(float volume); +}; + +#endif /* defined(__hifi__AudioDeviceScriptingInterface__) */ diff --git a/interface/src/ClipboardScriptingInterface.cpp b/interface/src/scripting/ClipboardScriptingInterface.cpp similarity index 100% rename from interface/src/ClipboardScriptingInterface.cpp rename to interface/src/scripting/ClipboardScriptingInterface.cpp diff --git a/interface/src/ClipboardScriptingInterface.h b/interface/src/scripting/ClipboardScriptingInterface.h similarity index 100% rename from interface/src/ClipboardScriptingInterface.h rename to interface/src/scripting/ClipboardScriptingInterface.h diff --git a/interface/src/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp similarity index 100% rename from interface/src/ControllerScriptingInterface.cpp rename to interface/src/scripting/ControllerScriptingInterface.cpp diff --git a/interface/src/ControllerScriptingInterface.h b/interface/src/scripting/ControllerScriptingInterface.h similarity index 100% rename from interface/src/ControllerScriptingInterface.h rename to interface/src/scripting/ControllerScriptingInterface.h diff --git a/interface/src/MenuScriptingInterface.cpp b/interface/src/scripting/MenuScriptingInterface.cpp similarity index 100% rename from interface/src/MenuScriptingInterface.cpp rename to interface/src/scripting/MenuScriptingInterface.cpp diff --git a/interface/src/MenuScriptingInterface.h b/interface/src/scripting/MenuScriptingInterface.h similarity index 100% rename from interface/src/MenuScriptingInterface.h rename to interface/src/scripting/MenuScriptingInterface.h diff --git a/interface/src/scripting/SettingsScriptingInterface.cpp b/interface/src/scripting/SettingsScriptingInterface.cpp new file mode 100644 index 0000000000..2a788c2776 --- /dev/null +++ b/interface/src/scripting/SettingsScriptingInterface.cpp @@ -0,0 +1,36 @@ +// +// SettingsScriptingInterface.cpp +// hifi +// +// Created by Brad Hefta-Gaub on 2/25/14 +// Copyright (c) 2014 HighFidelity, Inc. All rights reserved. +// + +#include "Application.h" +#include "SettingsScriptingInterface.h" + + +SettingsScriptingInterface* SettingsScriptingInterface::getInstance() { + static SettingsScriptingInterface sharedInstance; + return &sharedInstance; +} + +QVariant SettingsScriptingInterface::getValue(const QString& setting) { + QSettings* settings = Application::getInstance()->lockSettings(); + QVariant value = settings->value(setting); + Application::getInstance()->unlockSettings(); + return value; +} + +QVariant SettingsScriptingInterface::getValue(const QString& setting, const QVariant& defaultValue) { + QSettings* settings = Application::getInstance()->lockSettings(); + QVariant value = settings->value(setting, defaultValue); + Application::getInstance()->unlockSettings(); + return value; +} + +void SettingsScriptingInterface::setValue(const QString& setting, const QVariant& value) { + QSettings* settings = Application::getInstance()->lockSettings(); + settings->setValue(setting, value); + Application::getInstance()->unlockSettings(); +} diff --git a/interface/src/scripting/SettingsScriptingInterface.h b/interface/src/scripting/SettingsScriptingInterface.h new file mode 100644 index 0000000000..12bda2173f --- /dev/null +++ b/interface/src/scripting/SettingsScriptingInterface.h @@ -0,0 +1,30 @@ +// +// SettingsScriptingInterface.h +// hifi +// +// Created by Brad Hefta-Gaub on 3/22/14 +// Copyright (c) 2014 HighFidelity, Inc. All rights reserved. +// + +#ifndef __hifi__SettingsScriptingInterface__ +#define __hifi__SettingsScriptingInterface__ + +#include +#include +#include + +#include "Application.h" + +class SettingsScriptingInterface : public QObject { + Q_OBJECT + SettingsScriptingInterface() { }; +public: + static SettingsScriptingInterface* getInstance(); + +public slots: + QVariant getValue(const QString& setting); + QVariant getValue(const QString& setting, const QVariant& defaultValue); + void setValue(const QString& setting, const QVariant& value); +}; + +#endif /* defined(__hifi__SettingsScriptingInterface__) */ diff --git a/interface/src/BandwidthMeter.cpp b/interface/src/ui/BandwidthMeter.cpp similarity index 100% rename from interface/src/BandwidthMeter.cpp rename to interface/src/ui/BandwidthMeter.cpp diff --git a/interface/src/BandwidthMeter.h b/interface/src/ui/BandwidthMeter.h similarity index 100% rename from interface/src/BandwidthMeter.h rename to interface/src/ui/BandwidthMeter.h diff --git a/interface/src/ImportDialog.cpp b/interface/src/ui/ImportDialog.cpp similarity index 100% rename from interface/src/ImportDialog.cpp rename to interface/src/ui/ImportDialog.cpp diff --git a/interface/src/ImportDialog.h b/interface/src/ui/ImportDialog.h similarity index 100% rename from interface/src/ImportDialog.h rename to interface/src/ui/ImportDialog.h diff --git a/interface/src/InfoView.cpp b/interface/src/ui/InfoView.cpp similarity index 89% rename from interface/src/InfoView.cpp rename to interface/src/ui/InfoView.cpp index fbf63666d8..8ed4da254c 100644 --- a/interface/src/InfoView.cpp +++ b/interface/src/ui/InfoView.cpp @@ -38,11 +38,12 @@ void InfoView::forcedShow() { } bool InfoView::shouldShow() { + bool shouldShow = false; if (_forced) { return true; } - QSettings* settings = Application::getInstance()->getSettings(); + QSettings* settings = Application::getInstance()->lockSettings(); QString lastVersion = settings->value(SETTINGS_VERSION_KEY).toString(); @@ -51,10 +52,12 @@ bool InfoView::shouldShow() { if (version != QString::null && (lastVersion == QString::null || lastVersion != version)) { settings->setValue(SETTINGS_VERSION_KEY, version); - return true; + shouldShow = true; } else { - return false; - } + shouldShow = false; + } + Application::getInstance()->unlockSettings(); + return shouldShow; } void InfoView::loaded(bool ok) { diff --git a/interface/src/InfoView.h b/interface/src/ui/InfoView.h similarity index 100% rename from interface/src/InfoView.h rename to interface/src/ui/InfoView.h diff --git a/interface/src/ModelBrowser.cpp b/interface/src/ui/ModelBrowser.cpp similarity index 100% rename from interface/src/ModelBrowser.cpp rename to interface/src/ui/ModelBrowser.cpp diff --git a/interface/src/ModelBrowser.h b/interface/src/ui/ModelBrowser.h similarity index 100% rename from interface/src/ModelBrowser.h rename to interface/src/ui/ModelBrowser.h diff --git a/interface/src/Oscilloscope.cpp b/interface/src/ui/Oscilloscope.cpp similarity index 100% rename from interface/src/Oscilloscope.cpp rename to interface/src/ui/Oscilloscope.cpp diff --git a/interface/src/Oscilloscope.h b/interface/src/ui/Oscilloscope.h similarity index 100% rename from interface/src/Oscilloscope.h rename to interface/src/ui/Oscilloscope.h diff --git a/interface/src/ui/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp similarity index 98% rename from interface/src/ui/Base3DOverlay.cpp rename to interface/src/ui/overlays/Base3DOverlay.cpp index 67e7ea25f2..bcd2ca1cd2 100644 --- a/interface/src/ui/Base3DOverlay.cpp +++ b/interface/src/ui/overlays/Base3DOverlay.cpp @@ -12,7 +12,6 @@ #include #include "Base3DOverlay.h" -#include "TextRenderer.h" const glm::vec3 DEFAULT_POSITION = glm::vec3(0.0f, 0.0f, 0.0f); const float DEFAULT_LINE_WIDTH = 1.0f; diff --git a/interface/src/ui/Base3DOverlay.h b/interface/src/ui/overlays/Base3DOverlay.h similarity index 100% rename from interface/src/ui/Base3DOverlay.h rename to interface/src/ui/overlays/Base3DOverlay.h diff --git a/interface/src/ui/Cube3DOverlay.cpp b/interface/src/ui/overlays/Cube3DOverlay.cpp similarity index 100% rename from interface/src/ui/Cube3DOverlay.cpp rename to interface/src/ui/overlays/Cube3DOverlay.cpp diff --git a/interface/src/ui/Cube3DOverlay.h b/interface/src/ui/overlays/Cube3DOverlay.h similarity index 100% rename from interface/src/ui/Cube3DOverlay.h rename to interface/src/ui/overlays/Cube3DOverlay.h diff --git a/interface/src/ui/ImageOverlay.cpp b/interface/src/ui/overlays/ImageOverlay.cpp similarity index 100% rename from interface/src/ui/ImageOverlay.cpp rename to interface/src/ui/overlays/ImageOverlay.cpp diff --git a/interface/src/ui/ImageOverlay.h b/interface/src/ui/overlays/ImageOverlay.h similarity index 100% rename from interface/src/ui/ImageOverlay.h rename to interface/src/ui/overlays/ImageOverlay.h diff --git a/interface/src/ui/Line3DOverlay.cpp b/interface/src/ui/overlays/Line3DOverlay.cpp similarity index 100% rename from interface/src/ui/Line3DOverlay.cpp rename to interface/src/ui/overlays/Line3DOverlay.cpp diff --git a/interface/src/ui/Line3DOverlay.h b/interface/src/ui/overlays/Line3DOverlay.h similarity index 100% rename from interface/src/ui/Line3DOverlay.h rename to interface/src/ui/overlays/Line3DOverlay.h diff --git a/interface/src/ui/LocalVoxelsOverlay.cpp b/interface/src/ui/overlays/LocalVoxelsOverlay.cpp similarity index 98% rename from interface/src/ui/LocalVoxelsOverlay.cpp rename to interface/src/ui/overlays/LocalVoxelsOverlay.cpp index 7eaf9ed5c5..460f4eadb6 100644 --- a/interface/src/ui/LocalVoxelsOverlay.cpp +++ b/interface/src/ui/overlays/LocalVoxelsOverlay.cpp @@ -12,10 +12,10 @@ #include #include -#include #include #include "LocalVoxelsOverlay.h" +#include "voxels/VoxelSystem.h" QMap LocalVoxelsOverlay::_voxelSystemMap; diff --git a/interface/src/ui/LocalVoxelsOverlay.h b/interface/src/ui/overlays/LocalVoxelsOverlay.h similarity index 100% rename from interface/src/ui/LocalVoxelsOverlay.h rename to interface/src/ui/overlays/LocalVoxelsOverlay.h diff --git a/interface/src/ui/Overlay.cpp b/interface/src/ui/overlays/Overlay.cpp similarity index 100% rename from interface/src/ui/Overlay.cpp rename to interface/src/ui/overlays/Overlay.cpp diff --git a/interface/src/ui/Overlay.h b/interface/src/ui/overlays/Overlay.h similarity index 100% rename from interface/src/ui/Overlay.h rename to interface/src/ui/overlays/Overlay.h diff --git a/interface/src/ui/Overlay2D.cpp b/interface/src/ui/overlays/Overlay2D.cpp similarity index 100% rename from interface/src/ui/Overlay2D.cpp rename to interface/src/ui/overlays/Overlay2D.cpp diff --git a/interface/src/ui/Overlay2D.h b/interface/src/ui/overlays/Overlay2D.h similarity index 100% rename from interface/src/ui/Overlay2D.h rename to interface/src/ui/overlays/Overlay2D.h diff --git a/interface/src/ui/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp similarity index 100% rename from interface/src/ui/Overlays.cpp rename to interface/src/ui/overlays/Overlays.cpp diff --git a/interface/src/ui/Overlays.h b/interface/src/ui/overlays/Overlays.h similarity index 100% rename from interface/src/ui/Overlays.h rename to interface/src/ui/overlays/Overlays.h diff --git a/interface/src/ui/Sphere3DOverlay.cpp b/interface/src/ui/overlays/Sphere3DOverlay.cpp similarity index 100% rename from interface/src/ui/Sphere3DOverlay.cpp rename to interface/src/ui/overlays/Sphere3DOverlay.cpp diff --git a/interface/src/ui/Sphere3DOverlay.h b/interface/src/ui/overlays/Sphere3DOverlay.h similarity index 100% rename from interface/src/ui/Sphere3DOverlay.h rename to interface/src/ui/overlays/Sphere3DOverlay.h diff --git a/interface/src/ui/TextOverlay.cpp b/interface/src/ui/overlays/TextOverlay.cpp similarity index 98% rename from interface/src/ui/TextOverlay.cpp rename to interface/src/ui/overlays/TextOverlay.cpp index edaec6849a..1a6edb3ea2 100644 --- a/interface/src/ui/TextOverlay.cpp +++ b/interface/src/ui/overlays/TextOverlay.cpp @@ -12,7 +12,7 @@ #include #include "TextOverlay.h" -#include "TextRenderer.h" +#include "ui/TextRenderer.h" TextOverlay::TextOverlay() : _leftMargin(DEFAULT_MARGIN), diff --git a/interface/src/ui/TextOverlay.h b/interface/src/ui/overlays/TextOverlay.h similarity index 100% rename from interface/src/ui/TextOverlay.h rename to interface/src/ui/overlays/TextOverlay.h diff --git a/interface/src/ui/Volume3DOverlay.cpp b/interface/src/ui/overlays/Volume3DOverlay.cpp similarity index 100% rename from interface/src/ui/Volume3DOverlay.cpp rename to interface/src/ui/overlays/Volume3DOverlay.cpp diff --git a/interface/src/ui/Volume3DOverlay.h b/interface/src/ui/overlays/Volume3DOverlay.h similarity index 100% rename from interface/src/ui/Volume3DOverlay.h rename to interface/src/ui/overlays/Volume3DOverlay.h diff --git a/interface/src/PrimitiveRenderer.cpp b/interface/src/voxels/PrimitiveRenderer.cpp similarity index 100% rename from interface/src/PrimitiveRenderer.cpp rename to interface/src/voxels/PrimitiveRenderer.cpp diff --git a/interface/src/PrimitiveRenderer.h b/interface/src/voxels/PrimitiveRenderer.h similarity index 100% rename from interface/src/PrimitiveRenderer.h rename to interface/src/voxels/PrimitiveRenderer.h diff --git a/interface/src/VoxelFade.cpp b/interface/src/voxels/VoxelFade.cpp similarity index 100% rename from interface/src/VoxelFade.cpp rename to interface/src/voxels/VoxelFade.cpp diff --git a/interface/src/VoxelFade.h b/interface/src/voxels/VoxelFade.h similarity index 100% rename from interface/src/VoxelFade.h rename to interface/src/voxels/VoxelFade.h diff --git a/interface/src/VoxelHideShowThread.cpp b/interface/src/voxels/VoxelHideShowThread.cpp similarity index 100% rename from interface/src/VoxelHideShowThread.cpp rename to interface/src/voxels/VoxelHideShowThread.cpp diff --git a/interface/src/VoxelHideShowThread.h b/interface/src/voxels/VoxelHideShowThread.h similarity index 100% rename from interface/src/VoxelHideShowThread.h rename to interface/src/voxels/VoxelHideShowThread.h diff --git a/interface/src/VoxelImporter.cpp b/interface/src/voxels/VoxelImporter.cpp similarity index 97% rename from interface/src/VoxelImporter.cpp rename to interface/src/voxels/VoxelImporter.cpp index 9d8b8ad811..d3c1b259ae 100644 --- a/interface/src/VoxelImporter.cpp +++ b/interface/src/voxels/VoxelImporter.cpp @@ -6,13 +6,17 @@ // Copyright (c) 2013 High Fidelity, Inc. All rights reserved. // -#include -#include -#include +// include this before QGLWidget, which includes an earlier version of OpenGL +#include "InterfaceConfig.h" #include #include +#include +#include + +#include "voxels/VoxelImporter.h" + const QString SETTINGS_GROUP_NAME = "VoxelImport"; const QString IMPORT_DIALOG_SETTINGS_KEY = "ImportDialogSettings"; diff --git a/interface/src/VoxelImporter.h b/interface/src/voxels/VoxelImporter.h similarity index 93% rename from interface/src/VoxelImporter.h rename to interface/src/voxels/VoxelImporter.h index e77abaf18d..9ebfc2eef2 100644 --- a/interface/src/VoxelImporter.h +++ b/interface/src/voxels/VoxelImporter.h @@ -9,12 +9,12 @@ #ifndef __hifi__VoxelImporter__ #define __hifi__VoxelImporter__ -#include -#include - #include #include +#include "ui/ImportDialog.h" +#include "voxels/VoxelSystem.h" + class ImportTask; class VoxelImporter : public QObject { diff --git a/interface/src/VoxelPacketProcessor.cpp b/interface/src/voxels/VoxelPacketProcessor.cpp similarity index 100% rename from interface/src/VoxelPacketProcessor.cpp rename to interface/src/voxels/VoxelPacketProcessor.cpp diff --git a/interface/src/VoxelPacketProcessor.h b/interface/src/voxels/VoxelPacketProcessor.h similarity index 100% rename from interface/src/VoxelPacketProcessor.h rename to interface/src/voxels/VoxelPacketProcessor.h diff --git a/interface/src/VoxelSystem.cpp b/interface/src/voxels/VoxelSystem.cpp similarity index 100% rename from interface/src/VoxelSystem.cpp rename to interface/src/voxels/VoxelSystem.cpp diff --git a/interface/src/VoxelSystem.h b/interface/src/voxels/VoxelSystem.h similarity index 100% rename from interface/src/VoxelSystem.h rename to interface/src/voxels/VoxelSystem.h diff --git a/libraries/embedded-webserver/src/HTTPConnection.cpp b/libraries/embedded-webserver/src/HTTPConnection.cpp index 50ce72e0cd..8fc0a25dca 100755 --- a/libraries/embedded-webserver/src/HTTPConnection.cpp +++ b/libraries/embedded-webserver/src/HTTPConnection.cpp @@ -180,7 +180,7 @@ void HTTPConnection::readHeaders() { QByteArray clength = _requestHeaders.value("Content-Length"); if (clength.isEmpty()) { - _parentManager->handleHTTPRequest(this, _requestUrl.path()); + _parentManager->handleHTTPRequest(this, _requestUrl); } else { _requestContent.resize(clength.toInt()); diff --git a/libraries/embedded-webserver/src/HTTPManager.cpp b/libraries/embedded-webserver/src/HTTPManager.cpp index a217555a78..d106b6df59 100755 --- a/libraries/embedded-webserver/src/HTTPManager.cpp +++ b/libraries/embedded-webserver/src/HTTPManager.cpp @@ -15,15 +15,15 @@ #include "HTTPConnection.h" #include "HTTPManager.h" -bool HTTPManager::handleHTTPRequest(HTTPConnection* connection, const QString& path) { - if (_requestHandler && _requestHandler->handleHTTPRequest(connection, path)) { +bool HTTPManager::handleHTTPRequest(HTTPConnection* connection, const QUrl& url) { + if (_requestHandler && _requestHandler->handleHTTPRequest(connection, url)) { // this request was handled by our _requestHandler object // so we don't need to attempt to do so in the document root return true; } // check to see if there is a file to serve from the document root for this path - QString subPath = path; + QString subPath = url.path(); // remove any slash at the beginning of the path if (subPath.startsWith('/')) { @@ -38,6 +38,10 @@ bool HTTPManager::handleHTTPRequest(HTTPConnection* connection, const QString& p // this could be a directory with a trailing slash // send a redirect to the path with a slash so we can QString redirectLocation = '/' + subPath + '/'; + + if (!url.query().isEmpty()) { + redirectLocation += "?" + url.query(); + } QHash redirectHeader; redirectHeader.insert(QByteArray("Location"), redirectLocation.toUtf8()); diff --git a/libraries/embedded-webserver/src/HTTPManager.h b/libraries/embedded-webserver/src/HTTPManager.h index e3b44e7cdc..a8f9d723fa 100755 --- a/libraries/embedded-webserver/src/HTTPManager.h +++ b/libraries/embedded-webserver/src/HTTPManager.h @@ -20,7 +20,7 @@ class HTTPConnection; class HTTPRequestHandler { public: /// Handles an HTTP request. - virtual bool handleHTTPRequest(HTTPConnection* connection, const QString& path) = 0; + virtual bool handleHTTPRequest(HTTPConnection* connection, const QUrl& url) = 0; }; /// Handles HTTP connections @@ -30,7 +30,7 @@ public: /// Initializes the manager. HTTPManager(quint16 port, const QString& documentRoot, HTTPRequestHandler* requestHandler = NULL, QObject* parent = 0); - bool handleHTTPRequest(HTTPConnection* connection, const QString& path); + bool handleHTTPRequest(HTTPConnection* connection, const QUrl& url); protected slots: /// Accepts all pending connections diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index c820347cab..38948071ff 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -144,6 +144,7 @@ void ScriptEngine::init() { qScriptRegisterMetaType(&_engine, ParticleIDtoScriptValue, ParticleIDfromScriptValue); qScriptRegisterSequenceMetaType >(&_engine); qScriptRegisterSequenceMetaType >(&_engine); + qScriptRegisterSequenceMetaType >(&_engine); QScriptValue soundConstructorValue = _engine.newFunction(soundConstructor); QScriptValue soundMetaObject = _engine.newQMetaObject(&Sound::staticMetaObject, soundConstructorValue);