From 529286b2eabd25a424d7cc1097a5dafb344b2072 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 5 Jan 2017 14:46:16 -0800 Subject: [PATCH] More EntityScriptServer work --- assignment-client/src/Agent.cpp | 3 +- assignment-client/src/assets/AssetServer.cpp | 2 +- assignment-client/src/audio/AudioMixer.cpp | 2 +- assignment-client/src/avatars/AvatarMixer.cpp | 4 +- .../src/messages/MessagesMixer.cpp | 5 +- assignment-client/src/octree/OctreeServer.cpp | 4 +- .../src/scripts/EntityScriptServer.cpp | 161 +++++++++++++++++- .../src/scripts/EntityScriptServer.h | 17 +- domain-server/src/DomainServer.cpp | 4 +- 9 files changed, 186 insertions(+), 16 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index d13b708837..234ae239cd 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -54,7 +54,6 @@ static const int RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES = 10; Agent::Agent(ReceivedMessage& message) : ThreadedAssignment(message), - _entityEditSender(), _receivedAudioStream(RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES, RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES) { DependencyManager::get()->setPacketSender(&_entityEditSender); @@ -144,7 +143,7 @@ void Agent::handleAudioPacket(QSharedPointer message) { _receivedAudioStream.clearBuffer(); } -const QString AGENT_LOGGING_NAME = "agent"; +static const QString AGENT_LOGGING_NAME = "agent"; void Agent::run() { diff --git a/assignment-client/src/assets/AssetServer.cpp b/assignment-client/src/assets/AssetServer.cpp index 2fbe2f6dfe..017ffd94f1 100644 --- a/assignment-client/src/assets/AssetServer.cpp +++ b/assignment-client/src/assets/AssetServer.cpp @@ -137,7 +137,7 @@ void AssetServer::completeSetup() { cleanupUnmappedFiles(); } - nodeList->addNodeTypeToInterestSet(NodeType::Agent); + nodeList->addSetOfNodeTypesToNodeInterestSet({ NodeType::Agent, NodeType::EntityScriptServer }); } else { qCritical() << "Asset Server assignment will not continue because mapping file could not be loaded."; setFinished(true); diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 07639867eb..d5eb12c36d 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -398,7 +398,7 @@ void AudioMixer::start() { auto nodeList = DependencyManager::get(); // prepare the NodeList - nodeList->addNodeTypeToInterestSet(NodeType::Agent); + nodeList->addSetOfNodeTypesToNodeInterestSet({ NodeType::Agent, NodeType::EntityScriptServer }); nodeList->linkedDataCreateCallback = [&](Node* node) { getOrCreateClientData(node); }; // parse out any AudioMixer settings diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 11cbd73970..4568e1cedd 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -674,8 +674,8 @@ void AvatarMixer::run() { void AvatarMixer::domainSettingsRequestComplete() { auto nodeList = DependencyManager::get(); - nodeList->addNodeTypeToInterestSet(NodeType::Agent); - + nodeList->addSetOfNodeTypesToNodeInterestSet({ NodeType::Agent, NodeType::EntityScriptServer }); + // parse the settings to pull out the values we need parseDomainServerSettings(nodeList->getDomainHandler().getSettingsObject()); diff --git a/assignment-client/src/messages/MessagesMixer.cpp b/assignment-client/src/messages/MessagesMixer.cpp index 3baea67486..9555d1e160 100644 --- a/assignment-client/src/messages/MessagesMixer.cpp +++ b/assignment-client/src/messages/MessagesMixer.cpp @@ -83,5 +83,6 @@ void MessagesMixer::sendStatsPacket() { void MessagesMixer::run() { ThreadedAssignment::commonInit(MESSAGES_MIXER_LOGGING_NAME, NodeType::MessagesMixer); - DependencyManager::get()->addNodeTypeToInterestSet(NodeType::Agent); -} \ No newline at end of file + auto nodeList = DependencyManager::get(); + nodeList->addSetOfNodeTypesToNodeInterestSet({ NodeType::Agent, NodeType::EntityScriptServer }); +} diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 3e36250a82..7b681568b3 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -1136,8 +1136,8 @@ void OctreeServer::domainSettingsRequestComplete() { auto nodeList = DependencyManager::get(); // we need to ask the DS about agents so we can ping/reply with them - nodeList->addNodeTypeToInterestSet(NodeType::Agent); - + nodeList->addSetOfNodeTypesToNodeInterestSet({ NodeType::Agent, NodeType::EntityScriptServer }); + auto& packetReceiver = DependencyManager::get()->getPacketReceiver(); packetReceiver.registerListener(getMyQueryMessageType(), this, "handleOctreeQueryPacket"); packetReceiver.registerListener(PacketType::OctreeDataNack, this, "handleOctreeDataNackPacket"); diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index 66d1aa579d..2883d1a2ed 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -11,7 +11,166 @@ #include "EntityScriptServer.h" -EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssignment(message) { +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../entities/AssignmentParentFinder.h" + +static const int RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES = 10; + +EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : + ThreadedAssignment(message), + _receivedAudioStream(RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES, RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES) +{ + DependencyManager::get()->setPacketSender(&_entityEditSender); + + ResourceManager::init(); + + DependencyManager::registerInheritance(); + + DependencyManager::set(); + DependencyManager::set(); + DependencyManager::set(); + + DependencyManager::set(); + DependencyManager::set(); + + + auto& packetReceiver = DependencyManager::get()->getPacketReceiver(); + + packetReceiver.registerListenerForTypes({ PacketType::MixedAudio, PacketType::SilentAudioFrame }, + this, "handleAudioPacket"); + packetReceiver.registerListenerForTypes({ PacketType::OctreeStats, PacketType::EntityData, PacketType::EntityErase }, + this, "handleOctreePacket"); + packetReceiver.registerListener(PacketType::Jurisdiction, this, "handleJurisdictionPacket"); + packetReceiver.registerListener(PacketType::SelectedAudioFormat, this, "handleSelectedAudioFormat"); } + +static const QString ENTITY_SCRIPT_SERVER_LOGGING_NAME = "entity-script-server"; + +void EntityScriptServer::run() { + // make sure we request our script once the agent connects to the domain + auto nodeList = DependencyManager::get(); + + ThreadedAssignment::commonInit(ENTITY_SCRIPT_SERVER_LOGGING_NAME, NodeType::EntityScriptServer); + + // Setup MessagesClient + auto messagesClient = DependencyManager::set(); + QThread* messagesThread = new QThread; + messagesThread->setObjectName("Messages Client Thread"); + messagesClient->moveToThread(messagesThread); + connect(messagesThread, &QThread::started, messagesClient.data(), &MessagesClient::init); + messagesThread->start(); + + // make sure we hear about connected nodes so we can grab an ATP script if a request is pending + connect(nodeList.data(), &LimitedNodeList::nodeActivated, this, &EntityScriptServer::nodeActivated); + connect(nodeList.data(), &LimitedNodeList::nodeKilled, this, &EntityScriptServer::nodeKilled); + + nodeList->addSetOfNodeTypesToNodeInterestSet({ + NodeType::AudioMixer, NodeType::AvatarMixer, NodeType::EntityServer, NodeType::MessagesMixer, NodeType::AssetServer + }); +} + +void EntityScriptServer::nodeActivated(SharedNodePointer activatedNode) { + if (activatedNode->getType() == NodeType::AudioMixer) { + negotiateAudioFormat(); + } +} + +void EntityScriptServer::negotiateAudioFormat() { + auto nodeList = DependencyManager::get(); + auto negotiateFormatPacket = NLPacket::create(PacketType::NegotiateAudioFormat); + auto codecPlugins = PluginManager::getInstance()->getCodecPlugins(); + quint8 numberOfCodecs = (quint8)codecPlugins.size(); + negotiateFormatPacket->writePrimitive(numberOfCodecs); + for (auto& plugin : codecPlugins) { + auto codecName = plugin->getName(); + negotiateFormatPacket->writeString(codecName); + } + + // grab our audio mixer from the NodeList, if it exists + SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer); + + if (audioMixer) { + // send off this mute packet + nodeList->sendPacket(std::move(negotiateFormatPacket), *audioMixer); + } +} + +void EntityScriptServer::handleSelectedAudioFormat(QSharedPointer message) { + QString selectedCodecName = message->readString(); + selectAudioFormat(selectedCodecName); +} + +void EntityScriptServer::selectAudioFormat(const QString& selectedCodecName) { + _selectedCodecName = selectedCodecName; + + qDebug() << "Selected Codec:" << _selectedCodecName; + + // release any old codec encoder/decoder first... + if (_codec && _encoder) { + _codec->releaseEncoder(_encoder); + _encoder = nullptr; + _codec = nullptr; + } + _receivedAudioStream.cleanupCodec(); + + auto codecPlugins = PluginManager::getInstance()->getCodecPlugins(); + for (auto& plugin : codecPlugins) { + if (_selectedCodecName == plugin->getName()) { + _codec = plugin; + _receivedAudioStream.setupCodec(plugin, _selectedCodecName, AudioConstants::STEREO); + _encoder = plugin->createEncoder(AudioConstants::SAMPLE_RATE, AudioConstants::MONO); + qDebug() << "Selected Codec Plugin:" << _codec.get(); + break; + } + } +} + +void EntityScriptServer::handleAudioPacket(QSharedPointer message) { + _receivedAudioStream.parseData(*message); + + _lastReceivedAudioLoudness = _receivedAudioStream.getNextOutputFrameLoudness(); + _receivedAudioStream.clearBuffer(); +} + +void EntityScriptServer::nodeKilled(SharedNodePointer killedNode) { + +} + +void EntityScriptServer::sendStatsPacket() { + +} + +void EntityScriptServer::handleOctreePacket(QSharedPointer message, SharedNodePointer senderNode) { + +} + +void EntityScriptServer::handleJurisdictionPacket(QSharedPointer message, SharedNodePointer senderNode) { + +} + +void EntityScriptServer::aboutToFinish() { + // our entity tree is going to go away so tell that to the EntityScriptingInterface + DependencyManager::get()->setEntityTree(nullptr); + + ResourceManager::cleanup(); + + // cleanup the AudioInjectorManager (and any still running injectors) + DependencyManager::destroy(); + DependencyManager::destroy(); + + // cleanup codec & encoder + if (_codec && _encoder) { + _codec->releaseEncoder(_encoder); + _encoder = nullptr; + } +} diff --git a/assignment-client/src/scripts/EntityScriptServer.h b/assignment-client/src/scripts/EntityScriptServer.h index 842f3802cf..2d69b46057 100644 --- a/assignment-client/src/scripts/EntityScriptServer.h +++ b/assignment-client/src/scripts/EntityScriptServer.h @@ -14,8 +14,11 @@ #include +#include +#include #include +#include "MixedAudioStream.h" class EntityScriptServer : public ThreadedAssignment { Q_OBJECT @@ -23,6 +26,8 @@ class EntityScriptServer : public ThreadedAssignment { public: EntityScriptServer(ReceivedMessage& message); + virtual void aboutToFinish() override; + public slots: void run() override; void nodeActivated(SharedNodePointer activatedNode); @@ -30,14 +35,22 @@ public slots: void sendStatsPacket() override; private slots: - void handleAudioPacket(QSharedPointer message); void handleOctreePacket(QSharedPointer message, SharedNodePointer senderNode); void handleJurisdictionPacket(QSharedPointer message, SharedNodePointer senderNode); void handleSelectedAudioFormat(QSharedPointer message); - + void handleAudioPacket(QSharedPointer message); + private: + void negotiateAudioFormat(); + void selectAudioFormat(const QString& selectedCodecName); + EntityEditPacketSender _entityEditSender; + QString _selectedCodecName; + CodecPluginPointer _codec; + Encoder* _encoder { nullptr }; + MixedAudioStream _receivedAudioStream; + float _lastReceivedAudioLoudness; }; #endif // hifi_EntityScriptServer_h diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 0f7923519b..791b337764 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -808,9 +808,7 @@ void DomainServer::populateDefaultStaticAssignmentsExcludingTypes(const QSet(static_cast(defaultedType) + 1)) { - if (!excludedTypes.contains(defaultedType) - && defaultedType != Assignment::UNUSED_1 - && defaultedType != Assignment::AgentType) { + if (!excludedTypes.contains(defaultedType) && defaultedType != Assignment::AgentType) { if (defaultedType == Assignment::AssetServerType) { // Make sure the asset-server is enabled before adding it here.