Merge pull request #13555 from SamGondelman/destroy

Trying to fix dependency shutdown
This commit is contained in:
John Conklin II 2018-08-16 13:14:58 -07:00 committed by GitHub
commit 1edf1b4337
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 294 additions and 289 deletions

View file

@ -516,7 +516,7 @@ void Agent::setIsListeningToAudioStream(bool isListeningToAudioStream) {
auto nodeList = DependencyManager::get<NodeList>();
nodeList->eachMatchingNode(
[&](const SharedNodePointer& node)->bool {
[](const SharedNodePointer& node)->bool {
return (node->getType() == NodeType::AudioMixer) && node->getActiveSocket();
},
[&](const SharedNodePointer& node) {

View file

@ -264,7 +264,8 @@ void DomainGatekeeper::updateNodePermissions() {
QList<SharedNodePointer> nodesToKill;
auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
limitedNodeList->eachNode([this, limitedNodeList, &nodesToKill](const SharedNodePointer& node){
QWeakPointer<LimitedNodeList> limitedNodeListWeak = limitedNodeList;
limitedNodeList->eachNode([this, limitedNodeListWeak, &nodesToKill](const SharedNodePointer& node){
// the id and the username in NodePermissions will often be the same, but id is set before
// authentication and verifiedUsername is only set once they user's key has been confirmed.
QString verifiedUsername = node->getPermissions().getVerifiedUserName();
@ -296,7 +297,8 @@ void DomainGatekeeper::updateNodePermissions() {
machineFingerprint = nodeData->getMachineFingerprint();
auto sendingAddress = nodeData->getSendingSockAddr().getAddress();
isLocalUser = (sendingAddress == limitedNodeList->getLocalSockAddr().getAddress() ||
auto nodeList = limitedNodeListWeak.lock();
isLocalUser = ((nodeList && sendingAddress == nodeList->getLocalSockAddr().getAddress()) ||
sendingAddress == QHostAddress::LocalHost);
}
@ -458,7 +460,7 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect
// in case this is a node that's failing to connect
// double check we don't have the same node whose sockets match exactly already in the list
limitedNodeList->eachNodeBreakable([&](const SharedNodePointer& node){
limitedNodeList->eachNodeBreakable([nodeConnection, username, &existingNodeID](const SharedNodePointer& node){
if (node->getPublicSocket() == nodeConnection.publicSockAddr && node->getLocalSocket() == nodeConnection.localSockAddr) {
// we have a node that already has these exact sockets - this can occur if a node
@ -1009,7 +1011,7 @@ void DomainGatekeeper::refreshGroupsCache() {
getDomainOwnerFriendsList();
auto nodeList = DependencyManager::get<LimitedNodeList>();
nodeList->eachNode([&](const SharedNodePointer& node) {
nodeList->eachNode([this](const SharedNodePointer& node) {
if (!node->getPermissions().isAssignment) {
// this node is an agent
const QString& verifiedUserName = node->getPermissions().getVerifiedUserName();

View file

@ -1078,7 +1078,7 @@ bool DomainServer::isInInterestSet(const SharedNodePointer& nodeA, const SharedN
unsigned int DomainServer::countConnectedUsers() {
unsigned int result = 0;
auto nodeList = DependencyManager::get<LimitedNodeList>();
nodeList->eachNode([&](const SharedNodePointer& node){
nodeList->eachNode([&result](const SharedNodePointer& node){
// only count unassigned agents (i.e., users)
if (node->getType() == NodeType::Agent) {
auto nodeData = static_cast<DomainServerNodeData*>(node->getLinkedData());
@ -1181,7 +1181,7 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif
// DTLSServerSession* dtlsSession = _isUsingDTLS ? _dtlsSessions[senderSockAddr] : NULL;
if (nodeData->isAuthenticated()) {
// if this authenticated node has any interest types, send back those nodes as well
limitedNodeList->eachNode([&](const SharedNodePointer& otherNode) {
limitedNodeList->eachNode([this, node, &domainListPackets, &domainListStream](const SharedNodePointer& otherNode) {
if (otherNode->getUUID() != node->getUUID() && isInInterestSet(node, otherNode)) {
// since we're about to add a node to the packet we start a segment
domainListPackets->startSegment();
@ -1230,6 +1230,7 @@ QUuid DomainServer::connectionSecretForNodes(const SharedNodePointer& nodeA, con
void DomainServer::broadcastNewNode(const SharedNodePointer& addedNode) {
auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
QWeakPointer<LimitedNodeList> limitedNodeListWeak = limitedNodeList;
auto addNodePacket = NLPacket::create(PacketType::DomainServerAddedNode);
@ -1241,7 +1242,7 @@ void DomainServer::broadcastNewNode(const SharedNodePointer& addedNode) {
int connectionSecretIndex = addNodePacket->pos();
limitedNodeList->eachMatchingNode(
[&](const SharedNodePointer& node)->bool {
[this, addedNode](const SharedNodePointer& node)->bool {
if (node->getLinkedData() && node->getActiveSocket() && node != addedNode) {
// is the added Node in this node's interest list?
return isInInterestSet(node, addedNode);
@ -1249,16 +1250,19 @@ void DomainServer::broadcastNewNode(const SharedNodePointer& addedNode) {
return false;
}
},
[&](const SharedNodePointer& node) {
addNodePacket->seek(connectionSecretIndex);
QByteArray rfcConnectionSecret = connectionSecretForNodes(node, addedNode).toRfc4122();
// replace the bytes at the end of the packet for the connection secret between these nodes
addNodePacket->write(rfcConnectionSecret);
[this, &addNodePacket, connectionSecretIndex, addedNode, limitedNodeListWeak](const SharedNodePointer& node) {
// send off this packet to the node
limitedNodeList->sendUnreliablePacket(*addNodePacket, *node);
auto limitedNodeList = limitedNodeListWeak.lock();
if (limitedNodeList) {
addNodePacket->seek(connectionSecretIndex);
QByteArray rfcConnectionSecret = connectionSecretForNodes(node, addedNode).toRfc4122();
// replace the bytes at the end of the packet for the connection secret between these nodes
addNodePacket->write(rfcConnectionSecret);
limitedNodeList->sendUnreliablePacket(*addNodePacket, *node);
}
}
);
}
@ -2864,7 +2868,7 @@ void DomainServer::updateReplicationNodes(ReplicationServerDirection direction)
auto serversSettings = replicationSettings.value(serversKey).toList();
std::vector<HifiSockAddr> knownReplicationNodes;
nodeList->eachNode([&](const SharedNodePointer& otherNode) {
nodeList->eachNode([direction, &knownReplicationNodes](const SharedNodePointer& otherNode) {
if ((direction == Upstream && NodeType::isUpstream(otherNode->getType()))
|| (direction == Downstream && NodeType::isDownstream(otherNode->getType()))) {
knownReplicationNodes.push_back(otherNode->getPublicSocket());
@ -2902,7 +2906,7 @@ void DomainServer::updateReplicationNodes(ReplicationServerDirection direction)
// collect them in a vector to separately remove them with handleKillNode (since eachNode has a read lock and
// we cannot recursively take the write lock required by handleKillNode)
std::vector<SharedNodePointer> nodesToKill;
nodeList->eachNode([&](const SharedNodePointer& otherNode) {
nodeList->eachNode([this, direction, replicationNodesInSettings, replicationDirection, &nodesToKill](const SharedNodePointer& otherNode) {
if ((direction == Upstream && NodeType::isUpstream(otherNode->getType()))
|| (direction == Downstream && NodeType::isDownstream(otherNode->getType()))) {
bool nodeInSettings = find(replicationNodesInSettings.cbegin(), replicationNodesInSettings.cend(),

View file

@ -45,9 +45,7 @@ QString AboutUtil::getQtVersion() const {
}
void AboutUtil::openUrl(const QString& url) const {
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
auto tablet = tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system");
auto tablet = DependencyManager::get<TabletScriptingInterface>()->getTablet("com.highfidelity.interface.tablet.system");
auto hmd = DependencyManager::get<HMDScriptingInterface>();
auto offscreenUi = DependencyManager::get<OffscreenUi>();

View file

@ -1139,8 +1139,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
// setup a timer for domain-server check ins
QTimer* domainCheckInTimer = new QTimer(this);
connect(domainCheckInTimer, &QTimer::timeout, [this, nodeList] {
if (!isServerlessMode()) {
QWeakPointer<NodeList> nodeListWeak = nodeList;
connect(domainCheckInTimer, &QTimer::timeout, [this, nodeListWeak] {
auto nodeList = nodeListWeak.lock();
if (!isServerlessMode() && nodeList) {
nodeList->sendDomainServerCheckIn();
}
});
@ -1150,33 +1152,34 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
domainCheckInTimer->deleteLater();
});
{
auto audioIO = DependencyManager::get<AudioClient>().data();
audioIO->setPositionGetter([] {
auto avatarManager = DependencyManager::get<AvatarManager>();
auto myAvatar = avatarManager ? avatarManager->getMyAvatar() : nullptr;
auto audioIO = DependencyManager::get<AudioClient>();
audioIO->setPositionGetter([]{
auto avatarManager = DependencyManager::get<AvatarManager>();
auto myAvatar = avatarManager ? avatarManager->getMyAvatar() : nullptr;
return myAvatar ? myAvatar->getPositionForAudio() : Vectors::ZERO;
});
audioIO->setOrientationGetter([] {
auto avatarManager = DependencyManager::get<AvatarManager>();
auto myAvatar = avatarManager ? avatarManager->getMyAvatar() : nullptr;
return myAvatar ? myAvatar->getPositionForAudio() : Vectors::ZERO;
});
audioIO->setOrientationGetter([]{
auto avatarManager = DependencyManager::get<AvatarManager>();
auto myAvatar = avatarManager ? avatarManager->getMyAvatar() : nullptr;
return myAvatar ? myAvatar->getOrientationForAudio() : Quaternions::IDENTITY;
});
return myAvatar ? myAvatar->getOrientationForAudio() : Quaternions::IDENTITY;
});
recording::Frame::registerFrameHandler(AudioConstants::getAudioFrameName(), [&audioIO](recording::Frame::ConstPointer frame) {
audioIO->handleRecordedAudioInput(frame->data);
});
recording::Frame::registerFrameHandler(AudioConstants::getAudioFrameName(), [=](recording::Frame::ConstPointer frame) {
audioIO->handleRecordedAudioInput(frame->data);
});
connect(audioIO.data(), &AudioClient::inputReceived, [](const QByteArray& audio){
static auto recorder = DependencyManager::get<recording::Recorder>();
if (recorder->isRecording()) {
static const recording::FrameType AUDIO_FRAME_TYPE = recording::Frame::registerFrameType(AudioConstants::getAudioFrameName());
recorder->recordFrame(AUDIO_FRAME_TYPE, audio);
}
});
audioIO->startThread();
connect(audioIO, &AudioClient::inputReceived, [](const QByteArray& audio) {
static auto recorder = DependencyManager::get<recording::Recorder>();
if (recorder->isRecording()) {
static const recording::FrameType AUDIO_FRAME_TYPE = recording::Frame::registerFrameType(AudioConstants::getAudioFrameName());
recorder->recordFrame(AUDIO_FRAME_TYPE, audio);
}
});
audioIO->startThread();
}
// Make sure we don't time out during slow operations at startup
updateHeartbeat();
@ -1275,27 +1278,29 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
// Inititalize sample before registering
_sampleSound = DependencyManager::get<SoundCache>()->getSound(PathUtils::resourcesUrl("sounds/sample.wav"));
auto scriptEngines = DependencyManager::get<ScriptEngines>().data();
scriptEngines->registerScriptInitializer([this](ScriptEnginePointer engine){
registerScriptEngineWithApplicationServices(engine);
});
{
auto scriptEngines = DependencyManager::get<ScriptEngines>().data();
scriptEngines->registerScriptInitializer([this](ScriptEnginePointer engine) {
registerScriptEngineWithApplicationServices(engine);
});
connect(scriptEngines, &ScriptEngines::scriptCountChanged, scriptEngines, [this] {
auto scriptEngines = DependencyManager::get<ScriptEngines>();
if (scriptEngines->getRunningScripts().isEmpty()) {
getMyAvatar()->clearScriptableSettings();
}
}, Qt::QueuedConnection);
connect(scriptEngines, &ScriptEngines::scriptCountChanged, this, [this] {
auto scriptEngines = DependencyManager::get<ScriptEngines>();
if (scriptEngines->getRunningScripts().isEmpty()) {
getMyAvatar()->clearScriptableSettings();
}
}, Qt::QueuedConnection);
connect(scriptEngines, &ScriptEngines::scriptsReloading, scriptEngines, [this] {
getEntities()->reloadEntityScripts();
loadAvatarScripts(getMyAvatar()->getScriptUrls());
}, Qt::QueuedConnection);
connect(scriptEngines, &ScriptEngines::scriptsReloading, this, [this] {
getEntities()->reloadEntityScripts();
loadAvatarScripts(getMyAvatar()->getScriptUrls());
}, Qt::QueuedConnection);
connect(scriptEngines, &ScriptEngines::scriptLoadError,
scriptEngines, [](const QString& filename, const QString& error){
OffscreenUi::asyncWarning(nullptr, "Error Loading Script", filename + " failed to load.");
}, Qt::QueuedConnection);
connect(scriptEngines, &ScriptEngines::scriptLoadError,
this, [](const QString& filename, const QString& error) {
OffscreenUi::asyncWarning(nullptr, "Error Loading Script", filename + " failed to load.");
}, Qt::QueuedConnection);
}
#ifdef _WIN32
WSADATA WsaData;
@ -1365,10 +1370,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
// so we defer the setup of the `scripting::Audio` class until this point
{
auto audioScriptingInterface = DependencyManager::set<AudioScriptingInterface, scripting::Audio>();
connect(audioIO.data(), &AudioClient::mutedByMixer, audioScriptingInterface.data(), &AudioScriptingInterface::mutedByMixer);
connect(audioIO.data(), &AudioClient::receivedFirstPacket, audioScriptingInterface.data(), &AudioScriptingInterface::receivedFirstPacket);
connect(audioIO.data(), &AudioClient::disconnected, audioScriptingInterface.data(), &AudioScriptingInterface::disconnected);
connect(audioIO.data(), &AudioClient::muteEnvironmentRequested, [](glm::vec3 position, float radius) {
auto audioIO = DependencyManager::get<AudioClient>().data();
connect(audioIO, &AudioClient::mutedByMixer, audioScriptingInterface.data(), &AudioScriptingInterface::mutedByMixer);
connect(audioIO, &AudioClient::receivedFirstPacket, audioScriptingInterface.data(), &AudioScriptingInterface::receivedFirstPacket);
connect(audioIO, &AudioClient::disconnected, audioScriptingInterface.data(), &AudioScriptingInterface::disconnected);
connect(audioIO, &AudioClient::muteEnvironmentRequested, [](glm::vec3 position, float radius) {
auto audioClient = DependencyManager::get<AudioClient>();
auto audioScriptingInterface = DependencyManager::get<AudioScriptingInterface>();
auto myAvatarPosition = DependencyManager::get<AvatarManager>()->getMyAvatar()->getWorldPosition();
@ -1697,23 +1703,26 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
userInputMapper->registerDevice(_touchscreenVirtualPadDevice->getInputDevice());
}
// this will force the model the look at the correct directory (weird order of operations issue)
scriptEngines->reloadLocalFiles();
{
auto scriptEngines = DependencyManager::get<ScriptEngines>().data();
// this will force the model the look at the correct directory (weird order of operations issue)
scriptEngines->reloadLocalFiles();
// do this as late as possible so that all required subsystems are initialized
// If we've overridden the default scripts location, just load default scripts
// otherwise, load 'em all
// do this as late as possible so that all required subsystems are initialized
// If we've overridden the default scripts location, just load default scripts
// otherwise, load 'em all
// we just want to see if --scripts was set, we've already parsed it and done
// the change in PathUtils. Rather than pass that in the constructor, lets just
// look (this could be debated)
QString scriptsSwitch = QString("--").append(SCRIPTS_SWITCH);
QDir defaultScriptsLocation(getCmdOption(argc, constArgv, scriptsSwitch.toStdString().c_str()));
if (!defaultScriptsLocation.exists()) {
scriptEngines->loadDefaultScripts();
scriptEngines->defaultScriptsLocationOverridden(true);
} else {
scriptEngines->loadScripts();
// we just want to see if --scripts was set, we've already parsed it and done
// the change in PathUtils. Rather than pass that in the constructor, lets just
// look (this could be debated)
QString scriptsSwitch = QString("--").append(SCRIPTS_SWITCH);
QDir defaultScriptsLocation(getCmdOption(argc, constArgv, scriptsSwitch.toStdString().c_str()));
if (!defaultScriptsLocation.exists()) {
scriptEngines->loadDefaultScripts();
scriptEngines->defaultScriptsLocationOverridden(true);
} else {
scriptEngines->loadScripts();
}
}
// Make sure we don't time out during slow operations at startup
@ -1763,13 +1772,16 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
cameraMenuChanged();
}
// set the local loopback interface for local sounds
AudioInjector::setLocalAudioInterface(audioIO.data());
auto audioScriptingInterface = DependencyManager::get<AudioScriptingInterface>();
audioScriptingInterface->setLocalAudioInterface(audioIO.data());
connect(audioIO.data(), &AudioClient::noiseGateOpened, audioScriptingInterface.data(), &AudioScriptingInterface::noiseGateOpened);
connect(audioIO.data(), &AudioClient::noiseGateClosed, audioScriptingInterface.data(), &AudioScriptingInterface::noiseGateClosed);
connect(audioIO.data(), &AudioClient::inputReceived, audioScriptingInterface.data(), &AudioScriptingInterface::inputReceived);
{
auto audioIO = DependencyManager::get<AudioClient>().data();
// set the local loopback interface for local sounds
AudioInjector::setLocalAudioInterface(audioIO);
auto audioScriptingInterface = DependencyManager::get<AudioScriptingInterface>();
audioScriptingInterface->setLocalAudioInterface(audioIO);
connect(audioIO, &AudioClient::noiseGateOpened, audioScriptingInterface.data(), &AudioScriptingInterface::noiseGateOpened);
connect(audioIO, &AudioClient::noiseGateClosed, audioScriptingInterface.data(), &AudioScriptingInterface::noiseGateClosed);
connect(audioIO, &AudioClient::inputReceived, audioScriptingInterface.data(), &AudioScriptingInterface::inputReceived);
}
this->installEventFilter(this);
@ -1826,13 +1838,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
}
});
connect(entityScriptingInterface.data(), &EntityScriptingInterface::deletingEntity, [=](const EntityItemID& entityItemID) {
connect(entityScriptingInterface.data(), &EntityScriptingInterface::deletingEntity, [this](const EntityItemID& entityItemID) {
if (entityItemID == _keyboardFocusedEntity.get()) {
setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
}
});
connect(getEntities()->getTree().get(), &EntityTree::deletingEntity, [=](const EntityItemID& entityItemID) {
connect(getEntities()->getTree().get(), &EntityTree::deletingEntity, [](const EntityItemID& entityItemID) {
auto avatarManager = DependencyManager::get<AvatarManager>();
auto myAvatar = avatarManager ? avatarManager->getMyAvatar() : nullptr;
if (myAvatar) {
@ -1840,7 +1852,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
}
});
EntityTree::setAddMaterialToEntityOperator([&](const QUuid& entityID, graphics::MaterialLayer material, const std::string& parentMaterialName) {
EntityTree::setAddMaterialToEntityOperator([this](const QUuid& entityID, graphics::MaterialLayer material, const std::string& parentMaterialName) {
// try to find the renderable
auto renderable = getEntities()->renderableForEntityId(entityID);
if (renderable) {
@ -1855,7 +1867,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
}
return false;
});
EntityTree::setRemoveMaterialFromEntityOperator([&](const QUuid& entityID, graphics::MaterialPointer material, const std::string& parentMaterialName) {
EntityTree::setRemoveMaterialFromEntityOperator([this](const QUuid& entityID, graphics::MaterialPointer material, const std::string& parentMaterialName) {
// try to find the renderable
auto renderable = getEntities()->renderableForEntityId(entityID);
if (renderable) {
@ -1890,7 +1902,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
return false;
});
EntityTree::setAddMaterialToOverlayOperator([&](const QUuid& overlayID, graphics::MaterialLayer material, const std::string& parentMaterialName) {
EntityTree::setAddMaterialToOverlayOperator([this](const QUuid& overlayID, graphics::MaterialLayer material, const std::string& parentMaterialName) {
auto overlay = _overlays.getOverlay(overlayID);
if (overlay) {
overlay->addMaterial(material, parentMaterialName);
@ -1898,7 +1910,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
}
return false;
});
EntityTree::setRemoveMaterialFromOverlayOperator([&](const QUuid& overlayID, graphics::MaterialPointer material, const std::string& parentMaterialName) {
EntityTree::setRemoveMaterialFromOverlayOperator([this](const QUuid& overlayID, graphics::MaterialPointer material, const std::string& parentMaterialName) {
auto overlay = _overlays.getOverlay(overlayID);
if (overlay) {
overlay->removeMaterial(material, parentMaterialName);
@ -1909,13 +1921,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
// Keyboard focus handling for Web overlays.
auto overlays = &(qApp->getOverlays());
connect(overlays, &Overlays::overlayDeleted, [=](const OverlayID& overlayID) {
connect(overlays, &Overlays::overlayDeleted, [this](const OverlayID& overlayID) {
if (overlayID == _keyboardFocusedOverlay.get()) {
setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);
}
});
connect(this, &Application::aboutToQuit, [=]() {
connect(this, &Application::aboutToQuit, [this]() {
setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);
setKeyboardFocusEntity(UNKNOWN_ENTITY_ID);
});
@ -2184,23 +2196,22 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
QVariant testProperty = property(hifi::properties::TEST);
qDebug() << testProperty;
if (testProperty.isValid()) {
auto scriptEngines = DependencyManager::get<ScriptEngines>();
const auto testScript = property(hifi::properties::TEST).toUrl();
// Set last parameter to exit interface when the test script finishes, if so requested
scriptEngines->loadScript(testScript, false, false, false, false, quitWhenFinished);
DependencyManager::get<ScriptEngines>()->loadScript(testScript, false, false, false, false, quitWhenFinished);
// This is done so we don't get a "connection time-out" message when we haven't passed in a URL.
if (arguments().contains("--url")) {
auto reply = SandboxUtils::getStatus();
connect(reply, &QNetworkReply::finished, this, [=] {
connect(reply, &QNetworkReply::finished, this, [this, reply] {
handleSandboxStatus(reply);
});
}
} else {
PROFILE_RANGE(render, "GetSandboxStatus");
auto reply = SandboxUtils::getStatus();
connect(reply, &QNetworkReply::finished, this, [=] {
connect(reply, &QNetworkReply::finished, this, [this, reply] {
handleSandboxStatus(reply);
});
}
@ -2227,8 +2238,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
connect(&_myCamera, &Camera::modeUpdated, this, &Application::cameraModeChanged);
DependencyManager::get<PickManager>()->setShouldPickHUDOperator([&]() { return DependencyManager::get<HMDScriptingInterface>()->isHMDMode(); });
DependencyManager::get<PickManager>()->setCalculatePos2DFromHUDOperator([&](const glm::vec3& intersection) {
DependencyManager::get<PickManager>()->setShouldPickHUDOperator([]() { return DependencyManager::get<HMDScriptingInterface>()->isHMDMode(); });
DependencyManager::get<PickManager>()->setCalculatePos2DFromHUDOperator([this](const glm::vec3& intersection) {
const glm::vec2 MARGIN(25.0f);
glm::vec2 maxPos = _controllerScriptingInterface->getViewportDimensions() - MARGIN;
glm::vec2 pos2D = DependencyManager::get<HMDScriptingInterface>()->overlayFromWorldPoint(intersection);
@ -2238,7 +2249,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
// Setup the mouse ray pick and related operators
DependencyManager::get<EntityTreeRenderer>()->setMouseRayPickID(DependencyManager::get<PickManager>()->addPick(PickQuery::Ray, std::make_shared<MouseRayPick>(
PickFilter(PickScriptingInterface::PICK_ENTITIES() | PickScriptingInterface::PICK_INCLUDE_NONCOLLIDABLE()), 0.0f, true)));
DependencyManager::get<EntityTreeRenderer>()->setMouseRayPickResultOperator([&](unsigned int rayPickID) {
DependencyManager::get<EntityTreeRenderer>()->setMouseRayPickResultOperator([](unsigned int rayPickID) {
RayToEntityIntersectionResult entityResult;
entityResult.intersects = false;
auto pickResult = DependencyManager::get<PickManager>()->getPrevPickResultTyped<RayPickResult>(rayPickID);
@ -2254,7 +2265,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
}
return entityResult;
});
DependencyManager::get<EntityTreeRenderer>()->setSetPrecisionPickingOperator([&](unsigned int rayPickID, bool value) {
DependencyManager::get<EntityTreeRenderer>()->setSetPrecisionPickingOperator([](unsigned int rayPickID, bool value) {
DependencyManager::get<PickManager>()->setPrecisionPicking(rayPickID, value);
});
@ -2453,21 +2464,35 @@ void Application::cleanupBeforeQuit() {
_keyboardFocusHighlight = nullptr;
}
auto nodeList = DependencyManager::get<NodeList>();
{
auto nodeList = DependencyManager::get<NodeList>();
// send the domain a disconnect packet, force stoppage of domain-server check-ins
nodeList->getDomainHandler().disconnect();
nodeList->setIsShuttingDown(true);
// send the domain a disconnect packet, force stoppage of domain-server check-ins
nodeList->getDomainHandler().disconnect();
nodeList->setIsShuttingDown(true);
// tell the packet receiver we're shutting down, so it can drop packets
nodeList->getPacketReceiver().setShouldDropPackets(true);
// tell the packet receiver we're shutting down, so it can drop packets
nodeList->getPacketReceiver().setShouldDropPackets(true);
}
getEntities()->shutdown(); // tell the entities system we're shutting down, so it will stop running scripts
// Clear any queued processing (I/O, FBX/OBJ/Texture parsing)
QThreadPool::globalInstance()->clear();
DependencyManager::destroy<RecordingScriptingInterface>();
// FIXME: Something is still holding on to the ScriptEnginePointers contained in ScriptEngines, and they hold backpointers to ScriptEngines,
// so this doesn't shut down properly
DependencyManager::get<ScriptEngines>()->shutdownScripting(); // stop all currently running global scripts
// These classes hold ScriptEnginePointers, so they must be destroyed before ScriptEngines
// Must be done after shutdownScripting in case any scripts try to access these things
{
DependencyManager::destroy<StandAloneJSConsole>();
EntityTreePointer tree = getEntities()->getTree();
tree->setSimulation(nullptr);
DependencyManager::destroy<EntityTreeRenderer>();
}
DependencyManager::destroy<ScriptEngines>();
_displayPlugin.reset();
@ -2504,6 +2529,8 @@ void Application::cleanupBeforeQuit() {
DependencyManager::destroy<EyeTracker>();
#endif
DependencyManager::destroy<ContextOverlayInterface>(); // Must be destroyed before TabletScriptingInterface
// stop QML
DependencyManager::destroy<TabletScriptingInterface>();
DependencyManager::destroy<ToolbarScriptingInterface>();
@ -2515,10 +2542,6 @@ void Application::cleanupBeforeQuit() {
_snapshotSoundInjector->stop();
}
// FIXME: something else is holding a reference to AudioClient,
// so it must be explicitly synchronously stopped here
DependencyManager::get<AudioClient>()->cleanupBeforeQuit();
// destroy Audio so it and its threads have a chance to go down safely
// this must happen after QML, as there are unexplained audio crashes originating in qtwebengine
DependencyManager::destroy<AudioClient>();
@ -2558,9 +2581,6 @@ Application::~Application() {
_entityClipboard->eraseAllOctreeElements();
_entityClipboard.reset();
EntityTreePointer tree = getEntities()->getTree();
tree->setSimulation(nullptr);
_octreeProcessor.terminate();
_entityEditSender.terminate();
@ -3274,8 +3294,7 @@ void Application::showHelp() {
QUrlQuery queryString;
queryString.addQueryItem("handControllerName", handControllerName);
queryString.addQueryItem("defaultTab", defaultTab);
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
TabletProxy* tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet(SYSTEM_TABLET));
TabletProxy* tablet = dynamic_cast<TabletProxy*>(DependencyManager::get<TabletScriptingInterface>()->getTablet(SYSTEM_TABLET));
tablet->gotoWebScreen(PathUtils::resourcesUrl() + INFO_HELP_PATH + "?" + queryString.toString());
DependencyManager::get<HMDScriptingInterface>()->openTablet();
//InfoView::show(INFO_HELP_PATH, false, queryString.toString());
@ -3588,6 +3607,10 @@ static void dumpEventQueue(QThread* thread) {
bool Application::event(QEvent* event) {
if (_aboutToQuit) {
return false;
}
if (!Menu::getInstance()) {
return false;
}
@ -3992,10 +4015,6 @@ void Application::maybeToggleMenuVisible(QMouseEvent* event) const {
void Application::mouseMoveEvent(QMouseEvent* event) {
PROFILE_RANGE(app_input_mouse, __FUNCTION__);
if (_aboutToQuit) {
return;
}
maybeToggleMenuVisible(event);
auto& compositor = getApplicationCompositor();
@ -4060,11 +4079,9 @@ void Application::mousePressEvent(QMouseEvent* event) {
event->screenPos(), event->button(),
event->buttons(), event->modifiers());
if (!_aboutToQuit) {
getOverlays().mousePressEvent(&mappedEvent);
if (!_controllerScriptingInterface->areEntityClicksCaptured()) {
getEntities()->mousePressEvent(&mappedEvent);
}
getOverlays().mousePressEvent(&mappedEvent);
if (!_controllerScriptingInterface->areEntityClicksCaptured()) {
getEntities()->mousePressEvent(&mappedEvent);
}
_controllerScriptingInterface->emitMousePressEvent(&mappedEvent); // send events to any registered scripts
@ -4101,14 +4118,11 @@ void Application::mouseDoublePressEvent(QMouseEvent* event) {
event->screenPos(), event->button(),
event->buttons(), event->modifiers());
if (!_aboutToQuit) {
getOverlays().mouseDoublePressEvent(&mappedEvent);
if (!_controllerScriptingInterface->areEntityClicksCaptured()) {
getEntities()->mouseDoublePressEvent(&mappedEvent);
}
getOverlays().mouseDoublePressEvent(&mappedEvent);
if (!_controllerScriptingInterface->areEntityClicksCaptured()) {
getEntities()->mouseDoublePressEvent(&mappedEvent);
}
// if one of our scripts have asked to capture this event, then stop processing it
if (_controllerScriptingInterface->isMouseCaptured()) {
return;
@ -4127,10 +4141,8 @@ void Application::mouseReleaseEvent(QMouseEvent* event) {
event->screenPos(), event->button(),
event->buttons(), event->modifiers());
if (!_aboutToQuit) {
getOverlays().mouseReleaseEvent(&mappedEvent);
getEntities()->mouseReleaseEvent(&mappedEvent);
}
getOverlays().mouseReleaseEvent(&mappedEvent);
getEntities()->mouseReleaseEvent(&mappedEvent);
_controllerScriptingInterface->emitMouseReleaseEvent(&mappedEvent); // send events to any registered scripts
@ -4281,7 +4293,6 @@ bool Application::shouldPaint() const {
return false;
}
auto displayPlugin = getActiveDisplayPlugin();
#ifdef DEBUG_PAINT_DELAY
@ -4761,7 +4772,7 @@ bool Application::exportEntities(const QString& filename,
exportTree->createRootElement();
glm::vec3 root(TREE_SCALE, TREE_SCALE, TREE_SCALE);
bool success = true;
entityTree->withReadLock([&] {
entityTree->withReadLock([entityIDs, entityTree, givenOffset, myAvatarID, &root, &entities, &success, &exportTree] {
for (auto entityID : entityIDs) { // Gather entities and properties.
auto entityItem = entityTree->findEntityByEntityItemID(entityID);
if (!entityItem) {
@ -5510,6 +5521,10 @@ static bool domainLoadingInProgress = false;
void Application::update(float deltaTime) {
PROFILE_RANGE_EX(app, __FUNCTION__, 0xffff0000, (uint64_t)_renderFrameCount + 1);
if (_aboutToQuit) {
return;
}
if (!_physicsEnabled) {
if (!domainLoadingInProgress) {
PROFILE_ASYNC_BEGIN(app, "Scene Loading", "");
@ -5778,15 +5793,13 @@ void Application::update(float deltaTime) {
_entitySimulation->handleDeactivatedMotionStates(deactivations);
});
if (!_aboutToQuit) {
// handleCollisionEvents() AFTER handleChangedMotionStates()
{
PROFILE_RANGE(simulation_physics, "CollisionEvents");
avatarManager->handleCollisionEvents(collisionEvents);
// Collision events (and their scripts) must not be handled when we're locked, above. (That would risk
// deadlock.)
_entitySimulation->handleCollisionEvents(collisionEvents);
}
// handleCollisionEvents() AFTER handleChangedMotionStates()
{
PROFILE_RANGE(simulation_physics, "CollisionEvents");
avatarManager->handleCollisionEvents(collisionEvents);
// Collision events (and their scripts) must not be handled when we're locked, above. (That would risk
// deadlock.)
_entitySimulation->handleCollisionEvents(collisionEvents);
}
{
@ -5804,11 +5817,9 @@ void Application::update(float deltaTime) {
}
auto t4 = std::chrono::high_resolution_clock::now();
if (!_aboutToQuit) {
// NOTE: the getEntities()->update() call below will wait for lock
// and will provide non-physical entity motion
getEntities()->update(true); // update the models...
}
// NOTE: the getEntities()->update() call below will wait for lock
// and will provide non-physical entity motion
getEntities()->update(true); // update the models...
auto t5 = std::chrono::high_resolution_clock::now();
@ -6374,7 +6385,6 @@ void Application::domainURLChanged(QUrl domainURL) {
void Application::resettingDomain() {
_notifiedPacketVersionMismatchThisDomain = false;
auto nodeList = DependencyManager::get<NodeList>();
clearDomainOctreeDetails();
}
@ -6729,16 +6739,12 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe
pickScriptingInterface->registerMetaTypes(scriptEngine.data());
// connect this script engines printedMessage signal to the global ScriptEngines these various messages
connect(scriptEngine.data(), &ScriptEngine::printedMessage,
DependencyManager::get<ScriptEngines>().data(), &ScriptEngines::onPrintedMessage);
connect(scriptEngine.data(), &ScriptEngine::errorMessage,
DependencyManager::get<ScriptEngines>().data(), &ScriptEngines::onErrorMessage);
connect(scriptEngine.data(), &ScriptEngine::warningMessage,
DependencyManager::get<ScriptEngines>().data(), &ScriptEngines::onWarningMessage);
connect(scriptEngine.data(), &ScriptEngine::infoMessage,
DependencyManager::get<ScriptEngines>().data(), &ScriptEngines::onInfoMessage);
connect(scriptEngine.data(), &ScriptEngine::clearDebugWindow,
DependencyManager::get<ScriptEngines>().data(), &ScriptEngines::onClearDebugWindow);
auto scriptEngines = DependencyManager::get<ScriptEngines>().data();
connect(scriptEngine.data(), &ScriptEngine::printedMessage, scriptEngines, &ScriptEngines::onPrintedMessage);
connect(scriptEngine.data(), &ScriptEngine::errorMessage, scriptEngines, &ScriptEngines::onErrorMessage);
connect(scriptEngine.data(), &ScriptEngine::warningMessage, scriptEngines, &ScriptEngines::onWarningMessage);
connect(scriptEngine.data(), &ScriptEngine::infoMessage, scriptEngines, &ScriptEngines::onInfoMessage);
connect(scriptEngine.data(), &ScriptEngine::clearDebugWindow, scriptEngines, &ScriptEngines::onClearDebugWindow);
}
@ -7046,10 +7052,9 @@ void Application::showDialog(const QUrl& widgetUrl, const QUrl& tabletUrl, const
}
void Application::showScriptLogs() {
auto scriptEngines = DependencyManager::get<ScriptEngines>();
QUrl defaultScriptsLoc = PathUtils::defaultScriptsLocation();
defaultScriptsLoc.setPath(defaultScriptsLoc.path() + "developer/debugging/debugWindow.js");
scriptEngines->loadScript(defaultScriptsLoc.toString());
DependencyManager::get<ScriptEngines>()->loadScript(defaultScriptsLoc.toString());
}
void Application::showAssetServerWidget(QString filePath) {
@ -7615,7 +7620,6 @@ void Application::openUrl(const QUrl& url) const {
}
void Application::loadDialog() {
auto scriptEngines = DependencyManager::get<ScriptEngines>();
ModalDialogListener* dlg = OffscreenUi::getOpenFileNameAsync(_glWidget, tr("Open Script"),
getPreviousScriptLocation(),
tr("JavaScript Files (*.js)"));

View file

@ -64,7 +64,7 @@ void addAvatarEntities(const QVariantList& avatarEntities) {
EntityItemID id = EntityItemID(QUuid::createUuid());
bool success = true;
entityTree->withWriteLock([&] {
entityTree->withWriteLock([&entityTree, id, &entityProperties, &success] {
EntityItemPointer entity = entityTree->addEntity(id, entityProperties);
if (entity) {
if (entityProperties.queryAACubeRelatedPropertyChanged()) {

View file

@ -147,9 +147,11 @@ Menu::Menu() {
auto assetServerAction = addActionToQMenuAndActionHash(editMenu, MenuOption::AssetServer,
Qt::CTRL | Qt::SHIFT | Qt::Key_A,
qApp, SLOT(showAssetServerWidget()));
auto nodeList = DependencyManager::get<NodeList>();
QObject::connect(nodeList.data(), &NodeList::canWriteAssetsChanged, assetServerAction, &QAction::setEnabled);
assetServerAction->setEnabled(nodeList->getThisNodeCanWriteAssets());
{
auto nodeList = DependencyManager::get<NodeList>();
QObject::connect(nodeList.data(), &NodeList::canWriteAssetsChanged, assetServerAction, &QAction::setEnabled);
assetServerAction->setEnabled(nodeList->getThisNodeCanWriteAssets());
}
// Edit > Package Model as .fst...
addActionToQMenuAndActionHash(editMenu, MenuOption::PackageModel, 0,
@ -620,8 +622,11 @@ Menu::Menu() {
addCheckableActionToQMenuAndActionHash(networkMenu, MenuOption::SendWrongProtocolVersion, 0, false,
qApp, SLOT(sendWrongProtocolVersionsSignature(bool)));
addCheckableActionToQMenuAndActionHash(networkMenu, MenuOption::SendWrongDSConnectVersion, 0, false,
nodeList.data(), SLOT(toggleSendNewerDSConnectVersion(bool)));
{
auto nodeList = DependencyManager::get<NodeList>();
addCheckableActionToQMenuAndActionHash(networkMenu, MenuOption::SendWrongDSConnectVersion, 0, false,
nodeList.data(), SLOT(toggleSendNewerDSConnectVersion(bool)));
}
#endif
@ -655,10 +660,9 @@ Menu::Menu() {
action = addActionToQMenuAndActionHash(audioDebugMenu, "Stats...");
connect(action, &QAction::triggered, [] {
auto scriptEngines = DependencyManager::get<ScriptEngines>();
QUrl defaultScriptsLoc = PathUtils::defaultScriptsLocation();
defaultScriptsLoc.setPath(defaultScriptsLoc.path() + "developer/utilities/audio/stats.js");
scriptEngines->loadScript(defaultScriptsLoc.toString());
DependencyManager::get<ScriptEngines>()->loadScript(defaultScriptsLoc.toString());
});
action = addActionToQMenuAndActionHash(audioDebugMenu, "Buffers...");
@ -667,16 +671,14 @@ Menu::Menu() {
QString("hifi/tablet/TabletAudioBuffers.qml"), "AudioBuffersDialog");
});
auto audioIO = DependencyManager::get<AudioClient>();
addActionToQMenuAndActionHash(audioDebugMenu, MenuOption::MuteEnvironment, 0,
audioIO.data(), SLOT(sendMuteEnvironmentPacket()));
DependencyManager::get<AudioClient>().data(), SLOT(sendMuteEnvironmentPacket()));
action = addActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioScope);
connect(action, &QAction::triggered, [] {
auto scriptEngines = DependencyManager::get<ScriptEngines>();
QUrl defaultScriptsLoc = PathUtils::defaultScriptsLocation();
defaultScriptsLoc.setPath(defaultScriptsLoc.path() + "developer/utilities/audio/audioScope.js");
scriptEngines->loadScript(defaultScriptsLoc.toString());
DependencyManager::get<ScriptEngines>()->loadScript(defaultScriptsLoc.toString());
});
// Developer > Physics >>>
@ -756,10 +758,9 @@ Menu::Menu() {
// Developer > API Debugger
action = addActionToQMenuAndActionHash(developerMenu, "API Debugger");
connect(action, &QAction::triggered, [] {
auto scriptEngines = DependencyManager::get<ScriptEngines>();
QUrl defaultScriptsLoc = PathUtils::defaultScriptsLocation();
defaultScriptsLoc.setPath(defaultScriptsLoc.path() + "developer/utilities/tools/currentAPI.js");
scriptEngines->loadScript(defaultScriptsLoc.toString());
DependencyManager::get<ScriptEngines>()->loadScript(defaultScriptsLoc.toString());
});
// Developer > Log...
@ -767,11 +768,14 @@ Menu::Menu() {
qApp, SLOT(toggleLogDialog()));
auto essLogAction = addActionToQMenuAndActionHash(developerMenu, MenuOption::EntityScriptServerLog, 0,
qApp, SLOT(toggleEntityScriptServerLogDialog()));
QObject::connect(nodeList.data(), &NodeList::canRezChanged, essLogAction, [essLogAction] {
{
auto nodeList = DependencyManager::get<NodeList>();
QObject::connect(nodeList.data(), &NodeList::canRezChanged, essLogAction, [essLogAction] {
auto nodeList = DependencyManager::get<NodeList>();
essLogAction->setEnabled(nodeList->getThisNodeCanRez());
});
essLogAction->setEnabled(nodeList->getThisNodeCanRez());
});
essLogAction->setEnabled(nodeList->getThisNodeCanRez());
}
addActionToQMenuAndActionHash(developerMenu, "Script Log (HMD friendly)...", Qt::NoButton,
qApp, SLOT(showScriptLogs()));

View file

@ -79,7 +79,7 @@ AvatarManager::AvatarManager(QObject* parent) :
// when we hear that the user has ignored an avatar by session UUID
// immediately remove that avatar instead of waiting for the absence of packets from avatar mixer
connect(nodeList.data(), &NodeList::ignoredNode, this, [=](const QUuid& nodeID, bool enabled) {
connect(nodeList.data(), &NodeList::ignoredNode, this, [this](const QUuid& nodeID, bool enabled) {
if (enabled) {
removeAvatar(nodeID, KillAvatarReason::AvatarIgnored);
}
@ -318,16 +318,21 @@ void AvatarManager::postUpdate(float deltaTime, const render::ScenePointer& scen
void AvatarManager::sendIdentityRequest(const QUuid& avatarID) const {
auto nodeList = DependencyManager::get<NodeList>();
QWeakPointer<NodeList> nodeListWeak = nodeList;
nodeList->eachMatchingNode(
[&](const SharedNodePointer& node)->bool {
return node->getType() == NodeType::AvatarMixer && node->getActiveSocket();
},
[&](const SharedNodePointer& node) {
auto packet = NLPacket::create(PacketType::AvatarIdentityRequest, NUM_BYTES_RFC4122_UUID, true);
packet->write(avatarID.toRfc4122());
nodeList->sendPacket(std::move(packet), *node);
++_identityRequestsSent;
});
[](const SharedNodePointer& node)->bool {
return node->getType() == NodeType::AvatarMixer && node->getActiveSocket();
},
[this, avatarID, nodeListWeak](const SharedNodePointer& node) {
auto nodeList = nodeListWeak.lock();
if (nodeList) {
auto packet = NLPacket::create(PacketType::AvatarIdentityRequest, NUM_BYTES_RFC4122_UUID, true);
packet->write(avatarID.toRfc4122());
nodeList->sendPacket(std::move(packet), *node);
++_identityRequestsSent;
}
}
);
}
void AvatarManager::simulateAvatarFades(float deltaTime) {

View file

@ -498,14 +498,14 @@ void MyAvatar::update(float deltaTime) {
// Get audio loudness data from audio input device
// Also get the AudioClient so we can update the avatar bounding box data
// on the AudioClient side.
auto audio = DependencyManager::get<AudioClient>();
auto audio = DependencyManager::get<AudioClient>().data();
setAudioLoudness(audio->getLastInputLoudness());
setAudioAverageLoudness(audio->getAudioAverageInputLoudness());
glm::vec3 halfBoundingBoxDimensions(_characterController.getCapsuleRadius(), _characterController.getCapsuleHalfHeight(), _characterController.getCapsuleRadius());
// This might not be right! Isn't the capsule local offset in avatar space? -HRS 5/26/17
halfBoundingBoxDimensions += _characterController.getCapsuleLocalOffset();
QMetaObject::invokeMethod(audio.data(), "setAvatarBoundingBoxParameters",
QMetaObject::invokeMethod(audio, "setAvatarBoundingBoxParameters",
Q_ARG(glm::vec3, (getWorldPosition() - halfBoundingBoxDimensions)),
Q_ARG(glm::vec3, (halfBoundingBoxDimensions*2.0f)));

View file

@ -352,8 +352,7 @@ bool QmlCommerce::openApp(const QString& itemHref) {
QJsonObject appFileJsonObject = appFileJsonDocument.object();
QString homeUrl = appFileJsonObject["homeURL"].toString();
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
auto tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"));
auto tablet = dynamic_cast<TabletProxy*>(DependencyManager::get<TabletScriptingInterface>()->getTablet("com.highfidelity.interface.tablet.system"));
if (homeUrl.contains(".qml", Qt::CaseInsensitive)) {
tablet->loadQMLSource(homeUrl);
} else if (homeUrl.contains(".html", Qt::CaseInsensitive)) {

View file

@ -328,7 +328,7 @@ Wallet::Wallet() {
packetReceiver.registerListener(PacketType::ChallengeOwnership, this, "handleChallengeOwnershipPacket");
packetReceiver.registerListener(PacketType::ChallengeOwnershipRequest, this, "handleChallengeOwnershipPacket");
connect(ledger.data(), &Ledger::accountResult, this, [&](QJsonObject result) {
connect(ledger.data(), &Ledger::accountResult, this, [](QJsonObject result) {
auto wallet = DependencyManager::get<Wallet>();
auto walletScriptingInterface = DependencyManager::get<WalletScriptingInterface>();
uint status;

View file

@ -60,23 +60,20 @@ Audio::Audio() : _devices(_contextIsHMD) {
}
bool Audio::startRecording(const QString& filepath) {
auto client = DependencyManager::get<AudioClient>().data();
return resultWithWriteLock<bool>([&] {
return client->startRecording(filepath);
return DependencyManager::get<AudioClient>()->startRecording(filepath);
});
}
bool Audio::getRecording() {
auto client = DependencyManager::get<AudioClient>().data();
return resultWithReadLock<bool>([&] {
return client->getRecording();
return DependencyManager::get<AudioClient>()->getRecording();
});
}
void Audio::stopRecording() {
auto client = DependencyManager::get<AudioClient>().data();
withWriteLock([&] {
client->stopRecording();
DependencyManager::get<AudioClient>()->stopRecording();
});
}

View file

@ -360,11 +360,11 @@ void AudioInputDeviceList::onPeakValueListChanged(const QList<float>& peakValueL
}
AudioDevices::AudioDevices(bool& contextIsHMD) : _contextIsHMD(contextIsHMD) {
auto client = DependencyManager::get<AudioClient>();
auto client = DependencyManager::get<AudioClient>().data();
connect(client.data(), &AudioClient::deviceChanged, this, &AudioDevices::onDeviceChanged, Qt::QueuedConnection);
connect(client.data(), &AudioClient::devicesChanged, this, &AudioDevices::onDevicesChanged, Qt::QueuedConnection);
connect(client.data(), &AudioClient::peakValueListChanged, &_inputs, &AudioInputDeviceList::onPeakValueListChanged, Qt::QueuedConnection);
connect(client, &AudioClient::deviceChanged, this, &AudioDevices::onDeviceChanged, Qt::QueuedConnection);
connect(client, &AudioClient::devicesChanged, this, &AudioDevices::onDevicesChanged, Qt::QueuedConnection);
connect(client, &AudioClient::peakValueListChanged, &_inputs, &AudioInputDeviceList::onPeakValueListChanged, Qt::QueuedConnection);
_inputs.onDeviceChanged(client->getActiveAudioDevice(QAudio::AudioInput), contextIsHMD);
_outputs.onDeviceChanged(client->getActiveAudioDevice(QAudio::AudioOutput), contextIsHMD);
@ -446,7 +446,7 @@ void AudioDevices::onDevicesChanged(QAudio::Mode mode, const QList<QAudioDeviceI
static std::once_flag once;
std::call_once(once, [&] {
//readout settings
auto client = DependencyManager::get<AudioClient>();
auto client = DependencyManager::get<AudioClient>().data();
_inputs._hmdSavedDeviceName = getTargetDevice(true, QAudio::AudioInput);
_inputs._desktopSavedDeviceName = getTargetDevice(false, QAudio::AudioInput);
@ -494,9 +494,9 @@ void AudioDevices::onDevicesChanged(QAudio::Mode mode, const QList<QAudioDeviceI
void AudioDevices::chooseInputDevice(const QAudioDeviceInfo& device, bool isHMD) {
//check if current context equals device to change
if (_contextIsHMD == isHMD) {
auto client = DependencyManager::get<AudioClient>();
auto client = DependencyManager::get<AudioClient>().data();
_requestedInputDevice = device;
QMetaObject::invokeMethod(client.data(), "switchAudioDevice",
QMetaObject::invokeMethod(client, "switchAudioDevice",
Q_ARG(QAudio::Mode, QAudio::AudioInput),
Q_ARG(const QAudioDeviceInfo&, device));
} else {
@ -511,9 +511,9 @@ void AudioDevices::chooseInputDevice(const QAudioDeviceInfo& device, bool isHMD)
void AudioDevices::chooseOutputDevice(const QAudioDeviceInfo& device, bool isHMD) {
//check if current context equals device to change
if (_contextIsHMD == isHMD) {
auto client = DependencyManager::get<AudioClient>();
auto client = DependencyManager::get<AudioClient>().data();
_requestedOutputDevice = device;
QMetaObject::invokeMethod(client.data(), "switchAudioDevice",
QMetaObject::invokeMethod(client, "switchAudioDevice",
Q_ARG(QAudio::Mode, QAudio::AudioOutput),
Q_ARG(const QAudioDeviceInfo&, device));
} else {

View file

@ -312,7 +312,7 @@ JSConsole::~JSConsole() {
delete _ui;
}
void JSConsole::setScriptEngine(const ScriptEnginePointer& scriptEngine) {
void JSConsole::setScriptEngine(const ScriptEnginePointer& scriptEngine) {
if (_scriptEngine == scriptEngine && scriptEngine != nullptr) {
return;
}

View file

@ -162,9 +162,7 @@ void LoginDialog::createAccountFromStream(QString username) {
}
void LoginDialog::openUrl(const QString& url) const {
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
auto tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"));
auto tablet = dynamic_cast<TabletProxy*>(DependencyManager::get<TabletScriptingInterface>()->getTablet("com.highfidelity.interface.tablet.system"));
auto hmd = DependencyManager::get<HMDScriptingInterface>();
auto offscreenUi = DependencyManager::get<OffscreenUi>();

View file

@ -27,28 +27,27 @@
void setupPreferences() {
auto preferences = DependencyManager::get<Preferences>();
auto nodeList = DependencyManager::get<NodeList>();
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
static const QString AVATAR_BASICS { "Avatar Basics" };
{
auto getter = [=]()->QString { return myAvatar->getDisplayName(); };
auto setter = [=](const QString& value) { myAvatar->setDisplayName(value); };
auto getter = [myAvatar]()->QString { return myAvatar->getDisplayName(); };
auto setter = [myAvatar](const QString& value) { myAvatar->setDisplayName(value); };
auto preference = new EditPreference(AVATAR_BASICS, "Avatar display name (optional)", getter, setter);
preference->setPlaceholderText("Not showing a name");
preferences->addPreference(preference);
}
{
auto getter = [=]()->QString { return myAvatar->getCollisionSoundURL(); };
auto setter = [=](const QString& value) { myAvatar->setCollisionSoundURL(value); };
auto getter = [myAvatar]()->QString { return myAvatar->getCollisionSoundURL(); };
auto setter = [myAvatar](const QString& value) { myAvatar->setCollisionSoundURL(value); };
auto preference = new EditPreference(AVATAR_BASICS, "Avatar collision sound URL (optional)", getter, setter);
preference->setPlaceholderText("Enter the URL of a sound to play when you bump into something");
preferences->addPreference(preference);
}
{
auto getter = [=]()->QString { return myAvatar->getFullAvatarURLFromPreferences().toString(); };
auto setter = [=](const QString& value) { myAvatar->useFullAvatarURL(value, ""); qApp->clearAvatarOverrideUrl(); };
auto getter = [myAvatar]()->QString { return myAvatar->getFullAvatarURLFromPreferences().toString(); };
auto setter = [myAvatar](const QString& value) { myAvatar->useFullAvatarURL(value, ""); qApp->clearAvatarOverrideUrl(); };
auto preference = new AvatarPreference(AVATAR_BASICS, "Appearance", getter, setter);
preferences->addPreference(preference);
}
@ -163,8 +162,8 @@ void setupPreferences() {
static const QString VIEW_CATEGORY{ "View" };
{
auto getter = [=]()->float { return myAvatar->getRealWorldFieldOfView(); };
auto setter = [=](float value) { myAvatar->setRealWorldFieldOfView(value); };
auto getter = [myAvatar]()->float { return myAvatar->getRealWorldFieldOfView(); };
auto setter = [myAvatar](float value) { myAvatar->setRealWorldFieldOfView(value); };
auto preference = new SpinnerPreference(VIEW_CATEGORY, "Real world vertical field of view (angular size of monitor)", getter, setter);
preference->setMin(1);
preference->setMax(180);
@ -219,13 +218,13 @@ void setupPreferences() {
static const QString AVATAR_TUNING { "Avatar Tuning" };
{
auto getter = [=]()->QString { return myAvatar->getDominantHand(); };
auto setter = [=](const QString& value) { myAvatar->setDominantHand(value); };
auto getter = [myAvatar]()->QString { return myAvatar->getDominantHand(); };
auto setter = [myAvatar](const QString& value) { myAvatar->setDominantHand(value); };
preferences->addPreference(new PrimaryHandPreference(AVATAR_TUNING, "Dominant Hand", getter, setter));
}
{
auto getter = [=]()->float { return myAvatar->getTargetScale(); };
auto setter = [=](float value) { myAvatar->setTargetScale(value); };
auto getter = [myAvatar]()->float { return myAvatar->getTargetScale(); };
auto setter = [myAvatar](float value) { myAvatar->setTargetScale(value); };
auto preference = new SpinnerSliderPreference(AVATAR_TUNING, "Avatar Scale", getter, setter);
preference->setMin(0.25);
preference->setMax(4);
@ -240,16 +239,16 @@ void setupPreferences() {
}
{
auto getter = [=]()->QString { return myAvatar->getAnimGraphOverrideUrl().toString(); };
auto setter = [=](const QString& value) { myAvatar->setAnimGraphOverrideUrl(QUrl(value)); };
auto getter = [myAvatar]()->QString { return myAvatar->getAnimGraphOverrideUrl().toString(); };
auto setter = [myAvatar](const QString& value) { myAvatar->setAnimGraphOverrideUrl(QUrl(value)); };
auto preference = new EditPreference(AVATAR_TUNING, "Avatar animation JSON", getter, setter);
preference->setPlaceholderText("default");
preferences->addPreference(preference);
}
{
auto getter = [=]()->bool { return myAvatar->getCollisionsEnabled(); };
auto setter = [=](bool value) { myAvatar->setCollisionsEnabled(value); };
auto getter = [myAvatar]()->bool { return myAvatar->getCollisionsEnabled(); };
auto setter = [myAvatar](bool value) { myAvatar->setCollisionsEnabled(value); };
auto preference = new CheckPreference(AVATAR_TUNING, "Enable Avatar collisions", getter, setter);
preferences->addPreference(preference);
}
@ -270,20 +269,20 @@ void setupPreferences() {
{
static const QString movementsControlChannel = QStringLiteral("Hifi-Advanced-Movement-Disabler");
auto getter = [=]()->bool { return myAvatar->useAdvancedMovementControls(); };
auto setter = [=](bool value) { myAvatar->setUseAdvancedMovementControls(value); };
auto getter = [myAvatar]()->bool { return myAvatar->useAdvancedMovementControls(); };
auto setter = [myAvatar](bool value) { myAvatar->setUseAdvancedMovementControls(value); };
preferences->addPreference(new CheckPreference(VR_MOVEMENT,
QStringLiteral("Advanced movement for hand controllers"),
getter, setter));
}
{
auto getter = [=]()->bool { return myAvatar->getFlyingHMDPref(); };
auto setter = [=](bool value) { myAvatar->setFlyingHMDPref(value); };
auto getter = [myAvatar]()->bool { return myAvatar->getFlyingHMDPref(); };
auto setter = [myAvatar](bool value) { myAvatar->setFlyingHMDPref(value); };
preferences->addPreference(new CheckPreference(VR_MOVEMENT, "Flying & jumping (HMD)", getter, setter));
}
{
auto getter = [=]()->int { return myAvatar->getSnapTurn() ? 0 : 1; };
auto setter = [=](int value) { myAvatar->setSnapTurn(value == 0); };
auto getter = [myAvatar]()->int { return myAvatar->getSnapTurn() ? 0 : 1; };
auto setter = [myAvatar](int value) { myAvatar->setSnapTurn(value == 0); };
auto preference = new RadioButtonsPreference(VR_MOVEMENT, "Snap turn / Smooth turn", getter, setter);
QStringList items;
items << "Snap turn" << "Smooth turn";
@ -309,8 +308,8 @@ void setupPreferences() {
static const QString AVATAR_CAMERA{ "Mouse Sensitivity" };
{
auto getter = [=]()->float { return myAvatar->getPitchSpeed(); };
auto setter = [=](float value) { myAvatar->setPitchSpeed(value); };
auto getter = [myAvatar]()->float { return myAvatar->getPitchSpeed(); };
auto setter = [myAvatar](float value) { myAvatar->setPitchSpeed(value); };
auto preference = new SpinnerSliderPreference(AVATAR_CAMERA, "Y input:", getter, setter);
preference->setMin(1.0f);
preference->setMax(360.0f);
@ -319,8 +318,8 @@ void setupPreferences() {
preferences->addPreference(preference);
}
{
auto getter = [=]()->float { return myAvatar->getYawSpeed(); };
auto setter = [=](float value) { myAvatar->setYawSpeed(value); };
auto getter = [myAvatar]()->float { return myAvatar->getYawSpeed(); };
auto setter = [myAvatar](float value) { myAvatar->setYawSpeed(value); };
auto preference = new SpinnerSliderPreference(AVATAR_CAMERA, "X input:", getter, setter);
preference->setMin(1.0f);
preference->setMax(360.0f);
@ -381,12 +380,24 @@ void setupPreferences() {
{
static const QString NETWORKING("Networking");
auto nodelist = DependencyManager::get<NodeList>();
QWeakPointer<NodeList> nodeListWeak = DependencyManager::get<NodeList>();
{
static const int MIN_PORT_NUMBER { 0 };
static const int MAX_PORT_NUMBER { 65535 };
auto getter = [nodelist] { return static_cast<int>(nodelist->getSocketLocalPort()); };
auto setter = [nodelist](int preset) { nodelist->setSocketLocalPort(static_cast<quint16>(preset)); };
auto getter = [nodeListWeak] {
auto nodeList = nodeListWeak.lock();
if (nodeList) {
return static_cast<int>(nodeList->getSocketLocalPort());
} else {
return -1;
}
};
auto setter = [nodeListWeak](int preset) {
auto nodeList = nodeListWeak.lock();
if (nodeList) {
nodeList->setSocketLocalPort(static_cast<quint16>(preset));
}
};
auto preference = new IntSpinnerPreference(NETWORKING, "Listening Port", getter, setter);
preference->setMin(MIN_PORT_NUMBER);
preference->setMax(MAX_PORT_NUMBER);

View file

@ -174,7 +174,7 @@ void Stats::updateStats(bool force) {
int octreeServerCount = 0;
int pingOctreeMax = 0;
int totalEntityKbps = 0;
nodeList->eachNode([&](const SharedNodePointer& node) {
nodeList->eachNode([&totalPingOctree, &totalEntityKbps, &octreeServerCount, &pingOctreeMax](const SharedNodePointer& node) {
// TODO: this should also support entities
if (node->getType() == NodeType::EntityServer) {
totalPingOctree += node->getPingMs();
@ -219,7 +219,7 @@ void Stats::updateStats(bool force) {
STAT_UPDATE_FLOAT(myAvatarSendRate, avatarManager->getMyAvatarSendRate(), 0.1f);
SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer);
auto audioClient = DependencyManager::get<AudioClient>();
auto audioClient = DependencyManager::get<AudioClient>().data();
if (audioMixerNode || force) {
STAT_UPDATE(audioMixerKbps, (int)roundf(
bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AudioMixer) +

View file

@ -23,8 +23,7 @@ TestingDialog::TestingDialog(QWidget* parent) :
_console->setFixedHeight(TESTING_CONSOLE_HEIGHT);
auto _engines = DependencyManager::get<ScriptEngines>();
_engine = _engines->loadScript(qApp->applicationDirPath() + testRunnerRelativePath);
_engine = DependencyManager::get<ScriptEngines>()->loadScript(qApp->applicationDirPath() + testRunnerRelativePath);
_console->setScriptEngine(_engine);
connect(_engine.data(), &ScriptEngine::finished, this, &TestingDialog::onTestingFinished);
}

View file

@ -274,31 +274,14 @@ AudioClient::~AudioClient() {
}
void AudioClient::customDeleter() {
deleteLater();
}
void AudioClient::cleanupBeforeQuit() {
// FIXME: this should be put in customDeleter, but there is still a reference to this when it is called,
// so this must be explicitly, synchronously stopped
static ConditionalGuard guard;
if (QThread::currentThread() != thread()) {
// This will likely be called from the main thread, but we don't want to do blocking queued calls
// from the main thread, so we use a normal auto-connection invoke, and then use a conditional to wait
// for completion
// The effect is the same, yes, but we actually want to avoid the use of Qt::BlockingQueuedConnection
// in the code
QMetaObject::invokeMethod(this, "cleanupBeforeQuit");
guard.wait();
return;
}
#if defined(Q_OS_ANDROID)
_shouldRestartInputSetup = false;
#endif
stop();
_checkDevicesTimer->stop();
_checkPeakValuesTimer->stop();
guard.trigger();
deleteLater();
}
void AudioClient::handleMismatchAudioFormat(SharedNodePointer node, const QString& currentCodec, const QString& recievedCodec) {

View file

@ -171,7 +171,6 @@ public:
public slots:
void start();
void stop();
void cleanupBeforeQuit();
void handleAudioEnvironmentDataPacket(QSharedPointer<ReceivedMessage> message);
void handleAudioDataPacket(QSharedPointer<ReceivedMessage> message);

View file

@ -95,8 +95,6 @@ void AudioIOStats::processStreamStatsPacket(QSharedPointer<ReceivedMessage> mess
}
void AudioIOStats::publish() {
auto audioIO = DependencyManager::get<AudioClient>();
// call _receivedAudioStream's per-second callback
_receivedAudioStream->perSecondCallbackForUpdatingStats();

View file

@ -2069,7 +2069,7 @@ void AvatarData::sendIdentityPacket() {
auto packetList = NLPacketList::create(PacketType::AvatarIdentity, QByteArray(), true, true);
packetList->write(identityData);
nodeList->eachMatchingNode(
[&](const SharedNodePointer& node)->bool {
[](const SharedNodePointer& node)->bool {
return node->getType() == NodeType::AvatarMixer && node->getActiveSocket();
},
[&](const SharedNodePointer& node) {

View file

@ -1252,7 +1252,7 @@ bool EntityScriptingInterface::actionWorker(const QUuid& entityID,
EntityItemPointer entity;
bool doTransmit = false;
_entityTree->withWriteLock([&] {
_entityTree->withWriteLock([this, &entity, entityID, myNodeID, &doTransmit, actor, &properties] {
EntitySimulationPointer simulation = _entityTree->getSimulation();
entity = _entityTree->findEntityByEntityItemID(entityID);
if (!entity) {

View file

@ -1435,7 +1435,7 @@ void EntityTree::validatePop(const QString& certID, const EntityItemID& entityIt
QNetworkReply* networkReply = networkAccessManager.put(networkRequest, QJsonDocument(request).toJson());
connect(networkReply, &QNetworkReply::finished, [=]() {
connect(networkReply, &QNetworkReply::finished, [this, networkReply, entityItemID, certID, senderNode]() {
QJsonObject jsonObject = QJsonDocument::fromJson(networkReply->readAll()).object();
jsonObject = jsonObject["data"].toObject();

View file

@ -133,7 +133,7 @@ QUrl expandScriptUrl(const QUrl& rawScriptURL) {
QObject* scriptsModel();
bool NativeScriptInitializers::registerNativeScriptInitializer(NativeScriptInitializer initializer) {
return registerScriptInitializer([=](ScriptEnginePointer engine) {
return registerScriptInitializer([initializer](ScriptEnginePointer engine) {
initializer(qobject_cast<QScriptEngine*>(engine.data()));
});
}
@ -492,8 +492,7 @@ ScriptEnginePointer ScriptEngines::loadScript(const QUrl& scriptFilename, bool i
return scriptEngine;
}
scriptEngine = ScriptEnginePointer(new ScriptEngine(_context, NO_SCRIPT, "about:" + scriptFilename.fileName()));
addScriptEngine(scriptEngine);
scriptEngine = scriptEngineFactory(_context, NO_SCRIPT, "about:" + scriptFilename.fileName());
scriptEngine->setUserLoaded(isUserLoaded);
scriptEngine->setQuitWhenFinished(quitWhenFinished);
@ -564,10 +563,10 @@ int ScriptEngines::runScriptInitializers(ScriptEnginePointer scriptEngine) {
void ScriptEngines::launchScriptEngine(ScriptEnginePointer scriptEngine) {
connect(scriptEngine.data(), &ScriptEngine::finished, this, &ScriptEngines::onScriptFinished, Qt::DirectConnection);
connect(scriptEngine.data(), &ScriptEngine::loadScript, [&](const QString& scriptName, bool userLoaded) {
connect(scriptEngine.data(), &ScriptEngine::loadScript, [this](const QString& scriptName, bool userLoaded) {
loadScript(scriptName, userLoaded);
});
connect(scriptEngine.data(), &ScriptEngine::reloadScript, [&](const QString& scriptName, bool userLoaded) {
connect(scriptEngine.data(), &ScriptEngine::reloadScript, [this](const QString& scriptName, bool userLoaded) {
loadScript(scriptName, userLoaded, false, false, true);
});

View file

@ -139,7 +139,13 @@ QSharedPointer<T> DependencyManager::set(Args&&... args) {
template <typename T>
void DependencyManager::destroy() {
static size_t hashCode = manager().getHashCode<T>();
manager().safeGet(hashCode).clear();
QSharedPointer<Dependency>& shared = manager().safeGet(hashCode);
QWeakPointer<Dependency> weak = shared;
shared.clear();
// Check that the dependency was actually destroyed. If it wasn't, it was improperly captured somewhere
if (weak.lock()) {
qWarning() << "DependencyManager::destroy():" << typeid(T).name() << "was not properly destroyed!";
}
}
template<typename Base, typename Derived>

View file

@ -329,8 +329,7 @@ void OffscreenQmlSurface::onRootCreated() {
getSurfaceContext()->setContextProperty("offscreenWindow", QVariant::fromValue(getWindow()));
// Connect with the audio client and listen for audio device changes
auto audioIO = DependencyManager::get<AudioClient>();
connect(audioIO.data(), &AudioClient::deviceChanged, this, [&](QAudio::Mode mode, const QAudioDeviceInfo& device) {
connect(DependencyManager::get<AudioClient>().data(), &AudioClient::deviceChanged, this, [this](QAudio::Mode mode, const QAudioDeviceInfo& device) {
if (mode == QAudio::Mode::AudioOutput) {
QMetaObject::invokeMethod(this, "changeAudioOutputDevice", Qt::QueuedConnection, Q_ARG(QString, device.deviceName()));
}