/** * Handler for player data * $Id$ * $HeadURL$ * $Author$ * Created by hjl, SLSE, 2017-02-20 */ #include "handler_artillerie_sound.h" #include "settings.h" #include #include #include #include namespace CesArtillerySound { HandlerArtillerieSound::HandlerArtillerieSound(const std::shared_ptr &ddsHandler, const std::shared_ptr &buildingDataHandler, QObject *parent) : QObject(parent) , m_ddsHandler(ddsHandler) , m_handlerBuildingData(buildingDataHandler) , m_logger(CentralEffectSimulation::getLogger("Plugin.ArtillerySound.HandlerArtillerieSound")) { } HandlerArtillerieSound::~HandlerArtillerieSound() { } // end of dtor() //----------------------------------------------------------------------------- bool HandlerArtillerieSound::init() { if (Settings::cesPlayArtillerieSounds()) { DEBUG_LOG(m_logger) << "init with Artillerie-Sounds"; auto dtcAes = m_ddsHandler->dtcAes(); dtcAes->enableExplosionSingle(); connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::explosionSingleChanged, this, &HandlerArtillerieSound::onExplosionSingleChanged); dtcAes->enableTechnicalArea(); connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::technicalAreaChanged, this, &HandlerArtillerieSound::onTechnicalAreaChanged); } else DEBUG_LOG(m_logger) << "init without Artillerie-Sounds"; return true; } // end of init() //----------------------------------------------------------------------------- void HandlerArtillerieSound::onExplosionSingleChanged(const AreaEffectSimulation::ExplosionSingle &data, DataModification modType) { bool handleExplosion = false; if (modType != DataModification::eAdded && modType != DataModification::eModified) { m_explosionSingleState.remove(data.id()); return; } if (data.effectStateId() == AreaEffectSimulation::AesEffectState_def::EsRemoved) { DEBUG_LOG(m_logger) << "Remove SingleExplosion"; m_explosionSingleState.remove(data.id()); return; } // Only handle transitions from prepared or fired to activated if ((m_explosionSingleState.value(data.id()) == AreaEffectSimulation::AesEffectState_def::EsPrepared || m_explosionSingleState.value(data.id()) == AreaEffectSimulation::AesEffectState_def::EsFired) && data.effectStateId() == AreaEffectSimulation::AesEffectState_def::EsActivated) { DEBUG_LOG(m_logger) << "Handle SingleExplosion"; handleExplosion = true; } m_explosionSingleState.insert(data.id(), data.effectStateId()); DEBUG_LOG(m_logger) << "Got ExplosionSingle State=" << data.effectStateId() << " id=" << data.id(); if (handleExplosion) { DEBUG_LOG(m_logger) << "Handle ExplosionSingle (EsActivated) HandlerArtillerieSound"; auto assetPositions = m_handlerBuildingData->getAssetPositions(); /////////////////////////////////////////////////////////////////// /// Play Sound to each EGCU and OSGU volume depends on distance /////////////////////////////////////////////////////////////////// INFO_LOG(m_logger) << "printAssetPositions: "; QHashIterator i(assetPositions); while (i.hasNext()) { i.next(); INFO_LOG(m_logger) << "printAssetPositions: " << i.key() << ": " << i.value().structureElementId << " type = " << i.value().mountingPointType << " hostname =" << i.value().hostname << " pos=" << i.value().geoPosition << " posUtm=" << i.value().positionUtm.x() << "/" << i.value().positionUtm.y() << " zone=" << i.value().zone; // Calculate the distance between the speaker and the explosion const QPointF posExplosionUtm = CentralEffectSimulation::geographic2Utm(data.impactPosition(), i.value().zone); const qreal distance = qSqrt(qPow(posExplosionUtm.x() - i.value().positionUtm.x(), 2) + qPow(posExplosionUtm.y() - i.value().positionUtm.y(), 2)); int sound = Settings::cesSoundId(); const qreal distanceThreshold = Settings::cesDistanceThreshold(); // [m] const qreal factor = Settings::cesFactor(); const qreal cesReduceFactor = Settings::cesReduceFactor(); INFO_LOG(m_logger) << "Distance to Explosion =" << distance << " hostname =" << i.value().hostname << " distanceThreshold=" << distanceThreshold << " factor=" << factor; qreal volumePercent = 100; if (distance > distanceThreshold) volumePercent = factor * log10(distance) * cesReduceFactor; QString user = Settings::cesUser(); QString passwd = Settings::cesPasswd(); playSound(user, passwd, i.value().hostname, sound, volumePercent); } } } // onExplosionSingleChanged void HandlerArtillerieSound::playSound(QString &user, QString &passwd, const QString &host, int &sound, qreal &volume) { QUrl url; QString request = QStringLiteral("http://%1/hitsound.php?sound=%2&vol=%3") .arg(host) .arg(sound) .arg(volume); url.setUrl(request); url.setUserName(user); url.setPassword(passwd); DEBUG_LOG(m_logger) << "startRequest: " << url.toString(); startRequest(url); } void HandlerArtillerieSound::startRequest(const QUrl &requestedUrl) { DEBUG_LOG(m_logger) << "startRequest: " << requestedUrl.toString(); m_httpRequestAborted = false; auto reply = m_qnam.get(QNetworkRequest(requestedUrl)); connect(reply, &QNetworkReply::finished, this, &HandlerArtillerieSound::httpFinished); } void HandlerArtillerieSound::httpFinished() { DEBUG_LOG(m_logger) << "httpFinished"; auto reply = qobject_cast(sender()); if (!reply) return; if (m_httpRequestAborted) { ERROR_LOG(m_logger) << "httpRequestAborted"; reply->deleteLater(); return; } if (reply->error()) { QNetworkRequest request = reply->request(); QUrl url = request.url(); ERROR_LOG(m_logger) << "reply->error: " << reply->errorString() << " host=" << url.host() << " query='" << url.query() << "' '" << qUtf8Printable(url.toString()) << "'"; reply->deleteLater(); return; } // Sucess //parse the reply JSON and display result in the UI const QByteArray json(reply->readAll()); DEBUG_LOG(m_logger) << "Sucess " << json; reply->deleteLater(); } void HandlerArtillerieSound::onTechnicalAreaChanged(const AreaEffectSimulation::TechnicalArea &data, DataModification modType) { if (modType != DataModification::eAdded && modType != DataModification::eModified) { m_technicalAreas.remove(data.id()); return; } if (data.effectStateId() == AreaEffectSimulation::AesEffectState_def::EsRemoved) { DEBUG_LOG(m_logger) << "Remove TechnicalArea"; m_technicalAreas.remove(data.id()); return; } if (data.type() == AreaEffectSimulation::AesTechnicalAreaType_def::TatSoundZone) { int zone = -1; m_technicalAreas.insert(data.id(), data); DEBUG_LOG(m_logger) << "Handle TechnicalArea HandlerArtillerieSound id=" << data.id(); QPointF cornerButtomLeft = CentralEffectSimulation::geographic2Utm(data.area().cornerBottomLeft(), &zone); qreal x = cornerButtomLeft.x() + data.area().width() / 2; qreal y = cornerButtomLeft.y() + data.area().height() / 2; QPointF center(x, y); DEBUG_LOG(m_logger) << "Handle TechnicalArea HandlerArtillerieSound cornerButtomLeft = " << cornerButtomLeft.x() << "/" << cornerButtomLeft.y() << " zone=" << zone; DEBUG_LOG(m_logger) << "Handle TechnicalArea HandlerArtillerieSound center = " << center.x() << "/" << center.y() << " zone=" << zone; } } // onTechnicalAreaChanged } // namespace CesArtillerySound