/** Upgrade some of the MGMDs */ int runUpgrade_NotAllMGMD(NDBT_Context* ctx, NDBT_Step* step) { ctx->setProperty("MgmdNodeSet", (Uint32) NodeSet(NotAll)); ctx->setProperty("NdbdNodeSet", (Uint32) NodeSet(None)); int res = runUpgrade_Half(ctx, step); ctx->stopTest(); return res; }
NS_IMETHODIMP txNodeSetAdaptor::ItemAsString(PRUint32 aIndex, nsAString &aResult) { if (aIndex > (PRUint32)NodeSet()->size()) { return NS_ERROR_ILLEGAL_VALUE; } txXPathNodeUtils::appendNodeValue(NodeSet()->get(aIndex), aResult); return NS_OK; }
NS_IMETHODIMP txNodeSetAdaptor::Item(PRUint32 aIndex, nsIDOMNode **aResult) { *aResult = nullptr; if (aIndex > (PRUint32)NodeSet()->size()) { return NS_ERROR_ILLEGAL_VALUE; } return txXPathNativeNode::getNode(NodeSet()->get(aIndex), aResult); }
NS_IMETHODIMP txNodeSetAdaptor::ItemAsNumber(PRUint32 aIndex, double *aResult) { if (aIndex > (PRUint32)NodeSet()->size()) { return NS_ERROR_ILLEGAL_VALUE; } nsAutoString result; txXPathNodeUtils::appendNodeValue(NodeSet()->get(aIndex), result); *aResult = txDouble::toDouble(result); return NS_OK; }
NS_IMETHODIMP txNodeSetAdaptor::GetLength(PRUint32 *aLength) { *aLength = (PRUint32)NodeSet()->size(); return NS_OK; }
void MappingFunction3D::ideal( Sample location, MsqMatrix<3,3>& J, MsqError& err ) const { const Vector3D* coords = unit_element( element_topology(), true ); if (!coords) { MSQ_SETERR(err)(MsqError::UNSUPPORTED_ELEMENT); return; } const unsigned MAX_VERTS = 8; MsqVector<3> d_coeff_d_xi[MAX_VERTS]; size_t indices[MAX_VERTS], num_vtx = 0; derivatives( location, NodeSet(), indices, d_coeff_d_xi, num_vtx, err ); MSQ_ERRRTN(err); assert(num_vtx > 0 && num_vtx <= MAX_VERTS); J.zero(); for (size_t r = 0; r < num_vtx; ++r) { MsqMatrix<3,1> c( coords[indices[r]].to_array() ); J += c * transpose(d_coeff_d_xi[r]); } double size = Mesquite::cbrt(fabs(det(J))); assert(size > -1e-15); // no negative jacobians for ideal elements! divide( 1.0, size, size ); J *= size; }
NS_IMETHODIMP txNodeSetAdaptor::GetLength(uint32_t *aLength) { *aLength = (uint32_t)NodeSet()->size(); return NS_OK; }
NS_IMETHODIMP txNodeSetAdaptor::Add(nsIDOMNode *aNode) { NS_ENSURE_TRUE(mWritable, NS_ERROR_FAILURE); nsAutoPtr<txXPathNode> node(txXPathNativeNode::createXPathNode(aNode, true)); return node ? NodeSet()->add(*node) : NS_ERROR_OUT_OF_MEMORY; }
void Agent::run() { NodeList* nodeList = NodeList::getInstance(); nodeList->setOwnerType(NodeType::Agent); nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer); // figure out the URL for the script for this agent assignment QString scriptURLString("http://%1:8080/assignment/%2"); scriptURLString = scriptURLString.arg(NodeList::getInstance()->getDomainIP().toString(), uuidStringWithoutCurlyBraces(_uuid)); QNetworkAccessManager *networkManager = new QNetworkAccessManager(this); QNetworkReply *reply = networkManager->get(QNetworkRequest(QUrl(scriptURLString))); qDebug() << "Downloading script at" << scriptURLString; QEventLoop loop; QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); loop.exec(); QString scriptContents(reply->readAll()); qDebug() << "Downloaded script:" << scriptContents; timeval startTime; gettimeofday(&startTime, NULL); QTimer* domainServerTimer = new QTimer(this); connect(domainServerTimer, SIGNAL(timeout()), this, SLOT(checkInWithDomainServerOrExit())); domainServerTimer->start(DOMAIN_SERVER_CHECK_IN_USECS / 1000); QTimer* silentNodeTimer = new QTimer(this); connect(silentNodeTimer, SIGNAL(timeout()), nodeList, SLOT(removeSilentNodes())); silentNodeTimer->start(NODE_SILENCE_THRESHOLD_USECS / 1000); QTimer* pingNodesTimer = new QTimer(this); connect(pingNodesTimer, SIGNAL(timeout()), nodeList, SLOT(pingInactiveNodes())); pingNodesTimer->start(PING_INACTIVE_NODE_INTERVAL_USECS / 1000); // tell our script engine about our local particle tree _scriptEngine.getParticlesScriptingInterface()->setParticleTree(&_particleTree); // setup an Avatar for the script to use AvatarData scriptedAvatar; // give this AvatarData object to the script engine _scriptEngine.setAvatarData(&scriptedAvatar, "Avatar"); // register ourselves to the script engine _scriptEngine.registerGlobalObject("Agent", this); _scriptEngine.setScriptContents(scriptContents); _scriptEngine.run(); }
NodeSet Node::FindByXPath(const string &xpath, const NamespaceMap &namespaces) const { XPathEvaluator eval(xpath, Document()); eval.RegisterNamespaces(namespaces); XPathEvaluator::ObjectType type = XPathEvaluator::ObjectType::Undefined; if ( eval.Evaluate(shared_from_this(), &type) && type == XPathEvaluator::ObjectType::NodeSet ) return eval.NodeSetResult(); return NodeSet(); }
//! perform a query for a path and return the query result NodeSet query_raw(std::string const& xpath_query_str) const { try { return xml.select_nodes(xpath_query_str.c_str()); } catch (const pugi::xpath_exception& e) { std::cerr << "Exception caught in XmlReader::query -> " << e.what() << std::endl; throw XmlQueryException("Exception in XmlReader::query -> " + std::string(e.what())); return NodeSet(); } }
void Agent::run() { ThreadedAssignment::commonInit(AGENT_LOGGING_NAME, NodeType::Agent); auto nodeList = DependencyManager::get<NodeList>(); nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer << NodeType::EntityServer ); _pingTimer = new QTimer(this); connect(_pingTimer, SIGNAL(timeout()), SLOT(sendPingRequests())); _pingTimer->start(PING_INTERVAL); // figure out the URL for the script for this agent assignment QUrl scriptURL; if (_payload.isEmpty()) { scriptURL = QUrl(QString("http://%1:%2/assignment/%3") .arg(DependencyManager::get<NodeList>()->getDomainHandler().getIP().toString()) .arg(DOMAIN_SERVER_HTTP_PORT) .arg(uuidStringWithoutCurlyBraces(_uuid))); } else { scriptURL = QUrl(_payload); } QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); QNetworkRequest networkRequest = QNetworkRequest(scriptURL); networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); QNetworkReply* reply = networkAccessManager.get(networkRequest); QNetworkDiskCache* cache = new QNetworkDiskCache(); QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation); cache->setCacheDirectory(!cachePath.isEmpty() ? cachePath : "agentCache"); networkAccessManager.setCache(cache); qDebug() << "Downloading script at" << scriptURL.toString(); QEventLoop loop; QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); loop.exec(); QString scriptContents(reply->readAll()); delete reply; qDebug() << "Downloaded script:" << scriptContents; // setup an Avatar for the script to use ScriptableAvatar scriptedAvatar(&_scriptEngine); scriptedAvatar.setForceFaceTrackerConnected(true); // call model URL setters with empty URLs so our avatar, if user, will have the default models scriptedAvatar.setFaceModelURL(QUrl()); scriptedAvatar.setSkeletonModelURL(QUrl()); // give this AvatarData object to the script engine _scriptEngine.setAvatarData(&scriptedAvatar, "Avatar"); auto avatarHashMap = DependencyManager::set<AvatarHashMap>(); _scriptEngine.setAvatarHashMap(avatarHashMap.data(), "AvatarList"); auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver(); packetReceiver.registerListener(PacketType::BulkAvatarData, avatarHashMap.data(), "processAvatarDataPacket"); packetReceiver.registerListener(PacketType::KillAvatar, avatarHashMap.data(), "processKillAvatar"); packetReceiver.registerListener(PacketType::AvatarIdentity, avatarHashMap.data(), "processAvatarIdentityPacket"); packetReceiver.registerListener(PacketType::AvatarBillboard, avatarHashMap.data(), "processAvatarBillboardPacket"); // register ourselves to the script engine _scriptEngine.registerGlobalObject("Agent", this); if (!_payload.isEmpty()) { _scriptEngine.setParentURL(_payload); } _scriptEngine.init(); // must be done before we set up the viewers _scriptEngine.registerGlobalObject("SoundCache", DependencyManager::get<SoundCache>().data()); QScriptValue webSocketServerConstructorValue = _scriptEngine.newFunction(WebSocketServerClass::constructor); _scriptEngine.globalObject().setProperty("WebSocketServer", webSocketServerConstructorValue); auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>(); _scriptEngine.registerGlobalObject("EntityViewer", &_entityViewer); _entityViewer.setJurisdictionListener(entityScriptingInterface->getJurisdictionListener()); _entityViewer.init(); entityScriptingInterface->setEntityTree(_entityViewer.getTree()); _scriptEngine.setScriptContents(scriptContents); _scriptEngine.run(); setFinished(true); }
ATPClientApp::ATPClientApp(int argc, char* argv[]) : QCoreApplication(argc, argv) { // parse command-line QCommandLineParser parser; parser.setApplicationDescription("High Fidelity ATP-Client"); const QCommandLineOption helpOption = parser.addHelpOption(); const QCommandLineOption verboseOutput("v", "verbose output"); parser.addOption(verboseOutput); const QCommandLineOption uploadOption("T", "upload local file", "local-file-to-send"); parser.addOption(uploadOption); const QCommandLineOption authOption("u", "set usename and pass", "username:password"); parser.addOption(authOption); const QCommandLineOption outputFilenameOption("o", "output filename", "output-file-name"); parser.addOption(outputFilenameOption); const QCommandLineOption domainAddressOption("d", "domain-server address", "127.0.0.1"); parser.addOption(domainAddressOption); const QCommandLineOption listenPortOption("listenPort", "listen port", QString::number(INVALID_PORT)); parser.addOption(listenPortOption); if (!parser.parse(QCoreApplication::arguments())) { qCritical() << parser.errorText() << endl; parser.showHelp(); Q_UNREACHABLE(); } if (parser.isSet(helpOption)) { parser.showHelp(); Q_UNREACHABLE(); } _verbose = parser.isSet(verboseOutput); if (!_verbose) { QLoggingCategory::setFilterRules("qt.network.ssl.warning=false"); const_cast<QLoggingCategory*>(&networking())->setEnabled(QtDebugMsg, false); const_cast<QLoggingCategory*>(&networking())->setEnabled(QtInfoMsg, false); const_cast<QLoggingCategory*>(&networking())->setEnabled(QtWarningMsg, false); const_cast<QLoggingCategory*>(&shared())->setEnabled(QtDebugMsg, false); const_cast<QLoggingCategory*>(&shared())->setEnabled(QtInfoMsg, false); const_cast<QLoggingCategory*>(&shared())->setEnabled(QtWarningMsg, false); } QStringList posArgs = parser.positionalArguments(); if (posArgs.size() != 1) { qDebug() << "give remote url argument"; parser.showHelp(); Q_UNREACHABLE(); } _url = QUrl(posArgs[0]); if (_url.scheme() != "atp") { qDebug() << "url should start with atp:"; parser.showHelp(); Q_UNREACHABLE(); } int domainPort = 40103; if (_url.port() != -1) { domainPort = _url.port(); } if (parser.isSet(outputFilenameOption)) { _localOutputFile = parser.value(outputFilenameOption); } if (parser.isSet(uploadOption)) { _localUploadFile = parser.value(uploadOption); } if (parser.isSet(authOption)) { QStringList pieces = parser.value(authOption).split(":"); if (pieces.size() != 2) { qDebug() << "-u should be followed by username:password"; parser.showHelp(); Q_UNREACHABLE(); } _username = pieces[0]; _password = pieces[1]; _waitingForLogin = true; } if (parser.isSet(listenPortOption)) { _listenPort = parser.value(listenPortOption).toInt(); } _domainServerAddress = QString("127.0.0.1") + ":" + QString::number(domainPort); if (parser.isSet(domainAddressOption)) { _domainServerAddress = parser.value(domainAddressOption); } else if (!_url.host().isEmpty()) { QUrl domainURL; domainURL.setScheme("hifi"); domainURL.setHost(_url.host()); _domainServerAddress = domainURL.toString(); } DependencyManager::registerInheritance<LimitedNodeList, NodeList>(); DependencyManager::set<StatTracker>(); DependencyManager::set<AccountManager>([&]{ return QString(HIGH_FIDELITY_ATP_CLIENT_USER_AGENT); }); DependencyManager::set<AddressManager>(); DependencyManager::set<NodeList>(NodeType::Agent, _listenPort); auto accountManager = DependencyManager::get<AccountManager>(); accountManager->setIsAgent(true); accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL()); auto nodeList = DependencyManager::get<NodeList>(); // setup a timer for domain-server check ins _domainCheckInTimer = new QTimer(nodeList.data()); connect(_domainCheckInTimer, &QTimer::timeout, nodeList.data(), &NodeList::sendDomainServerCheckIn); _domainCheckInTimer->start(DOMAIN_SERVER_CHECK_IN_MSECS); // start the nodeThread so its event loop is running // (must happen after the checkin timer is created with the nodelist as it's parent) nodeList->startThread(); const DomainHandler& domainHandler = nodeList->getDomainHandler(); connect(&domainHandler, SIGNAL(hostnameChanged(const QString&)), SLOT(domainChanged(const QString&))); connect(&domainHandler, &DomainHandler::domainConnectionRefused, this, &ATPClientApp::domainConnectionRefused); connect(nodeList.data(), &NodeList::nodeAdded, this, &ATPClientApp::nodeAdded); connect(nodeList.data(), &NodeList::nodeKilled, this, &ATPClientApp::nodeKilled); connect(nodeList.data(), &NodeList::nodeActivated, this, &ATPClientApp::nodeActivated); connect(nodeList.data(), &NodeList::packetVersionMismatch, this, &ATPClientApp::notifyPacketVersionMismatch); nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer << NodeType::EntityServer << NodeType::AssetServer << NodeType::MessagesMixer); if (_verbose) { QString username = accountManager->getAccountInfo().getUsername(); qDebug() << "cached username is" << username << ", isLoggedIn =" << accountManager->isLoggedIn(); } if (!_username.isEmpty()) { connect(accountManager.data(), &AccountManager::newKeypair, this, [&](){ if (_verbose) { qDebug() << "new keypair has been created."; } }); connect(accountManager.data(), &AccountManager::loginComplete, this, [&](){ if (_verbose) { qDebug() << "login successful"; } _waitingForLogin = false; go(); }); connect(accountManager.data(), &AccountManager::loginFailed, this, [&](){ qDebug() << "login failed."; _waitingForLogin = false; go(); }); accountManager->requestAccessToken(_username, _password); } auto assetClient = DependencyManager::set<AssetClient>(); assetClient->init(); if (_verbose) { qDebug() << "domain-server address is" << _domainServerAddress; } DependencyManager::get<AddressManager>()->handleLookupString(_domainServerAddress, false); QTimer* _timeoutTimer = new QTimer(this); _timeoutTimer->setSingleShot(true); connect(_timeoutTimer, &QTimer::timeout, this, &ATPClientApp::timedOut); _timeoutTimer->start(TIMEOUT_MILLISECONDS); }
Node TarjanHD::hd(const Digraph& g, const DoubleArcMap& w, SubDigraph& subG, NodeNodeMap& mapToOrgG, NodeNodeMap& G2T, const ArcList& sortedArcs, int i) { assert(i >= 0); int m = static_cast<int>(sortedArcs.size()); assert(m == lemon::countArcs(subG)); int r = m - i; if (r == 0 || r == 1) { // add to _T a subtree rooted at node r, // labeled with w(e_m) and having n children labeled with // the vertices of subG Node root = _T.addNode(); _label[root] = w[sortedArcs.back()]; _T2OrgG[root] = lemon::INVALID; for (SubNodeIt v(subG); v != lemon::INVALID; ++v) { Node vv = G2T[v]; if (vv == lemon::INVALID) { vv = _T.addNode(); _label[vv] = -1; if (mapToOrgG[v] != lemon::INVALID) { _orgG2T[mapToOrgG[v]] = vv; _T2OrgG[vv] = mapToOrgG[v]; } } _T.addArc(vv, root); } return root; } else { int j = (i + m) % 2 == 0 ? (i + m) / 2 : (i + m) / 2 + 1; // remove arcs j+1 .. m ArcListIt arcEndIt, arcIt = sortedArcs.begin(); for (int k = 1; k <= m; ++k) { if (k == j + 1) { arcEndIt = arcIt; } if (k > j) { subG.disable(*arcIt); } ++arcIt; } // compute SCCs IntNodeMap comp(g, -1); int numSCC = lemon::stronglyConnectedComponents(subG, comp); if (numSCC == 1) { ArcList newSortedArcs(sortedArcs.begin(), arcEndIt); // _subG is strongly connected return hd(g, w, subG, mapToOrgG, G2T, newSortedArcs, i); } else { // determine strongly connected components NodeHasher<Digraph> hasher(g); NodeSetVector components(numSCC, NodeSet(42, hasher)); for (SubNodeIt v(subG); v != lemon::INVALID; ++v) { components[comp[v]].insert(v); } NodeVector roots(numSCC, lemon::INVALID); double w_i = i > 0 ? w[getArcByRank(sortedArcs, i)] : -std::numeric_limits<double>::max(); for (int k = 0; k < numSCC; ++k) { const NodeSet& component = components[k]; if (component.size() > 1) { // construct new sorted arc list for component: O(m) time ArcList newSortedArcs; for (ArcListIt arcIt = sortedArcs.begin(); arcIt != arcEndIt; ++arcIt) { Node u = g.source(*arcIt); Node v = g.target(*arcIt); bool u_in_comp = component.find(u) != component.end(); bool v_in_comp = component.find(v) != component.end(); if (u_in_comp && v_in_comp) { newSortedArcs.push_back(*arcIt); } } // remove nodes not in component from the graph for (NodeIt v(g); v != lemon::INVALID; ++v) { subG.status(v, component.find(v) != component.end()); } // find new_i, i.e. largest k such that w(e'_k) <= w(e_i) // if i == 0 or i > 0 but no such k exists => new_i := 0 int new_i = get_i(newSortedArcs, w, w_i); // recurse on strongly connected component roots[k] = hd(g, w, subG, mapToOrgG, G2T, newSortedArcs, new_i); } // enable all nodes again for (int k = 0; k < numSCC; ++k) { const NodeSet& component = components[k]; for (NodeSetIt nodeIt = component.begin(); nodeIt != component.end(); ++nodeIt) { subG.enable(*nodeIt); } } } // construct the condensed graph: // each strongly connected component is collapsed into a single node, and // from the resulting sets of multiple arcs retain only those with minimum weight Digraph c; DoubleArcMap ww(c); NodeNodeMap mapCToOrgG(c); NodeNodeMap C2T(c); ArcList newSortedArcs; int new_i = constructCondensedGraph(g, w, mapToOrgG, G2T, sortedArcs, comp, components, roots, j, c, ww, mapCToOrgG, C2T, newSortedArcs); BoolArcMap newArcFilter(c, true); BoolNodeMap newNodeFilter(c, true); SubDigraph subC(c, newNodeFilter, newArcFilter); Node root = hd(c, ww, subC, mapCToOrgG, C2T, newSortedArcs, new_i); return root; } } return lemon::INVALID; }
void ScriptEngine::run() { if (!_isInitialized) { init(); } _isRunning = true; emit runningStateChanged(); QScriptValue result = _engine.evaluate(_scriptContents); if (_engine.hasUncaughtException()) { int line = _engine.uncaughtExceptionLineNumber(); qDebug() << "Uncaught exception at line" << line << ":" << result.toString(); emit errorMessage("Uncaught exception at line" + QString::number(line) + ":" + result.toString()); } QElapsedTimer startTime; startTime.start(); int thisFrame = 0; NodeList* nodeList = NodeList::getInstance(); qint64 lastUpdate = usecTimestampNow(); while (!_isFinished) { int usecToSleep = (thisFrame++ * SCRIPT_DATA_CALLBACK_USECS) - startTime.nsecsElapsed() / 1000; // nsec to usec if (usecToSleep > 0) { usleep(usecToSleep); } if (_isFinished) { break; } QCoreApplication::processEvents(); if (_isFinished) { break; } if (_voxelsScriptingInterface.getVoxelPacketSender()->serversExist()) { // release the queue of edit voxel messages. _voxelsScriptingInterface.getVoxelPacketSender()->releaseQueuedMessages(); // since we're in non-threaded mode, call process so that the packets are sent if (!_voxelsScriptingInterface.getVoxelPacketSender()->isThreaded()) { _voxelsScriptingInterface.getVoxelPacketSender()->process(); } } if (_particlesScriptingInterface.getParticlePacketSender()->serversExist()) { // release the queue of edit voxel messages. _particlesScriptingInterface.getParticlePacketSender()->releaseQueuedMessages(); // since we're in non-threaded mode, call process so that the packets are sent if (!_particlesScriptingInterface.getParticlePacketSender()->isThreaded()) { _particlesScriptingInterface.getParticlePacketSender()->process(); } } if (_modelsScriptingInterface.getModelPacketSender()->serversExist()) { // release the queue of edit voxel messages. _modelsScriptingInterface.getModelPacketSender()->releaseQueuedMessages(); // since we're in non-threaded mode, call process so that the packets are sent if (!_modelsScriptingInterface.getModelPacketSender()->isThreaded()) { _modelsScriptingInterface.getModelPacketSender()->process(); } } if (_isAvatar && _avatarData) { const int SCRIPT_AUDIO_BUFFER_SAMPLES = floor(((SCRIPT_DATA_CALLBACK_USECS * SAMPLE_RATE) / (1000 * 1000)) + 0.5); const int SCRIPT_AUDIO_BUFFER_BYTES = SCRIPT_AUDIO_BUFFER_SAMPLES * sizeof(int16_t); QByteArray avatarPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarData); avatarPacket.append(_avatarData->toByteArray()); nodeList->broadcastToNodes(avatarPacket, NodeSet() << NodeType::AvatarMixer); if (_isListeningToAudioStream || _avatarSound) { // if we have an avatar audio stream then send it out to our audio-mixer bool silentFrame = true; int16_t numAvailableSamples = SCRIPT_AUDIO_BUFFER_SAMPLES; const int16_t* nextSoundOutput = NULL; if (_avatarSound) { const QByteArray& soundByteArray = _avatarSound->getByteArray(); nextSoundOutput = reinterpret_cast<const int16_t*>(soundByteArray.data() + _numAvatarSoundSentBytes); int numAvailableBytes = (soundByteArray.size() - _numAvatarSoundSentBytes) > SCRIPT_AUDIO_BUFFER_BYTES ? SCRIPT_AUDIO_BUFFER_BYTES : soundByteArray.size() - _numAvatarSoundSentBytes; numAvailableSamples = numAvailableBytes / sizeof(int16_t); // check if the all of the _numAvatarAudioBufferSamples to be sent are silence for (int i = 0; i < numAvailableSamples; ++i) { if (nextSoundOutput[i] != 0) { silentFrame = false; break; } } _numAvatarSoundSentBytes += numAvailableBytes; if (_numAvatarSoundSentBytes == soundByteArray.size()) { // we're done with this sound object - so set our pointer back to NULL // and our sent bytes back to zero _avatarSound = NULL; _numAvatarSoundSentBytes = 0; } } QByteArray audioPacket = byteArrayWithPopulatedHeader(silentFrame ? PacketTypeSilentAudioFrame : PacketTypeMicrophoneAudioNoEcho); QDataStream packetStream(&audioPacket, QIODevice::Append); // use the orientation and position of this avatar for the source of this audio packetStream.writeRawData(reinterpret_cast<const char*>(&_avatarData->getPosition()), sizeof(glm::vec3)); glm::quat headOrientation = _avatarData->getHeadOrientation(); packetStream.writeRawData(reinterpret_cast<const char*>(&headOrientation), sizeof(glm::quat)); if (silentFrame) { if (!_isListeningToAudioStream) { // if we have a silent frame and we're not listening then just send nothing and break out of here break; } // write the number of silent samples so the audio-mixer can uphold timing packetStream.writeRawData(reinterpret_cast<const char*>(&SCRIPT_AUDIO_BUFFER_SAMPLES), sizeof(int16_t)); } else if (nextSoundOutput) { // write the raw audio data packetStream.writeRawData(reinterpret_cast<const char*>(nextSoundOutput), numAvailableSamples * sizeof(int16_t)); } nodeList->broadcastToNodes(audioPacket, NodeSet() << NodeType::AudioMixer); } } qint64 now = usecTimestampNow(); float deltaTime = (float) (now - lastUpdate) / (float) USECS_PER_SECOND; emit update(deltaTime); lastUpdate = now; if (_engine.hasUncaughtException()) { int line = _engine.uncaughtExceptionLineNumber(); qDebug() << "Uncaught exception at line" << line << ":" << _engine.uncaughtException().toString(); emit errorMessage("Uncaught exception at line" + QString::number(line) + ":" + _engine.uncaughtException().toString()); } } emit scriptEnding(); // kill the avatar identity timer delete _avatarIdentityTimer; if (_voxelsScriptingInterface.getVoxelPacketSender()->serversExist()) { // release the queue of edit voxel messages. _voxelsScriptingInterface.getVoxelPacketSender()->releaseQueuedMessages(); // since we're in non-threaded mode, call process so that the packets are sent if (!_voxelsScriptingInterface.getVoxelPacketSender()->isThreaded()) { _voxelsScriptingInterface.getVoxelPacketSender()->process(); } } if (_particlesScriptingInterface.getParticlePacketSender()->serversExist()) { // release the queue of edit voxel messages. _particlesScriptingInterface.getParticlePacketSender()->releaseQueuedMessages(); // since we're in non-threaded mode, call process so that the packets are sent if (!_particlesScriptingInterface.getParticlePacketSender()->isThreaded()) { _particlesScriptingInterface.getParticlePacketSender()->process(); } } if (_modelsScriptingInterface.getModelPacketSender()->serversExist()) { // release the queue of edit voxel messages. _modelsScriptingInterface.getModelPacketSender()->releaseQueuedMessages(); // since we're in non-threaded mode, call process so that the packets are sent if (!_modelsScriptingInterface.getModelPacketSender()->isThreaded()) { _modelsScriptingInterface.getModelPacketSender()->process(); } } // If we were on a thread, then wait till it's done if (thread()) { thread()->quit(); } emit finished(_fileNameString); _isRunning = false; emit runningStateChanged(); }
_pendingAssignedNodes.emplace(std::piecewise_construct, std::forward_as_tuple(nodeUUID), std::forward_as_tuple(assignmentUUID, walletUUID, nodeVersion)); } QUuid DomainGatekeeper::assignmentUUIDForPendingAssignment(const QUuid& tempUUID) { auto it = _pendingAssignedNodes.find(tempUUID); if (it != _pendingAssignedNodes.end()) { return it->second.getAssignmentUUID(); } else { return QUuid(); } } const NodeSet STATICALLY_ASSIGNED_NODES = NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer << NodeType::EntityServer << NodeType::AssetServer << NodeType::MessagesMixer; void DomainGatekeeper::processConnectRequestPacket(QSharedPointer<ReceivedMessage> message) { if (message->getSize() == 0) { return; } QDataStream packetStream(message->getMessage()); // read a NodeConnectionData object from the packet so we can pass around this data while we're inspecting it NodeConnectionData nodeConnection = NodeConnectionData::fromDataStream(packetStream, message->getSenderSockAddr()); if (nodeConnection.localSockAddr.isNull() || nodeConnection.publicSockAddr.isNull()) {
void Agent::run() { ThreadedAssignment::commonInit(AGENT_LOGGING_NAME, NodeType::Agent); NodeList* nodeList = NodeList::getInstance(); nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer << NodeType::VoxelServer << NodeType::ParticleServer << NodeType::ModelServer ); // figure out the URL for the script for this agent assignment QUrl scriptURL; if (_payload.isEmpty()) { scriptURL = QUrl(QString("http://%1:%2/assignment/%3") .arg(NodeList::getInstance()->getDomainHandler().getIP().toString()) .arg(DOMAIN_SERVER_HTTP_PORT) .arg(uuidStringWithoutCurlyBraces(_uuid))); } else { scriptURL = QUrl(_payload); } NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); QNetworkReply *reply = networkAccessManager.get(QNetworkRequest(scriptURL)); QNetworkDiskCache* cache = new QNetworkDiskCache(); QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation); cache->setCacheDirectory(!cachePath.isEmpty() ? cachePath : "agentCache"); networkAccessManager.setCache(cache); qDebug() << "Downloading script at" << scriptURL.toString(); QEventLoop loop; QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); loop.exec(); QString scriptContents(reply->readAll()); qDebug() << "Downloaded script:" << scriptContents; // setup an Avatar for the script to use ScriptableAvatar scriptedAvatar(&_scriptEngine); scriptedAvatar.setForceFaceshiftConnected(true); // call model URL setters with empty URLs so our avatar, if user, will have the default models scriptedAvatar.setFaceModelURL(QUrl()); scriptedAvatar.setSkeletonModelURL(QUrl()); // give this AvatarData object to the script engine _scriptEngine.setAvatarData(&scriptedAvatar, "Avatar"); _scriptEngine.setAvatarHashMap(&_avatarHashMap, "AvatarList"); // register ourselves to the script engine _scriptEngine.registerGlobalObject("Agent", this); _scriptEngine.init(); // must be done before we set up the viewers _scriptEngine.registerGlobalObject("VoxelViewer", &_voxelViewer); // connect the VoxelViewer and the VoxelScriptingInterface to each other JurisdictionListener* voxelJL = _scriptEngine.getVoxelsScriptingInterface()->getJurisdictionListener(); _voxelViewer.setJurisdictionListener(voxelJL); _voxelViewer.init(); _scriptEngine.getVoxelsScriptingInterface()->setVoxelTree(_voxelViewer.getTree()); _scriptEngine.registerGlobalObject("ParticleViewer", &_particleViewer); JurisdictionListener* particleJL = _scriptEngine.getParticlesScriptingInterface()->getJurisdictionListener(); _particleViewer.setJurisdictionListener(particleJL); _particleViewer.init(); _scriptEngine.getParticlesScriptingInterface()->setParticleTree(_particleViewer.getTree()); _scriptEngine.registerGlobalObject("ModelViewer", &_modelViewer); JurisdictionListener* modelJL = _scriptEngine.getModelsScriptingInterface()->getJurisdictionListener(); _modelViewer.setJurisdictionListener(modelJL); _modelViewer.init(); _scriptEngine.getModelsScriptingInterface()->setModelTree(_modelViewer.getTree()); _scriptEngine.setScriptContents(scriptContents); _scriptEngine.run(); setFinished(true); }
void ScriptEngine::run() { // TODO: can we add a short circuit for _stoppingAllScripts here? What does it mean to not start running if // we're in the process of stopping? if (!_isInitialized) { init(); } _isRunning = true; _isFinished = false; emit runningStateChanged(); QScriptValue result = evaluate(_scriptContents); QElapsedTimer startTime; startTime.start(); int thisFrame = 0; auto nodeList = DependencyManager::get<NodeList>(); auto entityScriptingInterface = DependencyManager::get<EntityScriptingInterface>(); qint64 lastUpdate = usecTimestampNow(); while (!_isFinished) { int usecToSleep = (thisFrame++ * SCRIPT_DATA_CALLBACK_USECS) - startTime.nsecsElapsed() / 1000; // nsec to usec if (usecToSleep > 0) { usleep(usecToSleep); } if (_isFinished) { break; } QCoreApplication::processEvents(); if (_isFinished) { break; } if (!_isFinished && entityScriptingInterface->getEntityPacketSender()->serversExist()) { // release the queue of edit entity messages. entityScriptingInterface->getEntityPacketSender()->releaseQueuedMessages(); // since we're in non-threaded mode, call process so that the packets are sent if (!entityScriptingInterface->getEntityPacketSender()->isThreaded()) { entityScriptingInterface->getEntityPacketSender()->process(); } } if (!_isFinished && _isAvatar && _avatarData) { const int SCRIPT_AUDIO_BUFFER_SAMPLES = floor(((SCRIPT_DATA_CALLBACK_USECS * AudioConstants::SAMPLE_RATE) / (1000 * 1000)) + 0.5); const int SCRIPT_AUDIO_BUFFER_BYTES = SCRIPT_AUDIO_BUFFER_SAMPLES * sizeof(int16_t); QByteArray avatarByteArray = _avatarData->toByteArray(); auto avatarPacket = NLPacket::create(PacketType::AvatarData, avatarByteArray.size()); avatarPacket->write(avatarByteArray); nodeList->broadcastToNodes(std::move(avatarPacket), NodeSet() << NodeType::AvatarMixer); if (_isListeningToAudioStream || _avatarSound) { // if we have an avatar audio stream then send it out to our audio-mixer bool silentFrame = true; int16_t numAvailableSamples = SCRIPT_AUDIO_BUFFER_SAMPLES; const int16_t* nextSoundOutput = NULL; if (_avatarSound) { const QByteArray& soundByteArray = _avatarSound->getByteArray(); nextSoundOutput = reinterpret_cast<const int16_t*>(soundByteArray.data() + _numAvatarSoundSentBytes); int numAvailableBytes = (soundByteArray.size() - _numAvatarSoundSentBytes) > SCRIPT_AUDIO_BUFFER_BYTES ? SCRIPT_AUDIO_BUFFER_BYTES : soundByteArray.size() - _numAvatarSoundSentBytes; numAvailableSamples = numAvailableBytes / sizeof(int16_t); // check if the all of the _numAvatarAudioBufferSamples to be sent are silence for (int i = 0; i < numAvailableSamples; ++i) { if (nextSoundOutput[i] != 0) { silentFrame = false; break; } } _numAvatarSoundSentBytes += numAvailableBytes; if (_numAvatarSoundSentBytes == soundByteArray.size()) { // we're done with this sound object - so set our pointer back to NULL // and our sent bytes back to zero _avatarSound = NULL; _numAvatarSoundSentBytes = 0; } } auto audioPacket = NLPacket::create(silentFrame ? PacketType::SilentAudioFrame : PacketType::MicrophoneAudioNoEcho); // seek past the sequence number, will be packed when destination node is known audioPacket->seek(sizeof(quint16)); if (silentFrame) { if (!_isListeningToAudioStream) { // if we have a silent frame and we're not listening then just send nothing and break out of here break; } // write the number of silent samples so the audio-mixer can uphold timing audioPacket->writePrimitive(SCRIPT_AUDIO_BUFFER_SAMPLES); // use the orientation and position of this avatar for the source of this audio audioPacket->writePrimitive(_avatarData->getPosition()); glm::quat headOrientation = _avatarData->getHeadOrientation(); audioPacket->writePrimitive(headOrientation); } else if (nextSoundOutput) { // assume scripted avatar audio is mono and set channel flag to zero audioPacket->writePrimitive((quint8) 0); // use the orientation and position of this avatar for the source of this audio audioPacket->writePrimitive(_avatarData->getPosition()); glm::quat headOrientation = _avatarData->getHeadOrientation(); audioPacket->writePrimitive(headOrientation); // write the raw audio data audioPacket->write(reinterpret_cast<const char*>(nextSoundOutput), numAvailableSamples * sizeof(int16_t)); } // write audio packet to AudioMixer nodes auto nodeList = DependencyManager::get<NodeList>(); nodeList->eachNode([this, &nodeList, &audioPacket](const SharedNodePointer& node){ // only send to nodes of type AudioMixer if (node->getType() == NodeType::AudioMixer) { // pack sequence number quint16 sequence = _outgoingScriptAudioSequenceNumbers[node->getUUID()]++; audioPacket->seek(0); audioPacket->writePrimitive(sequence); // send audio packet nodeList->sendUnreliablePacket(*audioPacket, *node); } }); } } qint64 now = usecTimestampNow(); float deltaTime = (float) (now - lastUpdate) / (float) USECS_PER_SECOND; if (hasUncaughtException()) { int line = uncaughtExceptionLineNumber(); qCDebug(scriptengine) << "Uncaught exception at (" << _fileNameString << ") line" << line << ":" << uncaughtException().toString(); emit errorMessage("Uncaught exception at (" + _fileNameString + ") line" + QString::number(line) + ":" + uncaughtException().toString()); clearExceptions(); } if (!_isFinished) { emit update(deltaTime); } lastUpdate = now; } stopAllTimers(); // make sure all our timers are stopped if the script is ending emit scriptEnding(); // kill the avatar identity timer delete _avatarIdentityTimer; if (entityScriptingInterface->getEntityPacketSender()->serversExist()) { // release the queue of edit entity messages. entityScriptingInterface->getEntityPacketSender()->releaseQueuedMessages(); // since we're in non-threaded mode, call process so that the packets are sent if (!entityScriptingInterface->getEntityPacketSender()->isThreaded()) { // wait here till the edit packet sender is completely done sending while (entityScriptingInterface->getEntityPacketSender()->hasPacketsToSend()) { entityScriptingInterface->getEntityPacketSender()->process(); QCoreApplication::processEvents(); } } else { // FIXME - do we need to have a similar "wait here" loop for non-threaded packet senders? } } emit finished(_fileNameString); _isRunning = false; emit runningStateChanged(); emit doneRunning(); _doneRunningThisScript = true; }
ACClientApp::ACClientApp(int argc, char* argv[]) : QCoreApplication(argc, argv) { // parse command-line QCommandLineParser parser; parser.setApplicationDescription("High Fidelity AC client"); const QCommandLineOption helpOption = parser.addHelpOption(); const QCommandLineOption verboseOutput("v", "verbose output"); parser.addOption(verboseOutput); const QCommandLineOption authOption("u", "set usename and pass", "username:password"); parser.addOption(authOption); const QCommandLineOption domainAddressOption("d", "domain-server address", "127.0.0.1"); parser.addOption(domainAddressOption); const QCommandLineOption cacheSTUNOption("s", "cache stun-server response"); parser.addOption(cacheSTUNOption); const QCommandLineOption listenPortOption("listenPort", "listen port", QString::number(INVALID_PORT)); parser.addOption(listenPortOption); if (!parser.parse(QCoreApplication::arguments())) { qCritical() << parser.errorText() << endl; parser.showHelp(); Q_UNREACHABLE(); } if (parser.isSet(helpOption)) { parser.showHelp(); Q_UNREACHABLE(); } _verbose = parser.isSet(verboseOutput); if (!_verbose) { QLoggingCategory::setFilterRules("qt.network.ssl.warning=false"); const_cast<QLoggingCategory*>(&networking())->setEnabled(QtDebugMsg, false); const_cast<QLoggingCategory*>(&networking())->setEnabled(QtInfoMsg, false); const_cast<QLoggingCategory*>(&networking())->setEnabled(QtWarningMsg, false); const_cast<QLoggingCategory*>(&shared())->setEnabled(QtDebugMsg, false); const_cast<QLoggingCategory*>(&shared())->setEnabled(QtInfoMsg, false); const_cast<QLoggingCategory*>(&shared())->setEnabled(QtWarningMsg, false); } QString domainServerAddress = "127.0.0.1:40103"; if (parser.isSet(domainAddressOption)) { domainServerAddress = parser.value(domainAddressOption); } if (_verbose) { qDebug() << "domain-server address is" << domainServerAddress; } int listenPort = INVALID_PORT; if (parser.isSet(listenPortOption)) { listenPort = parser.value(listenPortOption).toInt(); } if (parser.isSet(authOption)) { QStringList pieces = parser.value(authOption).split(":"); if (pieces.size() != 2) { qDebug() << "-u should be followed by username:password"; parser.showHelp(); Q_UNREACHABLE(); } _username = pieces[0]; _password = pieces[1]; } DependencyManager::registerInheritance<LimitedNodeList, NodeList>(); DependencyManager::set<AccountManager>([&]{ return QString("Mozilla/5.0 (HighFidelityACClient)"); }); DependencyManager::set<AddressManager>(); DependencyManager::set<NodeList>(NodeType::Agent, listenPort); auto accountManager = DependencyManager::get<AccountManager>(); accountManager->setIsAgent(true); accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL()); auto nodeList = DependencyManager::get<NodeList>(); // setup a timer for domain-server check ins QTimer* domainCheckInTimer = new QTimer(nodeList.data()); connect(domainCheckInTimer, &QTimer::timeout, nodeList.data(), &NodeList::sendDomainServerCheckIn); domainCheckInTimer->start(DOMAIN_SERVER_CHECK_IN_MSECS); // start the nodeThread so its event loop is running // (must happen after the checkin timer is created with the nodelist as it's parent) nodeList->startThread(); const DomainHandler& domainHandler = nodeList->getDomainHandler(); connect(&domainHandler, SIGNAL(domainURLChanged(QUrl)), SLOT(domainChanged(QUrl))); connect(&domainHandler, &DomainHandler::domainConnectionRefused, this, &ACClientApp::domainConnectionRefused); connect(nodeList.data(), &NodeList::nodeAdded, this, &ACClientApp::nodeAdded); connect(nodeList.data(), &NodeList::nodeKilled, this, &ACClientApp::nodeKilled); connect(nodeList.data(), &NodeList::nodeActivated, this, &ACClientApp::nodeActivated); connect(nodeList.data(), &NodeList::packetVersionMismatch, this, &ACClientApp::notifyPacketVersionMismatch); nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer << NodeType::EntityServer << NodeType::AssetServer << NodeType::MessagesMixer); if (_verbose) { QString username = accountManager->getAccountInfo().getUsername(); qDebug() << "cached username is" << username << ", isLoggedIn =" << accountManager->isLoggedIn(); } if (!_username.isEmpty()) { connect(accountManager.data(), &AccountManager::newKeypair, this, [&](){ if (_verbose) { qDebug() << "new keypair has been created."; } }); connect(accountManager.data(), &AccountManager::loginComplete, this, [&](){ if (_verbose) { qDebug() << "login successful"; } }); connect(accountManager.data(), &AccountManager::loginFailed, this, [&](){ qDebug() << "login failed."; }); accountManager->requestAccessToken(_username, _password); } DependencyManager::get<AddressManager>()->handleLookupString(domainServerAddress, false); QTimer* doTimer = new QTimer(this); doTimer->setSingleShot(true); connect(doTimer, &QTimer::timeout, this, &ACClientApp::timedOut); doTimer->start(4000); }