mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 18:13:05 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi
This commit is contained in:
commit
f1fd8175d2
80 changed files with 552 additions and 154 deletions
|
@ -67,7 +67,11 @@ void attachNewBufferToNode(Node *newNode) {
|
||||||
AudioMixer::AudioMixer(const QByteArray& packet) :
|
AudioMixer::AudioMixer(const QByteArray& packet) :
|
||||||
ThreadedAssignment(packet),
|
ThreadedAssignment(packet),
|
||||||
_trailingSleepRatio(1.0f),
|
_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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
++_sumMixes;
|
||||||
|
|
||||||
glm::quat inverseOrientation = glm::inverse(listeningNodeBuffer->getOrientation());
|
glm::quat inverseOrientation = glm::inverse(listeningNodeBuffer->getOrientation());
|
||||||
|
|
||||||
float distanceSquareToSource = glm::dot(relativePosition, relativePosition);
|
float distanceSquareToSource = glm::dot(relativePosition, relativePosition);
|
||||||
|
@ -352,8 +358,21 @@ void AudioMixer::readPendingDatagrams() {
|
||||||
|
|
||||||
void AudioMixer::sendStatsPacket() {
|
void AudioMixer::sendStatsPacket() {
|
||||||
static QJsonObject statsObject;
|
static QJsonObject statsObject;
|
||||||
statsObject["trailing_sleep"] = _trailingSleepRatio;
|
statsObject["trailing_sleep_percentage"] = _trailingSleepRatio * 100.0f;
|
||||||
statsObject["min_audability_threshold"] = _minAudibilityThreshold;
|
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);
|
NodeList::getInstance()->sendStatsToDomainServer(statsObject);
|
||||||
}
|
}
|
||||||
|
@ -382,7 +401,6 @@ void AudioMixer::run() {
|
||||||
+ numBytesForPacketHeaderGivenPacketType(PacketTypeMixedAudio)];
|
+ numBytesForPacketHeaderGivenPacketType(PacketTypeMixedAudio)];
|
||||||
|
|
||||||
int usecToSleep = BUFFER_SEND_INTERVAL_USECS;
|
int usecToSleep = BUFFER_SEND_INTERVAL_USECS;
|
||||||
float audabilityCutoffRatio = 0;
|
|
||||||
|
|
||||||
const int TRAILING_AVERAGE_FRAMES = 100;
|
const int TRAILING_AVERAGE_FRAMES = 100;
|
||||||
int framesSinceCutoffEvent = TRAILING_AVERAGE_FRAMES;
|
int framesSinceCutoffEvent = TRAILING_AVERAGE_FRAMES;
|
||||||
|
@ -410,7 +428,7 @@ void AudioMixer::run() {
|
||||||
_trailingSleepRatio = (PREVIOUS_FRAMES_RATIO * _trailingSleepRatio)
|
_trailingSleepRatio = (PREVIOUS_FRAMES_RATIO * _trailingSleepRatio)
|
||||||
+ (usecToSleep * CURRENT_FRAME_RATIO / (float) BUFFER_SEND_INTERVAL_USECS);
|
+ (usecToSleep * CURRENT_FRAME_RATIO / (float) BUFFER_SEND_INTERVAL_USECS);
|
||||||
|
|
||||||
float lastCutoffRatio = audabilityCutoffRatio;
|
float lastCutoffRatio = _performanceThrottling;
|
||||||
bool hasRatioChanged = false;
|
bool hasRatioChanged = false;
|
||||||
|
|
||||||
if (framesSinceCutoffEvent >= TRAILING_AVERAGE_FRAMES) {
|
if (framesSinceCutoffEvent >= TRAILING_AVERAGE_FRAMES) {
|
||||||
|
@ -420,27 +438,27 @@ void AudioMixer::run() {
|
||||||
|
|
||||||
if (_trailingSleepRatio <= STRUGGLE_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD) {
|
if (_trailingSleepRatio <= STRUGGLE_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD) {
|
||||||
// we're struggling - change our min required loudness to reduce some load
|
// 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"
|
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;
|
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
|
// we've recovered and can back off the required loudness
|
||||||
audabilityCutoffRatio = audabilityCutoffRatio - RATIO_BACK_OFF;
|
_performanceThrottling = _performanceThrottling - RATIO_BACK_OFF;
|
||||||
|
|
||||||
if (audabilityCutoffRatio < 0) {
|
if (_performanceThrottling < 0) {
|
||||||
audabilityCutoffRatio = 0;
|
_performanceThrottling = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "Mixer is recovering, sleeping" << _trailingSleepRatio * 100 << "% of frame time. Old cutoff was"
|
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;
|
hasRatioChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasRatioChanged) {
|
if (hasRatioChanged) {
|
||||||
// set out min audability threshold from the new ratio
|
// 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;
|
qDebug() << "Minimum audability required to be mixed is now" << _minAudibilityThreshold;
|
||||||
|
|
||||||
framesSinceCutoffEvent = 0;
|
framesSinceCutoffEvent = 0;
|
||||||
|
@ -460,6 +478,8 @@ void AudioMixer::run() {
|
||||||
|
|
||||||
memcpy(clientMixBuffer + numBytesPacketHeader, _clientSamples, NETWORK_BUFFER_LENGTH_BYTES_STEREO);
|
memcpy(clientMixBuffer + numBytesPacketHeader, _clientSamples, NETWORK_BUFFER_LENGTH_BYTES_STEREO);
|
||||||
nodeList->writeDatagram(clientMixBuffer, NETWORK_BUFFER_LENGTH_BYTES_STEREO + numBytesPacketHeader, node);
|
nodeList->writeDatagram(clientMixBuffer, NETWORK_BUFFER_LENGTH_BYTES_STEREO + numBytesPacketHeader, node);
|
||||||
|
|
||||||
|
++_sumListeners;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -470,6 +490,8 @@ void AudioMixer::run() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
++_numStatFrames;
|
||||||
|
|
||||||
QCoreApplication::processEvents();
|
QCoreApplication::processEvents();
|
||||||
|
|
||||||
if (_isFinished) {
|
if (_isFinished) {
|
||||||
|
|
|
@ -44,6 +44,10 @@ private:
|
||||||
|
|
||||||
float _trailingSleepRatio;
|
float _trailingSleepRatio;
|
||||||
float _minAudibilityThreshold;
|
float _minAudibilityThreshold;
|
||||||
|
float _performanceThrottling;
|
||||||
|
int _numStatFrames;
|
||||||
|
int _sumListeners;
|
||||||
|
int _sumMixes;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* defined(__hifi__AudioMixer__) */
|
#endif /* defined(__hifi__AudioMixer__) */
|
||||||
|
|
|
@ -236,7 +236,7 @@ void OctreeServer::initHTTPManager(int port) {
|
||||||
_httpManager = new HTTPManager(port, documentRoot, this, this);
|
_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
|
#ifdef FORCE_CRASH
|
||||||
if (connection->requestOperation() == QNetworkAccessManager::GetOperation
|
if (connection->requestOperation() == QNetworkAccessManager::GetOperation
|
||||||
|
@ -259,9 +259,9 @@ bool OctreeServer::handleHTTPRequest(HTTPConnection* connection, const QString&
|
||||||
bool showStats = false;
|
bool showStats = false;
|
||||||
|
|
||||||
if (connection->requestOperation() == QNetworkAccessManager::GetOperation) {
|
if (connection->requestOperation() == QNetworkAccessManager::GetOperation) {
|
||||||
if (path == "/") {
|
if (url.path() == "/") {
|
||||||
showStats = true;
|
showStats = true;
|
||||||
} else if (path == "/resetStats") {
|
} else if (url.path() == "/resetStats") {
|
||||||
_octreeInboundPacketProcessor->resetStats();
|
_octreeInboundPacketProcessor->resetStats();
|
||||||
resetSendingStats();
|
resetSendingStats();
|
||||||
showStats = true;
|
showStats = true;
|
||||||
|
|
|
@ -97,7 +97,7 @@ public:
|
||||||
static void trackPacketSendingTime(float time);
|
static void trackPacketSendingTime(float time);
|
||||||
static float getAveragePacketSendingTime() { return _averagePacketSendingTime.getAverage(); }
|
static float getAveragePacketSendingTime() { return _averagePacketSendingTime.getAverage(); }
|
||||||
|
|
||||||
bool handleHTTPRequest(HTTPConnection* connection, const QString& path);
|
bool handleHTTPRequest(HTTPConnection* connection, const QUrl& url);
|
||||||
|
|
||||||
virtual void aboutToFinish();
|
virtual void aboutToFinish();
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
</div>
|
</div>
|
||||||
<script src='js/jquery-2.0.3.min.js'></script>
|
<script src='/js/jquery-2.0.3.min.js'></script>
|
||||||
<script src="js/bootstrap.min.js"></script>
|
<script src='/js/bootstrap.min.js'></script>
|
|
@ -4,8 +4,8 @@
|
||||||
<title>domain-server</title>
|
<title>domain-server</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<!-- Bootstrap -->
|
<!-- Bootstrap -->
|
||||||
<link href="css/bootstrap.min.css" rel="stylesheet" media="screen">
|
<link href="/css/bootstrap.min.css" rel="stylesheet" media="screen">
|
||||||
<link href="css/style.css" rel="stylesheet" media="screen">
|
<link href="/css/style.css" rel="stylesheet" media="screen">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
|
@ -7,7 +7,7 @@ $(document).ready(function(){
|
||||||
$.each(json.nodes, function (uuid, data) {
|
$.each(json.nodes, function (uuid, data) {
|
||||||
nodesTableBody += "<tr>";
|
nodesTableBody += "<tr>";
|
||||||
nodesTableBody += "<td>" + data.type + "</td>";
|
nodesTableBody += "<td>" + data.type + "</td>";
|
||||||
nodesTableBody += "<td><a href='nodes/" + uuid + "'>" + uuid + "</a></td>";
|
nodesTableBody += "<td><a href='stats/?uuid=" + uuid + "'>" + uuid + "</a></td>";
|
||||||
nodesTableBody += "<td>" + (data.pool ? data.pool : "") + "</td>";
|
nodesTableBody += "<td>" + (data.pool ? data.pool : "") + "</td>";
|
||||||
nodesTableBody += "<td>" + data.public.ip + "<span class='port'>:" + data.public.port + "</span></td>";
|
nodesTableBody += "<td>" + data.public.ip + "<span class='port'>:" + data.public.port + "</span></td>";
|
||||||
nodesTableBody += "<td>" + data.local.ip + "<span class='port'>:" + data.local.port + "</span></td>";
|
nodesTableBody += "<td>" + data.local.ip + "<span class='port'>:" + data.local.port + "</span></td>";
|
||||||
|
|
6
domain-server/resources/web/stats/index.shtml
Normal file
6
domain-server/resources/web/stats/index.shtml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<!--#include virtual="header.html"-->
|
||||||
|
<div id="stats-lead" class="table-lead"><h3>Stats</h3><div class="lead-line"></div></div>
|
||||||
|
<table id="stats-table" class="table"><tbody></tbody></table>
|
||||||
|
<!--#include virtual="footer.html"-->
|
||||||
|
<script src='js/stats.js'></script>
|
||||||
|
<!--#include virtual="page-end.html"-->
|
31
domain-server/resources/web/stats/js/stats.js
Normal file
31
domain-server/resources/web/stats/js/stats.js
Normal file
|
@ -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 += "<tr>";
|
||||||
|
statsTableBody += "<td>" + key + "</td>";
|
||||||
|
statsTableBody += "<td>" + value + "</td>";
|
||||||
|
statsTableBody += "</tr>";
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#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);
|
||||||
|
});
|
|
@ -651,14 +651,14 @@ QJsonObject DomainServer::jsonObjectForNode(const SharedNodePointer& node) {
|
||||||
return nodeJson;
|
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 JSON_MIME_TYPE = "application/json";
|
||||||
|
|
||||||
const QString URI_ASSIGNMENT = "/assignment";
|
const QString URI_ASSIGNMENT = "/assignment";
|
||||||
const QString URI_NODES = "/nodes";
|
const QString URI_NODES = "/nodes";
|
||||||
|
|
||||||
if (connection->requestOperation() == QNetworkAccessManager::GetOperation) {
|
if (connection->requestOperation() == QNetworkAccessManager::GetOperation) {
|
||||||
if (path == "/assignments.json") {
|
if (url.path() == "/assignments.json") {
|
||||||
// user is asking for json list of assignments
|
// user is asking for json list of assignments
|
||||||
|
|
||||||
// setup the JSON
|
// setup the JSON
|
||||||
|
@ -702,7 +702,7 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QString&
|
||||||
|
|
||||||
// we've processed this request
|
// we've processed this request
|
||||||
return true;
|
return true;
|
||||||
} else if (path == QString("%1.json").arg(URI_NODES)) {
|
} else if (url.path() == QString("%1.json").arg(URI_NODES)) {
|
||||||
// setup the JSON
|
// setup the JSON
|
||||||
QJsonObject rootJSON;
|
QJsonObject rootJSON;
|
||||||
QJsonObject nodesJSON;
|
QJsonObject nodesJSON;
|
||||||
|
@ -727,10 +727,10 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QString&
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
const QString NODE_REGEX_STRING =
|
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);
|
QRegExp nodeShowRegex(NODE_REGEX_STRING);
|
||||||
|
|
||||||
if (nodeShowRegex.indexIn(path) != -1) {
|
if (nodeShowRegex.indexIn(url.path()) != -1) {
|
||||||
QUuid matchingUUID = QUuid(nodeShowRegex.cap(1));
|
QUuid matchingUUID = QUuid(nodeShowRegex.cap(1));
|
||||||
|
|
||||||
// see if we have a node that matches this ID
|
// 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<DomainServerNodeData*>(matchingNode->getLinkedData())
|
QJsonDocument statsDocument(reinterpret_cast<DomainServerNodeData*>(matchingNode->getLinkedData())
|
||||||
->getStatsJSONObject());
|
->getStatsJSONObject());
|
||||||
|
|
||||||
// send the resposne
|
// send the response
|
||||||
connection->respond(HTTPConnection::StatusCode200, statsDocument.toJson(), qPrintable(JSON_MIME_TYPE));
|
connection->respond(HTTPConnection::StatusCode200, statsDocument.toJson(), qPrintable(JSON_MIME_TYPE));
|
||||||
|
|
||||||
// tell the caller we processed the request
|
// tell the caller we processed the request
|
||||||
|
@ -749,7 +749,7 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QString&
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (connection->requestOperation() == QNetworkAccessManager::PostOperation) {
|
} 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
|
// this is a script upload - ask the HTTPConnection to parse the form data
|
||||||
QList<FormData> formData = connection->parseFormData();
|
QList<FormData> formData = connection->parseFormData();
|
||||||
|
|
||||||
|
@ -796,11 +796,11 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QString&
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (connection->requestOperation() == QNetworkAccessManager::DeleteOperation) {
|
} 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
|
// this is a request to DELETE a node by UUID
|
||||||
|
|
||||||
// pull the UUID from the url
|
// 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()) {
|
if (!deleteUUID.isNull()) {
|
||||||
SharedNodePointer nodeToKill = NodeList::getInstance()->nodeWithUUID(deleteUUID);
|
SharedNodePointer nodeToKill = NodeList::getInstance()->nodeWithUUID(deleteUUID);
|
||||||
|
|
|
@ -30,7 +30,7 @@ public:
|
||||||
|
|
||||||
bool requiresAuthentication() const { return !_nodeAuthenticationURL.isEmpty(); }
|
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);
|
void exit(int retCode = 0);
|
||||||
|
|
||||||
|
|
52
examples/audioDeviceExample.js
Normal file
52
examples/audioDeviceExample.js
Normal file
|
@ -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();
|
18
examples/settingsExample.js
Normal file
18
examples/settingsExample.js
Normal file
|
@ -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();
|
|
@ -48,7 +48,7 @@ configure_file(InterfaceVersion.h.in "${PROJECT_BINARY_DIR}/includes/InterfaceVe
|
||||||
|
|
||||||
# grab the implementation and header files from src dirs
|
# grab the implementation and header files from src dirs
|
||||||
file(GLOB INTERFACE_SRCS src/*.cpp src/*.h)
|
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)
|
file(GLOB_RECURSE SUBDIR_SRCS src/${SUBDIR}/*.cpp src/${SUBDIR}/*.h)
|
||||||
set(INTERFACE_SRCS ${INTERFACE_SRCS} "${SUBDIR_SRCS}")
|
set(INTERFACE_SRCS ${INTERFACE_SRCS} "${SUBDIR_SRCS}")
|
||||||
endforeach(SUBDIR)
|
endforeach(SUBDIR)
|
||||||
|
|
|
@ -65,17 +65,21 @@
|
||||||
#include <FstReader.h>
|
#include <FstReader.h>
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "ClipboardScriptingInterface.h"
|
|
||||||
#include "InterfaceVersion.h"
|
#include "InterfaceVersion.h"
|
||||||
#include "Menu.h"
|
#include "Menu.h"
|
||||||
#include "MenuScriptingInterface.h"
|
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
#include "devices/OculusManager.h"
|
#include "devices/OculusManager.h"
|
||||||
#include "devices/TV3DManager.h"
|
#include "devices/TV3DManager.h"
|
||||||
#include "renderer/ProgramObject.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/Snapshot.h"
|
||||||
|
#include "ui/TextRenderer.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -3559,6 +3563,8 @@ void Application::loadScript(const QString& fileNameString) {
|
||||||
|
|
||||||
scriptEngine->registerGlobalObject("Overlays", &_overlays);
|
scriptEngine->registerGlobalObject("Overlays", &_overlays);
|
||||||
scriptEngine->registerGlobalObject("Menu", MenuScriptingInterface::getInstance());
|
scriptEngine->registerGlobalObject("Menu", MenuScriptingInterface::getInstance());
|
||||||
|
scriptEngine->registerGlobalObject("Settings", SettingsScriptingInterface::getInstance());
|
||||||
|
scriptEngine->registerGlobalObject("AudioDevice", AudioDeviceScriptingInterface::getInstance());
|
||||||
|
|
||||||
QThread* workerThread = new QThread(this);
|
QThread* workerThread = new QThread(this);
|
||||||
|
|
||||||
|
|
|
@ -29,12 +29,12 @@
|
||||||
#include <ParticleEditPacketSender.h>
|
#include <ParticleEditPacketSender.h>
|
||||||
#include <ScriptEngine.h>
|
#include <ScriptEngine.h>
|
||||||
#include <OctreeQuery.h>
|
#include <OctreeQuery.h>
|
||||||
|
#include <ViewFrustum.h>
|
||||||
|
#include <VoxelEditPacketSender.h>
|
||||||
|
|
||||||
#include "Audio.h"
|
#include "Audio.h"
|
||||||
#include "BandwidthMeter.h"
|
|
||||||
#include "BuckyBalls.h"
|
#include "BuckyBalls.h"
|
||||||
#include "Camera.h"
|
#include "Camera.h"
|
||||||
#include "ControllerScriptingInterface.h"
|
|
||||||
#include "DatagramProcessor.h"
|
#include "DatagramProcessor.h"
|
||||||
#include "Environment.h"
|
#include "Environment.h"
|
||||||
#include "FileLogger.h"
|
#include "FileLogger.h"
|
||||||
|
@ -44,13 +44,6 @@
|
||||||
#include "PacketHeaders.h"
|
#include "PacketHeaders.h"
|
||||||
#include "ParticleTreeRenderer.h"
|
#include "ParticleTreeRenderer.h"
|
||||||
#include "Stars.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/Avatar.h"
|
||||||
#include "avatar/AvatarManager.h"
|
#include "avatar/AvatarManager.h"
|
||||||
#include "avatar/MyAvatar.h"
|
#include "avatar/MyAvatar.h"
|
||||||
|
@ -63,13 +56,20 @@
|
||||||
#include "renderer/PointShader.h"
|
#include "renderer/PointShader.h"
|
||||||
#include "renderer/TextureCache.h"
|
#include "renderer/TextureCache.h"
|
||||||
#include "renderer/VoxelShader.h"
|
#include "renderer/VoxelShader.h"
|
||||||
|
#include "scripting/ControllerScriptingInterface.h"
|
||||||
#include "ui/BandwidthDialog.h"
|
#include "ui/BandwidthDialog.h"
|
||||||
|
#include "ui/BandwidthMeter.h"
|
||||||
#include "ui/OctreeStatsDialog.h"
|
#include "ui/OctreeStatsDialog.h"
|
||||||
#include "ui/RearMirrorTools.h"
|
#include "ui/RearMirrorTools.h"
|
||||||
#include "ui/LodToolsDialog.h"
|
#include "ui/LodToolsDialog.h"
|
||||||
#include "ui/LogDialog.h"
|
#include "ui/LogDialog.h"
|
||||||
#include "ui/UpdateDialog.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;
|
class QAction;
|
||||||
|
@ -172,7 +172,11 @@ public:
|
||||||
Visage* getVisage() { return &_visage; }
|
Visage* getVisage() { return &_visage; }
|
||||||
SixenseManager* getSixenseManager() { return &_sixenseManager; }
|
SixenseManager* getSixenseManager() { return &_sixenseManager; }
|
||||||
BandwidthMeter* getBandwidthMeter() { return &_bandwidthMeter; }
|
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; }
|
QMainWindow* getWindow() { return _window; }
|
||||||
NodeToOctreeSceneStats* getOcteeSceneStats() { return &_octreeServerSceneStats; }
|
NodeToOctreeSceneStats* getOcteeSceneStats() { return &_octreeServerSceneStats; }
|
||||||
void lockOctreeSceneStats() { _octreeSceneStatsLock.lockForRead(); }
|
void lockOctreeSceneStats() { _octreeSceneStatsLock.lockForRead(); }
|
||||||
|
@ -353,6 +357,7 @@ private:
|
||||||
DatagramProcessor _datagramProcessor;
|
DatagramProcessor _datagramProcessor;
|
||||||
|
|
||||||
QNetworkAccessManager* _networkAccessManager;
|
QNetworkAccessManager* _networkAccessManager;
|
||||||
|
QMutex _settingsMutex;
|
||||||
QSettings* _settings;
|
QSettings* _settings;
|
||||||
|
|
||||||
glm::vec3 _gravity;
|
glm::vec3 _gravity;
|
||||||
|
|
|
@ -92,6 +92,16 @@ void Audio::reset() {
|
||||||
_ringBuffer.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) {
|
QAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) {
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
if (QAudioDeviceInfo::availableDevices(mode).size() > 1) {
|
if (QAudioDeviceInfo::availableDevices(mode).size() > 1) {
|
||||||
|
@ -249,27 +259,105 @@ void Audio::start() {
|
||||||
_desiredOutputFormat.setChannelCount(2);
|
_desiredOutputFormat.setChannelCount(2);
|
||||||
|
|
||||||
QAudioDeviceInfo inputDeviceInfo = defaultAudioDeviceForMode(QAudio::AudioInput);
|
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)) {
|
if (!inputFormatSupported || !outputFormatSupported) {
|
||||||
qDebug() << "The format to be used for audio input is" << _inputFormat;
|
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<QString> Audio::getDeviceNames(QAudio::Mode mode) {
|
||||||
|
QVector<QString> 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);
|
_audioInput = new QAudioInput(inputDeviceInfo, _inputFormat, this);
|
||||||
_numInputCallbackBytes = NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL * _inputFormat.channelCount()
|
_numInputCallbackBytes = NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL * _inputFormat.channelCount()
|
||||||
* (_inputFormat.sampleRate() / SAMPLE_RATE)
|
* (_inputFormat.sampleRate() / SAMPLE_RATE)
|
||||||
/ CALLBACK_ACCELERATOR_RATIO;
|
/ CALLBACK_ACCELERATOR_RATIO;
|
||||||
_audioInput->setBufferSize(_numInputCallbackBytes);
|
_audioInput->setBufferSize(_numInputCallbackBytes);
|
||||||
|
|
||||||
QAudioDeviceInfo outputDeviceInfo = defaultAudioDeviceForMode(QAudio::AudioOutput);
|
// how do we want to handle input working, but output not working?
|
||||||
qDebug() << "The audio output device is" << outputDeviceInfo.deviceName();
|
|
||||||
|
|
||||||
if (adjustedFormatForAudioDevice(outputDeviceInfo, _desiredOutputFormat, _outputFormat)) {
|
|
||||||
qDebug() << "The format to be used for audio output is" << _outputFormat;
|
|
||||||
|
|
||||||
_inputRingBuffer.resizeForFrameSize(_numInputCallbackBytes * CALLBACK_ACCELERATOR_RATIO / sizeof(int16_t));
|
_inputRingBuffer.resizeForFrameSize(_numInputCallbackBytes * CALLBACK_ACCELERATOR_RATIO / sizeof(int16_t));
|
||||||
_inputDevice = _audioInput->start();
|
_inputDevice = _audioInput->start();
|
||||||
connect(_inputDevice, SIGNAL(readyRead()), this, SLOT(handleAudioInput()));
|
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
|
// setup our general output device for audio-mixer audio
|
||||||
_audioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this);
|
_audioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this);
|
||||||
_audioOutput->setBufferSize(_ringBuffer.getSampleCapacity() * sizeof(int16_t));
|
_audioOutput->setBufferSize(_ringBuffer.getSampleCapacity() * sizeof(int16_t));
|
||||||
|
@ -278,17 +366,15 @@ void Audio::start() {
|
||||||
|
|
||||||
// setup a loopback audio output device
|
// setup a loopback audio output device
|
||||||
_loopbackAudioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this);
|
_loopbackAudioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this);
|
||||||
|
|
||||||
// setup a procedural audio output device
|
// setup a procedural audio output device
|
||||||
_proceduralAudioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this);
|
_proceduralAudioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this);
|
||||||
|
|
||||||
gettimeofday(&_lastReceiveTime, NULL);
|
gettimeofday(&_lastReceiveTime, NULL);
|
||||||
|
supportedFormat = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
return supportedFormat;
|
||||||
qDebug() << "Unable to set up audio I/O because of a problem with input or output formats.";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Audio::handleAudioInput() {
|
void Audio::handleAudioInput() {
|
||||||
|
@ -309,13 +395,15 @@ void Audio::handleAudioInput() {
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::EchoLocalAudio) && !_muted) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::EchoLocalAudio) && !_muted) {
|
||||||
// if this person wants local loopback add that to the locally injected audio
|
// 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
|
// we didn't have the loopback output device going so set that up now
|
||||||
_loopbackOutputDevice = _loopbackAudioOutput->start();
|
_loopbackOutputDevice = _loopbackAudioOutput->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_inputFormat == _outputFormat) {
|
if (_inputFormat == _outputFormat) {
|
||||||
_loopbackOutputDevice->write(inputByteArray);
|
if (_loopbackOutputDevice) {
|
||||||
|
_loopbackOutputDevice->write(inputByteArray);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
static float loopbackOutputToInputRatio = (_outputFormat.sampleRate() / (float) _inputFormat.sampleRate())
|
static float loopbackOutputToInputRatio = (_outputFormat.sampleRate() / (float) _inputFormat.sampleRate())
|
||||||
* (_outputFormat.channelCount() / _inputFormat.channelCount());
|
* (_outputFormat.channelCount() / _inputFormat.channelCount());
|
||||||
|
@ -326,7 +414,9 @@ void Audio::handleAudioInput() {
|
||||||
inputByteArray.size() / sizeof(int16_t),
|
inputByteArray.size() / sizeof(int16_t),
|
||||||
loopBackByteArray.size() / sizeof(int16_t), _inputFormat, _outputFormat);
|
loopBackByteArray.size() / sizeof(int16_t), _inputFormat, _outputFormat);
|
||||||
|
|
||||||
_loopbackOutputDevice->write(loopBackByteArray);
|
if (_loopbackOutputDevice) {
|
||||||
|
_loopbackOutputDevice->write(loopBackByteArray);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -455,7 +545,7 @@ void Audio::handleAudioInput() {
|
||||||
addProceduralSounds(monoAudioSamples,
|
addProceduralSounds(monoAudioSamples,
|
||||||
NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL);
|
NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL);
|
||||||
|
|
||||||
if (!_proceduralOutputDevice) {
|
if (!_proceduralOutputDevice && _proceduralAudioOutput) {
|
||||||
_proceduralOutputDevice = _proceduralAudioOutput->start();
|
_proceduralOutputDevice = _proceduralAudioOutput->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -469,7 +559,9 @@ void Audio::handleAudioInput() {
|
||||||
NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL * 4,
|
NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL * 4,
|
||||||
_desiredInputFormat, _outputFormat);
|
_desiredInputFormat, _outputFormat);
|
||||||
|
|
||||||
_proceduralOutputDevice->write(proceduralOutput);
|
if (_proceduralOutputDevice) {
|
||||||
|
_proceduralOutputDevice->write(proceduralOutput);
|
||||||
|
}
|
||||||
|
|
||||||
NodeList* nodeList = NodeList::getInstance();
|
NodeList* nodeList = NodeList::getInstance();
|
||||||
SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer);
|
SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer);
|
||||||
|
@ -553,7 +645,7 @@ void Audio::addReceivedAudioToBuffer(const QByteArray& audioByteArray) {
|
||||||
static float networkOutputToOutputRatio = (_desiredOutputFormat.sampleRate() / (float) _outputFormat.sampleRate())
|
static float networkOutputToOutputRatio = (_desiredOutputFormat.sampleRate() / (float) _outputFormat.sampleRate())
|
||||||
* (_desiredOutputFormat.channelCount() / (float) _outputFormat.channelCount());
|
* (_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 don't have any audio data left in the output buffer
|
||||||
// we just starved
|
// we just starved
|
||||||
//qDebug() << "Audio output just starved.";
|
//qDebug() << "Audio output just starved.";
|
||||||
|
|
|
@ -19,17 +19,20 @@
|
||||||
|
|
||||||
#include "InterfaceConfig.h"
|
#include "InterfaceConfig.h"
|
||||||
|
|
||||||
|
#include <QAudio>
|
||||||
|
#include <QAudioInput>
|
||||||
|
#include <QGLWidget>
|
||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
#include <QtCore/QVector>
|
#include <QtCore/QVector>
|
||||||
#include <QtMultimedia/QAudioFormat>
|
#include <QtMultimedia/QAudioFormat>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
#include <AbstractAudioInterface.h>
|
#include <AbstractAudioInterface.h>
|
||||||
#include <AudioRingBuffer.h>
|
#include <AudioRingBuffer.h>
|
||||||
#include <StdDev.h>
|
#include <StdDev.h>
|
||||||
|
|
||||||
#include "Oscilloscope.h"
|
#include "ui/Oscilloscope.h"
|
||||||
|
|
||||||
#include <QGLWidget>
|
|
||||||
|
|
||||||
static const int NUM_AUDIO_CHANNELS = 2;
|
static const int NUM_AUDIO_CHANNELS = 2;
|
||||||
|
|
||||||
|
@ -72,7 +75,7 @@ public:
|
||||||
|
|
||||||
int getNetworkSampleRate() { return SAMPLE_RATE; }
|
int getNetworkSampleRate() { return SAMPLE_RATE; }
|
||||||
int getNetworkBufferLengthSamplesPerChannel() { return NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; }
|
int getNetworkBufferLengthSamplesPerChannel() { return NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void start();
|
void start();
|
||||||
void addReceivedAudioToBuffer(const QByteArray& audioByteArray);
|
void addReceivedAudioToBuffer(const QByteArray& audioByteArray);
|
||||||
|
@ -83,10 +86,21 @@ public slots:
|
||||||
|
|
||||||
virtual void handleAudioByteArray(const QByteArray& audioByteArray);
|
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<QString> getDeviceNames(QAudio::Mode mode);
|
||||||
|
|
||||||
|
float getInputVolume() const { return (_audioInput) ? _audioInput->volume() : 0.0f; }
|
||||||
|
void setInputVolume(float volume) { if (_audioInput) _audioInput->setVolume(volume); }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
bool muteToggled();
|
bool muteToggled();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
QByteArray firstInputFrame;
|
QByteArray firstInputFrame;
|
||||||
QAudioInput* _audioInput;
|
QAudioInput* _audioInput;
|
||||||
QAudioFormat _desiredInputFormat;
|
QAudioFormat _desiredInputFormat;
|
||||||
|
@ -105,6 +119,9 @@ private:
|
||||||
QIODevice* _proceduralOutputDevice;
|
QIODevice* _proceduralOutputDevice;
|
||||||
AudioRingBuffer _inputRingBuffer;
|
AudioRingBuffer _inputRingBuffer;
|
||||||
AudioRingBuffer _ringBuffer;
|
AudioRingBuffer _ringBuffer;
|
||||||
|
|
||||||
|
QString _inputAudioDeviceName;
|
||||||
|
QString _outputAudioDeviceName;
|
||||||
|
|
||||||
Oscilloscope* _scope;
|
Oscilloscope* _scope;
|
||||||
StDev _stdev;
|
StDev _stdev;
|
||||||
|
|
|
@ -33,11 +33,11 @@
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "Menu.h"
|
#include "Menu.h"
|
||||||
#include "MenuScriptingInterface.h"
|
#include "scripting/MenuScriptingInterface.h"
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
#include "InfoView.h"
|
#include "ui/InfoView.h"
|
||||||
#include "ui/MetavoxelEditor.h"
|
#include "ui/MetavoxelEditor.h"
|
||||||
#include "ModelBrowser.h"
|
#include "ui/ModelBrowser.h"
|
||||||
|
|
||||||
|
|
||||||
Menu* Menu::_instance = NULL;
|
Menu* Menu::_instance = NULL;
|
||||||
|
@ -374,8 +374,10 @@ Menu::~Menu() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::loadSettings(QSettings* settings) {
|
void Menu::loadSettings(QSettings* settings) {
|
||||||
|
bool lockedSettings = false;
|
||||||
if (!settings) {
|
if (!settings) {
|
||||||
settings = Application::getInstance()->getSettings();
|
settings = Application::getInstance()->lockSettings();
|
||||||
|
lockedSettings = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_audioJitterBufferSamples = loadSetting(settings, "audioJitterBufferSamples", 0);
|
_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.
|
// TODO: cache more settings in MyAvatar that are checked with very high frequency.
|
||||||
MyAvatar* myAvatar = Application::getInstance()->getAvatar();
|
MyAvatar* myAvatar = Application::getInstance()->getAvatar();
|
||||||
myAvatar->updateCollisionFlags();
|
myAvatar->updateCollisionFlags();
|
||||||
|
|
||||||
|
if (lockedSettings) {
|
||||||
|
Application::getInstance()->unlockSettings();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::saveSettings(QSettings* settings) {
|
void Menu::saveSettings(QSettings* settings) {
|
||||||
|
bool lockedSettings = false;
|
||||||
if (!settings) {
|
if (!settings) {
|
||||||
settings = Application::getInstance()->getSettings();
|
settings = Application::getInstance()->lockSettings();
|
||||||
|
lockedSettings = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
settings->setValue("audioJitterBufferSamples", _audioJitterBufferSamples);
|
settings->setValue("audioJitterBufferSamples", _audioJitterBufferSamples);
|
||||||
|
@ -430,6 +438,9 @@ void Menu::saveSettings(QSettings* settings) {
|
||||||
Application::getInstance()->getAvatar()->saveData(settings);
|
Application::getInstance()->getAvatar()->saveData(settings);
|
||||||
NodeList::getInstance()->saveData(settings);
|
NodeList::getInstance()->saveData(settings);
|
||||||
|
|
||||||
|
if (lockedSettings) {
|
||||||
|
Application::getInstance()->unlockSettings();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::importSettings() {
|
void Menu::importSettings() {
|
||||||
|
|
|
@ -27,10 +27,7 @@ Hand::Hand(Avatar* owningAvatar) :
|
||||||
HandData((AvatarData*)owningAvatar),
|
HandData((AvatarData*)owningAvatar),
|
||||||
|
|
||||||
_owningAvatar(owningAvatar),
|
_owningAvatar(owningAvatar),
|
||||||
_renderAlpha(1.0),
|
_renderAlpha(1.0)
|
||||||
_collisionCenter(0,0,0),
|
|
||||||
_collisionAge(0),
|
|
||||||
_collisionDuration(0)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,10 +39,6 @@ void Hand::reset() {
|
||||||
|
|
||||||
void Hand::simulate(float deltaTime, bool isMine) {
|
void Hand::simulate(float deltaTime, bool isMine) {
|
||||||
|
|
||||||
if (_collisionAge > 0.f) {
|
|
||||||
_collisionAge += deltaTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
calculateGeometry();
|
calculateGeometry();
|
||||||
|
|
||||||
if (isMine) {
|
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() {
|
void Hand::calculateGeometry() {
|
||||||
// generate finger tip balls....
|
// generate finger tip balls....
|
||||||
_leapFingerTipBalls.clear();
|
_leapFingerTipBalls.clear();
|
||||||
|
@ -312,21 +285,6 @@ void Hand::render(bool isMine) {
|
||||||
renderLeapHands(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_DEPTH_TEST);
|
||||||
glEnable(GL_RESCALE_NORMAL);
|
glEnable(GL_RESCALE_NORMAL);
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
|
|
||||||
#include "InterfaceConfig.h"
|
#include "InterfaceConfig.h"
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
#include "VoxelSystem.h"
|
|
||||||
|
|
||||||
|
|
||||||
class Avatar;
|
class Avatar;
|
||||||
|
@ -72,13 +71,6 @@ private:
|
||||||
std::vector<HandBall> _leapFingerTipBalls;
|
std::vector<HandBall> _leapFingerTipBalls;
|
||||||
std::vector<HandBall> _leapFingerRootBalls;
|
std::vector<HandBall> _leapFingerRootBalls;
|
||||||
|
|
||||||
glm::vec3 _lastFingerAddVoxel, _lastFingerDeleteVoxel;
|
|
||||||
VoxelDetail _collidingVoxel;
|
|
||||||
|
|
||||||
glm::vec3 _collisionCenter;
|
|
||||||
float _collisionAge;
|
|
||||||
float _collisionDuration;
|
|
||||||
|
|
||||||
// private methods
|
// private methods
|
||||||
void setLeapHands(const std::vector<glm::vec3>& handPositions,
|
void setLeapHands(const std::vector<glm::vec3>& handPositions,
|
||||||
const std::vector<glm::vec3>& handNormals);
|
const std::vector<glm::vec3>& handNormals);
|
||||||
|
@ -88,8 +80,6 @@ private:
|
||||||
|
|
||||||
void calculateGeometry();
|
void calculateGeometry();
|
||||||
|
|
||||||
void handleVoxelCollision(PalmData* palm, const glm::vec3& fingerTipPosition, VoxelTreeElement* voxel, float deltaTime);
|
|
||||||
|
|
||||||
void playSlaps(PalmData& palm, Avatar* avatar);
|
void playSlaps(PalmData& palm, Avatar* avatar);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#include "Menu.h"
|
#include "Menu.h"
|
||||||
#include "MyAvatar.h"
|
#include "MyAvatar.h"
|
||||||
#include "Physics.h"
|
#include "Physics.h"
|
||||||
#include "VoxelSystem.h"
|
|
||||||
#include "devices/Faceshift.h"
|
#include "devices/Faceshift.h"
|
||||||
#include "devices/OculusManager.h"
|
#include "devices/OculusManager.h"
|
||||||
#include "ui/TextRenderer.h"
|
#include "ui/TextRenderer.h"
|
||||||
|
|
69
interface/src/scripting/AudioDeviceScriptingInterface.cpp
Normal file
69
interface/src/scripting/AudioDeviceScriptingInterface.cpp
Normal file
|
@ -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<QString> AudioDeviceScriptingInterface::getInputDevices() {
|
||||||
|
return Application::getInstance()->getAudio()->getDeviceNames(QAudio::AudioInput);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<QString> 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);
|
||||||
|
}
|
41
interface/src/scripting/AudioDeviceScriptingInterface.h
Normal file
41
interface/src/scripting/AudioDeviceScriptingInterface.h
Normal file
|
@ -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 <QDebug>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#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<QString> getInputDevices();
|
||||||
|
QVector<QString> getOutputDevices();
|
||||||
|
|
||||||
|
float getInputVolume();
|
||||||
|
void setInputVolume(float volume);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* defined(__hifi__AudioDeviceScriptingInterface__) */
|
36
interface/src/scripting/SettingsScriptingInterface.cpp
Normal file
36
interface/src/scripting/SettingsScriptingInterface.cpp
Normal file
|
@ -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();
|
||||||
|
}
|
30
interface/src/scripting/SettingsScriptingInterface.h
Normal file
30
interface/src/scripting/SettingsScriptingInterface.h
Normal file
|
@ -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 <QDebug>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#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__) */
|
|
@ -38,11 +38,12 @@ void InfoView::forcedShow() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InfoView::shouldShow() {
|
bool InfoView::shouldShow() {
|
||||||
|
bool shouldShow = false;
|
||||||
if (_forced) {
|
if (_forced) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSettings* settings = Application::getInstance()->getSettings();
|
QSettings* settings = Application::getInstance()->lockSettings();
|
||||||
|
|
||||||
QString lastVersion = settings->value(SETTINGS_VERSION_KEY).toString();
|
QString lastVersion = settings->value(SETTINGS_VERSION_KEY).toString();
|
||||||
|
|
||||||
|
@ -51,10 +52,12 @@ bool InfoView::shouldShow() {
|
||||||
|
|
||||||
if (version != QString::null && (lastVersion == QString::null || lastVersion != version)) {
|
if (version != QString::null && (lastVersion == QString::null || lastVersion != version)) {
|
||||||
settings->setValue(SETTINGS_VERSION_KEY, version);
|
settings->setValue(SETTINGS_VERSION_KEY, version);
|
||||||
return true;
|
shouldShow = true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
shouldShow = false;
|
||||||
}
|
}
|
||||||
|
Application::getInstance()->unlockSettings();
|
||||||
|
return shouldShow;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InfoView::loaded(bool ok) {
|
void InfoView::loaded(bool ok) {
|
|
@ -12,7 +12,6 @@
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
#include "Base3DOverlay.h"
|
#include "Base3DOverlay.h"
|
||||||
#include "TextRenderer.h"
|
|
||||||
|
|
||||||
const glm::vec3 DEFAULT_POSITION = glm::vec3(0.0f, 0.0f, 0.0f);
|
const glm::vec3 DEFAULT_POSITION = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||||
const float DEFAULT_LINE_WIDTH = 1.0f;
|
const float DEFAULT_LINE_WIDTH = 1.0f;
|
|
@ -12,10 +12,10 @@
|
||||||
#include <QGLWidget>
|
#include <QGLWidget>
|
||||||
#include <QScriptValue>
|
#include <QScriptValue>
|
||||||
|
|
||||||
#include <VoxelSystem.h>
|
|
||||||
#include <Application.h>
|
#include <Application.h>
|
||||||
|
|
||||||
#include "LocalVoxelsOverlay.h"
|
#include "LocalVoxelsOverlay.h"
|
||||||
|
#include "voxels/VoxelSystem.h"
|
||||||
|
|
||||||
QMap<QString, WeakVoxelSystemPointer> LocalVoxelsOverlay::_voxelSystemMap;
|
QMap<QString, WeakVoxelSystemPointer> LocalVoxelsOverlay::_voxelSystemMap;
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
#include "TextOverlay.h"
|
#include "TextOverlay.h"
|
||||||
#include "TextRenderer.h"
|
#include "ui/TextRenderer.h"
|
||||||
|
|
||||||
TextOverlay::TextOverlay() :
|
TextOverlay::TextOverlay() :
|
||||||
_leftMargin(DEFAULT_MARGIN),
|
_leftMargin(DEFAULT_MARGIN),
|
|
@ -6,13 +6,17 @@
|
||||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <VoxelImporter.h>
|
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||||
#include <Application.h>
|
#include "InterfaceConfig.h"
|
||||||
#include <LocalVoxelsList.h>
|
|
||||||
|
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QThreadPool>
|
#include <QThreadPool>
|
||||||
|
|
||||||
|
#include <Application.h>
|
||||||
|
#include <LocalVoxelsList.h>
|
||||||
|
|
||||||
|
#include "voxels/VoxelImporter.h"
|
||||||
|
|
||||||
const QString SETTINGS_GROUP_NAME = "VoxelImport";
|
const QString SETTINGS_GROUP_NAME = "VoxelImport";
|
||||||
const QString IMPORT_DIALOG_SETTINGS_KEY = "ImportDialogSettings";
|
const QString IMPORT_DIALOG_SETTINGS_KEY = "ImportDialogSettings";
|
||||||
|
|
|
@ -9,12 +9,12 @@
|
||||||
#ifndef __hifi__VoxelImporter__
|
#ifndef __hifi__VoxelImporter__
|
||||||
#define __hifi__VoxelImporter__
|
#define __hifi__VoxelImporter__
|
||||||
|
|
||||||
#include <VoxelSystem.h>
|
|
||||||
#include <ImportDialog.h>
|
|
||||||
|
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QRunnable>
|
#include <QRunnable>
|
||||||
|
|
||||||
|
#include "ui/ImportDialog.h"
|
||||||
|
#include "voxels/VoxelSystem.h"
|
||||||
|
|
||||||
class ImportTask;
|
class ImportTask;
|
||||||
|
|
||||||
class VoxelImporter : public QObject {
|
class VoxelImporter : public QObject {
|
|
@ -180,7 +180,7 @@ void HTTPConnection::readHeaders() {
|
||||||
|
|
||||||
QByteArray clength = _requestHeaders.value("Content-Length");
|
QByteArray clength = _requestHeaders.value("Content-Length");
|
||||||
if (clength.isEmpty()) {
|
if (clength.isEmpty()) {
|
||||||
_parentManager->handleHTTPRequest(this, _requestUrl.path());
|
_parentManager->handleHTTPRequest(this, _requestUrl);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
_requestContent.resize(clength.toInt());
|
_requestContent.resize(clength.toInt());
|
||||||
|
|
|
@ -15,15 +15,15 @@
|
||||||
#include "HTTPConnection.h"
|
#include "HTTPConnection.h"
|
||||||
#include "HTTPManager.h"
|
#include "HTTPManager.h"
|
||||||
|
|
||||||
bool HTTPManager::handleHTTPRequest(HTTPConnection* connection, const QString& path) {
|
bool HTTPManager::handleHTTPRequest(HTTPConnection* connection, const QUrl& url) {
|
||||||
if (_requestHandler && _requestHandler->handleHTTPRequest(connection, path)) {
|
if (_requestHandler && _requestHandler->handleHTTPRequest(connection, url)) {
|
||||||
// this request was handled by our _requestHandler object
|
// this request was handled by our _requestHandler object
|
||||||
// so we don't need to attempt to do so in the document root
|
// so we don't need to attempt to do so in the document root
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check to see if there is a file to serve from the document root for this path
|
// 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
|
// remove any slash at the beginning of the path
|
||||||
if (subPath.startsWith('/')) {
|
if (subPath.startsWith('/')) {
|
||||||
|
@ -38,6 +38,10 @@ bool HTTPManager::handleHTTPRequest(HTTPConnection* connection, const QString& p
|
||||||
// this could be a directory with a trailing slash
|
// this could be a directory with a trailing slash
|
||||||
// send a redirect to the path with a slash so we can
|
// send a redirect to the path with a slash so we can
|
||||||
QString redirectLocation = '/' + subPath + '/';
|
QString redirectLocation = '/' + subPath + '/';
|
||||||
|
|
||||||
|
if (!url.query().isEmpty()) {
|
||||||
|
redirectLocation += "?" + url.query();
|
||||||
|
}
|
||||||
|
|
||||||
QHash<QByteArray, QByteArray> redirectHeader;
|
QHash<QByteArray, QByteArray> redirectHeader;
|
||||||
redirectHeader.insert(QByteArray("Location"), redirectLocation.toUtf8());
|
redirectHeader.insert(QByteArray("Location"), redirectLocation.toUtf8());
|
||||||
|
|
|
@ -20,7 +20,7 @@ class HTTPConnection;
|
||||||
class HTTPRequestHandler {
|
class HTTPRequestHandler {
|
||||||
public:
|
public:
|
||||||
/// Handles an HTTP request.
|
/// 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
|
/// Handles HTTP connections
|
||||||
|
@ -30,7 +30,7 @@ public:
|
||||||
/// Initializes the manager.
|
/// Initializes the manager.
|
||||||
HTTPManager(quint16 port, const QString& documentRoot, HTTPRequestHandler* requestHandler = NULL, QObject* parent = 0);
|
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:
|
protected slots:
|
||||||
/// Accepts all pending connections
|
/// Accepts all pending connections
|
||||||
|
|
|
@ -144,6 +144,7 @@ void ScriptEngine::init() {
|
||||||
qScriptRegisterMetaType(&_engine, ParticleIDtoScriptValue, ParticleIDfromScriptValue);
|
qScriptRegisterMetaType(&_engine, ParticleIDtoScriptValue, ParticleIDfromScriptValue);
|
||||||
qScriptRegisterSequenceMetaType<QVector<ParticleID> >(&_engine);
|
qScriptRegisterSequenceMetaType<QVector<ParticleID> >(&_engine);
|
||||||
qScriptRegisterSequenceMetaType<QVector<glm::vec2> >(&_engine);
|
qScriptRegisterSequenceMetaType<QVector<glm::vec2> >(&_engine);
|
||||||
|
qScriptRegisterSequenceMetaType<QVector<QString> >(&_engine);
|
||||||
|
|
||||||
QScriptValue soundConstructorValue = _engine.newFunction(soundConstructor);
|
QScriptValue soundConstructorValue = _engine.newFunction(soundConstructor);
|
||||||
QScriptValue soundMetaObject = _engine.newQMetaObject(&Sound::staticMetaObject, soundConstructorValue);
|
QScriptValue soundMetaObject = _engine.newQMetaObject(&Sound::staticMetaObject, soundConstructorValue);
|
||||||
|
|
Loading…
Reference in a new issue