示例#1
0
/**
   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;
}
示例#7
0
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;
}
示例#9
0
文件: Agent.cpp 项目: hifialanwu/hifi
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();    
}
示例#10
0
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();
}
示例#11
0
 //! 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();
    }
 }   
示例#12
0
文件: Agent.cpp 项目: rabedik/hifi
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);
}
示例#13
0
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);
}
示例#14
0
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;
}
示例#15
0
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();
}
示例#16
0
    _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()) {
示例#17
0
文件: Agent.cpp 项目: JeroMiya/hifi
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);
}
示例#18
0
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;
}
示例#19
0
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);
}