From bbdf4a12055c154fd2685ff007a6a8565b1803de Mon Sep 17 00:00:00 2001 From: stojce Date: Sat, 8 Feb 2014 01:10:26 +0100 Subject: [PATCH 01/39] Allow logged-in users to name their current location & orientation --- data-server/src/DataServer.cpp | 70 ++++++++++++++++++++ interface/CMakeLists.txt | 2 +- interface/src/DatagramProcessor.cpp | 3 + interface/src/Menu.cpp | 77 +++++++++++++++++++++- interface/src/Menu.h | 4 ++ interface/src/location/LocationManager.cpp | 26 ++++++++ interface/src/location/LocationManager.h | 37 +++++++++++ interface/src/location/NamedLocation.cpp | 46 +++++++++++++ interface/src/location/NamedLocation.h | 63 ++++++++++++++++++ libraries/shared/src/DataServerClient.cpp | 73 ++++++++++++++++++++ libraries/shared/src/DataServerClient.h | 12 +++- libraries/shared/src/PacketHeaders.h | 3 + 12 files changed, 410 insertions(+), 6 deletions(-) create mode 100644 interface/src/location/LocationManager.cpp create mode 100644 interface/src/location/LocationManager.h create mode 100644 interface/src/location/NamedLocation.cpp create mode 100644 interface/src/location/NamedLocation.h diff --git a/data-server/src/DataServer.cpp b/data-server/src/DataServer.cpp index 43fc52fb06..258afb755f 100644 --- a/data-server/src/DataServer.cpp +++ b/data-server/src/DataServer.cpp @@ -20,6 +20,11 @@ const quint16 DATA_SERVER_LISTEN_PORT = 3282; const char REDIS_HOSTNAME[] = "127.0.0.1"; const unsigned short REDIS_PORT = 6379; +const int ARGV_FIXED_INDEX_START = 2; + +const char REDIS_HASH_MULTIPLE_SET[] = "HMSET"; +const char REDIS_HASH_SET[] = "HSET"; +const char REDIS_HASH_GET_ALL[] = "HGETALL"; DataServer::DataServer(int argc, char* argv[]) : QCoreApplication(argc, argv), @@ -65,6 +70,71 @@ void DataServer::readPendingDatagrams() { PacketType requestType = packetTypeForPacket(receivedPacket); + if ((requestType == PacketTypeDataServerHashPut || requestType == PacketTypeDataServerHashGet) && + packetVersionMatch(receivedPacket)) { + + QDataStream packetStream(receivedPacket); + int numReceivedHeaderBytes = numBytesForPacketHeader(receivedPacket); + packetStream.skipRawData(numReceivedHeaderBytes); + + // pull the sequence number used for this packet + quint8 sequenceNumber = 0; + + packetStream >> sequenceNumber; + + // pull the UUID that we will need as part of the key + QString userString; + packetStream >> userString; + + if (requestType == PacketTypeDataServerHashPut) { + QString dataKey, dataValue; + QStringList redisCommandKeys, redisCommandValues; + + while(true) { + packetStream >> dataKey >> dataValue; + if (dataKey.isNull() || dataKey.isEmpty()) { + break; + } + redisAppendCommand(_redis, "%s %s %s %s", + REDIS_HASH_SET, + qPrintable(userString), + qPrintable(dataKey), + qPrintable(dataValue)); + }; + + redisReply* reply = NULL; + redisGetReply(_redis, (void **) &reply); + + if (reply->type == REDIS_REPLY_INTEGER && reply->integer == 0) { + QByteArray replyPacket = byteArrayWithPopluatedHeader(PacketTypeDataServerConfirm, _uuid); + replyPacket.append(sequenceNumber); + _socket.writeDatagram(replyPacket, senderSockAddr.getAddress(), senderSockAddr.getPort()); + } + + freeReplyObject(reply); + reply = NULL; + } else { + + redisReply* reply = (redisReply*) redisCommand(_redis, "%s %s", REDIS_HASH_GET_ALL, qPrintable(userString)); + + QByteArray sendPacket = byteArrayWithPopluatedHeader(PacketTypeDataServerHashSend, _uuid); + QDataStream sendPacketStream(&sendPacket, QIODevice::Append); + + sendPacketStream << sequenceNumber; + sendPacketStream << userString; + + if (reply->type == REDIS_REPLY_ARRAY && reply->elements > 0) { + for (int i = 0; i < reply->elements; i++) { + sendPacketStream << QString(reply->element[i]->str); + } + } + // reply back with the send packet + _socket.writeDatagram(sendPacket, senderSockAddr.getAddress(), senderSockAddr.getPort()); + freeReplyObject(reply); + reply = NULL; + } + } + if ((requestType == PacketTypeDataServerPut || requestType == PacketTypeDataServerGet) && packetVersionMatch(receivedPacket)) { diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 6af6ed478d..4c300f6fda 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -57,7 +57,7 @@ configure_file(InterfaceVersion.h.in ${PROJECT_BINARY_DIR}/includes/InterfaceVer # grab the implementation and header files from src dirs file(GLOB INTERFACE_SRCS src/*.cpp src/*.h) -foreach(SUBDIR avatar devices renderer ui starfield) +foreach(SUBDIR avatar devices renderer ui starfield location) 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/DatagramProcessor.cpp b/interface/src/DatagramProcessor.cpp index 24ec956c62..52e8b72ab2 100644 --- a/interface/src/DatagramProcessor.cpp +++ b/interface/src/DatagramProcessor.cpp @@ -116,7 +116,10 @@ void DatagramProcessor::processDatagrams() { } case PacketTypeDataServerGet: case PacketTypeDataServerPut: + case PacketTypeDataServerHashPut: + case PacketTypeDataServerHashGet: case PacketTypeDataServerSend: + case PacketTypeDataServerHashSend: case PacketTypeDataServerConfirm: DataServerClient::processMessageFromDataServer(incomingPacket); break; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 67eaa8782c..3b2b09fcd7 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -114,7 +115,12 @@ Menu::Menu() : MenuOption::GoToLocation, Qt::CTRL | Qt::SHIFT | Qt::Key_L, this, - SLOT(goToLocation())); + SLOT(goToLocation())); + addActionToQMenuAndActionHash(fileMenu, + MenuOption::NameLocation, + Qt::CTRL | Qt::Key_N, + this, + SLOT(nameLocation())); addActionToQMenuAndActionHash(fileMenu, MenuOption::GoTo, Qt::Key_At, @@ -152,8 +158,9 @@ Menu::Menu() : addActionToQMenuAndActionHash(editMenu, MenuOption::CutVoxels, Qt::CTRL | Qt::Key_X, appInstance, SLOT(cutVoxels())); addActionToQMenuAndActionHash(editMenu, MenuOption::CopyVoxels, Qt::CTRL | Qt::Key_C, appInstance, SLOT(copyVoxels())); addActionToQMenuAndActionHash(editMenu, MenuOption::PasteVoxels, Qt::CTRL | Qt::Key_V, appInstance, SLOT(pasteVoxels())); - addActionToQMenuAndActionHash(editMenu, MenuOption::NudgeVoxels, Qt::CTRL | Qt::Key_N, appInstance, SLOT(nudgeVoxels())); - + // TODO: add new shortcut + addActionToQMenuAndActionHash(editMenu, MenuOption::NudgeVoxels, 0, appInstance, SLOT(nudgeVoxels())); + #ifdef __APPLE__ addActionToQMenuAndActionHash(editMenu, MenuOption::DeleteVoxels, Qt::Key_Backspace, appInstance, SLOT(deleteVoxels())); #else @@ -964,6 +971,70 @@ void Menu::goTo() { sendFakeEnterEvent(); } +void Menu::namedLocationCreated(LocationManager::LocationCreateResponse response, NamedLocation* location) { + + if (response == LocationManager::AlreadyExists) { + QMessageBox msgBox; + msgBox.setText("That name has been claimed by " + location->getCreatedBy() + ", try something else."); + msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); + msgBox.button(QMessageBox::Ok)->setText("Go to user"); + int ret = msgBox.exec(); + + if (ret == QMessageBox::Ok) { + DataServerClient::getValuesForKeysAndUserString( + QStringList() + << DataServerKey::Domain + << DataServerKey::Position + << DataServerKey::Orientation, + location->getCreatedBy(), + Application::getInstance()->getProfile()); + } + } +} + +void Menu::nameLocation() { + // check if user is logged in or show login dialog if not + Profile* profile = Application::getInstance()->getProfile(); + if (profile->getUsername().isNull()) { + QMessageBox msgBox; + msgBox.setText("We need to tie this location to your username."); + msgBox.setInformativeText("Please login first, then try naming the location again."); + msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); + msgBox.button(QMessageBox::Ok)->setText("Login"); + if (msgBox.exec() == QMessageBox::Ok) { + login(); + } + return; + } + + QInputDialog nameDialog(Application::getInstance()->getWindow()); + nameDialog.setWindowTitle("Name this location"); + nameDialog.setLabelText("Name this location, then share that name with others.\n" + "When they come here, they'll be in the same location and orientation\n" + "(wherever you are standing and looking now) as you.\n\n" + "Location name:"); + + nameDialog.setWindowFlags(Qt::Sheet); + nameDialog.resize((int) (nameDialog.parentWidget()->size().width() * 0.30), nameDialog.size().height()); + + if (nameDialog.exec() == QDialog::Accepted) { + + QString locationName = nameDialog.textValue().trimmed(); + if (locationName.isEmpty()) { + return; + } + + MyAvatar* myAvatar = Application::getInstance()->getAvatar(); + + LocationManager* manager = new LocationManager(); + connect(manager, + SIGNAL(creationCompleted(LocationManager::LocationCreateResponse, NamedLocation*)), + SLOT(namedLocationCreated(LocationManager::LocationCreateResponse, NamedLocation*))); + + manager->createNamedLocation(locationName, profile->getUsername(), myAvatar->getPosition(), myAvatar->getOrientation()); + } +} + void Menu::goToLocation() { MyAvatar* myAvatar = Application::getInstance()->getAvatar(); glm::vec3 avatarPos = myAvatar->getPosition(); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 5e49ca6fd1..08306f8dd0 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -15,6 +15,7 @@ #include #include +#include "location/LocationManager.h" enum FrustumDrawMode { FRUSTUM_DRAW_MODE_ALL, @@ -101,6 +102,7 @@ private slots: void editPreferences(); void goToDomain(); void goToLocation(); + void nameLocation(); void bandwidthDetailsClosed(); void voxelStatsDetailsClosed(); void lodToolsClosed(); @@ -111,6 +113,7 @@ private slots: void resetSwatchColors(); void showMetavoxelEditor(); void audioMuteToggled(); + void namedLocationCreated(LocationManager::LocationCreateResponse response, NamedLocation* location); private: static Menu* _instance; @@ -210,6 +213,7 @@ namespace MenuOption { const QString GlowMode = "Cycle Glow Mode"; const QString GoToDomain = "Go To Domain..."; const QString GoToLocation = "Go To Location..."; + const QString NameLocation = "Name this location"; const QString GoTo = "Go To..."; const QString ImportVoxels = "Import Voxels"; const QString ImportVoxelsClipboard = "Import Voxels to Clipboard"; diff --git a/interface/src/location/LocationManager.cpp b/interface/src/location/LocationManager.cpp new file mode 100644 index 0000000000..11a099ae80 --- /dev/null +++ b/interface/src/location/LocationManager.cpp @@ -0,0 +1,26 @@ +// +// LocationManager.cpp +// hifi +// +// Created by Stojce Slavkovski on 2/7/14. +// +// + +#include "LocationManager.h" + +void LocationManager::createNamedLocation(QString locationName, QString creator, glm::vec3 location, glm::quat orientation) { + _namedLocation = new NamedLocation(locationName, creator, location, orientation); + connect(_namedLocation, SIGNAL(dataReceived(bool)), SLOT(locationDataReceived(bool))); + DataServerClient::getHashFieldsForKey(DataServerKey::NamedLocation, _namedLocation->locationName(), _namedLocation); +} + +void LocationManager::locationDataReceived(bool locationExists) { + disconnect(_namedLocation, SIGNAL(dataReceived(bool)), this, SLOT(locationDataReceived(bool))); + if (locationExists) { + emit creationCompleted(AlreadyExists, _namedLocation); + } else { + DataServerClient::putHashFieldsForKey(DataServerKey::NamedLocation, _namedLocation->locationName(), _namedLocation); + emit creationCompleted(Created, _namedLocation); + } +} + diff --git a/interface/src/location/LocationManager.h b/interface/src/location/LocationManager.h new file mode 100644 index 0000000000..29a29b0496 --- /dev/null +++ b/interface/src/location/LocationManager.h @@ -0,0 +1,37 @@ +// +// LocationManager.h +// hifi +// +// Created by Stojce Slavkovski on 2/7/14. +// +// + +#ifndef __hifi__LocationManager__ +#define __hifi__LocationManager__ + +#include +#include "NamedLocation.h" + +class LocationManager : public QObject { + Q_OBJECT + +public: + enum LocationCreateResponse { + Created, + AlreadyExists + }; + + LocationManager() { }; + void createNamedLocation(QString locationName, QString creator, glm::vec3 location, glm::quat orientation); + +signals: + void creationCompleted(LocationManager::LocationCreateResponse response, NamedLocation* location); + +private: + NamedLocation* _namedLocation; + +private slots: + void locationDataReceived(bool locationExists); +}; + +#endif /* defined(__hifi__LocationManager__) */ diff --git a/interface/src/location/NamedLocation.cpp b/interface/src/location/NamedLocation.cpp new file mode 100644 index 0000000000..977f368091 --- /dev/null +++ b/interface/src/location/NamedLocation.cpp @@ -0,0 +1,46 @@ +// +// LocationManager.cpp +// hifi +// +// Created by Stojce Slavkovski on 2/1/14. +// +// + +#include "NamedLocation.h" + +// deserialize data +void NamedLocation::processDataServerResponse(const QString& userString, + const QStringList& keyList, + const QStringList& valueList) { + for (int i = 0; i < keyList.count(); i++) { + if (keyList[i] == "creator") { + _createdBy = valueList[i]; + } else if (keyList[i] == "location") { + QStringList locationCoords = valueList[i].split(","); + if (locationCoords.length() == 3) { + _location = glm::vec3(locationCoords[0].toLong(), locationCoords[1].toLong(), locationCoords[2].toLong()); + } + } else if (keyList[i] == "orientation") { + + QStringList orientationCoords = valueList[i].split(","); + if (orientationCoords.length() == 4) { + _orientation = glm::quat(orientationCoords[0].toLong(), + orientationCoords[1].toLong(), + orientationCoords[2].toLong(), + orientationCoords[3].toLong()); + } + } + } + + emit dataReceived(keyList.count() > 0); +} + +// serialize data +QHash NamedLocation::getHashData() { + QHash response; + qDebug() << QString::fromStdString(glm::to_string(_location)); + response["location"] = QString::number(_location.x) + "," + QString::number(_location.y) + "," + QString::number(_location.z); + response["creator"] = _createdBy; + response["orientation"] = QString::number(_orientation.x) + "," + QString::number(_orientation.y) + "," + QString::number(_orientation.z) + "," + QString::number(_orientation.w); + return response; +} \ No newline at end of file diff --git a/interface/src/location/NamedLocation.h b/interface/src/location/NamedLocation.h new file mode 100644 index 0000000000..ea315ebf9b --- /dev/null +++ b/interface/src/location/NamedLocation.h @@ -0,0 +1,63 @@ +// +// NamedLocation.h +// hifi +// +// Created by Stojce Slavkovski on 2/1/14. +// +// + +#ifndef __hifi__NamedLocation__ +#define __hifi__NamedLocation__ + +#include +#include +#include + +#include "DataServerClient.h" + +class NamedLocation : public QObject, public DataServerCallbackObject, public DataServerCallerObject { + Q_OBJECT + +public: + + NamedLocation(QString locationName, QString createdBy, glm::vec3 location, glm::quat orientation) { + _locationName = locationName; + _createdBy = createdBy; + _location = location; + _orientation = orientation; + } + + bool isEmpty() { return _locationName.isNull() || _locationName.isEmpty(); } + + // DataServerCallbackObject implementation + void processDataServerResponse(const QString& userString, const QStringList& keyList, const QStringList& valueList); + + // DataServerCallerObject implementation + QHash getHashData(); + + // properties >> + void setLocationName(QString locationName) { _locationName = locationName; } + QString locationName() { return _locationName; } + + void createdBy(QString createdBy) { _createdBy = createdBy; } + QString getCreatedBy() { return _createdBy; } + + void setLocation(glm::vec3 location) { _location = location; } + glm::vec3 location() { return _location; } + + void setOrientation(glm::quat orentation) { _orientation = orentation; } + glm::quat orientation() { return _orientation; } + // properties << + +signals: + void dataReceived(bool locationExists); + +private: + QString _locationName; + QString _createdBy; + glm::vec3 _location; + glm::quat _orientation; + +}; + +#endif /* defined(__hifi__NamedLocation__) */ diff --git a/libraries/shared/src/DataServerClient.cpp b/libraries/shared/src/DataServerClient.cpp index fd003aa3bb..3b6fe2dbf6 100644 --- a/libraries/shared/src/DataServerClient.cpp +++ b/libraries/shared/src/DataServerClient.cpp @@ -88,6 +88,44 @@ void DataServerClient::getValueForKeyAndUserString(const QString& key, const QSt getValuesForKeysAndUserString(QStringList(key), userString, callbackObject); } +void DataServerClient::getHashFieldsForKey(const QString serverKey, QString keyValue, DataServerCallbackObject* callbackObject) { + + QByteArray getPacket = byteArrayWithPopluatedHeader(PacketTypeDataServerHashGet); + QDataStream packetStream(&getPacket, QIODevice::Append); + packetStream << _sequenceNumber << serverKey + ":" + keyValue; + + // add the getPacket to our map of unconfirmed packets, will be deleted once we get a response from the nameserver + _unmatchedPackets.insert(_sequenceNumber, getPacket); + _callbackObjects.insert(_sequenceNumber, callbackObject); + + // send the get to the data server + NodeList::getInstance()->getNodeSocket().writeDatagram(getPacket, dataServerSockAddr().getAddress(), + dataServerSockAddr().getPort()); + _sequenceNumber++; +} + +void DataServerClient::putHashFieldsForKey(const QString serverKey, QString keyValue, DataServerCallerObject* callerObject) { + + QByteArray putPacket = byteArrayWithPopluatedHeader(PacketTypeDataServerHashPut); + QDataStream packetStream(&putPacket, QIODevice::Append); + packetStream << _sequenceNumber << serverKey + ":" + keyValue; + + QHash hashData(callerObject->getHashData()); + QHash::const_iterator i = hashData.constBegin(); + while (i != hashData.constEnd()) { + packetStream << i.key() << i.value(); + ++i; + } + // add the getPacket to our map of unconfirmed packets, will be deleted once we get a response from the nameserver + _unmatchedPackets.insert(_sequenceNumber, putPacket); + + // send this put request to the data server + NodeList::getInstance()->getNodeSocket().writeDatagram(putPacket, dataServerSockAddr().getAddress(), + dataServerSockAddr().getPort()); + + _sequenceNumber++; +} + void DataServerClient::processConfirmFromDataServer(const QByteArray& packet) { removeMatchedPacketFromMap(packet); } @@ -113,12 +151,47 @@ void DataServerClient::processSendFromDataServer(const QByteArray& packet) { valueListString.split(MULTI_KEY_VALUE_SEPARATOR)); } } +void DataServerClient::processHashSendFromDataServer(const QByteArray& packet) { + + // pull the user string from the packet so we know who to associate this with + QDataStream packetStream(packet); + packetStream.skipRawData(numBytesForPacketHeader(packet)); + + quint8 sequenceNumber = 0; + packetStream >> sequenceNumber; + + if (_callbackObjects.find(sequenceNumber) != _callbackObjects.end()) { + // remove the packet from our two maps, it's matched + DataServerCallbackObject* callbackObject = _callbackObjects.take(sequenceNumber); + _unmatchedPackets.remove(sequenceNumber); + + QString userString, keyString, valueString; + QStringList keyList, valueList; + + packetStream >> userString; + + while(true) { + packetStream >> keyString; + packetStream >> valueString; + if (keyString.isNull() || keyString.isEmpty()) { + break; + } + + keyList << keyString; + valueList << valueString; + } + callbackObject->processDataServerResponse(userString, keyList, valueList); + } +} void DataServerClient::processMessageFromDataServer(const QByteArray& packet) { switch (packetTypeForPacket(packet)) { case PacketTypeDataServerSend: processSendFromDataServer(packet); break; + case PacketTypeDataServerHashSend: + processHashSendFromDataServer(packet); + break; case PacketTypeDataServerConfirm: processConfirmFromDataServer(packet); break; diff --git a/libraries/shared/src/DataServerClient.h b/libraries/shared/src/DataServerClient.h index 0360576645..d2f846cc6b 100644 --- a/libraries/shared/src/DataServerClient.h +++ b/libraries/shared/src/DataServerClient.h @@ -18,6 +18,11 @@ #include "HifiSockAddr.h" +class DataServerCallerObject { +public: + virtual QHash getHashData() = 0; +}; + class DataServerCallbackObject { public: virtual void processDataServerResponse(const QString& userString, const QStringList& keyList, const QStringList& valueList) = 0; @@ -35,14 +40,16 @@ public: static void getValueForKeyAndUUID(const QString& key, const QUuid& uuid, DataServerCallbackObject* callbackObject); static void getValuesForKeysAndUUID(const QStringList& keys, const QUuid& uuid, DataServerCallbackObject* callbackObject); static void getValuesForKeysAndUserString(const QStringList& keys, const QString& userString, - DataServerCallbackObject* callbackObject); - + DataServerCallbackObject* callbackObject); + static void getHashFieldsForKey(const QString serverKey, QString keyValue, DataServerCallbackObject* callbackObject); + static void putHashFieldsForKey(const QString serverKey, QString keyValue, DataServerCallerObject* callerObject); static void processMessageFromDataServer(const QByteArray& packet); static void resendUnmatchedPackets(); private: static void processConfirmFromDataServer(const QByteArray& packet); static void processSendFromDataServer(const QByteArray& packet); + static void processHashSendFromDataServer(const QByteArray& packet); static void removeMatchedPacketFromMap(const QByteArray& packet); static QMap _unmatchedPackets; @@ -57,6 +64,7 @@ namespace DataServerKey { const QString Position = "position"; const QString Orientation = "orientation"; const QString UUID = "uuid"; + const QString NamedLocation = "namedlocation"; } #endif /* defined(__hifi__DataServerClient__) */ diff --git a/libraries/shared/src/PacketHeaders.h b/libraries/shared/src/PacketHeaders.h index 543dce0504..84f074b0a7 100644 --- a/libraries/shared/src/PacketHeaders.h +++ b/libraries/shared/src/PacketHeaders.h @@ -36,6 +36,9 @@ enum PacketType { PacketTypeCreateAssignment, PacketTypeDataServerPut, PacketTypeDataServerGet, + PacketTypeDataServerHashPut, + PacketTypeDataServerHashGet, + PacketTypeDataServerHashSend, PacketTypeDataServerSend, PacketTypeDataServerConfirm, PacketTypeVoxelQuery, From d1c8a693876809d3f9b305b04e52d0c883e68991 Mon Sep 17 00:00:00 2001 From: stojce Date: Sat, 8 Feb 2014 09:25:49 +0100 Subject: [PATCH 02/39] New DataServer features --- data-server/src/DataServer.cpp | 6 ++++-- interface/src/Menu.cpp | 2 +- libraries/shared/src/NodeList.cpp | 1 + libraries/shared/src/PacketHeaders.cpp | 3 +++ 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/data-server/src/DataServer.cpp b/data-server/src/DataServer.cpp index 429a2ec331..16a274607d 100644 --- a/data-server/src/DataServer.cpp +++ b/data-server/src/DataServer.cpp @@ -69,9 +69,9 @@ void DataServer::readPendingDatagrams() { senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer()); PacketType requestType = packetTypeForPacket(receivedPacket); - + if ((requestType == PacketTypeDataServerHashPut || requestType == PacketTypeDataServerHashGet) && - packetVersionMatch(receivedPacket)) { + receivedPacket[numBytesArithmeticCodingFromBuffer(receivedPacket.data())] == versionForPacketType(requestType)) { QDataStream packetStream(receivedPacket); int numReceivedHeaderBytes = numBytesForPacketHeader(receivedPacket); @@ -95,6 +95,7 @@ void DataServer::readPendingDatagrams() { if (dataKey.isNull() || dataKey.isEmpty()) { break; } + redisAppendCommand(_redis, "%s %s %s %s", REDIS_HASH_SET, qPrintable(userString), @@ -127,6 +128,7 @@ void DataServer::readPendingDatagrams() { for (int i = 0; i < reply->elements; i++) { sendPacketStream << QString(reply->element[i]->str); } + qDebug() << "Found data for key" << userString; } // reply back with the send packet _socket.writeDatagram(sendPacket, senderSockAddr.getAddress(), senderSockAddr.getPort()); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 1d3c1cf589..3f7fe8385b 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -998,7 +998,7 @@ void Menu::namedLocationCreated(LocationManager::LocationCreateResponse response void Menu::nameLocation() { // check if user is logged in or show login dialog if not Profile* profile = Application::getInstance()->getProfile(); - if (profile->getUsername().isNull()) { + if (profile->getUUID().isNull()) { QMessageBox msgBox; msgBox.setText("We need to tie this location to your username."); msgBox.setInformativeText("Please login first, then try naming the location again."); diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 2672f3b27b..ca378207df 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -97,6 +97,7 @@ bool NodeList::packetVersionAndHashMatch(const QByteArray& packet) { const QSet NON_VERIFIED_PACKETS = QSet() << PacketTypeDomainList << PacketTypeDomainListRequest << PacketTypeStunResponse << PacketTypeDataServerConfirm << PacketTypeDataServerGet << PacketTypeDataServerPut << PacketTypeDataServerSend + << PacketTypeDataServerHashGet << PacketTypeDataServerHashPut << PacketTypeDataServerHashSend << PacketTypeCreateAssignment << PacketTypeRequestAssignment; if (!NON_VERIFIED_PACKETS.contains(packetTypeForPacket(packet))) { diff --git a/libraries/shared/src/PacketHeaders.cpp b/libraries/shared/src/PacketHeaders.cpp index b46a57d4aa..168d6700c1 100644 --- a/libraries/shared/src/PacketHeaders.cpp +++ b/libraries/shared/src/PacketHeaders.cpp @@ -56,6 +56,9 @@ PacketVersion versionForPacketType(PacketType type) { case PacketTypeDataServerPut: case PacketTypeDataServerConfirm: case PacketTypeDataServerSend: + case PacketTypeDataServerHashPut: + case PacketTypeDataServerHashGet: + case PacketTypeDataServerHashSend: return 1; default: return 0; From 95d0128c74bf0436c9e750238b335785e32c2fd7 Mon Sep 17 00:00:00 2001 From: stojce Date: Wed, 12 Mar 2014 18:53:25 +0100 Subject: [PATCH 03/39] Using new API client --- data-server/src/DataServer.cpp | 263 --------------------- interface/src/Menu.cpp | 78 +++++- interface/src/Menu.h | 4 + interface/src/location/LocationManager.cpp | 48 +++- interface/src/location/LocationManager.h | 21 +- interface/src/location/NamedLocation.cpp | 100 +++++--- interface/src/location/NamedLocation.h | 33 ++- libraries/shared/src/AccountManager.h | 3 +- 8 files changed, 213 insertions(+), 337 deletions(-) delete mode 100644 data-server/src/DataServer.cpp diff --git a/data-server/src/DataServer.cpp b/data-server/src/DataServer.cpp deleted file mode 100644 index 16a274607d..0000000000 --- a/data-server/src/DataServer.cpp +++ /dev/null @@ -1,263 +0,0 @@ -// -// DataServer.cpp -// hifi -// -// Created by Stephen Birarda on 1/20/2014. -// Copyright (c) 2014 HighFidelity, Inc. All rights reserved. -// - -#include -#include -#include - -#include -#include -#include - -#include "DataServer.h" - -const quint16 DATA_SERVER_LISTEN_PORT = 3282; - -const char REDIS_HOSTNAME[] = "127.0.0.1"; -const unsigned short REDIS_PORT = 6379; -const int ARGV_FIXED_INDEX_START = 2; - -const char REDIS_HASH_MULTIPLE_SET[] = "HMSET"; -const char REDIS_HASH_SET[] = "HSET"; -const char REDIS_HASH_GET_ALL[] = "HGETALL"; - -DataServer::DataServer(int argc, char* argv[]) : - QCoreApplication(argc, argv), - _socket(), - _redis(NULL), - _uuid(QUuid::createUuid()) -{ - _socket.bind(QHostAddress::Any, DATA_SERVER_LISTEN_PORT); - - connect(&_socket, &QUdpSocket::readyRead, this, &DataServer::readPendingDatagrams); - - _redis = redisConnect(REDIS_HOSTNAME, REDIS_PORT); - - if (_redis && _redis->err) { - if (_redis) { - qDebug() << "Redis connection error:" << _redis->errstr; - } else { - qDebug("Redis connection error - can't allocate redis context."); - } - - // couldn't connect to redis, bail out - QMetaObject::invokeMethod(this, "quit", Qt::QueuedConnection); - } -} - -DataServer::~DataServer() { - // disconnect from redis and free the context - if (_redis) { - redisFree(_redis); - } -} - -const int MAX_PACKET_SIZE = 1500; - -void DataServer::readPendingDatagrams() { - QByteArray receivedPacket; - HifiSockAddr senderSockAddr; - - while (_socket.hasPendingDatagrams()) { - receivedPacket.resize(_socket.pendingDatagramSize()); - _socket.readDatagram(receivedPacket.data(), _socket.pendingDatagramSize(), - senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer()); - - PacketType requestType = packetTypeForPacket(receivedPacket); - - if ((requestType == PacketTypeDataServerHashPut || requestType == PacketTypeDataServerHashGet) && - receivedPacket[numBytesArithmeticCodingFromBuffer(receivedPacket.data())] == versionForPacketType(requestType)) { - - QDataStream packetStream(receivedPacket); - int numReceivedHeaderBytes = numBytesForPacketHeader(receivedPacket); - packetStream.skipRawData(numReceivedHeaderBytes); - - // pull the sequence number used for this packet - quint8 sequenceNumber = 0; - - packetStream >> sequenceNumber; - - // pull the UUID that we will need as part of the key - QString userString; - packetStream >> userString; - - if (requestType == PacketTypeDataServerHashPut) { - QString dataKey, dataValue; - QStringList redisCommandKeys, redisCommandValues; - - while(true) { - packetStream >> dataKey >> dataValue; - if (dataKey.isNull() || dataKey.isEmpty()) { - break; - } - - redisAppendCommand(_redis, "%s %s %s %s", - REDIS_HASH_SET, - qPrintable(userString), - qPrintable(dataKey), - qPrintable(dataValue)); - }; - - redisReply* reply = NULL; - redisGetReply(_redis, (void **) &reply); - - if (reply->type == REDIS_REPLY_INTEGER && reply->integer == 0) { - QByteArray replyPacket = byteArrayWithPopluatedHeader(PacketTypeDataServerConfirm, _uuid); - replyPacket.append(sequenceNumber); - _socket.writeDatagram(replyPacket, senderSockAddr.getAddress(), senderSockAddr.getPort()); - } - - freeReplyObject(reply); - reply = NULL; - } else { - - redisReply* reply = (redisReply*) redisCommand(_redis, "%s %s", REDIS_HASH_GET_ALL, qPrintable(userString)); - - QByteArray sendPacket = byteArrayWithPopluatedHeader(PacketTypeDataServerHashSend, _uuid); - QDataStream sendPacketStream(&sendPacket, QIODevice::Append); - - sendPacketStream << sequenceNumber; - sendPacketStream << userString; - - if (reply->type == REDIS_REPLY_ARRAY && reply->elements > 0) { - for (int i = 0; i < reply->elements; i++) { - sendPacketStream << QString(reply->element[i]->str); - } - qDebug() << "Found data for key" << userString; - } - // reply back with the send packet - _socket.writeDatagram(sendPacket, senderSockAddr.getAddress(), senderSockAddr.getPort()); - freeReplyObject(reply); - reply = NULL; - } - } - - if ((requestType == PacketTypeDataServerPut || requestType == PacketTypeDataServerGet) && - receivedPacket[numBytesArithmeticCodingFromBuffer(receivedPacket.data())] == versionForPacketType(requestType)) { - - QDataStream packetStream(receivedPacket); - int numReceivedHeaderBytes = numBytesForPacketHeader(receivedPacket); - packetStream.skipRawData(numReceivedHeaderBytes); - - // pull the sequence number used for this packet - quint8 sequenceNumber = 0; - - packetStream >> sequenceNumber; - - // pull the UUID that we will need as part of the key - QString userString; - packetStream >> userString; - QUuid parsedUUID(userString); - - if (parsedUUID.isNull()) { - // we failed to parse a UUID, this means the user has sent us a username - - // ask redis for the UUID for this user - redisReply* reply = (redisReply*) redisCommand(_redis, "GET user:%s", qPrintable(userString)); - - if (reply->type == REDIS_REPLY_STRING) { - parsedUUID = QUuid(QString(reply->str)); - } - - if (!parsedUUID.isNull()) { - qDebug() << "Found UUID" << parsedUUID << "for username" << userString; - } else { - qDebug() << "Failed UUID lookup for username" << userString; - } - - freeReplyObject(reply); - reply = NULL; - } - - if (!parsedUUID.isNull()) { - if (requestType == PacketTypeDataServerPut) { - - // pull the key and value that specifies the data the user is putting/getting - QString dataKey, dataValue; - - packetStream >> dataKey >> dataValue; - - qDebug("Sending command to redis: SET uuid:%s:%s %s", - qPrintable(uuidStringWithoutCurlyBraces(parsedUUID)), - qPrintable(dataKey), qPrintable(dataValue)); - - redisReply* reply = (redisReply*) redisCommand(_redis, "SET uuid:%s:%s %s", - qPrintable(uuidStringWithoutCurlyBraces(parsedUUID)), - qPrintable(dataKey), qPrintable(dataValue)); - - if (reply->type == REDIS_REPLY_STATUS && strcmp("OK", reply->str) == 0) { - // if redis stored the value successfully reply back with a confirm - // which is a reply packet with the sequence number - QByteArray replyPacket = byteArrayWithPopluatedHeader(PacketTypeDataServerConfirm, _uuid); - - replyPacket.append(sequenceNumber); - - _socket.writeDatagram(replyPacket, senderSockAddr.getAddress(), senderSockAddr.getPort()); - } - - freeReplyObject(reply); - } else { - // setup a send packet with the returned data - // leverage the packetData sent by overwriting and appending - QByteArray sendPacket = byteArrayWithPopluatedHeader(PacketTypeDataServerSend, _uuid); - QDataStream sendPacketStream(&sendPacket, QIODevice::Append); - - sendPacketStream << sequenceNumber; - - // pull the key list that specifies the data the user is putting/getting - QString keyListString; - packetStream >> keyListString; - - if (keyListString != "uuid") { - - // copy the parsed UUID - sendPacketStream << uuidStringWithoutCurlyBraces(parsedUUID); - - const char MULTI_KEY_VALUE_SEPARATOR = '|'; - - // append the keyListString back to the sendPacket - sendPacketStream << keyListString; - - QStringList keyList = keyListString.split(MULTI_KEY_VALUE_SEPARATOR); - QStringList valueList; - - foreach (const QString& dataKey, keyList) { - qDebug("Sending command to redis: GET uuid:%s:%s", - qPrintable(uuidStringWithoutCurlyBraces(parsedUUID)), - qPrintable(dataKey)); - redisReply* reply = (redisReply*) redisCommand(_redis, "GET uuid:%s:%s", - qPrintable(uuidStringWithoutCurlyBraces(parsedUUID)), - qPrintable(dataKey)); - - if (reply->len) { - // copy the value that redis returned - valueList << QString(reply->str); - } else { - // didn't find a value - insert a space - valueList << QChar(' '); - } - - freeReplyObject(reply); - } - - // append the value QStringList using the right separator - sendPacketStream << valueList.join(MULTI_KEY_VALUE_SEPARATOR); - } else { - // user was asking for their UUID - sendPacketStream << userString; - sendPacketStream << QString("uuid"); - sendPacketStream << uuidStringWithoutCurlyBraces(parsedUUID); - } - - // reply back with the send packet - _socket.writeDatagram(sendPacket, senderSockAddr.getAddress(), senderSockAddr.getPort()); - } - } - } - } -} diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 0674826342..5224d234fb 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -115,13 +116,18 @@ Menu::Menu() : addActionToQMenuAndActionHash(fileMenu, MenuOption::GoToDomain, Qt::CTRL | Qt::Key_D, - this, - SLOT(goToDomainDialog())); + this, + SLOT(goToDomainDialog())); addActionToQMenuAndActionHash(fileMenu, MenuOption::GoToLocation, Qt::CTRL | Qt::SHIFT | Qt::Key_L, - this, - SLOT(goToLocation())); + this, + SLOT(goToLocation())); + addActionToQMenuAndActionHash(fileMenu, + MenuOption::NameLocation, + Qt::CTRL | Qt::Key_N, + this, + SLOT(nameLocation())); addActionToQMenuAndActionHash(fileMenu, MenuOption::GoTo, Qt::Key_At, @@ -400,6 +406,7 @@ void Menu::saveSettings(QSettings* settings) { scanMenuBar(&saveAction, settings); Application::getInstance()->getAvatar()->saveData(settings); NodeList::getInstance()->saveData(settings); + } void Menu::importSettings() { @@ -959,6 +966,69 @@ void Menu::goToLocation() { sendFakeEnterEvent(); } +void Menu::namedLocationCreated(LocationManager::NamedLocationCreateResponse response, NamedLocation* location) { + + if (response == LocationManager::Created) { + return; + } + + QMessageBox msgBox; + switch (response) { + case LocationManager::AlreadyExists: + msgBox.setText("That name has been already claimed, try something else."); + break; + default: + msgBox.setText("An unexpected error has occurred, please try again later."); + break; + } + + msgBox.exec(); +} + +void Menu::nameLocation() { + // check if user is logged in or show login dialog if not + + AccountManager& accountManager = AccountManager::getInstance(); + if (!accountManager.isLoggedIn() && 1 > 2) { + QMessageBox msgBox; + msgBox.setText("We need to tie this location to your username."); + msgBox.setInformativeText("Please login first, then try naming the location again."); + msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); + msgBox.button(QMessageBox::Ok)->setText("Login"); + if (msgBox.exec() == QMessageBox::Ok) { + loginForCurrentDomain(); + } + + return; + } + + QInputDialog nameDialog(Application::getInstance()->getWindow()); + nameDialog.setWindowTitle("Name this location"); + nameDialog.setLabelText("Name this location, then share that name with others.\n" + "When they come here, they'll be in the same location and orientation\n" + "(wherever you are standing and looking now) as you.\n\n" + "Location name:"); + + nameDialog.setWindowFlags(Qt::Sheet); + nameDialog.resize((int) (nameDialog.parentWidget()->size().width() * 0.30), nameDialog.size().height()); + + if (nameDialog.exec() == QDialog::Accepted) { + + QString locationName = nameDialog.textValue().trimmed(); + if (locationName.isEmpty()) { + return; + } + + MyAvatar* myAvatar = Application::getInstance()->getAvatar(); + LocationManager* manager = new LocationManager(); + connect(manager, &LocationManager::creationCompleted, this, &Menu::namedLocationCreated); + NamedLocation* location = new NamedLocation(locationName, + myAvatar->getPosition(), myAvatar->getOrientation(), + NodeList::getInstance()->getDomainInfo().getHostname()); + manager->createNamedLocation(location); + } +} + void Menu::pasteToVoxel() { QInputDialog pasteToOctalCodeDialog(Application::getInstance()->getWindow()); pasteToOctalCodeDialog.setWindowTitle("Paste to Voxel"); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 204b93dd4a..d701861cf1 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -17,6 +17,7 @@ #include #include #include +#include "location/LocationManager.h" const float ADJUST_LOD_DOWN_FPS = 40.0; const float ADJUST_LOD_UP_FPS = 55.0; @@ -134,6 +135,7 @@ private slots: void editPreferences(); void goToDomainDialog(); void goToLocation(); + void nameLocation(); void bandwidthDetailsClosed(); void voxelStatsDetailsClosed(); void lodToolsClosed(); @@ -141,6 +143,7 @@ private slots: void runTests(); void showMetavoxelEditor(); void audioMuteToggled(); + void namedLocationCreated(LocationManager::NamedLocationCreateResponse response, NamedLocation* location); private: static Menu* _instance; @@ -241,6 +244,7 @@ namespace MenuOption { const QString GlowMode = "Cycle Glow Mode"; const QString GoToDomain = "Go To Domain..."; const QString GoToLocation = "Go To Location..."; + const QString NameLocation = "Name this location"; const QString GoTo = "Go To..."; const QString IncreaseAvatarSize = "Increase Avatar Size"; const QString IncreaseVoxelSize = "Increase Voxel Size"; diff --git a/interface/src/location/LocationManager.cpp b/interface/src/location/LocationManager.cpp index f57ed0f48d..0588c66818 100644 --- a/interface/src/location/LocationManager.cpp +++ b/interface/src/location/LocationManager.cpp @@ -8,19 +8,47 @@ #include "LocationManager.h" -void LocationManager::createNamedLocation(QString locationName, QString creator, glm::vec3 location, glm::quat orientation) { - _namedLocation = new NamedLocation(locationName, creator, location, orientation); - connect(_namedLocation, SIGNAL(dataReceived(bool)), SLOT(locationDataReceived(bool))); - // DataServerClient::getHashFieldsForKey(DataServerKey::NamedLocation, _namedLocation->locationName(), _namedLocation); +const QString GET_USER_ADDRESS = "/api/v1/users/%1/address"; +const QString GET_PLACE_ADDRESS = "/api/v1/places/%1/address"; +const QString GET_ADDRESSES = "/api/v1/addresses/%1/address"; +const QString POST_PLACE_CREATE = "/api/v1/places/"; + +LocationManager& LocationManager::getInstance() { + static LocationManager sharedInstance; + return sharedInstance; } -void LocationManager::locationDataReceived(bool locationExists) { - disconnect(_namedLocation, SIGNAL(dataReceived(bool)), this, SLOT(locationDataReceived(bool))); - if (locationExists) { - emit creationCompleted(AlreadyExists, _namedLocation); +void LocationManager::namedLocationDataReceived(const QJsonObject& data) { + if (data.isEmpty()) { + return; + } + + qDebug() << data; + if (data.contains("status") && data["status"].toString() == "success") { + NamedLocation* location = new NamedLocation(data["data"].toObject()); + emit creationCompleted(LocationManager::Created, location); } else { - // DataServerClient::putHashFieldsForKey(DataServerKey::NamedLocation, _namedLocation->locationName(), _namedLocation); - emit creationCompleted(Created, _namedLocation); + emit creationCompleted(LocationManager::AlreadyExists, NULL); } } +void LocationManager::errorDataReceived(QNetworkReply::NetworkError error, const QString& message) { + emit creationCompleted(LocationManager::SystemError, NULL); +} + +void LocationManager::createNamedLocation(NamedLocation* namedLocation) { + AccountManager& accountManager = AccountManager::getInstance(); + if (accountManager.isLoggedIn()) { + JSONCallbackParameters callbackParams; + callbackParams.jsonCallbackReceiver = this; + callbackParams.jsonCallbackMethod = "namedLocationDataReceived"; + callbackParams.errorCallbackReceiver = this; + callbackParams.errorCallbackMethod = "errorDataReceived"; + + qDebug() << namedLocation->toJsonString(); + accountManager.authenticatedRequest(POST_PLACE_CREATE, QNetworkAccessManager::PostOperation, + callbackParams, namedLocation->toJsonString().toUtf8()); + } +} + + diff --git a/interface/src/location/LocationManager.h b/interface/src/location/LocationManager.h index 29a29b0496..4282d0e795 100644 --- a/interface/src/location/LocationManager.h +++ b/interface/src/location/LocationManager.h @@ -11,27 +11,32 @@ #include #include "NamedLocation.h" +#include "AccountManager.h" class LocationManager : public QObject { Q_OBJECT public: - enum LocationCreateResponse { + static LocationManager& getInstance(); + + enum NamedLocationCreateResponse { Created, - AlreadyExists + AlreadyExists, + SystemError }; LocationManager() { }; - void createNamedLocation(QString locationName, QString creator, glm::vec3 location, glm::quat orientation); + void createNamedLocation(NamedLocation* namedLocation); + + void goTo(QString destination); + void goToUser(QString userName); signals: - void creationCompleted(LocationManager::LocationCreateResponse response, NamedLocation* location); - -private: - NamedLocation* _namedLocation; + void creationCompleted(LocationManager::NamedLocationCreateResponse response, NamedLocation* location); private slots: - void locationDataReceived(bool locationExists); + void namedLocationDataReceived(const QJsonObject& data); + void errorDataReceived(QNetworkReply::NetworkError error, const QString& message); }; #endif /* defined(__hifi__LocationManager__) */ diff --git a/interface/src/location/NamedLocation.cpp b/interface/src/location/NamedLocation.cpp index 977f368091..af96794fd0 100644 --- a/interface/src/location/NamedLocation.cpp +++ b/interface/src/location/NamedLocation.cpp @@ -8,39 +8,73 @@ #include "NamedLocation.h" -// deserialize data -void NamedLocation::processDataServerResponse(const QString& userString, - const QStringList& keyList, - const QStringList& valueList) { - for (int i = 0; i < keyList.count(); i++) { - if (keyList[i] == "creator") { - _createdBy = valueList[i]; - } else if (keyList[i] == "location") { - QStringList locationCoords = valueList[i].split(","); - if (locationCoords.length() == 3) { - _location = glm::vec3(locationCoords[0].toLong(), locationCoords[1].toLong(), locationCoords[2].toLong()); - } - } else if (keyList[i] == "orientation") { - - QStringList orientationCoords = valueList[i].split(","); - if (orientationCoords.length() == 4) { - _orientation = glm::quat(orientationCoords[0].toLong(), - orientationCoords[1].toLong(), - orientationCoords[2].toLong(), - orientationCoords[3].toLong()); - } - } - } - - emit dataReceived(keyList.count() > 0); +const QString JSON_FORMAT = "{\"address\":{\"position\":\"%1,%2,%3\"," + "\"orientation\":\"%4,%5,%6,%7\",\"domain\":\"%8\"},\"name\":\"%9\"}"; + +QString NamedLocation::toJsonString() { + return JSON_FORMAT.arg(QString::number(_location.x), + QString::number(_location.y), + QString::number(_location.z), + QString::number(_orientation.w), + QString::number(_orientation.x), + QString::number(_orientation.y), + QString::number(_orientation.z), + _domain, + _locationName); } -// serialize data -QHash NamedLocation::getHashData() { - QHash response; - qDebug() << QString::fromStdString(glm::to_string(_location)); - response["location"] = QString::number(_location.x) + "," + QString::number(_location.y) + "," + QString::number(_location.z); - response["creator"] = _createdBy; - response["orientation"] = QString::number(_orientation.x) + "," + QString::number(_orientation.y) + "," + QString::number(_orientation.z) + "," + QString::number(_orientation.w); - return response; +NamedLocation::NamedLocation(const QJsonObject jsonData) { + + bool hasProperties; + + if (jsonData.contains("name")) { + hasProperties = true; + _locationName = jsonData["name"].toString(); + } + + if (jsonData.contains("username")) { + hasProperties = true; + _createdBy = jsonData["username"].toString(); + } + + if (jsonData.contains("domain")) { + hasProperties = true; + _domain = jsonData["domain"].toString(); + } + + // parse position + if (jsonData.contains("position")) { + hasProperties = true; + const int NUMBER_OF_POSITION_ITEMS = 3; + const int X_ITEM = 0; + const int Y_ITEM = 1; + const int Z_ITEM = 2; + + QStringList coordinateItems = jsonData["position"].toString().split(",", QString::SkipEmptyParts); + if (coordinateItems.size() == NUMBER_OF_POSITION_ITEMS) { + double x = coordinateItems[X_ITEM].trimmed().toDouble(); + double y = coordinateItems[Y_ITEM].trimmed().toDouble(); + double z = coordinateItems[Z_ITEM].trimmed().toDouble(); + _location = glm::vec3(x, y, z); + } + } + + // parse orientation + if (jsonData.contains("orientation")) { + hasProperties = true; + QStringList orientationItems = jsonData["orientation"] .toString().split(",", QString::SkipEmptyParts); + const int NUMBER_OF_ORIENTATION_ITEMS = 4; + const int W_ITEM = 0; + const int X_ITEM = 1; + const int Y_ITEM = 2; + const int Z_ITEM = 3; + + if (orientationItems.size() == NUMBER_OF_ORIENTATION_ITEMS) { + double w = orientationItems[W_ITEM].trimmed().toDouble(); + double x = orientationItems[X_ITEM].trimmed().toDouble(); + double y = orientationItems[Y_ITEM].trimmed().toDouble(); + double z = orientationItems[Z_ITEM].trimmed().toDouble(); + _orientation = glm::quat(w, x, y, z); + } + } } \ No newline at end of file diff --git a/interface/src/location/NamedLocation.h b/interface/src/location/NamedLocation.h index ba3c532317..4bc8c2e2ad 100644 --- a/interface/src/location/NamedLocation.h +++ b/interface/src/location/NamedLocation.h @@ -13,50 +13,47 @@ #include #include -// #include "DataServerClient.h" +#include -class NamedLocation : public QObject { //, public DataServerCallbackObject, public DataServerCallerObject { +class NamedLocation : public QObject { Q_OBJECT public: - - NamedLocation(QString locationName, QString createdBy, glm::vec3 location, glm::quat orientation) { + NamedLocation(QString locationName, glm::vec3 location, glm::quat orientation, QString domain) { _locationName = locationName; - _createdBy = createdBy; _location = location; _orientation = orientation; + _domain = domain; } + NamedLocation(const QJsonObject jsonData); + + QString toJsonString(); + bool isEmpty() { return _locationName.isNull() || _locationName.isEmpty(); } - // DataServerCallbackObject implementation - void processDataServerResponse(const QString& userString, const QStringList& keyList, const QStringList& valueList); - - // DataServerCallerObject implementation - QHash getHashData(); - - // properties >> void setLocationName(QString locationName) { _locationName = locationName; } QString locationName() { return _locationName; } - - void createdBy(QString createdBy) { _createdBy = createdBy; } - QString getCreatedBy() { return _createdBy; } - + void setLocation(glm::vec3 location) { _location = location; } glm::vec3 location() { return _location; } void setOrientation(glm::quat orentation) { _orientation = orentation; } glm::quat orientation() { return _orientation; } - // properties << - + + void setDomain(QString domain) { _domain = domain; } + QString domain() { return _domain; } + signals: void dataReceived(bool locationExists); private: + QString _locationName; QString _createdBy; glm::vec3 _location; glm::quat _orientation; + QString _domain; }; diff --git a/libraries/shared/src/AccountManager.h b/libraries/shared/src/AccountManager.h index 8b3c6b362c..b0797e78ca 100644 --- a/libraries/shared/src/AccountManager.h +++ b/libraries/shared/src/AccountManager.h @@ -50,8 +50,9 @@ public: Q_INVOKABLE bool checkAndSignalForAccessToken(); void requestAccessToken(const QString& login, const QString& password); - + QString getUsername() const { return _accountInfo.getUsername(); } + QString getAccessToken() const { return _accountInfo.getAccessToken().token; } void destroy() { delete _networkAccessManager; } From fd201c450bb48f79f79f7c0ee24a72907022ba79 Mon Sep 17 00:00:00 2001 From: stojce Date: Wed, 12 Mar 2014 23:02:21 +0100 Subject: [PATCH 04/39] Multiple destinations implementation --- interface/interface_en.ts | 8 +- interface/src/Menu.cpp | 112 ++++---------- interface/src/Menu.h | 1 + interface/src/location/LocationManager.cpp | 169 ++++++++++++++++++++- interface/src/location/LocationManager.h | 17 ++- 5 files changed, 214 insertions(+), 93 deletions(-) diff --git a/interface/interface_en.ts b/interface/interface_en.ts index a8f78cd36e..20d7a74c09 100644 --- a/interface/interface_en.ts +++ b/interface/interface_en.ts @@ -113,18 +113,18 @@ Menu - + Open .ini config file - - + + Text files (*.ini) - + Save .ini config file diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 6845ab2064..a11692ad12 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -37,6 +37,7 @@ #include "InfoView.h" #include "ui/MetavoxelEditor.h" + Menu* Menu::_instance = NULL; Menu* Menu::getInstance() { @@ -79,7 +80,7 @@ Menu::Menu() : _loginAction(NULL) { Application *appInstance = Application::getInstance(); - + QMenu* fileMenu = addMenu("File"); #ifdef Q_OS_MAC @@ -860,67 +861,11 @@ void Menu::goToDomainDialog() { } void Menu::goToOrientation(QString orientation) { - - if (orientation.isEmpty()) { - return; - } - - QStringList orientationItems = orientation.split(QRegExp("_|,"), QString::SkipEmptyParts); - - const int NUMBER_OF_ORIENTATION_ITEMS = 4; - const int W_ITEM = 0; - const int X_ITEM = 1; - const int Y_ITEM = 2; - const int Z_ITEM = 3; - - if (orientationItems.size() == NUMBER_OF_ORIENTATION_ITEMS) { - - double w = replaceLastOccurrence('-', '.', orientationItems[W_ITEM].trimmed()).toDouble(); - double x = replaceLastOccurrence('-', '.', orientationItems[X_ITEM].trimmed()).toDouble(); - double y = replaceLastOccurrence('-', '.', orientationItems[Y_ITEM].trimmed()).toDouble(); - double z = replaceLastOccurrence('-', '.', orientationItems[Z_ITEM].trimmed()).toDouble(); - - glm::quat newAvatarOrientation(w, x, y, z); - - MyAvatar* myAvatar = Application::getInstance()->getAvatar(); - glm::quat avatarOrientation = myAvatar->getOrientation(); - if (newAvatarOrientation != avatarOrientation) { - myAvatar->setOrientation(newAvatarOrientation); - } - } + LocationManager::getInstance().goToDestination(orientation); } bool Menu::goToDestination(QString destination) { - - QStringList coordinateItems = destination.split(QRegExp("_|,"), QString::SkipEmptyParts); - - const int NUMBER_OF_COORDINATE_ITEMS = 3; - const int X_ITEM = 0; - const int Y_ITEM = 1; - const int Z_ITEM = 2; - if (coordinateItems.size() == NUMBER_OF_COORDINATE_ITEMS) { - - double x = replaceLastOccurrence('-', '.', coordinateItems[X_ITEM].trimmed()).toDouble(); - double y = replaceLastOccurrence('-', '.', coordinateItems[Y_ITEM].trimmed()).toDouble(); - double z = replaceLastOccurrence('-', '.', coordinateItems[Z_ITEM].trimmed()).toDouble(); - - glm::vec3 newAvatarPos(x, y, z); - - MyAvatar* myAvatar = Application::getInstance()->getAvatar(); - glm::vec3 avatarPos = myAvatar->getPosition(); - if (newAvatarPos != avatarPos) { - // send a node kill request, indicating to other clients that they should play the "disappeared" effect - MyAvatar::sendKillAvatar(); - - qDebug("Going To Location: %f, %f, %f...", x, y, z); - myAvatar->setPosition(newAvatarPos); - } - - return true; - } - - // no coordinates were parsed - return false; + return LocationManager::getInstance().goToDestination(destination); } void Menu::goTo() { @@ -935,25 +880,33 @@ void Menu::goTo() { int dialogReturn = gotoDialog.exec(); if (dialogReturn == QDialog::Accepted && !gotoDialog.textValue().isEmpty()) { - - destination = gotoDialog.textValue(); - - // go to coordinate destination or to Username - if (!goToDestination(destination)) { - JSONCallbackParameters callbackParams; - callbackParams.jsonCallbackReceiver = Application::getInstance()->getAvatar(); - callbackParams.jsonCallbackMethod = "goToLocationFromResponse"; - - // there's a username entered by the user, make a request to the data-server for the associated location - AccountManager::getInstance().authenticatedRequest("/api/v1/users/" + gotoDialog.textValue() + "/address", - QNetworkAccessManager::GetOperation, - callbackParams); - } + LocationManager* manager = new LocationManager(); + manager->goTo(gotoDialog.textValue()); + connect(manager, &LocationManager::multipleDestinationsFound, this, &Menu::multipleDestinationsDecision); } sendFakeEnterEvent(); } +void Menu::multipleDestinationsDecision(const QJsonObject& userData, const QJsonObject& placeData) { + QMessageBox msgBox; + msgBox.setText("Both user and location exists with same name"); + msgBox.setInformativeText("Where you wanna go?"); + msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Open); + msgBox.button(QMessageBox::Ok)->setText("User"); + msgBox.button(QMessageBox::Open)->setText("Place"); + int userResponse = msgBox.exec(); + + if (userResponse == QMessageBox::Ok) { + Application::getInstance()->getAvatar()->goToLocationFromResponse(userData); + } else if (userResponse == QMessageBox::Open) { + Application::getInstance()->getAvatar()->goToLocationFromResponse(userData); + } + + LocationManager* manager = reinterpret_cast(sender()); + disconnect(manager, &LocationManager::multipleDestinationsFound, this, &Menu::multipleDestinationsDecision); +} + void Menu::goToLocation() { MyAvatar* myAvatar = Application::getInstance()->getAvatar(); glm::vec3 avatarPos = myAvatar->getPosition(); @@ -999,7 +952,7 @@ void Menu::nameLocation() { // check if user is logged in or show login dialog if not AccountManager& accountManager = AccountManager::getInstance(); - if (!accountManager.isLoggedIn() && 1 > 2) { + if (!accountManager.isLoggedIn()) { QMessageBox msgBox; msgBox.setText("We need to tie this location to your username."); msgBox.setInformativeText("Please login first, then try naming the location again."); @@ -1278,17 +1231,6 @@ void Menu::addAvatarCollisionSubMenu(QMenu* overMenu) { 0, true, avatar, SLOT(updateCollisionFlags())); } -QString Menu::replaceLastOccurrence(QChar search, QChar replace, QString string) { - int lastIndex; - lastIndex = string.lastIndexOf(search); - if (lastIndex > 0) { - lastIndex = string.lastIndexOf(search); - string.replace(lastIndex, 1, replace); - } - - return string; -} - QAction* Menu::getActionFromName(const QString& menuName, QMenu* menu) { QList menuActions; if (menu) { diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 6ff0d79662..d47c156aa8 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -149,6 +149,7 @@ private slots: void toggleChat(); void audioMuteToggled(); void namedLocationCreated(LocationManager::NamedLocationCreateResponse response, NamedLocation* location); + void multipleDestinationsDecision(const QJsonObject& userData, const QJsonObject& placeData); private: static Menu* _instance; diff --git a/interface/src/location/LocationManager.cpp b/interface/src/location/LocationManager.cpp index 0588c66818..61ed401766 100644 --- a/interface/src/location/LocationManager.cpp +++ b/interface/src/location/LocationManager.cpp @@ -7,12 +7,17 @@ // #include "LocationManager.h" +#include "Application.h" const QString GET_USER_ADDRESS = "/api/v1/users/%1/address"; const QString GET_PLACE_ADDRESS = "/api/v1/places/%1/address"; -const QString GET_ADDRESSES = "/api/v1/addresses/%1/address"; const QString POST_PLACE_CREATE = "/api/v1/places/"; + +LocationManager::LocationManager() : _userData(), _placeData() { + +}; + LocationManager& LocationManager::getInstance() { static LocationManager sharedInstance; return sharedInstance; @@ -23,7 +28,6 @@ void LocationManager::namedLocationDataReceived(const QJsonObject& data) { return; } - qDebug() << data; if (data.contains("status") && data["status"].toString() == "success") { NamedLocation* location = new NamedLocation(data["data"].toObject()); emit creationCompleted(LocationManager::Created, location); @@ -45,10 +49,169 @@ void LocationManager::createNamedLocation(NamedLocation* namedLocation) { callbackParams.errorCallbackReceiver = this; callbackParams.errorCallbackMethod = "errorDataReceived"; - qDebug() << namedLocation->toJsonString(); accountManager.authenticatedRequest(POST_PLACE_CREATE, QNetworkAccessManager::PostOperation, callbackParams, namedLocation->toJsonString().toUtf8()); } } +void LocationManager::goTo(QString destination) { + + if (destination.startsWith("@")) { + // remove '@' and go to user + goToUser(destination.remove(0, 1)); + return; + } + + if (destination.startsWith("#")) { + // remove '#' and go to named place + goToPlace(destination.remove(0, 1)); + return; + } + + // go to coordinate destination or to Username + if (!goToDestination(destination)) { + // reset data on local variables + _userData = QJsonObject(); + _placeData = QJsonObject(); + + JSONCallbackParameters callbackParams; + callbackParams.jsonCallbackReceiver = this; + callbackParams.jsonCallbackMethod = "goToUserFromResponse"; + AccountManager::getInstance().authenticatedRequest(GET_USER_ADDRESS.arg(destination), + QNetworkAccessManager::GetOperation, + callbackParams); + + callbackParams.jsonCallbackMethod = "goToLocationFromResponse"; + AccountManager::getInstance().authenticatedRequest(GET_PLACE_ADDRESS.arg(destination), + QNetworkAccessManager::GetOperation, + callbackParams); + } +} + +void LocationManager::goToUserFromResponse(const QJsonObject& jsonObject) { + _userData = jsonObject; + checkForMultipleDestinations(); +} + +void LocationManager::goToLocationFromResponse(const QJsonObject& jsonObject) { + _placeData = jsonObject; + checkForMultipleDestinations(); +} + +void LocationManager::checkForMultipleDestinations() { + if (!_userData.isEmpty() && !_placeData.isEmpty()) { + if (_userData.contains("status") && _userData["status"].toString() == "success" && + _placeData.contains("status") && _placeData["status"].toString() == "success") { + emit multipleDestinationsFound(_userData, _placeData); + return; + } + + if (_userData.contains("status") && _userData["status"].toString() == "success") { + Application::getInstance()->getAvatar()->goToLocationFromResponse(_userData); + return; + } + + if (_placeData.contains("status") && _placeData["status"].toString() == "success") { + Application::getInstance()->getAvatar()->goToLocationFromResponse(_placeData); + return; + } + + emit locationChanged(); + } +} + +void LocationManager::goToUser(QString userName) { + + JSONCallbackParameters callbackParams; + callbackParams.jsonCallbackReceiver = Application::getInstance()->getAvatar(); + callbackParams.jsonCallbackMethod = "goToLocationFromResponse"; + + AccountManager::getInstance().authenticatedRequest(GET_USER_ADDRESS.arg(userName), + QNetworkAccessManager::GetOperation, + callbackParams); +} + +void LocationManager::goToPlace(QString placeName) { + JSONCallbackParameters callbackParams; + callbackParams.jsonCallbackReceiver = Application::getInstance()->getAvatar(); + callbackParams.jsonCallbackMethod = "goToLocationFromResponse"; + + AccountManager::getInstance().authenticatedRequest(GET_PLACE_ADDRESS.arg(placeName), + QNetworkAccessManager::GetOperation, + callbackParams); +} + +void LocationManager::goToOrientation(QString orientation) { + if (orientation.isEmpty()) { + return; + } + + QStringList orientationItems = orientation.split(QRegExp("_|,"), QString::SkipEmptyParts); + + const int NUMBER_OF_ORIENTATION_ITEMS = 4; + const int W_ITEM = 0; + const int X_ITEM = 1; + const int Y_ITEM = 2; + const int Z_ITEM = 3; + + if (orientationItems.size() == NUMBER_OF_ORIENTATION_ITEMS) { + + double w = replaceLastOccurrence('-', '.', orientationItems[W_ITEM].trimmed()).toDouble(); + double x = replaceLastOccurrence('-', '.', orientationItems[X_ITEM].trimmed()).toDouble(); + double y = replaceLastOccurrence('-', '.', orientationItems[Y_ITEM].trimmed()).toDouble(); + double z = replaceLastOccurrence('-', '.', orientationItems[Z_ITEM].trimmed()).toDouble(); + + glm::quat newAvatarOrientation(w, x, y, z); + + MyAvatar* myAvatar = Application::getInstance()->getAvatar(); + glm::quat avatarOrientation = myAvatar->getOrientation(); + if (newAvatarOrientation != avatarOrientation) { + myAvatar->setOrientation(newAvatarOrientation); + } + } +} + +bool LocationManager::goToDestination(QString destination) { + + QStringList coordinateItems = destination.split(QRegExp("_|,"), QString::SkipEmptyParts); + + const int NUMBER_OF_COORDINATE_ITEMS = 3; + const int X_ITEM = 0; + const int Y_ITEM = 1; + const int Z_ITEM = 2; + if (coordinateItems.size() == NUMBER_OF_COORDINATE_ITEMS) { + + double x = replaceLastOccurrence('-', '.', coordinateItems[X_ITEM].trimmed()).toDouble(); + double y = replaceLastOccurrence('-', '.', coordinateItems[Y_ITEM].trimmed()).toDouble(); + double z = replaceLastOccurrence('-', '.', coordinateItems[Z_ITEM].trimmed()).toDouble(); + + glm::vec3 newAvatarPos(x, y, z); + + MyAvatar* myAvatar = Application::getInstance()->getAvatar(); + glm::vec3 avatarPos = myAvatar->getPosition(); + if (newAvatarPos != avatarPos) { + // send a node kill request, indicating to other clients that they should play the "disappeared" effect + MyAvatar::sendKillAvatar(); + + qDebug("Going To Location: %f, %f, %f...", x, y, z); + myAvatar->setPosition(newAvatarPos); + } + + return true; + } + + // no coordinates were parsed + return false; +} + +QString LocationManager::replaceLastOccurrence(QChar search, QChar replace, QString string) { + int lastIndex; + lastIndex = string.lastIndexOf(search); + if (lastIndex > 0) { + lastIndex = string.lastIndexOf(search); + string.replace(lastIndex, 1, replace); + } + + return string; +} diff --git a/interface/src/location/LocationManager.h b/interface/src/location/LocationManager.h index 4282d0e795..6d5beacae5 100644 --- a/interface/src/location/LocationManager.h +++ b/interface/src/location/LocationManager.h @@ -25,18 +25,33 @@ public: SystemError }; - LocationManager() { }; + LocationManager(); void createNamedLocation(NamedLocation* namedLocation); void goTo(QString destination); void goToUser(QString userName); + void goToPlace(QString placeName); + void goToOrientation(QString orientation); + bool goToDestination(QString destination); + +private: + QString replaceLastOccurrence(QChar search, QChar replace, QString string); + QJsonObject _userData; + QJsonObject _placeData; + + void checkForMultipleDestinations(); signals: void creationCompleted(LocationManager::NamedLocationCreateResponse response, NamedLocation* location); + void multipleDestinationsFound(const QJsonObject& userData, const QJsonObject& placeData); + void locationChanged(); private slots: void namedLocationDataReceived(const QJsonObject& data); void errorDataReceived(QNetworkReply::NetworkError error, const QString& message); + void goToLocationFromResponse(const QJsonObject& jsonObject); + void goToUserFromResponse(const QJsonObject& jsonObject); + }; #endif /* defined(__hifi__LocationManager__) */ From d92426c37dd6c70216598291fd280cf0e4fc0561 Mon Sep 17 00:00:00 2001 From: stojce Date: Wed, 12 Mar 2014 23:11:44 +0100 Subject: [PATCH 05/39] translation auto corrected --- interface/interface_en.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/interface/interface_en.ts b/interface/interface_en.ts index 20d7a74c09..58796e1aa4 100644 --- a/interface/interface_en.ts +++ b/interface/interface_en.ts @@ -4,22 +4,22 @@ Application - + Export Voxels - + Sparse Voxel Octree Files (*.svo) - + Open Script - + JavaScript Files (*.js) @@ -113,18 +113,18 @@ Menu - + Open .ini config file - - + + Text files (*.ini) - + Save .ini config file From e231c8486b20da47dd4c1ea565ec7e8ea73eb36a Mon Sep 17 00:00:00 2001 From: stojce Date: Thu, 13 Mar 2014 07:47:33 +0100 Subject: [PATCH 06/39] Using singleton for location manager --- interface/interface_en.ts | 8 ++++---- interface/src/Menu.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/interface/interface_en.ts b/interface/interface_en.ts index e658d15ba7..46d050787a 100644 --- a/interface/interface_en.ts +++ b/interface/interface_en.ts @@ -4,22 +4,22 @@ Application - + Export Voxels - + Sparse Voxel Octree Files (*.svo) - + Open Script - + JavaScript Files (*.js) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 69cbd4a963..eb4386b84c 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -884,7 +884,7 @@ void Menu::goTo() { int dialogReturn = gotoDialog.exec(); if (dialogReturn == QDialog::Accepted && !gotoDialog.textValue().isEmpty()) { - LocationManager* manager = new LocationManager(); + LocationManager* manager = &LocationManager::getInstance(); manager->goTo(gotoDialog.textValue()); connect(manager, &LocationManager::multipleDestinationsFound, this, &Menu::multipleDestinationsDecision); } From e964b846de1e094d40310f8158a1e9c53fa8f4fd Mon Sep 17 00:00:00 2001 From: stojce Date: Thu, 13 Mar 2014 08:03:23 +0100 Subject: [PATCH 07/39] - url encoding for get requests --- interface/src/location/LocationManager.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/interface/src/location/LocationManager.cpp b/interface/src/location/LocationManager.cpp index 61ed401766..f23915506d 100644 --- a/interface/src/location/LocationManager.cpp +++ b/interface/src/location/LocationManager.cpp @@ -74,6 +74,7 @@ void LocationManager::goTo(QString destination) { _userData = QJsonObject(); _placeData = QJsonObject(); + destination = QString::QString(QUrl::toPercentEncoding(destination)); JSONCallbackParameters callbackParams; callbackParams.jsonCallbackReceiver = this; callbackParams.jsonCallbackMethod = "goToUserFromResponse"; @@ -126,6 +127,7 @@ void LocationManager::goToUser(QString userName) { callbackParams.jsonCallbackReceiver = Application::getInstance()->getAvatar(); callbackParams.jsonCallbackMethod = "goToLocationFromResponse"; + userName = QString::QString(QUrl::toPercentEncoding(userName)); AccountManager::getInstance().authenticatedRequest(GET_USER_ADDRESS.arg(userName), QNetworkAccessManager::GetOperation, callbackParams); @@ -136,6 +138,7 @@ void LocationManager::goToPlace(QString placeName) { callbackParams.jsonCallbackReceiver = Application::getInstance()->getAvatar(); callbackParams.jsonCallbackMethod = "goToLocationFromResponse"; + placeName = QString::QString(QUrl::toPercentEncoding(placeName)); AccountManager::getInstance().authenticatedRequest(GET_PLACE_ADDRESS.arg(placeName), QNetworkAccessManager::GetOperation, callbackParams); From be804e0f864ff17ba7ed3c940d67206db8f9dcc8 Mon Sep 17 00:00:00 2001 From: stojce Date: Thu, 13 Mar 2014 09:30:59 +0100 Subject: [PATCH 08/39] Fixes for linux build --- interface/src/location/LocationManager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/location/LocationManager.cpp b/interface/src/location/LocationManager.cpp index f23915506d..986371ac88 100644 --- a/interface/src/location/LocationManager.cpp +++ b/interface/src/location/LocationManager.cpp @@ -74,7 +74,7 @@ void LocationManager::goTo(QString destination) { _userData = QJsonObject(); _placeData = QJsonObject(); - destination = QString::QString(QUrl::toPercentEncoding(destination)); + destination = QString(QUrl::toPercentEncoding(destination)); JSONCallbackParameters callbackParams; callbackParams.jsonCallbackReceiver = this; callbackParams.jsonCallbackMethod = "goToUserFromResponse"; @@ -127,7 +127,7 @@ void LocationManager::goToUser(QString userName) { callbackParams.jsonCallbackReceiver = Application::getInstance()->getAvatar(); callbackParams.jsonCallbackMethod = "goToLocationFromResponse"; - userName = QString::QString(QUrl::toPercentEncoding(userName)); + userName = QString(QUrl::toPercentEncoding(userName)); AccountManager::getInstance().authenticatedRequest(GET_USER_ADDRESS.arg(userName), QNetworkAccessManager::GetOperation, callbackParams); @@ -138,7 +138,7 @@ void LocationManager::goToPlace(QString placeName) { callbackParams.jsonCallbackReceiver = Application::getInstance()->getAvatar(); callbackParams.jsonCallbackMethod = "goToLocationFromResponse"; - placeName = QString::QString(QUrl::toPercentEncoding(placeName)); + placeName = QString(QUrl::toPercentEncoding(placeName)); AccountManager::getInstance().authenticatedRequest(GET_PLACE_ADDRESS.arg(placeName), QNetworkAccessManager::GetOperation, callbackParams); From b3cbcc6cd6b841962cc181ffc58d2946a948eac7 Mon Sep 17 00:00:00 2001 From: stojce Date: Thu, 13 Mar 2014 10:20:16 +0100 Subject: [PATCH 09/39] minor cleanup of unused data --- libraries/shared/src/NodeList.cpp | 1 - libraries/shared/src/PacketHeaders.cpp | 3 --- libraries/shared/src/PacketHeaders.h | 3 --- 3 files changed, 7 deletions(-) diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 523d18929c..263e29bc94 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -97,7 +97,6 @@ bool NodeList::packetVersionAndHashMatch(const QByteArray& packet) { << PacketTypeDomainServerAuthRequest << PacketTypeDomainConnectRequest << PacketTypeStunResponse << PacketTypeDataServerConfirm << PacketTypeDataServerGet << PacketTypeDataServerPut << PacketTypeDataServerSend - << PacketTypeDataServerHashGet << PacketTypeDataServerHashPut << PacketTypeDataServerHashSend << PacketTypeCreateAssignment << PacketTypeRequestAssignment; if (!NON_VERIFIED_PACKETS.contains(checkType)) { diff --git a/libraries/shared/src/PacketHeaders.cpp b/libraries/shared/src/PacketHeaders.cpp index 88996adceb..eccfa4fefa 100644 --- a/libraries/shared/src/PacketHeaders.cpp +++ b/libraries/shared/src/PacketHeaders.cpp @@ -58,9 +58,6 @@ PacketVersion versionForPacketType(PacketType type) { case PacketTypeDataServerPut: case PacketTypeDataServerConfirm: case PacketTypeDataServerSend: - case PacketTypeDataServerHashPut: - case PacketTypeDataServerHashGet: - case PacketTypeDataServerHashSend: return 1; case PacketTypeVoxelSet: case PacketTypeVoxelSetDestructive: diff --git a/libraries/shared/src/PacketHeaders.h b/libraries/shared/src/PacketHeaders.h index 47a4c65409..0122e36a61 100644 --- a/libraries/shared/src/PacketHeaders.h +++ b/libraries/shared/src/PacketHeaders.h @@ -39,9 +39,6 @@ enum PacketType { PacketTypeCreateAssignment, PacketTypeDataServerPut, PacketTypeDataServerGet, - PacketTypeDataServerHashPut, - PacketTypeDataServerHashGet, - PacketTypeDataServerHashSend, PacketTypeDataServerSend, PacketTypeDataServerConfirm, PacketTypeVoxelQuery, From 576b8acef3d253f546fef78ccf5b1e9818307f39 Mon Sep 17 00:00:00 2001 From: stojce Date: Fri, 14 Mar 2014 20:09:03 +0100 Subject: [PATCH 10/39] CR fixes --- interface/interface_en.ts | 8 ++-- interface/src/Menu.cpp | 4 +- interface/src/Menu.h | 6 +-- interface/src/location/LocationManager.cpp | 43 ++++++++++------- interface/src/location/LocationManager.h | 7 +-- interface/src/location/NamedLocation.cpp | 56 ---------------------- interface/src/location/NamedLocation.h | 2 - 7 files changed, 38 insertions(+), 88 deletions(-) diff --git a/interface/interface_en.ts b/interface/interface_en.ts index c52ec91671..786a76530c 100644 --- a/interface/interface_en.ts +++ b/interface/interface_en.ts @@ -113,18 +113,18 @@ Menu - + Open .ini config file - - + + Text files (*.ini) - + Save .ini config file diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index b322e6567c..98a00e05c9 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -19,12 +19,12 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include @@ -940,7 +940,7 @@ void Menu::goToLocation() { sendFakeEnterEvent(); } -void Menu::namedLocationCreated(LocationManager::NamedLocationCreateResponse response, NamedLocation* location) { +void Menu::namedLocationCreated(LocationManager::NamedLocationCreateResponse response) { if (response == LocationManager::Created) { return; diff --git a/interface/src/Menu.h b/interface/src/Menu.h index b124315cbb..df622be6ac 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -17,9 +17,9 @@ #include #include #include -#include "location/LocationManager.h" -#include +#include "location/LocationManager.h" +#include "ui/ChatWindow.h" const float ADJUST_LOD_DOWN_FPS = 40.0; const float ADJUST_LOD_UP_FPS = 55.0; @@ -149,7 +149,7 @@ private slots: void showChat(); void toggleChat(); void audioMuteToggled(); - void namedLocationCreated(LocationManager::NamedLocationCreateResponse response, NamedLocation* location); + void namedLocationCreated(LocationManager::NamedLocationCreateResponse response); void multipleDestinationsDecision(const QJsonObject& userData, const QJsonObject& placeData); private: diff --git a/interface/src/location/LocationManager.cpp b/interface/src/location/LocationManager.cpp index 986371ac88..b83094ba4c 100644 --- a/interface/src/location/LocationManager.cpp +++ b/interface/src/location/LocationManager.cpp @@ -6,8 +6,8 @@ // // -#include "LocationManager.h" #include "Application.h" +#include "LocationManager.h" const QString GET_USER_ADDRESS = "/api/v1/users/%1/address"; const QString GET_PLACE_ADDRESS = "/api/v1/places/%1/address"; @@ -29,15 +29,14 @@ void LocationManager::namedLocationDataReceived(const QJsonObject& data) { } if (data.contains("status") && data["status"].toString() == "success") { - NamedLocation* location = new NamedLocation(data["data"].toObject()); - emit creationCompleted(LocationManager::Created, location); + emit creationCompleted(LocationManager::Created); } else { - emit creationCompleted(LocationManager::AlreadyExists, NULL); + emit creationCompleted(LocationManager::AlreadyExists); } } void LocationManager::errorDataReceived(QNetworkReply::NetworkError error, const QString& message) { - emit creationCompleted(LocationManager::SystemError, NULL); + emit creationCompleted(LocationManager::SystemError); } void LocationManager::createNamedLocation(NamedLocation* namedLocation) { @@ -149,7 +148,7 @@ void LocationManager::goToOrientation(QString orientation) { return; } - QStringList orientationItems = orientation.split(QRegExp("_|,"), QString::SkipEmptyParts); + QStringList orientationItems = orientation.remove(' ').split(QRegExp("_|,"), QString::SkipEmptyParts); const int NUMBER_OF_ORIENTATION_ITEMS = 4; const int W_ITEM = 0; @@ -159,10 +158,16 @@ void LocationManager::goToOrientation(QString orientation) { if (orientationItems.size() == NUMBER_OF_ORIENTATION_ITEMS) { - double w = replaceLastOccurrence('-', '.', orientationItems[W_ITEM].trimmed()).toDouble(); - double x = replaceLastOccurrence('-', '.', orientationItems[X_ITEM].trimmed()).toDouble(); - double y = replaceLastOccurrence('-', '.', orientationItems[Y_ITEM].trimmed()).toDouble(); - double z = replaceLastOccurrence('-', '.', orientationItems[Z_ITEM].trimmed()).toDouble(); + // replace last occurrence of '_' with decimal point + replaceLastOccurrence('-', '.', orientationItems[W_ITEM]); + replaceLastOccurrence('-', '.', orientationItems[X_ITEM]); + replaceLastOccurrence('-', '.', orientationItems[Y_ITEM]); + replaceLastOccurrence('-', '.', orientationItems[Z_ITEM]); + + double w = orientationItems[W_ITEM].toDouble(); + double x = orientationItems[X_ITEM].toDouble(); + double y = orientationItems[Y_ITEM].toDouble(); + double z = orientationItems[Z_ITEM].toDouble(); glm::quat newAvatarOrientation(w, x, y, z); @@ -176,7 +181,7 @@ void LocationManager::goToOrientation(QString orientation) { bool LocationManager::goToDestination(QString destination) { - QStringList coordinateItems = destination.split(QRegExp("_|,"), QString::SkipEmptyParts); + QStringList coordinateItems = destination.remove(' ').split(QRegExp("_|,"), QString::SkipEmptyParts); const int NUMBER_OF_COORDINATE_ITEMS = 3; const int X_ITEM = 0; @@ -184,9 +189,14 @@ bool LocationManager::goToDestination(QString destination) { const int Z_ITEM = 2; if (coordinateItems.size() == NUMBER_OF_COORDINATE_ITEMS) { - double x = replaceLastOccurrence('-', '.', coordinateItems[X_ITEM].trimmed()).toDouble(); - double y = replaceLastOccurrence('-', '.', coordinateItems[Y_ITEM].trimmed()).toDouble(); - double z = replaceLastOccurrence('-', '.', coordinateItems[Z_ITEM].trimmed()).toDouble(); + // replace last occurrence of '_' with decimal point + replaceLastOccurrence('-', '.', coordinateItems[X_ITEM]); + replaceLastOccurrence('-', '.', coordinateItems[Y_ITEM]); + replaceLastOccurrence('-', '.', coordinateItems[Z_ITEM]); + + double x = coordinateItems[X_ITEM].toDouble(); + double y = coordinateItems[Y_ITEM].toDouble(); + double z = coordinateItems[Z_ITEM].toDouble(); glm::vec3 newAvatarPos(x, y, z); @@ -207,14 +217,11 @@ bool LocationManager::goToDestination(QString destination) { return false; } -QString LocationManager::replaceLastOccurrence(QChar search, QChar replace, QString string) { +void LocationManager::replaceLastOccurrence(const QChar search, const QChar replace, QString& string) { int lastIndex; lastIndex = string.lastIndexOf(search); if (lastIndex > 0) { lastIndex = string.lastIndexOf(search); string.replace(lastIndex, 1, replace); } - - return string; } - diff --git a/interface/src/location/LocationManager.h b/interface/src/location/LocationManager.h index 6d5beacae5..a6bdaf66b4 100644 --- a/interface/src/location/LocationManager.h +++ b/interface/src/location/LocationManager.h @@ -10,8 +10,9 @@ #define __hifi__LocationManager__ #include -#include "NamedLocation.h" + #include "AccountManager.h" +#include "NamedLocation.h" class LocationManager : public QObject { Q_OBJECT @@ -35,14 +36,14 @@ public: bool goToDestination(QString destination); private: - QString replaceLastOccurrence(QChar search, QChar replace, QString string); QJsonObject _userData; QJsonObject _placeData; + void replaceLastOccurrence(const QChar search, const QChar replace, QString& string); void checkForMultipleDestinations(); signals: - void creationCompleted(LocationManager::NamedLocationCreateResponse response, NamedLocation* location); + void creationCompleted(LocationManager::NamedLocationCreateResponse response); void multipleDestinationsFound(const QJsonObject& userData, const QJsonObject& placeData); void locationChanged(); diff --git a/interface/src/location/NamedLocation.cpp b/interface/src/location/NamedLocation.cpp index af96794fd0..c6daef4961 100644 --- a/interface/src/location/NamedLocation.cpp +++ b/interface/src/location/NamedLocation.cpp @@ -22,59 +22,3 @@ QString NamedLocation::toJsonString() { _domain, _locationName); } - -NamedLocation::NamedLocation(const QJsonObject jsonData) { - - bool hasProperties; - - if (jsonData.contains("name")) { - hasProperties = true; - _locationName = jsonData["name"].toString(); - } - - if (jsonData.contains("username")) { - hasProperties = true; - _createdBy = jsonData["username"].toString(); - } - - if (jsonData.contains("domain")) { - hasProperties = true; - _domain = jsonData["domain"].toString(); - } - - // parse position - if (jsonData.contains("position")) { - hasProperties = true; - const int NUMBER_OF_POSITION_ITEMS = 3; - const int X_ITEM = 0; - const int Y_ITEM = 1; - const int Z_ITEM = 2; - - QStringList coordinateItems = jsonData["position"].toString().split(",", QString::SkipEmptyParts); - if (coordinateItems.size() == NUMBER_OF_POSITION_ITEMS) { - double x = coordinateItems[X_ITEM].trimmed().toDouble(); - double y = coordinateItems[Y_ITEM].trimmed().toDouble(); - double z = coordinateItems[Z_ITEM].trimmed().toDouble(); - _location = glm::vec3(x, y, z); - } - } - - // parse orientation - if (jsonData.contains("orientation")) { - hasProperties = true; - QStringList orientationItems = jsonData["orientation"] .toString().split(",", QString::SkipEmptyParts); - const int NUMBER_OF_ORIENTATION_ITEMS = 4; - const int W_ITEM = 0; - const int X_ITEM = 1; - const int Y_ITEM = 2; - const int Z_ITEM = 3; - - if (orientationItems.size() == NUMBER_OF_ORIENTATION_ITEMS) { - double w = orientationItems[W_ITEM].trimmed().toDouble(); - double x = orientationItems[X_ITEM].trimmed().toDouble(); - double y = orientationItems[Y_ITEM].trimmed().toDouble(); - double z = orientationItems[Z_ITEM].trimmed().toDouble(); - _orientation = glm::quat(w, x, y, z); - } - } -} \ No newline at end of file diff --git a/interface/src/location/NamedLocation.h b/interface/src/location/NamedLocation.h index 4bc8c2e2ad..81af03b45e 100644 --- a/interface/src/location/NamedLocation.h +++ b/interface/src/location/NamedLocation.h @@ -26,8 +26,6 @@ public: _domain = domain; } - NamedLocation(const QJsonObject jsonData); - QString toJsonString(); bool isEmpty() { return _locationName.isNull() || _locationName.isEmpty(); } From 2a03cf1bab0da6a380cb1c27dd2aef8f689f9812 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 14 Mar 2014 17:17:38 -0700 Subject: [PATCH 11/39] make throttle rendering not adjust LOD --- interface/src/Application.cpp | 4 ++-- interface/src/Application.h | 3 ++- interface/src/GLCanvas.h | 1 + 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 37b2810c68..50dbf1b51a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1607,8 +1607,8 @@ bool Application::isLookingAtMyAvatar(Avatar* avatar) { } void Application::updateLOD() { - // adjust it unless we were asked to disable this feature - if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableAutoAdjustLOD)) { + // adjust it unless we were asked to disable this feature, or if we're currently in throttleRendering mode + if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableAutoAdjustLOD) && !isThrottleRendering()) { Menu::getInstance()->autoAdjustLOD(_fps); } } diff --git a/interface/src/Application.h b/interface/src/Application.h index a9fa04904f..cbfbf4166d 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -147,6 +147,7 @@ public: glm::vec3 getMouseVoxelWorldCoordinates(const VoxelDetail& mouseVoxel); QGLWidget* getGLWidget() { return _glWidget; } + bool isThrottleRendering() const { return _glWidget->isThrottleRendering(); } MyAvatar* getAvatar() { return _myAvatar; } Audio* getAudio() { return &_audio; } Camera* getCamera() { return &_myCamera; } @@ -339,7 +340,7 @@ private: void displayRearMirrorTools(); QMainWindow* _window; - QGLWidget* _glWidget; + GLCanvas* _glWidget; // our GLCanvas has a couple extra features bool _statsExpanded; BandwidthMeter _bandwidthMeter; diff --git a/interface/src/GLCanvas.h b/interface/src/GLCanvas.h index e6dcc38977..e6d96141b4 100644 --- a/interface/src/GLCanvas.h +++ b/interface/src/GLCanvas.h @@ -17,6 +17,7 @@ class GLCanvas : public QGLWidget { Q_OBJECT public: GLCanvas(); + bool isThrottleRendering() const { return _throttleRendering; } protected: QTimer _frameTimer; From a5eb5d6515a9fe88f0c2f02d324a2bdbb973c438 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 14 Mar 2014 17:22:35 -0700 Subject: [PATCH 12/39] handle minimize case --- interface/src/GLCanvas.cpp | 4 ++++ interface/src/GLCanvas.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/interface/src/GLCanvas.cpp b/interface/src/GLCanvas.cpp index ea04002ddb..d6ef9d180c 100644 --- a/interface/src/GLCanvas.cpp +++ b/interface/src/GLCanvas.cpp @@ -19,6 +19,10 @@ GLCanvas::GLCanvas() : QGLWidget(QGLFormat(QGL::NoDepthBuffer)), { } +bool GLCanvas::isThrottleRendering() const { + return _throttleRendering || Application::getInstance()->getWindow()->isMinimized(); +} + void GLCanvas::initializeGL() { Application::getInstance()->initializeGL(); setAttribute(Qt::WA_AcceptTouchEvents); diff --git a/interface/src/GLCanvas.h b/interface/src/GLCanvas.h index e6d96141b4..ad396a48ce 100644 --- a/interface/src/GLCanvas.h +++ b/interface/src/GLCanvas.h @@ -17,7 +17,7 @@ class GLCanvas : public QGLWidget { Q_OBJECT public: GLCanvas(); - bool isThrottleRendering() const { return _throttleRendering; } + bool isThrottleRendering() const; protected: QTimer _frameTimer; From 711e6ca3f5b4dff11154f1db763cb1f766fb294c Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 14 Mar 2014 17:43:55 -0700 Subject: [PATCH 13/39] clean up casts and types to fix warnings in a cleaner way --- libraries/octree/src/OctreeSceneStats.cpp | 4 ++-- libraries/octree/src/OctreeSceneStats.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/octree/src/OctreeSceneStats.cpp b/libraries/octree/src/OctreeSceneStats.cpp index 5cf906d82d..a21ab60493 100644 --- a/libraries/octree/src/OctreeSceneStats.cpp +++ b/libraries/octree/src/OctreeSceneStats.cpp @@ -919,13 +919,13 @@ void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet, if (wantExtraDebugging) { qDebug() << "too many _missingSequenceNumbers:" << _missingSequenceNumbers.size(); } - foreach(unsigned int missingItem, _missingSequenceNumbers) { + foreach(uint16_t missingItem, _missingSequenceNumbers) { if (wantExtraDebugging) { qDebug() << "checking item:" << missingItem << "is it in need of pruning?"; qDebug() << "(_incomingLastSequence - MAX_MISSING_SEQUENCE_OLD_AGE):" << (_incomingLastSequence - MAX_MISSING_SEQUENCE_OLD_AGE); } - if (missingItem <= (unsigned int)std::max(0, (int)_incomingLastSequence - (int)MAX_MISSING_SEQUENCE_OLD_AGE)) { + if (missingItem <= std::max(0, _incomingLastSequence - MAX_MISSING_SEQUENCE_OLD_AGE)) { if (wantExtraDebugging) { qDebug() << "pruning really old missing sequence:" << missingItem; } diff --git a/libraries/octree/src/OctreeSceneStats.h b/libraries/octree/src/OctreeSceneStats.h index 2b39b3434c..866c5d0b85 100644 --- a/libraries/octree/src/OctreeSceneStats.h +++ b/libraries/octree/src/OctreeSceneStats.h @@ -269,7 +269,7 @@ private: unsigned int _incomingLate; /// out of order later than expected unsigned int _incomingReallyLate; /// out of order and later than MAX_MISSING_SEQUENCE_OLD_AGE late unsigned int _incomingPossibleDuplicate; /// out of order possibly a duplicate - QSet _missingSequenceNumbers; + QSet _missingSequenceNumbers; SimpleMovingAverage _incomingFlightTimeAverage; // features related items From c958ae8cfbdf4d502ad9e71630dd22783af83586 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 14 Mar 2014 17:47:19 -0700 Subject: [PATCH 14/39] fix LocalVoxelsOverlay types to match --- interface/src/ui/LocalVoxelsOverlay.cpp | 2 +- interface/src/ui/LocalVoxelsOverlay.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/LocalVoxelsOverlay.cpp b/interface/src/ui/LocalVoxelsOverlay.cpp index 9ad1428535..7eaf9ed5c5 100644 --- a/interface/src/ui/LocalVoxelsOverlay.cpp +++ b/interface/src/ui/LocalVoxelsOverlay.cpp @@ -41,7 +41,7 @@ void LocalVoxelsOverlay::update(float deltatime) { } _tree->lockForRead(); - if (_visible && _voxelCount != (int)_tree->getOctreeElementsCount()) { + if (_visible && _voxelCount != _tree->getOctreeElementsCount()) { _voxelCount = _tree->getOctreeElementsCount(); _voxelSystem->forceRedrawEntireTree(); } diff --git a/interface/src/ui/LocalVoxelsOverlay.h b/interface/src/ui/LocalVoxelsOverlay.h index c5582a54eb..2b3ba1f535 100644 --- a/interface/src/ui/LocalVoxelsOverlay.h +++ b/interface/src/ui/LocalVoxelsOverlay.h @@ -43,7 +43,7 @@ private: QString _treeName; StrongVoxelTreePointer _tree; // so that the tree doesn't get freed - int _voxelCount; + unsigned long _voxelCount; StrongVoxelSystemPointer _voxelSystem; }; From 72449fdb6a827ab0d1f094e2f03b3f7626687771 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 14 Mar 2014 17:50:57 -0700 Subject: [PATCH 15/39] initial optimizations to AudioMixer with mmx additions --- assignment-client/src/audio/AudioMixer.cpp | 71 ++++++++++++++++------ interface/interface_en.ts | 16 ++--- libraries/audio/src/AudioRingBuffer.cpp | 3 - libraries/audio/src/AudioRingBuffer.h | 4 ++ 4 files changed, 64 insertions(+), 30 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 812acc8d70..572da1a6c4 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -6,6 +6,7 @@ // Copyright (c) 2013 HighFidelity, Inc. All rights reserved. // +#include #include #include #include @@ -157,27 +158,59 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf // if the bearing relative angle to source is > 0 then the delayed channel is the right one int delayedChannelOffset = (bearingRelativeAngleToSource > 0.0f) ? 1 : 0; int goodChannelOffset = delayedChannelOffset == 0 ? 1 : 0; + + const int16_t* nextOutputStart = bufferToAdd->getNextOutput(); + const int16_t* delayNextOutputStart = nextOutputStart - numSamplesDelay; + const int16_t* bufferStart = bufferToAdd->getBuffer(); + int ringBufferSampleCapacity = bufferToAdd->getSampleCapacity(); + + if (delayNextOutputStart < bufferStart) { + delayNextOutputStart = bufferStart + ringBufferSampleCapacity - numSamplesDelay; + } - for (int s = 0; s < NETWORK_BUFFER_LENGTH_SAMPLES_STEREO; s += 2) { - if ((s / 2) < numSamplesDelay) { - // pull the earlier sample for the delayed channel - int earlierSample = (*bufferToAdd)[(s / 2) - numSamplesDelay] * attenuationCoefficient * weakChannelAmplitudeRatio; - _clientSamples[s + delayedChannelOffset] = glm::clamp(_clientSamples[s + delayedChannelOffset] + earlierSample, - MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); - } - - // pull the current sample for the good channel - int16_t currentSample = (*bufferToAdd)[s / 2] * attenuationCoefficient; - _clientSamples[s + goodChannelOffset] = glm::clamp(_clientSamples[s + goodChannelOffset] + currentSample, - MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); - - if ((s / 2) + numSamplesDelay < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL) { - // place the current sample at the right spot in the delayed channel - int16_t clampedSample = glm::clamp((int) (_clientSamples[s + (numSamplesDelay * 2) + delayedChannelOffset] - + (currentSample * weakChannelAmplitudeRatio)), - MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); - _clientSamples[s + (numSamplesDelay * 2) + delayedChannelOffset] = clampedSample; + int16_t correctMixSample[2], correctBufferSample[2], delayMixSample[2], delayBufferSample[2]; + int delayedChannelIndex[2]; + + float attenuationAndWeakChannelRatio = attenuationCoefficient * weakChannelAmplitudeRatio; + + for (int s = 0; s < NETWORK_BUFFER_LENGTH_SAMPLES_STEREO; s += 4) { + + // setup the int16_t variables for the two sample sets + correctBufferSample[0] = nextOutputStart[s / 2] * attenuationCoefficient; + correctBufferSample[1] = nextOutputStart[(s / 2) + 1] * attenuationCoefficient; + correctMixSample[0] = _clientSamples[s + goodChannelOffset]; + correctMixSample[1] = _clientSamples[s + goodChannelOffset + 2]; + + for (int i = 0; i < 2; ++i) { + if ((s / 2) + numSamplesDelay + i < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL) { + // for the delayed channel we fill the range (n + numSamplesDelay) to NETWORK_BUFFER_LENGTH_SAMPLES_STEREO first + delayedChannelIndex[i] = s + (numSamplesDelay * 2) + (i * 2) + delayedChannelOffset; + delayBufferSample[i] = correctBufferSample[i] * weakChannelAmplitudeRatio; + } else { + // now that the right most range has been filled, we go back to fill in numSamples delay at the beginning + int samplesBack = (s / 2) - NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL + i; + + delayBufferSample[i] = delayNextOutputStart[numSamplesDelay + samplesBack] * attenuationAndWeakChannelRatio; + delayedChannelIndex[i] = (numSamplesDelay + samplesBack) * 2 + delayedChannelOffset; + } } + + delayMixSample[0] = _clientSamples[delayedChannelIndex[0]]; + delayMixSample[1] = _clientSamples[delayedChannelIndex[1]]; + + __m64 bufferSamples = _mm_set_pi16(correctMixSample[0], correctMixSample[1], delayMixSample[0], delayMixSample[1]); + __m64 addedSamples = _mm_set_pi16(correctBufferSample[0], correctBufferSample[1], + delayBufferSample[0], delayBufferSample[1]); + + // perform the MMX add (with saturation) of two correct and delayed samples + __m64 mmxResult = _mm_adds_pi16(bufferSamples, addedSamples); + int16_t* shortResults = reinterpret_cast(&mmxResult); + + // assign the results from the result of the mmx arithmetic + _clientSamples[s + goodChannelOffset] = shortResults[3]; + _clientSamples[s + goodChannelOffset + 2] = shortResults[2]; + _clientSamples[delayedChannelIndex[0]] = shortResults[1]; + _clientSamples[delayedChannelIndex[1]] = shortResults[0]; } } diff --git a/interface/interface_en.ts b/interface/interface_en.ts index 80433032dc..0be997acba 100644 --- a/interface/interface_en.ts +++ b/interface/interface_en.ts @@ -4,22 +4,22 @@ Application - + Export Voxels - + Sparse Voxel Octree Files (*.svo) - + Open Script - + JavaScript Files (*.js) @@ -113,18 +113,18 @@ Menu - + Open .ini config file - - + + Text files (*.ini) - + Save .ini config file diff --git a/libraries/audio/src/AudioRingBuffer.cpp b/libraries/audio/src/AudioRingBuffer.cpp index 9bac210c39..56f6d038c2 100644 --- a/libraries/audio/src/AudioRingBuffer.cpp +++ b/libraries/audio/src/AudioRingBuffer.cpp @@ -121,9 +121,6 @@ qint64 AudioRingBuffer::writeData(const char* data, qint64 maxSize) { } int16_t& AudioRingBuffer::operator[](const int index) { - // make sure this is a valid index - assert(index > -_sampleCapacity && index < _sampleCapacity); - return *shiftedPositionAccomodatingWrap(_nextOutput, index); } diff --git a/libraries/audio/src/AudioRingBuffer.h b/libraries/audio/src/AudioRingBuffer.h index b6e75a2e86..577c01a63c 100644 --- a/libraries/audio/src/AudioRingBuffer.h +++ b/libraries/audio/src/AudioRingBuffer.h @@ -45,6 +45,10 @@ public: int getSampleCapacity() const { return _sampleCapacity; } int parseData(const QByteArray& packet); + + // assume callers using this will never wrap around the end + const int16_t* getNextOutput() { return _nextOutput; } + const int16_t* getBuffer() { return _buffer; } qint64 readSamples(int16_t* destination, qint64 maxSamples); qint64 writeSamples(const int16_t* source, qint64 maxSamples); From 0e7e337807e61290cc568bd80a0d20f885b184b6 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 14 Mar 2014 18:05:40 -0700 Subject: [PATCH 16/39] fixed uninitialized variable warning --- libraries/shared/src/ShapeCollider.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/ShapeCollider.cpp b/libraries/shared/src/ShapeCollider.cpp index 7f36d948e8..e83e6842a9 100644 --- a/libraries/shared/src/ShapeCollider.cpp +++ b/libraries/shared/src/ShapeCollider.cpp @@ -313,7 +313,7 @@ bool capsuleCapsule(const CapsuleShape* capsuleA, const CapsuleShape* capsuleB, // Since there are only three comparisons to do we unroll the sort algorithm... // and use a fifth slot as temp during swap. - if (points[4] > points[2]) { + if (points[1] > points[2]) { points[4] = points[1]; points[1] = points[2]; points[2] = points[4]; From 2766860b52fec7f3ebf519f1ed15a7767e48714f Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 14 Mar 2014 18:11:22 -0700 Subject: [PATCH 17/39] fix some windows warnings in fsbinarystream.cpp --- interface/external/faceshift/src/fsbinarystream.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/external/faceshift/src/fsbinarystream.cpp b/interface/external/faceshift/src/fsbinarystream.cpp index 0a2d41e4b3..96434afd9b 100644 --- a/interface/external/faceshift/src/fsbinarystream.cpp +++ b/interface/external/faceshift/src/fsbinarystream.cpp @@ -160,7 +160,7 @@ void fsBinaryStream::received(long int sz, const char *data) { new_end = m_end + sz; } - if (new_end > Size(m_buffer.size())) m_buffer.resize(1.5*new_end); + if (new_end > Size(m_buffer.size())) m_buffer.resize((new_end * 15 / 10)); // HIFI: to get 1.5 without warnings memcpy(&m_buffer[0] + m_end, data, sz); m_end += sz; @@ -172,7 +172,7 @@ static bool decodeInfo(fsTrackingData & _trackingData, const std::string &buffer success &= read_pod(_trackingData.m_timestamp, buffer, start); unsigned char tracking_successfull = 0; success &= read_pod( tracking_successfull, buffer, start ); - _trackingData.m_trackingSuccessful = bool(tracking_successfull); + _trackingData.m_trackingSuccessful = bool(tracking_successfull != 0); // HIFI: get rid of windows warning return success; } From c0ee3fa1f0bd1831cc8945a82d85568884bf5022 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 14 Mar 2014 18:14:54 -0700 Subject: [PATCH 18/39] fix unix warning --- libraries/shared/src/SharedUtil.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index 70fac3efe4..e5aded2798 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -631,8 +631,7 @@ void debug::setDeadBeef(void* memoryVoid, int size) { } void debug::checkDeadBeef(void* memoryVoid, int size) { - unsigned char* memoryAt = (unsigned char*)memoryVoid; - assert(memcmp(memoryAt, DEADBEEF, std::min(size, DEADBEEF_SIZE)) != 0); + assert(memcmp((unsigned char*)memoryVoid, DEADBEEF, std::min(size, DEADBEEF_SIZE)) != 0); } // Safe version of glm::eulerAngles; uses the factorization method described in David Eberly's From c6f8d34ded2cc05966192a66eacf3dbfca723b0e Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 14 Mar 2014 18:16:38 -0700 Subject: [PATCH 19/39] fix unix warning --- libraries/shared/src/NodeList.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 263e29bc94..0cca9731b0 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -348,7 +348,7 @@ void NodeList::addSetOfNodeTypesToNodeInterestSet(const NodeSet& setOfNodeTypes) const uint32_t RFC_5389_MAGIC_COOKIE = 0x2112A442; const int NUM_BYTES_STUN_HEADER = 20; -const int NUM_STUN_REQUESTS_BEFORE_FALLBACK = 5; +const unsigned int NUM_STUN_REQUESTS_BEFORE_FALLBACK = 5; void NodeList::sendSTUNRequest() { const char STUN_SERVER_HOSTNAME[] = "stun.highfidelity.io"; From 1f775058717857b894df380076ca026d02bf3b37 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 14 Mar 2014 18:35:34 -0700 Subject: [PATCH 20/39] more unix warnings cleanup --- libraries/octree/src/Octree.cpp | 9 ++++----- libraries/octree/src/OctreePacketData.cpp | 2 +- libraries/octree/src/OctreePacketData.h | 14 +++++++------- libraries/octree/src/OctreeRenderer.cpp | 10 +++++----- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 4c8ed8c9f6..fc867ec698 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -807,13 +807,14 @@ int Octree::encodeTreeBitstream(OctreeElement* node, // write the octal code bool roomForOctalCode = false; // assume the worst - int codeLength; + int codeLength = 1; // assume root if (params.chopLevels) { unsigned char* newCode = chopOctalCode(node->getOctalCode(), params.chopLevels); roomForOctalCode = packetData->startSubTree(newCode); if (newCode) { delete newCode; + codeLength = numberOfThreeBitSectionsInCode(newCode); } else { codeLength = 1; } @@ -1559,14 +1560,13 @@ void Octree::copySubTreeIntoNewTree(OctreeElement* startNode, Octree* destinatio } static OctreePacketData packetData; - int bytesWritten = 0; while (!nodeBag.isEmpty()) { OctreeElement* subTree = nodeBag.extract(); packetData.reset(); // reset the packet between usage // ask our tree to write a bitsteam EncodeBitstreamParams params(INT_MAX, IGNORE_VIEW_FRUSTUM, WANT_COLOR, NO_EXISTS_BITS, chopLevels); - bytesWritten = encodeTreeBitstream(subTree, &packetData, nodeBag, params); + encodeTreeBitstream(subTree, &packetData, nodeBag, params); // ask destination tree to read the bitstream ReadBitstreamToTreeParams args(WANT_COLOR, NO_EXISTS_BITS); destinationTree->readBitstreamToTree(packetData.getUncompressedData(), packetData.getUncompressedSize(), args); @@ -1595,7 +1595,6 @@ void Octree::copyFromTreeIntoSubTree(Octree* sourceTree, OctreeElement* destinat nodeBag.insert(sourceTree->_rootNode); static OctreePacketData packetData; - int bytesWritten = 0; while (!nodeBag.isEmpty()) { OctreeElement* subTree = nodeBag.extract(); @@ -1604,7 +1603,7 @@ void Octree::copyFromTreeIntoSubTree(Octree* sourceTree, OctreeElement* destinat // ask our tree to write a bitsteam EncodeBitstreamParams params(INT_MAX, IGNORE_VIEW_FRUSTUM, WANT_COLOR, NO_EXISTS_BITS); - bytesWritten = sourceTree->encodeTreeBitstream(subTree, &packetData, nodeBag, params); + sourceTree->encodeTreeBitstream(subTree, &packetData, nodeBag, params); // ask destination tree to read the bitstream bool wantImportProgress = true; diff --git a/libraries/octree/src/OctreePacketData.cpp b/libraries/octree/src/OctreePacketData.cpp index bb613f57c1..5123d0711a 100644 --- a/libraries/octree/src/OctreePacketData.cpp +++ b/libraries/octree/src/OctreePacketData.cpp @@ -23,7 +23,7 @@ OctreePacketData::OctreePacketData(bool enableCompression, int targetSize) { changeSettings(enableCompression, targetSize); // does reset... } -void OctreePacketData::changeSettings(bool enableCompression, int targetSize) { +void OctreePacketData::changeSettings(bool enableCompression, size_t targetSize) { _enableCompression = enableCompression; _targetSize = std::min(MAX_OCTREE_UNCOMRESSED_PACKET_SIZE, targetSize); reset(); diff --git a/libraries/octree/src/OctreePacketData.h b/libraries/octree/src/OctreePacketData.h index a71a3f893c..526cb7c65e 100644 --- a/libraries/octree/src/OctreePacketData.h +++ b/libraries/octree/src/OctreePacketData.h @@ -30,15 +30,15 @@ typedef uint16_t OCTREE_PACKET_INTERNAL_SECTION_SIZE; const int MAX_OCTREE_PACKET_SIZE = MAX_PACKET_SIZE; // this is overly conservative - sizeof(PacketType) is 8 bytes but a packed PacketType could be as small as one byte -const int OCTREE_PACKET_EXTRA_HEADERS_SIZE = sizeof(OCTREE_PACKET_FLAGS) +const size_t OCTREE_PACKET_EXTRA_HEADERS_SIZE = sizeof(OCTREE_PACKET_FLAGS) + sizeof(OCTREE_PACKET_SEQUENCE) + sizeof(OCTREE_PACKET_SENT_TIME); -const int MAX_OCTREE_PACKET_DATA_SIZE = MAX_PACKET_SIZE - (MAX_PACKET_HEADER_BYTES + OCTREE_PACKET_EXTRA_HEADERS_SIZE); +const size_t MAX_OCTREE_PACKET_DATA_SIZE = MAX_PACKET_SIZE - (MAX_PACKET_HEADER_BYTES + OCTREE_PACKET_EXTRA_HEADERS_SIZE); -const int MAX_OCTREE_UNCOMRESSED_PACKET_SIZE = MAX_OCTREE_PACKET_DATA_SIZE; +const size_t MAX_OCTREE_UNCOMRESSED_PACKET_SIZE = MAX_OCTREE_PACKET_DATA_SIZE; -const int MINIMUM_ATTEMPT_MORE_PACKING = sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE) + 40; -const int COMPRESS_PADDING = 15; +const size_t MINIMUM_ATTEMPT_MORE_PACKING = sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE) + 40; +const size_t COMPRESS_PADDING = 15; const int REASONABLE_NUMBER_OF_PACKING_ATTEMPTS = 5; const int PACKET_IS_COLOR_BIT = 0; @@ -69,7 +69,7 @@ public: ~OctreePacketData(); /// change compression and target size settings - void changeSettings(bool enableCompression = false, int targetSize = MAX_OCTREE_PACKET_DATA_SIZE); + void changeSettings(bool enableCompression = false, size_t targetSize = MAX_OCTREE_PACKET_DATA_SIZE); /// reset completely, all data is discarded void reset(); @@ -186,7 +186,7 @@ private: /// append a single byte, might fail if byte would cause packet to be too large bool append(unsigned char byte); - int _targetSize; + size_t _targetSize; bool _enableCompression; unsigned char _uncompressed[MAX_OCTREE_UNCOMRESSED_PACKET_SIZE]; diff --git a/libraries/octree/src/OctreeRenderer.cpp b/libraries/octree/src/OctreeRenderer.cpp index 8fdc2139af..1066e53845 100644 --- a/libraries/octree/src/OctreeRenderer.cpp +++ b/libraries/octree/src/OctreeRenderer.cpp @@ -57,9 +57,9 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar bool showTimingDetails = false; // Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showTimingDetails, "OctreeRenderer::processDatagram()",showTimingDetails); - int packetLength = dataByteArray.size(); + size_t packetLength = dataByteArray.size(); PacketType command = packetTypeForPacket(dataByteArray); - int numBytesPacketHeader = numBytesForPacketHeader(dataByteArray); + size_t numBytesPacketHeader = numBytesForPacketHeader(dataByteArray); QUuid sourceUUID = uuidFromPacketHeader(dataByteArray); PacketType expectedType = getExpectedPacketType(); @@ -86,11 +86,11 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar int flightTime = arrivedAt - sentAt + clockSkew; OCTREE_PACKET_INTERNAL_SECTION_SIZE sectionLength = 0; - int dataBytes = packetLength - (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE); + size_t dataBytes = packetLength - (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE); if (extraDebugging) { qDebug("OctreeRenderer::processDatagram() ... Got Packet Section" - " color:%s compressed:%s sequence: %u flight:%d usec size:%d data:%d", + " color:%s compressed:%s sequence: %u flight:%d usec size:%lu data:%lu", debug::valueOf(packetIsColored), debug::valueOf(packetIsCompressed), sequence, flightTime, packetLength, dataBytes); } @@ -119,7 +119,7 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar packetData.loadFinalizedContent(dataAt, sectionLength); if (extraDebugging) { qDebug("OctreeRenderer::processDatagram() ... Got Packet Section" - " color:%s compressed:%s sequence: %u flight:%d usec size:%d data:%d" + " color:%s compressed:%s sequence: %u flight:%d usec size:%lu data:%lu" " subsection:%d sectionLength:%d uncompressed:%d", debug::valueOf(packetIsColored), debug::valueOf(packetIsCompressed), sequence, flightTime, packetLength, dataBytes, subsection, sectionLength, From 0200ac9da868d624066b13440b9cb84ba550d364 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 14 Mar 2014 22:43:31 -0700 Subject: [PATCH 21/39] more unix warnings fixes --- interface/src/VoxelSystem.cpp | 14 +++++--------- interface/src/VoxelSystem.h | 4 ++-- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index a8bdeb1114..6c4ed12e9e 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -243,7 +243,7 @@ VoxelSystem::~VoxelSystem() { // This is called by the main application thread on both the initialization of the application and when // the preferences dialog box is called/saved -void VoxelSystem::setMaxVoxels(int maxVoxels) { +void VoxelSystem::setMaxVoxels(unsigned long maxVoxels) { if (maxVoxels == _maxVoxels) { return; } @@ -550,7 +550,7 @@ int VoxelSystem::parseData(const QByteArray& packet) { int flightTime = arrivedAt - sentAt; OCTREE_PACKET_INTERNAL_SECTION_SIZE sectionLength = 0; - int dataBytes = packet.size() - (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE); + size_t dataBytes = packet.size() - (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE); int subsection = 1; while (dataBytes > 0) { @@ -576,7 +576,7 @@ int VoxelSystem::parseData(const QByteArray& packet) { packetData.loadFinalizedContent(dataAt, sectionLength); if (Application::getInstance()->getLogger()->extraDebugging()) { qDebug("VoxelSystem::parseData() ... Got Packet Section" - " color:%s compressed:%s sequence: %u flight:%d usec size:%d data:%d" + " color:%s compressed:%s sequence: %u flight:%d usec size:%d data:%lu" " subsection:%d sectionLength:%d uncompressed:%d", debug::valueOf(packetIsColored), debug::valueOf(packetIsCompressed), sequence, flightTime, packet.size(), dataBytes, subsection, sectionLength, @@ -919,13 +919,11 @@ void VoxelSystem::copyWrittenDataSegmentToReadArrays(glBufferIndex segmentStart, // Depending on if we're using per vertex normals, we will need more or less vertex points per voxel int vertexPointsPerVoxel = GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL; - GLintptr segmentStartAt = segmentStart * vertexPointsPerVoxel * sizeof(GLfloat); GLsizeiptr segmentSizeBytes = segmentLength * vertexPointsPerVoxel * sizeof(GLfloat); GLfloat* readVerticesAt = _readVerticesArray + (segmentStart * vertexPointsPerVoxel); GLfloat* writeVerticesAt = _writeVerticesArray + (segmentStart * vertexPointsPerVoxel); memcpy(readVerticesAt, writeVerticesAt, segmentSizeBytes); - segmentStartAt = segmentStart * vertexPointsPerVoxel * sizeof(GLubyte); segmentSizeBytes = segmentLength * vertexPointsPerVoxel * sizeof(GLubyte); GLubyte* readColorsAt = _readColorsArray + (segmentStart * vertexPointsPerVoxel); GLubyte* writeColorsAt = _writeColorsArray + (segmentStart * vertexPointsPerVoxel); @@ -1958,10 +1956,8 @@ bool VoxelSystem::showAllSubTreeOperation(OctreeElement* element, void* extraDat // If we've culled at least once, then we will use the status of this voxel in the last culled frustum to determine // how to proceed. If we've never culled, then we just consider all these voxels to be UNKNOWN so that we will not // consider that case. - ViewFrustum::location inLastCulledFrustum; - if (args->culledOnce && args->wantDeltaFrustums) { - inLastCulledFrustum = voxel->inFrustum(args->lastViewFrustum); + ViewFrustum::location inLastCulledFrustum = voxel->inFrustum(args->lastViewFrustum); // if this node is fully inside our last culled view frustum, then we don't need to recurse further if (inLastCulledFrustum == ViewFrustum::INSIDE) { @@ -2001,7 +1997,7 @@ bool VoxelSystem::hideOutOfViewOperation(OctreeElement* element, void* extraData // If we've culled at least once, then we will use the status of this voxel in the last culled frustum to determine // how to proceed. If we've never culled, then we just consider all these voxels to be UNKNOWN so that we will not // consider that case. - ViewFrustum::location inLastCulledFrustum; + ViewFrustum::location inLastCulledFrustum = ViewFrustum::OUTSIDE; // assume outside, but should get reset to actual value if (args->culledOnce && args->wantDeltaFrustums) { inLastCulledFrustum = voxel->inFrustum(args->lastViewFrustum); diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 49b47c6f25..bdc55450dd 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -67,7 +67,7 @@ public: ViewFrustum* getLastCulledViewFrustum() { return &_lastCulledViewFrustum; } - void setMaxVoxels(int maxVoxels); + void setMaxVoxels(unsigned long maxVoxels); long int getMaxVoxels() const { return _maxVoxels; } unsigned long getVoxelMemoryUsageRAM() const { return _memoryUsageRAM; } unsigned long getVoxelMemoryUsageVBO() const { return _memoryUsageVBO; } @@ -263,7 +263,7 @@ private: bool _usePrimitiveRenderer; ///< Flag primitive renderer for use PrimitiveRenderer* _renderer; ///< Voxel renderer - static const int _sNumOctantsPerHemiVoxel = 4; + static const unsigned int _sNumOctantsPerHemiVoxel = 4; static int _sCorrectedChildIndex[8]; static unsigned short _sSwizzledOcclusionBits[64]; ///< Swizzle value of bit pairs of the value of index static unsigned char _sOctantIndexToBitMask[8]; ///< Map octant index to partition mask From 61a905961e0116575cf4875eb2297d9a000533bc Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 14 Mar 2014 22:48:32 -0700 Subject: [PATCH 22/39] darnit I hate casts.. --- libraries/octree/src/OctreePacketData.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/octree/src/OctreePacketData.cpp b/libraries/octree/src/OctreePacketData.cpp index 5123d0711a..219d8612fc 100644 --- a/libraries/octree/src/OctreePacketData.cpp +++ b/libraries/octree/src/OctreePacketData.cpp @@ -369,7 +369,7 @@ bool OctreePacketData::compressContent() { QByteArray compressedData = qCompress(uncompressedData, uncompressedSize, MAX_COMPRESSION); - if (compressedData.size() < MAX_OCTREE_PACKET_DATA_SIZE) { + if (compressedData.size() < (int)MAX_OCTREE_PACKET_DATA_SIZE) { _compressedBytes = compressedData.size(); for (int i = 0; i < _compressedBytes; i++) { _compressed[i] = compressedData[i]; From 4a6cc99be672985d983ecba1e3b7c5fda98fe371 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Sat, 15 Mar 2014 21:30:45 -0700 Subject: [PATCH 23/39] slightly different approach to windows warning fix --- interface/external/faceshift/src/fsbinarystream.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/external/faceshift/src/fsbinarystream.cpp b/interface/external/faceshift/src/fsbinarystream.cpp index 96434afd9b..85f3ac7e7f 100644 --- a/interface/external/faceshift/src/fsbinarystream.cpp +++ b/interface/external/faceshift/src/fsbinarystream.cpp @@ -160,7 +160,7 @@ void fsBinaryStream::received(long int sz, const char *data) { new_end = m_end + sz; } - if (new_end > Size(m_buffer.size())) m_buffer.resize((new_end * 15 / 10)); // HIFI: to get 1.5 without warnings + if (new_end > Size(m_buffer.size())) m_buffer.resize((int)(1.5f * (float)new_end)); // HIFI: to get 1.5 without warnings memcpy(&m_buffer[0] + m_end, data, sz); m_end += sz; From adb6ffe7c4eb8ea66cc57591bb086acda26bf490 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 15 Mar 2014 22:00:44 -0700 Subject: [PATCH 24/39] more warnings fixes --- animation-server/src/AnimationServer.cpp | 21 +++++++------------ assignment-client/src/audio/AudioMixer.cpp | 1 - .../src/octree/OctreeSendThread.cpp | 4 +--- interface/src/Util.cpp | 10 ++++----- libraries/voxels/src/VoxelTreeElement.cpp | 7 ++++--- 5 files changed, 17 insertions(+), 26 deletions(-) diff --git a/animation-server/src/AnimationServer.cpp b/animation-server/src/AnimationServer.cpp index b165590c30..1f0828ec17 100644 --- a/animation-server/src/AnimationServer.cpp +++ b/animation-server/src/AnimationServer.cpp @@ -40,13 +40,13 @@ bool waitForVoxelServer = true; const int ANIMATION_LISTEN_PORT = 40107; int ANIMATE_FPS = 60; double ANIMATE_FPS_IN_MILLISECONDS = 1000.0/ANIMATE_FPS; // determines FPS from our desired FPS -int ANIMATE_VOXELS_INTERVAL_USECS = (ANIMATE_FPS_IN_MILLISECONDS * 1000.0); // converts from milliseconds to usecs +quint64 ANIMATE_VOXELS_INTERVAL_USECS = (ANIMATE_FPS_IN_MILLISECONDS * 1000); // converts from milliseconds to usecs int PROCESSING_FPS = 60; double PROCESSING_FPS_IN_MILLISECONDS = 1000.0/PROCESSING_FPS; // determines FPS from our desired FPS int FUDGE_USECS = 650; // a little bit of fudge to actually do some processing -int PROCESSING_INTERVAL_USECS = (PROCESSING_FPS_IN_MILLISECONDS * 1000.0) - FUDGE_USECS; // converts from milliseconds to usecs +quint64 PROCESSING_INTERVAL_USECS = (PROCESSING_FPS_IN_MILLISECONDS * 1000) - FUDGE_USECS; // converts from milliseconds to usecs bool wantLocalDomain = false; @@ -611,9 +611,6 @@ void* animateVoxels(void* args) { } lastProcessTime = usecTimestampNow(); - int packetsStarting = 0; - int packetsEnding = 0; - // The while loop will be running at PROCESSING_FPS, but we only want to call these animation functions at // ANIMATE_FPS. So we check out last animate time and only call these if we've elapsed that time. quint64 now = usecTimestampNow(); @@ -627,8 +624,6 @@ void* animateVoxels(void* args) { animateLoopsPerAnimate++; lastAnimateTime = now; - packetsStarting = ::voxelEditPacketSender->packetsToSendCount(); - // some animations //sendVoxelBlinkMessage(); @@ -652,8 +647,6 @@ void* animateVoxels(void* args) { doBuildStreet(); } - packetsEnding = ::voxelEditPacketSender->packetsToSendCount(); - if (animationElapsed > ANIMATE_VOXELS_INTERVAL_USECS) { animationElapsed -= ANIMATE_VOXELS_INTERVAL_USECS; // credit ourselves one animation frame } else { @@ -670,9 +663,9 @@ void* animateVoxels(void* args) { processesPerAnimate++; } // dynamically sleep until we need to fire off the next set of voxels - quint64 usecToSleep = PROCESSING_INTERVAL_USECS - (usecTimestampNow() - lastProcessTime); - if (usecToSleep > PROCESSING_INTERVAL_USECS) { - usecToSleep = PROCESSING_INTERVAL_USECS; + quint64 usecToSleep = ::PROCESSING_INTERVAL_USECS - (usecTimestampNow() - lastProcessTime); + if (usecToSleep > ::PROCESSING_INTERVAL_USECS) { + usecToSleep = ::PROCESSING_INTERVAL_USECS; } if (usecToSleep > 0) { @@ -758,7 +751,7 @@ AnimationServer::AnimationServer(int &argc, char **argv) : } } printf("ANIMATE_FPS=%d\n",ANIMATE_FPS); - printf("ANIMATE_VOXELS_INTERVAL_USECS=%d\n",ANIMATE_VOXELS_INTERVAL_USECS); + printf("ANIMATE_VOXELS_INTERVAL_USECS=%llu\n",ANIMATE_VOXELS_INTERVAL_USECS); const char* processingFPSCommand = getCmdOption(argc, (const char**) argv, "--ProcessingFPS"); const char* processingIntervalCommand = getCmdOption(argc, (const char**) argv, "--ProcessingInterval"); @@ -774,7 +767,7 @@ AnimationServer::AnimationServer(int &argc, char **argv) : } } printf("PROCESSING_FPS=%d\n",PROCESSING_FPS); - printf("PROCESSING_INTERVAL_USECS=%d\n",PROCESSING_INTERVAL_USECS); + printf("PROCESSING_INTERVAL_USECS=%llu\n",PROCESSING_INTERVAL_USECS); nodeList->linkedDataCreateCallback = NULL; // do we need a callback? diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 812acc8d70..4c745ef2eb 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -79,7 +79,6 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf if (bufferToAdd != listeningNodeBuffer) { // if the two buffer pointers do not match then these are different buffers - glm::vec3 listenerPosition = listeningNodeBuffer->getPosition(); glm::vec3 relativePosition = bufferToAdd->getPosition() - listeningNodeBuffer->getPosition(); glm::quat inverseOrientation = glm::inverse(listeningNodeBuffer->getOrientation()); diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index ef69771607..09ebb99298 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -54,15 +54,13 @@ bool OctreeSendThread::process() { nodeData = (OctreeQueryNode*) node->getLinkedData(); - int packetsSent = 0; - // Sometimes the node data has not yet been linked, in which case we can't really do anything if (nodeData) { bool viewFrustumChanged = nodeData->updateCurrentViewFrustum(); if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) { printf("nodeData->updateCurrentViewFrustum() changed=%s\n", debug::valueOf(viewFrustumChanged)); } - packetsSent = packetDistributor(node, nodeData, viewFrustumChanged); + packetDistributor(node, nodeData, viewFrustumChanged); } } else { _nodeMissingCount++; diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index 45b2c4a616..f54bfb9d00 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -535,7 +535,7 @@ void runTimingTests() { } gettimeofday(&endTime, NULL); elapsedMsecs = diffclock(&startTime, &endTime); - qDebug("rand() stored in array usecs: %f", 1000.0f * elapsedMsecs / (float) numTests); + qDebug("rand() stored in array usecs: %f, first result:%d", 1000.0f * elapsedMsecs / (float) numTests, iResults[0]); // Random number generation using randFloat() gettimeofday(&startTime, NULL); @@ -544,7 +544,7 @@ void runTimingTests() { } gettimeofday(&endTime, NULL); elapsedMsecs = diffclock(&startTime, &endTime); - qDebug("randFloat() stored in array usecs: %f", 1000.0f * elapsedMsecs / (float) numTests); + qDebug("randFloat() stored in array usecs: %f, first result: %f", 1000.0f * elapsedMsecs / (float) numTests, fResults[0]); // PowF function fTest = 1145323.2342f; @@ -567,8 +567,8 @@ void runTimingTests() { } gettimeofday(&endTime, NULL); elapsedMsecs = diffclock(&startTime, &endTime); - qDebug("vector math usecs: %f [%f msecs total for %d tests]", - 1000.0f * elapsedMsecs / (float) numTests, elapsedMsecs, numTests); + qDebug("vector math usecs: %f [%f msecs total for %d tests], last result:%f", + 1000.0f * elapsedMsecs / (float) numTests, elapsedMsecs, numTests, distance); // Vec3 test glm::vec3 vecA(randVector()), vecB(randVector()); @@ -581,7 +581,7 @@ void runTimingTests() { } gettimeofday(&endTime, NULL); elapsedMsecs = diffclock(&startTime, &endTime); - qDebug("vec3 assign and dot() usecs: %f", 1000.0f * elapsedMsecs / (float) numTests); + qDebug("vec3 assign and dot() usecs: %f, last result:%f", 1000.0f * elapsedMsecs / (float) numTests, result); } float loadSetting(QSettings* settings, const char* name, float defaultValue) { diff --git a/libraries/voxels/src/VoxelTreeElement.cpp b/libraries/voxels/src/VoxelTreeElement.cpp index be6bd50e3d..debcfee987 100644 --- a/libraries/voxels/src/VoxelTreeElement.cpp +++ b/libraries/voxels/src/VoxelTreeElement.cpp @@ -178,13 +178,14 @@ void VoxelTreeElement::calculateAverageFromChildren() { bool VoxelTreeElement::collapseChildren() { // scan children, verify that they are ALL present and accounted for bool allChildrenMatch = true; // assume the best (ottimista) - int red,green,blue; + int red = 0; + int green = 0; + int blue = 0; for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { VoxelTreeElement* childAt = getChildAtIndex(i); // if no child, child isn't a leaf, or child doesn't have a color if (!childAt || !childAt->isLeaf() || !childAt->isColored()) { - allChildrenMatch=false; - //qDebug("SADNESS child missing or not colored! i=%d\n",i); + allChildrenMatch = false; break; } else { if (i==0) { From 851764a7053c2501b9b03e4b5ce80043c5ddc7ab Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 15 Mar 2014 22:36:43 -0700 Subject: [PATCH 25/39] more warning fixes --- libraries/avatars/src/AvatarData.cpp | 2 +- libraries/avatars/src/HandData.cpp | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 518b10ddea..21de041343 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -288,7 +288,7 @@ int AvatarData::parseData(const QByteArray& packet) { // joint data int jointCount = *sourceBuffer++; _jointData.resize(jointCount); - unsigned char validity; + unsigned char validity = 0; // although always set below, this fixes a warning of potential uninitialized use int validityBit = 0; for (int i = 0; i < jointCount; i++) { if (validityBit == 0) { diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index 46dade6d64..15be4636a7 100644 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -217,11 +217,12 @@ int HandData::decodeRemoteData(const QByteArray& dataByteArray) { palm.setActive(false); } - // One byte for error checking safety. - unsigned char requiredLength = (unsigned char)(sourceBuffer - startPosition); - unsigned char checkLength = *sourceBuffer++; - assert(checkLength == requiredLength); - + // One byte for error checking safety. Last byte contains the expected length (less itself) + // actualLength less expected byte = (sourceBuffer - startPosition) + // expectedLength less expected byte = (*sourceBuffer) + assert((unsigned char)(sourceBuffer - startPosition) == (unsigned char)(*sourceBuffer)); + sourceBuffer++; // skip the trailing byte which is expected length + return sourceBuffer - startPosition; } From 6f85cfdb2f153302948d53dbe4d826a9d118d57f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 15 Mar 2014 23:00:03 -0700 Subject: [PATCH 26/39] more warnings fixes --- assignment-client/src/octree/OctreeQueryNode.h | 6 +++--- assignment-client/src/octree/OctreeSendThread.cpp | 2 +- libraries/octree/src/OctreePacketData.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/assignment-client/src/octree/OctreeQueryNode.h b/assignment-client/src/octree/OctreeQueryNode.h index 6d4dee300a..29fdea0da2 100644 --- a/assignment-client/src/octree/OctreeQueryNode.h +++ b/assignment-client/src/octree/OctreeQueryNode.h @@ -34,13 +34,13 @@ public: void writeToPacket(const unsigned char* buffer, int bytes); // writes to end of packet const unsigned char* getPacket() const { return _octreePacket; } - int getPacketLength() const { return (MAX_PACKET_SIZE - _octreePacketAvailableBytes); } + unsigned int getPacketLength() const { return (MAX_PACKET_SIZE - _octreePacketAvailableBytes); } bool isPacketWaiting() const { return _octreePacketWaiting; } bool packetIsDuplicate() const; bool shouldSuppressDuplicatePacket(); - int getAvailable() const { return _octreePacketAvailableBytes; } + unsigned int getAvailable() const { return _octreePacketAvailableBytes; } int getMaxSearchLevel() const { return _maxSearchLevel; } void resetMaxSearchLevel() { _maxSearchLevel = 1; } void incrementMaxSearchLevel() { _maxSearchLevel++; } @@ -92,7 +92,7 @@ private: bool _viewSent; unsigned char* _octreePacket; unsigned char* _octreePacketAt; - int _octreePacketAvailableBytes; + unsigned int _octreePacketAvailableBytes; bool _octreePacketWaiting; unsigned char* _lastOctreePacket; diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 09ebb99298..35e9869910 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -506,7 +506,7 @@ int OctreeSendThread::packetDistributor(const SharedNodePointer& node, OctreeQue } if (forceDebugging || (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug())) { - qDebug(">>>>>> calling writeToPacket() available=%d compressedSize=%d uncompressedSize=%d target=%d", + qDebug(">>>>>> calling writeToPacket() available=%d compressedSize=%d uncompressedSize=%d target=%lu", nodeData->getAvailable(), _packetData.getFinalizedSize(), _packetData.getUncompressedSize(), _packetData.getTargetSize()); } diff --git a/libraries/octree/src/OctreePacketData.h b/libraries/octree/src/OctreePacketData.h index 526cb7c65e..245f0668cd 100644 --- a/libraries/octree/src/OctreePacketData.h +++ b/libraries/octree/src/OctreePacketData.h @@ -168,7 +168,7 @@ public: bool isCompressed() const { return _enableCompression; } /// returns the target uncompressed size - int getTargetSize() const { return _targetSize; } + size_t getTargetSize() const { return _targetSize; } /// displays contents for debugging void debugContent(); From 08d89a4565b2632b1f18c4dec6da99dc1e65a6f0 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 15 Mar 2014 23:17:03 -0700 Subject: [PATCH 27/39] arg windows signedness warnings --- assignment-client/src/octree/OctreeQueryNode.cpp | 2 +- assignment-client/src/octree/OctreeQueryNode.h | 2 +- assignment-client/src/octree/OctreeSendThread.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/assignment-client/src/octree/OctreeQueryNode.cpp b/assignment-client/src/octree/OctreeQueryNode.cpp index 8cb577d2f9..3d5fbefc1f 100644 --- a/assignment-client/src/octree/OctreeQueryNode.cpp +++ b/assignment-client/src/octree/OctreeQueryNode.cpp @@ -156,7 +156,7 @@ void OctreeQueryNode::resetOctreePacket(bool lastWasSurpressed) { _octreePacketWaiting = false; } -void OctreeQueryNode::writeToPacket(const unsigned char* buffer, int bytes) { +void OctreeQueryNode::writeToPacket(const unsigned char* buffer, unsigned int bytes) { // compressed packets include lead bytes which contain compressed size, this allows packing of // multiple compressed portions together if (_currentPacketIsCompressed) { diff --git a/assignment-client/src/octree/OctreeQueryNode.h b/assignment-client/src/octree/OctreeQueryNode.h index 29fdea0da2..2a976c6421 100644 --- a/assignment-client/src/octree/OctreeQueryNode.h +++ b/assignment-client/src/octree/OctreeQueryNode.h @@ -31,7 +31,7 @@ public: void resetOctreePacket(bool lastWasSurpressed = false); // resets octree packet to after "V" header - void writeToPacket(const unsigned char* buffer, int bytes); // writes to end of packet + void writeToPacket(const unsigned char* buffer, unsigned int bytes); // writes to end of packet const unsigned char* getPacket() const { return _octreePacket; } unsigned int getPacketLength() const { return (MAX_PACKET_SIZE - _octreePacketAvailableBytes); } diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 35e9869910..0259c31374 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -492,7 +492,7 @@ int OctreeSendThread::packetDistributor(const SharedNodePointer& node, OctreeQue // if for some reason the finalized size is greater than our available size, then probably the "compressed" // form actually inflated beyond our padding, and in this case we will send the current packet, then // write to out new packet... - int writtenSize = _packetData.getFinalizedSize() + unsigned int writtenSize = _packetData.getFinalizedSize() + (nodeData->getCurrentPacketIsCompressed() ? sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE) : 0); From 5709a8893e56cabf5721c0a58aa45ec6668fc869 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 15 Mar 2014 23:19:16 -0700 Subject: [PATCH 28/39] more unix signedness warnings --- assignment-client/src/octree/OctreeQueryNode.h | 2 +- assignment-client/src/octree/OctreeSendThread.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/octree/OctreeQueryNode.h b/assignment-client/src/octree/OctreeQueryNode.h index 2a976c6421..e48b7aaff4 100644 --- a/assignment-client/src/octree/OctreeQueryNode.h +++ b/assignment-client/src/octree/OctreeQueryNode.h @@ -96,7 +96,7 @@ private: bool _octreePacketWaiting; unsigned char* _lastOctreePacket; - int _lastOctreePacketLength; + unsigned int _lastOctreePacketLength; int _duplicatePacketCount; quint64 _firstSuppressedPacket; diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 0259c31374..0c99e94c04 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -140,7 +140,7 @@ int OctreeSendThread::handlePacketSend(const SharedNodePointer& node, OctreeQuer if (nodeData->stats.isReadyToSend()) { // Send the stats message to the client unsigned char* statsMessage = nodeData->stats.getStatsMessage(); - int statsMessageLength = nodeData->stats.getStatsMessageLength(); + unsigned int statsMessageLength = nodeData->stats.getStatsMessageLength(); // If the size of the stats message and the voxel message will fit in a packet, then piggyback them if (nodeData->getPacketLength() + statsMessageLength < MAX_PACKET_SIZE) { From 7d7e1ff28ac0b47d71e38b46d8b62d59b46a6e0b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 15 Mar 2014 23:37:52 -0700 Subject: [PATCH 29/39] one more crack at this signedness comparisons on unix --- assignment-client/src/octree/OctreeSendThread.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 0c99e94c04..498ddb9e2c 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -140,10 +140,11 @@ int OctreeSendThread::handlePacketSend(const SharedNodePointer& node, OctreeQuer if (nodeData->stats.isReadyToSend()) { // Send the stats message to the client unsigned char* statsMessage = nodeData->stats.getStatsMessage(); - unsigned int statsMessageLength = nodeData->stats.getStatsMessageLength(); + int statsMessageLength = nodeData->stats.getStatsMessageLength(); + int piggyBackSize = nodeData->getPacketLength() + statsMessageLength; // If the size of the stats message and the voxel message will fit in a packet, then piggyback them - if (nodeData->getPacketLength() + statsMessageLength < MAX_PACKET_SIZE) { + if (piggyBackSize < MAX_PACKET_SIZE) { // copy voxel message to back of stats message memcpy(statsMessage + statsMessageLength, nodeData->getPacket(), nodeData->getPacketLength()); From bd6b70ee32c6a88a03b82b4e081416688d9c4f4b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sun, 16 Mar 2014 11:07:24 -0700 Subject: [PATCH 30/39] use unsigned int vs size_t, since that just seems more correct --- .../src/octree/OctreeSendThread.cpp | 2 +- interface/src/VoxelSystem.cpp | 4 ++-- libraries/octree/src/OctreePacketData.cpp | 2 +- libraries/octree/src/OctreePacketData.h | 16 ++++++++-------- libraries/octree/src/OctreeRenderer.cpp | 10 +++++----- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 498ddb9e2c..85839bc53f 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -507,7 +507,7 @@ int OctreeSendThread::packetDistributor(const SharedNodePointer& node, OctreeQue } if (forceDebugging || (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug())) { - qDebug(">>>>>> calling writeToPacket() available=%d compressedSize=%d uncompressedSize=%d target=%lu", + qDebug(">>>>>> calling writeToPacket() available=%d compressedSize=%d uncompressedSize=%d target=%u", nodeData->getAvailable(), _packetData.getFinalizedSize(), _packetData.getUncompressedSize(), _packetData.getTargetSize()); } diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 6c4ed12e9e..4db5af3c04 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -550,7 +550,7 @@ int VoxelSystem::parseData(const QByteArray& packet) { int flightTime = arrivedAt - sentAt; OCTREE_PACKET_INTERNAL_SECTION_SIZE sectionLength = 0; - size_t dataBytes = packet.size() - (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE); + unsigned int dataBytes = packet.size() - (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE); int subsection = 1; while (dataBytes > 0) { @@ -576,7 +576,7 @@ int VoxelSystem::parseData(const QByteArray& packet) { packetData.loadFinalizedContent(dataAt, sectionLength); if (Application::getInstance()->getLogger()->extraDebugging()) { qDebug("VoxelSystem::parseData() ... Got Packet Section" - " color:%s compressed:%s sequence: %u flight:%d usec size:%d data:%lu" + " color:%s compressed:%s sequence: %u flight:%d usec size:%d data:%u" " subsection:%d sectionLength:%d uncompressed:%d", debug::valueOf(packetIsColored), debug::valueOf(packetIsCompressed), sequence, flightTime, packet.size(), dataBytes, subsection, sectionLength, diff --git a/libraries/octree/src/OctreePacketData.cpp b/libraries/octree/src/OctreePacketData.cpp index 219d8612fc..5bd4fdce49 100644 --- a/libraries/octree/src/OctreePacketData.cpp +++ b/libraries/octree/src/OctreePacketData.cpp @@ -23,7 +23,7 @@ OctreePacketData::OctreePacketData(bool enableCompression, int targetSize) { changeSettings(enableCompression, targetSize); // does reset... } -void OctreePacketData::changeSettings(bool enableCompression, size_t targetSize) { +void OctreePacketData::changeSettings(bool enableCompression, unsigned int targetSize) { _enableCompression = enableCompression; _targetSize = std::min(MAX_OCTREE_UNCOMRESSED_PACKET_SIZE, targetSize); reset(); diff --git a/libraries/octree/src/OctreePacketData.h b/libraries/octree/src/OctreePacketData.h index 245f0668cd..5d7a904a4c 100644 --- a/libraries/octree/src/OctreePacketData.h +++ b/libraries/octree/src/OctreePacketData.h @@ -30,15 +30,15 @@ typedef uint16_t OCTREE_PACKET_INTERNAL_SECTION_SIZE; const int MAX_OCTREE_PACKET_SIZE = MAX_PACKET_SIZE; // this is overly conservative - sizeof(PacketType) is 8 bytes but a packed PacketType could be as small as one byte -const size_t OCTREE_PACKET_EXTRA_HEADERS_SIZE = sizeof(OCTREE_PACKET_FLAGS) +const unsigned int OCTREE_PACKET_EXTRA_HEADERS_SIZE = sizeof(OCTREE_PACKET_FLAGS) + sizeof(OCTREE_PACKET_SEQUENCE) + sizeof(OCTREE_PACKET_SENT_TIME); -const size_t MAX_OCTREE_PACKET_DATA_SIZE = MAX_PACKET_SIZE - (MAX_PACKET_HEADER_BYTES + OCTREE_PACKET_EXTRA_HEADERS_SIZE); +const unsigned int MAX_OCTREE_PACKET_DATA_SIZE = MAX_PACKET_SIZE - (MAX_PACKET_HEADER_BYTES + OCTREE_PACKET_EXTRA_HEADERS_SIZE); -const size_t MAX_OCTREE_UNCOMRESSED_PACKET_SIZE = MAX_OCTREE_PACKET_DATA_SIZE; +const unsigned int MAX_OCTREE_UNCOMRESSED_PACKET_SIZE = MAX_OCTREE_PACKET_DATA_SIZE; -const size_t MINIMUM_ATTEMPT_MORE_PACKING = sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE) + 40; -const size_t COMPRESS_PADDING = 15; +const unsigned int MINIMUM_ATTEMPT_MORE_PACKING = sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE) + 40; +const unsigned int COMPRESS_PADDING = 15; const int REASONABLE_NUMBER_OF_PACKING_ATTEMPTS = 5; const int PACKET_IS_COLOR_BIT = 0; @@ -69,7 +69,7 @@ public: ~OctreePacketData(); /// change compression and target size settings - void changeSettings(bool enableCompression = false, size_t targetSize = MAX_OCTREE_PACKET_DATA_SIZE); + void changeSettings(bool enableCompression = false, unsigned int targetSize = MAX_OCTREE_PACKET_DATA_SIZE); /// reset completely, all data is discarded void reset(); @@ -168,7 +168,7 @@ public: bool isCompressed() const { return _enableCompression; } /// returns the target uncompressed size - size_t getTargetSize() const { return _targetSize; } + unsigned int getTargetSize() const { return _targetSize; } /// displays contents for debugging void debugContent(); @@ -186,7 +186,7 @@ private: /// append a single byte, might fail if byte would cause packet to be too large bool append(unsigned char byte); - size_t _targetSize; + unsigned int _targetSize; bool _enableCompression; unsigned char _uncompressed[MAX_OCTREE_UNCOMRESSED_PACKET_SIZE]; diff --git a/libraries/octree/src/OctreeRenderer.cpp b/libraries/octree/src/OctreeRenderer.cpp index 1066e53845..5d4543e3aa 100644 --- a/libraries/octree/src/OctreeRenderer.cpp +++ b/libraries/octree/src/OctreeRenderer.cpp @@ -57,9 +57,9 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar bool showTimingDetails = false; // Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showTimingDetails, "OctreeRenderer::processDatagram()",showTimingDetails); - size_t packetLength = dataByteArray.size(); + unsigned int packetLength = dataByteArray.size(); PacketType command = packetTypeForPacket(dataByteArray); - size_t numBytesPacketHeader = numBytesForPacketHeader(dataByteArray); + unsigned int numBytesPacketHeader = numBytesForPacketHeader(dataByteArray); QUuid sourceUUID = uuidFromPacketHeader(dataByteArray); PacketType expectedType = getExpectedPacketType(); @@ -86,11 +86,11 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar int flightTime = arrivedAt - sentAt + clockSkew; OCTREE_PACKET_INTERNAL_SECTION_SIZE sectionLength = 0; - size_t dataBytes = packetLength - (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE); + unsigned int dataBytes = packetLength - (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE); if (extraDebugging) { qDebug("OctreeRenderer::processDatagram() ... Got Packet Section" - " color:%s compressed:%s sequence: %u flight:%d usec size:%lu data:%lu", + " color:%s compressed:%s sequence: %u flight:%d usec size:%u data:%u", debug::valueOf(packetIsColored), debug::valueOf(packetIsCompressed), sequence, flightTime, packetLength, dataBytes); } @@ -119,7 +119,7 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar packetData.loadFinalizedContent(dataAt, sectionLength); if (extraDebugging) { qDebug("OctreeRenderer::processDatagram() ... Got Packet Section" - " color:%s compressed:%s sequence: %u flight:%d usec size:%lu data:%lu" + " color:%s compressed:%s sequence: %u flight:%d usec size:%u data:%u" " subsection:%d sectionLength:%d uncompressed:%d", debug::valueOf(packetIsColored), debug::valueOf(packetIsCompressed), sequence, flightTime, packetLength, dataBytes, subsection, sectionLength, From f652df939966731edcce1c8bd88fea2c3016e82e Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 17 Mar 2014 09:19:05 -0700 Subject: [PATCH 31/39] break on MTU size packets from domain-list, closes #2312 --- domain-server/src/DomainServer.cpp | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index a425052970..216d249858 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -423,17 +423,25 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif QDataStream broadcastDataStream(&broadcastPacket, QIODevice::Append); broadcastDataStream << node->getUUID(); + int numBroadcastPacketLeadBytes = broadcastDataStream.device()->pos(); + DomainServerNodeData* nodeData = reinterpret_cast(node->getLinkedData()); NodeList* nodeList = NodeList::getInstance(); + if (nodeInterestList.size() > 0) { // if the node has any interest types, send back those nodes as well foreach (const SharedNodePointer& otherNode, nodeList->getNodeHash()) { + + // reset our nodeByteArray and nodeDataStream + QByteArray nodeByteArray; + QDataStream nodeDataStream(&nodeByteArray, QIODevice::Append); + if (otherNode->getUUID() != node->getUUID() && nodeInterestList.contains(otherNode->getType())) { // don't send avatar nodes to other avatars, that will come from avatar mixer - broadcastDataStream << *otherNode.data(); + nodeDataStream << *otherNode.data(); // pack the secret that these two nodes will use to communicate with each other QUuid secretUUID = nodeData->getSessionSecretHash().value(otherNode->getUUID()); @@ -450,11 +458,26 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif } - broadcastDataStream << secretUUID; + nodeDataStream << secretUUID; + + if (broadcastPacket.size() + nodeByteArray.size() > MAX_PACKET_SIZE) { + // we need to break here and start a new packet + // so send the current one + + nodeList->writeDatagram(broadcastPacket, node, senderSockAddr); + + // reset the broadcastPacket structure + broadcastPacket.resize(numBroadcastPacketLeadBytes); + broadcastDataStream.device()->seek(numBroadcastPacketLeadBytes); + } + + // append the nodeByteArray to the current state of broadcastDataStream + broadcastPacket.append(nodeByteArray); } } } + // always write the last broadcastPacket nodeList->writeDatagram(broadcastPacket, node, senderSockAddr); } From 05d652227963d56d2dc46978f1f67fb990b4acb4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 17 Mar 2014 10:02:00 -0700 Subject: [PATCH 32/39] more MMX optimizations to AudioMixer for delayed samples --- assignment-client/src/audio/AudioMixer.cpp | 133 +++++++++++++++------ assignment-client/src/audio/AudioMixer.h | 5 +- 2 files changed, 103 insertions(+), 35 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 572da1a6c4..f8e68340cb 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -74,9 +74,7 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf float attenuationCoefficient = 1.0f; int numSamplesDelay = 0; float weakChannelAmplitudeRatio = 1.0f; - - const int PHASE_DELAY_AT_90 = 20; - + if (bufferToAdd != listeningNodeBuffer) { // if the two buffer pointers do not match then these are different buffers @@ -150,7 +148,7 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf // figure out the number of samples of delay and the ratio of the amplitude // in the weak channel for audio spatialization float sinRatio = fabsf(sinf(bearingRelativeAngleToSource)); - numSamplesDelay = PHASE_DELAY_AT_90 * sinRatio; + numSamplesDelay = SAMPLE_PHASE_DELAY_AT_90 * sinRatio; weakChannelAmplitudeRatio = 1 - (PHASE_AMPLITUDE_RATIO_AT_90 * sinRatio); } } @@ -160,45 +158,28 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf int goodChannelOffset = delayedChannelOffset == 0 ? 1 : 0; const int16_t* nextOutputStart = bufferToAdd->getNextOutput(); - const int16_t* delayNextOutputStart = nextOutputStart - numSamplesDelay; + const int16_t* bufferStart = bufferToAdd->getBuffer(); int ringBufferSampleCapacity = bufferToAdd->getSampleCapacity(); - - if (delayNextOutputStart < bufferStart) { - delayNextOutputStart = bufferStart + ringBufferSampleCapacity - numSamplesDelay; - } - int16_t correctMixSample[2], correctBufferSample[2], delayMixSample[2], delayBufferSample[2]; - int delayedChannelIndex[2]; - - float attenuationAndWeakChannelRatio = attenuationCoefficient * weakChannelAmplitudeRatio; + int16_t correctBufferSample[2], delayBufferSample[2]; + int delayedChannelIndex = 0; for (int s = 0; s < NETWORK_BUFFER_LENGTH_SAMPLES_STEREO; s += 4) { // setup the int16_t variables for the two sample sets correctBufferSample[0] = nextOutputStart[s / 2] * attenuationCoefficient; correctBufferSample[1] = nextOutputStart[(s / 2) + 1] * attenuationCoefficient; - correctMixSample[0] = _clientSamples[s + goodChannelOffset]; - correctMixSample[1] = _clientSamples[s + goodChannelOffset + 2]; - for (int i = 0; i < 2; ++i) { - if ((s / 2) + numSamplesDelay + i < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL) { - // for the delayed channel we fill the range (n + numSamplesDelay) to NETWORK_BUFFER_LENGTH_SAMPLES_STEREO first - delayedChannelIndex[i] = s + (numSamplesDelay * 2) + (i * 2) + delayedChannelOffset; - delayBufferSample[i] = correctBufferSample[i] * weakChannelAmplitudeRatio; - } else { - // now that the right most range has been filled, we go back to fill in numSamples delay at the beginning - int samplesBack = (s / 2) - NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL + i; - - delayBufferSample[i] = delayNextOutputStart[numSamplesDelay + samplesBack] * attenuationAndWeakChannelRatio; - delayedChannelIndex[i] = (numSamplesDelay + samplesBack) * 2 + delayedChannelOffset; - } - } + delayedChannelIndex = s + (numSamplesDelay * 2) + delayedChannelOffset; - delayMixSample[0] = _clientSamples[delayedChannelIndex[0]]; - delayMixSample[1] = _clientSamples[delayedChannelIndex[1]]; + delayBufferSample[0] = correctBufferSample[0] * weakChannelAmplitudeRatio; + delayBufferSample[1] = correctBufferSample[1] * weakChannelAmplitudeRatio; - __m64 bufferSamples = _mm_set_pi16(correctMixSample[0], correctMixSample[1], delayMixSample[0], delayMixSample[1]); + __m64 bufferSamples = _mm_set_pi16(_clientSamples[s + goodChannelOffset], + _clientSamples[s + goodChannelOffset + 2], + _clientSamples[delayedChannelIndex], + _clientSamples[delayedChannelIndex + 2]); __m64 addedSamples = _mm_set_pi16(correctBufferSample[0], correctBufferSample[1], delayBufferSample[0], delayBufferSample[1]); @@ -209,8 +190,92 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf // assign the results from the result of the mmx arithmetic _clientSamples[s + goodChannelOffset] = shortResults[3]; _clientSamples[s + goodChannelOffset + 2] = shortResults[2]; - _clientSamples[delayedChannelIndex[0]] = shortResults[1]; - _clientSamples[delayedChannelIndex[1]] = shortResults[0]; + _clientSamples[delayedChannelIndex] = shortResults[1]; + _clientSamples[delayedChannelIndex + 2] = shortResults[0]; + } + + // The following code is pretty gross and redundant, but AFAIK it's the best way to avoid + // too many conditionals in handling the delay samples at the beginning of _clientSamples. + // Basically we try to take the samples in batches of four, and then handle the remainder + // conditionally to get rid of the rest. + + if (numSamplesDelay > 0) { + // if there was a sample delay for this buffer, we need to pull samples prior to the nextOutput + // to stick at the beginning + float attenuationAndWeakChannelRatio = attenuationCoefficient * weakChannelAmplitudeRatio; + const int16_t* delayNextOutputStart = nextOutputStart - numSamplesDelay; + if (delayNextOutputStart < bufferStart) { + delayNextOutputStart = bufferStart + ringBufferSampleCapacity - numSamplesDelay; + } + + int i = 0; + + while (i + 3 < numSamplesDelay) { + // handle the first cases where we can MMX add four samples at once + int parentIndex = i * 2; + __m64 bufferSamples = _mm_setr_pi16(_clientSamples[parentIndex + delayedChannelOffset], + _clientSamples[parentIndex + 2 + delayedChannelOffset], + _clientSamples[parentIndex + 4 + delayedChannelOffset], + _clientSamples[parentIndex + 6 + delayedChannelOffset]); + __m64 addSamples = _mm_set_pi16(delayNextOutputStart[i] * attenuationAndWeakChannelRatio, + delayNextOutputStart[i + 1] * attenuationAndWeakChannelRatio, + delayNextOutputStart[i + 2] * attenuationAndWeakChannelRatio, + delayNextOutputStart[i + 3] * attenuationAndWeakChannelRatio); + __m64 mmxResult = _mm_adds_pi16(bufferSamples, addSamples); + int16_t* shortResults = reinterpret_cast(&mmxResult); + + _clientSamples[parentIndex + delayedChannelOffset] = shortResults[3]; + _clientSamples[parentIndex + 2 + delayedChannelOffset] = shortResults[2]; + _clientSamples[parentIndex + 4 + delayedChannelOffset] = shortResults[1]; + _clientSamples[parentIndex + 6 + delayedChannelOffset] = shortResults[0]; + + // push the index + i += 4; + } + + int parentIndex = i * 2; + + if (i + 2 < numSamplesDelay) { + // MMX add only three delayed samples + + __m64 bufferSamples = _mm_set_pi16(_clientSamples[parentIndex + delayedChannelOffset], + _clientSamples[parentIndex + 2 + delayedChannelOffset], + _clientSamples[parentIndex + 4 + delayedChannelOffset], + 0); + __m64 addSamples = _mm_set_pi16(delayNextOutputStart[i] * attenuationAndWeakChannelRatio, + delayNextOutputStart[i + 1] * attenuationAndWeakChannelRatio, + delayNextOutputStart[i + 2] * attenuationAndWeakChannelRatio, + 0); + __m64 mmxResult = _mm_adds_pi16(bufferSamples, addSamples); + int16_t* shortResults = reinterpret_cast(&mmxResult); + + _clientSamples[parentIndex + delayedChannelOffset] = shortResults[3]; + _clientSamples[parentIndex + 2 + delayedChannelOffset] = shortResults[2]; + _clientSamples[parentIndex + 4 + delayedChannelOffset] = shortResults[1]; + + } else if (i + 1 < numSamplesDelay) { + // MMX add two delayed samples + __m64 bufferSamples = _mm_set_pi16(_clientSamples[parentIndex + delayedChannelOffset], + _clientSamples[parentIndex + 2 + delayedChannelOffset], 0, 0); + __m64 addSamples = _mm_set_pi16(delayNextOutputStart[i] * attenuationAndWeakChannelRatio, + delayNextOutputStart[i + 1] * attenuationAndWeakChannelRatio, 0, 0); + + __m64 mmxResult = _mm_adds_pi16(bufferSamples, addSamples); + int16_t* shortResults = reinterpret_cast(&mmxResult); + + _clientSamples[parentIndex + delayedChannelOffset] = shortResults[3]; + _clientSamples[parentIndex + 2 + delayedChannelOffset] = shortResults[2]; + + } else if (i < numSamplesDelay) { + // MMX add a single delayed sample + __m64 bufferSamples = _mm_set_pi16(_clientSamples[parentIndex + delayedChannelOffset], 0, 0, 0); + __m64 addSamples = _mm_set_pi16(delayNextOutputStart[i] * attenuationAndWeakChannelRatio, 0, 0, 0); + + __m64 mmxResult = _mm_adds_pi16(bufferSamples, addSamples); + int16_t* shortResults = reinterpret_cast(&mmxResult); + + _clientSamples[parentIndex + delayedChannelOffset] = shortResults[3]; + } } } @@ -303,7 +368,7 @@ void AudioMixer::run() { && ((AudioMixerClientData*) node->getLinkedData())->getAvatarAudioRingBuffer()) { prepareMixForListeningNode(node.data()); - memcpy(_clientMixBuffer.data() + numBytesPacketHeader, _clientSamples, sizeof(_clientSamples)); + memcpy(_clientMixBuffer.data() + numBytesPacketHeader, _clientSamples, NETWORK_BUFFER_LENGTH_BYTES_STEREO); nodeList->writeDatagram(_clientMixBuffer, node); } } diff --git a/assignment-client/src/audio/AudioMixer.h b/assignment-client/src/audio/AudioMixer.h index ae5998100f..8032649c17 100644 --- a/assignment-client/src/audio/AudioMixer.h +++ b/assignment-client/src/audio/AudioMixer.h @@ -16,6 +16,8 @@ class PositionalAudioRingBuffer; class AvatarAudioRingBuffer; +const int SAMPLE_PHASE_DELAY_AT_90 = 20; + /// Handles assignments of type AudioMixer - mixing streams of audio and re-distributing to various clients. class AudioMixer : public ThreadedAssignment { Q_OBJECT @@ -38,7 +40,8 @@ private: QByteArray _clientMixBuffer; - int16_t _clientSamples[NETWORK_BUFFER_LENGTH_SAMPLES_STEREO]; + // client samples capacity is larger than what will be sent to optimize mixing + int16_t _clientSamples[NETWORK_BUFFER_LENGTH_SAMPLES_STEREO + SAMPLE_PHASE_DELAY_AT_90]; }; #endif /* defined(__hifi__AudioMixer__) */ From 2478c995f201ca67a3bdd4965f48c3f351f6c041 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 17 Mar 2014 10:05:44 -0700 Subject: [PATCH 33/39] clarifications to BUILD to remove confusing instructions, closes #2327 --- BUILD.md | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/BUILD.md b/BUILD.md index 1bc5145704..e033916e08 100644 --- a/BUILD.md +++ b/BUILD.md @@ -104,9 +104,7 @@ We don't currently have a Windows installer, so before running Interface, you wi CMake will need to know where the headers and libraries for required external dependencies are. If you installed ZLIB using the installer, the FindZLIB cmake module will be able to find it. This isn't the case for the others. -You have the choice of setting a variable specific to each library, or having a folder using a defined structure that contains all of the libs. - -The recommended route is to place all of the dependencies in one place and set one ENV variable - HIFI_LIB_DIR. That ENV variable should point to a directory with the following structure: +The recommended route for CMake to find external dependencies is to place all of the dependencies in one folder and set one ENV variable - HIFI_LIB_DIR. That ENV variable should point to a directory with the following structure: root_lib_dir -> glm @@ -128,14 +126,6 @@ The recommended route is to place all of the dependencies in one place and set o For many of the external libraries where precompiled binaries are readily available you should be able to simply copy the extracted folder that you get from the download links provided at the top of the guide. Otherwise you may need to build from source and install the built product to this directory. The `root_lib_dir` in the above example can be wherever you choose on your system - as long as the environment variable HIFI_LIB_DIR is set to it. -Should you want to define a location for each library, these are the associated variables you will want to set: - -`GLM_ROOT_DIR, GLUT_ROOT_DIR, GLEW_ROOT_DIR` - -They can be set in your ENV or by passing them to the cmake command on the command line. (There is an example of this in the CMake section earlier in this guide.) - -Each of those designates the root directory that contains the sub-folders for each library. For example, if the GLEW_ROOT_DIR is `C:\libs\glew`, then we would expect to find an `include` folder and a `lib` folder inside `C:\libs\glew`. - *NOTE: Qt does not support 64-bit builds on Windows 7, so you must use the 32-bit version of libraries for interface.exe to run. The 32-bit version of the static library is the one linked by our CMake find modules* #### DLLs From a1fe41fc1d4ad9e2203be1f78caa553be0318423 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 17 Mar 2014 10:10:26 -0700 Subject: [PATCH 34/39] repair a conflicted translation file --- interface/interface_en.ts | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/interface/interface_en.ts b/interface/interface_en.ts index d640db2952..75ada1910c 100644 --- a/interface/interface_en.ts +++ b/interface/interface_en.ts @@ -14,20 +14,12 @@ -<<<<<<< HEAD - -======= ->>>>>>> 5182ab190432324cdb0d0221c15fe57fe1e602c6 Open Script -<<<<<<< HEAD - -======= ->>>>>>> 5182ab190432324cdb0d0221c15fe57fe1e602c6 JavaScript Files (*.js) @@ -121,31 +113,18 @@ Menu -<<<<<<< HEAD - -======= ->>>>>>> 5182ab190432324cdb0d0221c15fe57fe1e602c6 Open .ini config file -<<<<<<< HEAD - - -======= ->>>>>>> 5182ab190432324cdb0d0221c15fe57fe1e602c6 Text files (*.ini) -<<<<<<< HEAD - -======= ->>>>>>> 5182ab190432324cdb0d0221c15fe57fe1e602c6 Save .ini config file From cc1d309c15e87dd8cfc0fdc18979befe514aeb1f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 17 Mar 2014 10:13:29 -0700 Subject: [PATCH 35/39] some really trivial magic number replacements --- assignment-client/src/audio/AudioMixer.cpp | 37 ++++++++++++---------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index f8e68340cb..24f2c90020 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -165,6 +165,8 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf int16_t correctBufferSample[2], delayBufferSample[2]; int delayedChannelIndex = 0; + const int SINGLE_STEREO_OFFSET = 2; + for (int s = 0; s < NETWORK_BUFFER_LENGTH_SAMPLES_STEREO; s += 4) { // setup the int16_t variables for the two sample sets @@ -177,9 +179,9 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf delayBufferSample[1] = correctBufferSample[1] * weakChannelAmplitudeRatio; __m64 bufferSamples = _mm_set_pi16(_clientSamples[s + goodChannelOffset], - _clientSamples[s + goodChannelOffset + 2], + _clientSamples[s + goodChannelOffset + SINGLE_STEREO_OFFSET], _clientSamples[delayedChannelIndex], - _clientSamples[delayedChannelIndex + 2]); + _clientSamples[delayedChannelIndex + SINGLE_STEREO_OFFSET]); __m64 addedSamples = _mm_set_pi16(correctBufferSample[0], correctBufferSample[1], delayBufferSample[0], delayBufferSample[1]); @@ -189,9 +191,9 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf // assign the results from the result of the mmx arithmetic _clientSamples[s + goodChannelOffset] = shortResults[3]; - _clientSamples[s + goodChannelOffset + 2] = shortResults[2]; + _clientSamples[s + goodChannelOffset + SINGLE_STEREO_OFFSET] = shortResults[2]; _clientSamples[delayedChannelIndex] = shortResults[1]; - _clientSamples[delayedChannelIndex + 2] = shortResults[0]; + _clientSamples[delayedChannelIndex + SINGLE_STEREO_OFFSET] = shortResults[0]; } // The following code is pretty gross and redundant, but AFAIK it's the best way to avoid @@ -199,6 +201,9 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf // Basically we try to take the samples in batches of four, and then handle the remainder // conditionally to get rid of the rest. + const int DOUBLE_STEREO_OFFSET = 4; + const int TRIPLE_STEREO_OFFSET = 6; + if (numSamplesDelay > 0) { // if there was a sample delay for this buffer, we need to pull samples prior to the nextOutput // to stick at the beginning @@ -214,9 +219,9 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf // handle the first cases where we can MMX add four samples at once int parentIndex = i * 2; __m64 bufferSamples = _mm_setr_pi16(_clientSamples[parentIndex + delayedChannelOffset], - _clientSamples[parentIndex + 2 + delayedChannelOffset], - _clientSamples[parentIndex + 4 + delayedChannelOffset], - _clientSamples[parentIndex + 6 + delayedChannelOffset]); + _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset], + _clientSamples[parentIndex + DOUBLE_STEREO_OFFSET + delayedChannelOffset], + _clientSamples[parentIndex + TRIPLE_STEREO_OFFSET + delayedChannelOffset]); __m64 addSamples = _mm_set_pi16(delayNextOutputStart[i] * attenuationAndWeakChannelRatio, delayNextOutputStart[i + 1] * attenuationAndWeakChannelRatio, delayNextOutputStart[i + 2] * attenuationAndWeakChannelRatio, @@ -225,9 +230,9 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf int16_t* shortResults = reinterpret_cast(&mmxResult); _clientSamples[parentIndex + delayedChannelOffset] = shortResults[3]; - _clientSamples[parentIndex + 2 + delayedChannelOffset] = shortResults[2]; - _clientSamples[parentIndex + 4 + delayedChannelOffset] = shortResults[1]; - _clientSamples[parentIndex + 6 + delayedChannelOffset] = shortResults[0]; + _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[2]; + _clientSamples[parentIndex + DOUBLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[1]; + _clientSamples[parentIndex + TRIPLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[0]; // push the index i += 4; @@ -239,8 +244,8 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf // MMX add only three delayed samples __m64 bufferSamples = _mm_set_pi16(_clientSamples[parentIndex + delayedChannelOffset], - _clientSamples[parentIndex + 2 + delayedChannelOffset], - _clientSamples[parentIndex + 4 + delayedChannelOffset], + _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset], + _clientSamples[parentIndex + DOUBLE_STEREO_OFFSET + delayedChannelOffset], 0); __m64 addSamples = _mm_set_pi16(delayNextOutputStart[i] * attenuationAndWeakChannelRatio, delayNextOutputStart[i + 1] * attenuationAndWeakChannelRatio, @@ -250,13 +255,13 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf int16_t* shortResults = reinterpret_cast(&mmxResult); _clientSamples[parentIndex + delayedChannelOffset] = shortResults[3]; - _clientSamples[parentIndex + 2 + delayedChannelOffset] = shortResults[2]; - _clientSamples[parentIndex + 4 + delayedChannelOffset] = shortResults[1]; + _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[2]; + _clientSamples[parentIndex + DOUBLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[1]; } else if (i + 1 < numSamplesDelay) { // MMX add two delayed samples __m64 bufferSamples = _mm_set_pi16(_clientSamples[parentIndex + delayedChannelOffset], - _clientSamples[parentIndex + 2 + delayedChannelOffset], 0, 0); + _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset], 0, 0); __m64 addSamples = _mm_set_pi16(delayNextOutputStart[i] * attenuationAndWeakChannelRatio, delayNextOutputStart[i + 1] * attenuationAndWeakChannelRatio, 0, 0); @@ -264,7 +269,7 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf int16_t* shortResults = reinterpret_cast(&mmxResult); _clientSamples[parentIndex + delayedChannelOffset] = shortResults[3]; - _clientSamples[parentIndex + 2 + delayedChannelOffset] = shortResults[2]; + _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[2]; } else if (i < numSamplesDelay) { // MMX add a single delayed sample From 288272f051437b03f4ae9c6910601e7474f48e11 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 17 Mar 2014 11:26:35 -0700 Subject: [PATCH 36/39] fix a reversed MMX add --- assignment-client/src/audio/AudioMixer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 660da1dc52..1637f88859 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -217,7 +217,7 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf while (i + 3 < numSamplesDelay) { // handle the first cases where we can MMX add four samples at once int parentIndex = i * 2; - __m64 bufferSamples = _mm_setr_pi16(_clientSamples[parentIndex + delayedChannelOffset], + __m64 bufferSamples = _mm_set_pi16(_clientSamples[parentIndex + delayedChannelOffset], _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset], _clientSamples[parentIndex + DOUBLE_STEREO_OFFSET + delayedChannelOffset], _clientSamples[parentIndex + TRIPLE_STEREO_OFFSET + delayedChannelOffset]); From bc9deb5db7075e069426f22ef3caeb14cbd6cab7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 17 Mar 2014 14:29:53 -0700 Subject: [PATCH 37/39] handle trivial case of not mixing silent audio streams --- assignment-client/src/audio/AudioMixer.cpp | 15 ++++++++------- .../src/audio/AudioMixerClientData.cpp | 11 +++++++++++ .../src/audio/AudioMixerClientData.h | 4 ++++ libraries/audio/src/AudioRingBuffer.cpp | 14 ++++++++++++++ libraries/audio/src/AudioRingBuffer.h | 2 ++ 5 files changed, 39 insertions(+), 7 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 1637f88859..be4da8870d 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -301,7 +301,8 @@ void AudioMixer::prepareMixForListeningNode(Node* node) { if ((*otherNode != *node || otherNodeBuffer->shouldLoopbackForNode()) - && otherNodeBuffer->willBeAddedToMix()) { + && otherNodeBuffer->willBeAddedToMix() + && otherNodeClientData->getNextOutputLoudness() != 0) { addBufferToMixForListeningNodeWithBuffer(otherNodeBuffer, nodeRingBuffer); } } @@ -355,12 +356,6 @@ void AudioMixer::run() { while (!_isFinished) { - QCoreApplication::processEvents(); - - if (_isFinished) { - break; - } - foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { if (node->getLinkedData()) { ((AudioMixerClientData*) node->getLinkedData())->checkBuffersBeforeFrameSend(JITTER_BUFFER_SAMPLES); @@ -383,6 +378,12 @@ void AudioMixer::run() { ((AudioMixerClientData*) node->getLinkedData())->pushBuffersAfterFrameSend(); } } + + QCoreApplication::processEvents(); + + if (_isFinished) { + break; + } int usecToSleep = usecTimestamp(&startTime) + (++nextFrame * BUFFER_SEND_INTERVAL_USECS) - usecTimestampNow(); diff --git a/assignment-client/src/audio/AudioMixerClientData.cpp b/assignment-client/src/audio/AudioMixerClientData.cpp index a41889e77c..8907796094 100644 --- a/assignment-client/src/audio/AudioMixerClientData.cpp +++ b/assignment-client/src/audio/AudioMixerClientData.cpp @@ -13,6 +13,13 @@ #include "AudioMixerClientData.h" +AudioMixerClientData::AudioMixerClientData() : + _ringBuffers(), + _nextOutputLoudness(0) +{ + +} + AudioMixerClientData::~AudioMixerClientData() { for (unsigned int i = 0; i < _ringBuffers.size(); i++) { // delete this attached PositionalAudioRingBuffer @@ -80,6 +87,10 @@ void AudioMixerClientData::checkBuffersBeforeFrameSend(int jitterBufferLengthSam // this is a ring buffer that is ready to go // set its flag so we know to push its buffer when all is said and done _ringBuffers[i]->setWillBeAddedToMix(true); + + // calculate the average loudness for the next NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL + // that would be mixed in + _nextOutputLoudness = _ringBuffers[i]->averageLoudnessForBoundarySamples(NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL); } } } diff --git a/assignment-client/src/audio/AudioMixerClientData.h b/assignment-client/src/audio/AudioMixerClientData.h index 8031dfec3e..bb10098e23 100644 --- a/assignment-client/src/audio/AudioMixerClientData.h +++ b/assignment-client/src/audio/AudioMixerClientData.h @@ -18,16 +18,20 @@ class AudioMixerClientData : public NodeData { public: + AudioMixerClientData(); ~AudioMixerClientData(); const std::vector getRingBuffers() const { return _ringBuffers; } AvatarAudioRingBuffer* getAvatarAudioRingBuffer() const; + float getNextOutputLoudness() const { return _nextOutputLoudness; } + int parseData(const QByteArray& packet); void checkBuffersBeforeFrameSend(int jitterBufferLengthSamples); void pushBuffersAfterFrameSend(); private: std::vector _ringBuffers; + float _nextOutputLoudness; }; #endif /* defined(__hifi__AudioMixerClientData__) */ diff --git a/libraries/audio/src/AudioRingBuffer.cpp b/libraries/audio/src/AudioRingBuffer.cpp index 56f6d038c2..aed601ec39 100644 --- a/libraries/audio/src/AudioRingBuffer.cpp +++ b/libraries/audio/src/AudioRingBuffer.cpp @@ -55,6 +55,20 @@ int AudioRingBuffer::parseData(const QByteArray& packet) { return writeData(packet.data() + numBytesPacketHeader, packet.size() - numBytesPacketHeader); } +float AudioRingBuffer::averageLoudnessForBoundarySamples(int numSamples) { + // ForBoundarySamples means that we expect the number of samples not to roll of the end of the ring buffer + float averageLoudness = 0; + + for (int i = 0; i < numSamples; ++i) { + averageLoudness += _nextOutput[i]; + } + + averageLoudness /= numSamples; + averageLoudness /= MAX_SAMPLE_VALUE; + + return averageLoudness; +} + qint64 AudioRingBuffer::readSamples(int16_t* destination, qint64 maxSamples) { return readData((char*) destination, maxSamples * sizeof(int16_t)); } diff --git a/libraries/audio/src/AudioRingBuffer.h b/libraries/audio/src/AudioRingBuffer.h index 577c01a63c..c4d3f87814 100644 --- a/libraries/audio/src/AudioRingBuffer.h +++ b/libraries/audio/src/AudioRingBuffer.h @@ -49,6 +49,8 @@ public: // assume callers using this will never wrap around the end const int16_t* getNextOutput() { return _nextOutput; } const int16_t* getBuffer() { return _buffer; } + + float averageLoudnessForBoundarySamples(int numSamples); qint64 readSamples(int16_t* destination, qint64 maxSamples); qint64 writeSamples(const int16_t* source, qint64 maxSamples); From 1428d2d1de772a611baa7d182f48be5a0f014fcc Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 17 Mar 2014 14:35:04 -0700 Subject: [PATCH 38/39] take an absolute value for correct loudness --- libraries/audio/src/AudioRingBuffer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/audio/src/AudioRingBuffer.cpp b/libraries/audio/src/AudioRingBuffer.cpp index aed601ec39..d07a334d81 100644 --- a/libraries/audio/src/AudioRingBuffer.cpp +++ b/libraries/audio/src/AudioRingBuffer.cpp @@ -60,7 +60,7 @@ float AudioRingBuffer::averageLoudnessForBoundarySamples(int numSamples) { float averageLoudness = 0; for (int i = 0; i < numSamples; ++i) { - averageLoudness += _nextOutput[i]; + averageLoudness += fabsf(_nextOutput[i]); } averageLoudness /= numSamples; From c7e12824a8e03c6c06ee0fe41a18a6d0c7ebb36a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 17 Mar 2014 14:35:26 -0700 Subject: [PATCH 39/39] clarify check for audio loudness in AudioMixer --- assignment-client/src/audio/AudioMixer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index be4da8870d..aeabd1548b 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -302,7 +302,7 @@ void AudioMixer::prepareMixForListeningNode(Node* node) { if ((*otherNode != *node || otherNodeBuffer->shouldLoopbackForNode()) && otherNodeBuffer->willBeAddedToMix() - && otherNodeClientData->getNextOutputLoudness() != 0) { + && otherNodeClientData->getNextOutputLoudness() > 0) { addBufferToMixForListeningNodeWithBuffer(otherNodeBuffer, nodeRingBuffer); } }