Merge pull request #772 from birarda/assignee

initial stub of assignment work
This commit is contained in:
ZappoMan 2013-08-05 10:56:31 -07:00
commit 1c45845842
29 changed files with 311 additions and 33 deletions

View file

@ -10,6 +10,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
add_subdirectory(animation-server)
add_subdirectory(assignment-server)
add_subdirectory(avatar-mixer)
add_subdirectory(audio-mixer)
add_subdirectory(domain-server)

View file

@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 2.8)
set(TARGET_NAME assignment-server)
set(ROOT_DIR ..)
set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
include(${MACRO_DIR}/SetupHifiProject.cmake)
setup_hifi_project(${TARGET_NAME} TRUE)
# link in the shared library
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})

View file

@ -0,0 +1,57 @@
//
// main.cpp
// assignment-server
//
// Created by Stephen Birarda on 7/1/13.
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#include <arpa/inet.h>
#include <fstream>
#include <queue>
#include <PacketHeaders.h>
#include <SharedUtil.h>
#include <UDPSocket.h>
const int MAX_PACKET_SIZE_BYTES = 1400;
struct Assignment {};
int main(int argc, const char* argv[]) {
std::queue<Assignment> assignmentQueue;
sockaddr_in senderSocket;
unsigned char senderData[MAX_PACKET_SIZE_BYTES] = {};
ssize_t receivedBytes = 0;
UDPSocket serverSocket(ASSIGNMENT_SERVER_PORT);
int numHeaderBytes = numBytesForPacketHeader((unsigned char*) &PACKET_TYPE_SEND_ASSIGNMENT);
unsigned char assignmentPacket[numHeaderBytes + sizeof(char)];
populateTypeAndVersion(assignmentPacket, PACKET_TYPE_SEND_ASSIGNMENT);
while (true) {
if (serverSocket.receive((sockaddr*) &senderSocket, &senderData, &receivedBytes)) {
// int numHeaderBytes = numBytesForPacketHeader(senderData);
if (senderData[0] == PACKET_TYPE_REQUEST_ASSIGNMENT) {
// grab the FI assignment in the queue, if it exists
if (assignmentQueue.size() > 0) {
// Assignment firstAssignment = assignmentQueue.front();
assignmentQueue.pop();
// send the assignment
serverSocket.send((sockaddr*) &senderSocket, assignmentPacket, sizeof(assignmentPacket));
}
} else if (senderData[0] == PACKET_TYPE_SEND_ASSIGNMENT) {
Assignment newAssignment;
// add this assignment to the queue
assignmentQueue.push(newAssignment);
}
}
}
}

View file

@ -375,7 +375,7 @@ int main(int argc, const char* argv[]) {
InjectedAudioRingBuffer* ringBuffer = (InjectedAudioRingBuffer*) node->getLinkedData();
if (memcmp(ringBuffer->getStreamIdentifier(),
packetData + 1,
packetData + numBytesForPacketHeader(packetData),
STREAM_IDENTIFIER_NUM_BYTES) == 0) {
// this is the matching stream, assign to matchingInjector and stop looking
matchingInjector = &*node;

View file

@ -18,4 +18,4 @@ include_glm(${TARGET_NAME} ${ROOT_DIR})
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
link_hifi_library(avatars ${TARGET_NAME} ${ROOT_DIR})
link_hifi_library(audio ${TARGET_NAME} ${ROOT_DIR})
link_hifi_library(audio ${TARGET_NAME} ${ROOT_DIR})

View file

@ -35,17 +35,24 @@ Pod::Spec.new do |s|
# s.exclude_files = 'Classes/Exclude'
s.subspec "shared" do |sp|
sp.source_files = "libraries/shared/src"
sp.public_header_files = "librares/shared/src"
sp.source_files = 'libraries/shared/src', 'libraries/shared/moc_*'
sp.exclude_files = "libraries/shared/src/UrlReader.*"
sp.dependency 'glm'
sp.xcconfig = { 'CLANG_CXX_LIBRARY' => "libc++" }
end
s.subspec "audio" do |sp|
sp.source_files = "libraries/audio/src"
sp.public_header_files = "libraries/audio/src"
sp.xcconfig = { 'CLANG_CXX_LIBRARY' => "libc++" }
sp.dependency 'glm'
end
s.subspec "avatars" do |sp|
sp.source_files = 'libraries/avatars/src', 'libraries/avatars/moc_*'
sp.dependency 'glm'
end
s.xcconfig = { 'HEADER_SEARCH_PATHS' => '${PODS_ROOT}/../../qt5-device/qtbase/include' }
s.libraries = 'libQtCoreCombined', 'libQt5Network', 'libQt5Script'
# A list of file patterns which select the header files that should be
# made available to the application. If the pattern is a directory then the

View file

@ -21,7 +21,7 @@ class QNetworkReply;
class Avatar;
class AvatarVoxelSystem : public QObject, public VoxelSystem {
class AvatarVoxelSystem : public VoxelSystem {
Q_OBJECT
public:

View file

@ -61,6 +61,8 @@ void* AudioInjectionManager::injectAudioViaThread(void* args) {
Node* audioMixer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_AUDIO_MIXER);
if (audioMixer) {
_destinationSocket = *audioMixer->getActiveSocket();
} else {
pthread_exit(0);
}
}

View file

@ -6,12 +6,12 @@
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
//
#include <fstream>
#include <cstring>
#include <fstream>
#include <limits>
#include <SharedUtil.h>
#include <PacketHeaders.h>
#include <UDPSocket.h>
#include <SharedUtil.h>
#include "AudioInjector.h"
@ -21,7 +21,8 @@ AudioInjector::AudioInjector(const char* filename) :
_radius(0.0f),
_volume(MAX_INJECTOR_VOLUME),
_indexOfNextSlot(0),
_isInjectingAudio(false)
_isInjectingAudio(false),
_lastFrameIntensity(0.0f)
{
loadRandomIdentifier(_streamIdentifier, STREAM_IDENTIFIER_NUM_BYTES);
@ -51,7 +52,8 @@ AudioInjector::AudioInjector(int maxNumSamples) :
_radius(0.0f),
_volume(MAX_INJECTOR_VOLUME),
_indexOfNextSlot(0),
_isInjectingAudio(false)
_isInjectingAudio(false),
_lastFrameIntensity(0.0f)
{
loadRandomIdentifier(_streamIdentifier, STREAM_IDENTIFIER_NUM_BYTES);
@ -114,6 +116,18 @@ void AudioInjector::injectAudio(UDPSocket* injectorSocket, sockaddr* destination
injectorSocket->send(destinationSocket, dataPacket, sizeof(dataPacket));
// calculate the intensity for this frame
float lastRMS = 0;
for (int j = 0; j < BUFFER_LENGTH_SAMPLES_PER_CHANNEL; j++) {
lastRMS += _audioSampleArray[i + j] * _audioSampleArray[i + j];
}
lastRMS /= BUFFER_LENGTH_SAMPLES_PER_CHANNEL;
lastRMS = sqrtf(lastRMS);
_lastFrameIntensity = lastRMS / std::numeric_limits<int16_t>::max();
int usecToSleep = usecTimestamp(&startTime) + (++nextFrame * INJECT_INTERVAL_USECS) - usecTimestampNow();
if (usecToSleep > 0) {
usleep(usecToSleep);
@ -131,8 +145,8 @@ void AudioInjector::addSample(const int16_t sample) {
}
}
void AudioInjector::addSamples(int16_t* sampleBuffer, int numSamples) {
if (_audioSampleArray + _indexOfNextSlot + numSamples <= _audioSampleArray + (_numTotalSamples / sizeof(int16_t))) {
void AudioInjector::addSamples(int16_t* sampleBuffer, int numSamples) {
if (_audioSampleArray + _indexOfNextSlot + numSamples <= _audioSampleArray + _numTotalSamples) {
// only copy the audio from the sample buffer if there's space
memcpy(_audioSampleArray + _indexOfNextSlot, sampleBuffer, numSamples * sizeof(int16_t));
_indexOfNextSlot += numSamples;

View file

@ -9,8 +9,7 @@
#ifndef __hifi__AudioInjector__
#define __hifi__AudioInjector__
#include <glm/glm.hpp>
#include <glm/gtx/quaternion.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/component_wise.hpp>
#include <UDPSocket.h>
@ -36,6 +35,8 @@ public:
unsigned char getVolume() const { return _volume; }
void setVolume(unsigned char volume) { _volume = volume; }
float getLastFrameIntensity() const { return _lastFrameIntensity; }
const glm::vec3& getPosition() const { return _position; }
void setPosition(const glm::vec3& position) { _position = position; }
@ -57,6 +58,7 @@ private:
unsigned char _volume;
int _indexOfNextSlot;
bool _isInjectingAudio;
float _lastFrameIntensity;
};
#endif /* defined(__hifi__AudioInjector__) */

View file

@ -0,0 +1,88 @@
//
// Agent.cpp
// hifi
//
// Created by Stephen Birarda on 7/1/13.
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
//
#import <QtScript/QScriptEngine>
#import <QtNetwork/QtNetwork>
#include <NodeList.h>
#include "AvatarData.h"
#include "Agent.h"
Agent::Agent() :
_shouldStop(false)
{
}
void Agent::run(QUrl scriptURL) {
NodeList::getInstance()->setOwnerType(NODE_TYPE_AGENT);
NodeList::getInstance()->setNodeTypesOfInterest(&NODE_TYPE_AVATAR_MIXER, 1);
QNetworkAccessManager* manager = new QNetworkAccessManager();
qDebug() << "Attemping download of " << scriptURL;
QNetworkReply* reply = manager->get(QNetworkRequest(scriptURL));
QEventLoop loop;
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
QString scriptString = QString(reply->readAll());
QScriptEngine engine;
AvatarData *testAvatarData = new AvatarData;
QScriptValue avatarDataValue = engine.newQObject(testAvatarData);
engine.globalObject().setProperty("AvatarData", avatarDataValue);
QScriptValue agentValue = engine.newQObject(this);
engine.globalObject().setProperty("Agent", agentValue);
qDebug() << "Downloaded script:" << scriptString;
qDebug() << "Evaluated script:" << engine.evaluate(scriptString).toString();
timeval thisSend;
timeval lastDomainServerCheckIn = {};
int numMicrosecondsSleep = 0;
const float DATA_SEND_INTERVAL_USECS = (1 / 60) * 1000 * 1000;
sockaddr_in senderAddress;
unsigned char receivedData[MAX_PACKET_SIZE];
ssize_t receivedBytes;
while (!_shouldStop) {
// update the thisSend timeval to the current time
gettimeofday(&thisSend, NULL);
// send a check in packet to the domain server if DOMAIN_SERVER_CHECK_IN_USECS has elapsed
if (usecTimestampNow() - usecTimestamp(&lastDomainServerCheckIn) >= DOMAIN_SERVER_CHECK_IN_USECS) {
gettimeofday(&lastDomainServerCheckIn, NULL);
NodeList::getInstance()->sendDomainServerCheckIn();
}
emit preSendCallback();
testAvatarData->sendData();
if (NodeList::getInstance()->getNodeSocket()->receive((sockaddr*) &senderAddress, receivedData, &receivedBytes)) {
NodeList::getInstance()->processNodeData((sockaddr*) &senderAddress, receivedData, receivedBytes);
}
// sleep for the correct amount of time to have data send be consistently timed
if ((numMicrosecondsSleep = DATA_SEND_INTERVAL_USECS - (usecTimestampNow() - usecTimestamp(&thisSend))) > 0) {
usleep(numMicrosecondsSleep);
}
}
}

View file

@ -0,0 +1,32 @@
//
// Agent.h
// hifi
//
// Created by Stephen Birarda on 7/1/13.
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
//
#ifndef __hifi__Agent__
#define __hifi__Agent__
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include "SharedUtil.h"
#include <QtCore/QObject>
#include <QtCore/QUrl>
class Agent : public QObject {
Q_OBJECT
public:
Agent();
bool volatile _shouldStop;
void run(QUrl scriptUrl);
signals:
void preSendCallback();
};
#endif /* defined(__hifi__Operative__) */

View file

@ -10,8 +10,9 @@
#include <cstring>
#include <stdint.h>
#include <SharedUtil.h>
#include <NodeList.h>
#include <PacketHeaders.h>
#include <SharedUtil.h>
#include "AvatarData.h"
#include <VoxelConstants.h>
@ -50,6 +51,22 @@ AvatarData::~AvatarData() {
delete _handData;
}
void AvatarData::sendData() {
// called from Agent visual loop to send data
if (Node* avatarMixer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_AVATAR_MIXER)) {
unsigned char packet[MAX_PACKET_SIZE];
unsigned char* endOfPacket = packet;
endOfPacket += populateTypeAndVersion(endOfPacket, PACKET_TYPE_HEAD_DATA);
endOfPacket += packNodeId(endOfPacket, NodeList::getInstance()->getOwnerID());
int numPacketBytes = (endOfPacket - packet) + getBroadcastData(endOfPacket);
NodeList::getInstance()->getNodeSocket()->send(avatarMixer->getActiveSocket(), packet, numPacketBytes);
}
}
int AvatarData::getBroadcastData(unsigned char* destinationBuffer) {
unsigned char* bufferStart = destinationBuffer;

View file

@ -16,6 +16,8 @@
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include <QtCore/QObject>
#include <NodeData.h>
#include "HeadData.h"
#include "HandData.h"
@ -39,6 +41,7 @@ enum KeyState
class JointData;
class AvatarData : public NodeData {
Q_OBJECT
public:
AvatarData(Node* owningNode = NULL);
~AvatarData();
@ -53,7 +56,6 @@ public:
// Body Rotation
float getBodyYaw() const { return _bodyYaw; }
void setBodyYaw(float bodyYaw) { _bodyYaw = bodyYaw; }
float getBodyPitch() const { return _bodyPitch; }
void setBodyPitch(float bodyPitch) { _bodyPitch = bodyPitch; }
float getBodyRoll() const {return _bodyRoll; }
@ -103,6 +105,11 @@ public:
void setHeadData(HeadData* headData) { _headData = headData; }
void setHandData(HandData* handData) { _handData = handData; }
public slots:
void setPosition(float x, float y, float z) { _position = glm::vec3(x, y, z); }
void setBodyYaw(float bodyYaw) { _bodyYaw = bodyYaw; }
void sendData();
protected:
glm::vec3 _position;
glm::vec3 _handPosition;

View file

@ -13,7 +13,7 @@
#include <vector>
#include <glm/glm.hpp>
#include <glm/gtx/quaternion.hpp>
#include <glm/gtc/quaternion.hpp>
class AvatarData;
class FingerData;

View file

@ -26,3 +26,6 @@ if (UNIX AND NOT APPLE)
target_link_libraries(${TARGET_NAME} ${CMAKE_THREAD_LIBS_INIT})
endif (UNIX AND NOT APPLE)
# include GLM
include(${MACRO_DIR}/IncludeGLM.cmake)
include_glm(${TARGET_NAME} ${ROOT_DIR})

View file

@ -21,7 +21,7 @@
#include "SharedUtil.h"
#include "UDPSocket.h"
#include <QDebug>
#include <QtCore/QDebug>
int unpackNodeId(unsigned char* packedData, uint16_t* nodeId) {
memcpy(nodeId, packedData, sizeof(uint16_t));
@ -75,6 +75,7 @@ const char* NODE_TYPE_NAME_AUDIO_MIXER = "Audio Mixer";
const char* NODE_TYPE_NAME_AVATAR_MIXER = "Avatar Mixer";
const char* NODE_TYPE_NAME_AUDIO_INJECTOR = "Audio Injector";
const char* NODE_TYPE_NAME_ANIMATION_SERVER = "Animation Server";
const char* NODE_TYPE_NAME_UNASSIGNED = "Unassigned";
const char* NODE_TYPE_NAME_UNKNOWN = "Unknown";
const char* Node::getTypeName() const {

View file

@ -18,7 +18,7 @@
#include <sys/socket.h>
#endif
#include <QDebug>
#include <QtCore/QDebug>
#include "NodeData.h"
#include "SimpleMovingAverage.h"

View file

@ -9,9 +9,12 @@
#ifndef hifi_NodeData_h
#define hifi_NodeData_h
#include <QtCore/QObject>
class Node;
class NodeData {
class NodeData : public QObject {
Q_OBJECT
public:
NodeData(Node* owningNode);

View file

@ -11,7 +11,7 @@
#include <cstdlib>
#include <cstdio>
#include <QDebug>
#include <QtCore/QDebug>
#include "NodeList.h"
#include "NodeTypes.h"
@ -366,6 +366,15 @@ int NodeList::processDomainServerList(unsigned char* packetData, size_t dataByte
return readNodes;
}
void NodeList::sendAssignmentRequest() {
const char ASSIGNMENT_SERVER_HOSTNAME[] = "assignment.highfidelity.io";
static sockaddr_in assignmentServerSocket = socketForHostname(ASSIGNMENT_SERVER_HOSTNAME);
assignmentServerSocket.sin_port = htons(ASSIGNMENT_SERVER_PORT);
_nodeSocket.send((sockaddr*) &assignmentServerSocket, &PACKET_TYPE_REQUEST_ASSIGNMENT, 1);
}
Node* NodeList::addOrUpdateNode(sockaddr* publicSocket, sockaddr* localSocket, char nodeType, uint16_t nodeId) {
NodeList::iterator node = end();

View file

@ -14,9 +14,10 @@
#include <iterator>
#include <unistd.h>
#include <QSettings>
#include <QtCore/QSettings>
#include "Node.h"
#include "NodeTypes.h"
#include "UDPSocket.h"
#ifdef _WIN32
@ -54,14 +55,16 @@ public:
NodeListIterator begin() const;
NodeListIterator end() const;
NODE_TYPE getOwnerType() const { return _ownerType; }
void setOwnerType(NODE_TYPE ownerType) { _ownerType = ownerType; }
const char* getDomainHostname() const { return _domainHostname; };
void setDomainHostname(const char* domainHostname);
void setDomainIP(const char* domainIP);
void setDomainIPToLocalhost();
char getOwnerType() const { return _ownerType; }
uint16_t getLastNodeID() const { return _lastNodeID; }
void increaseNodeID() { ++_lastNodeID; }
@ -80,9 +83,12 @@ public:
void clear();
void setNodeTypesOfInterest(const char* nodeTypesOfInterest, int numNodeTypesOfInterest);
void sendDomainServerCheckIn();
int processDomainServerList(unsigned char *packetData, size_t dataBytes);
void sendAssignmentRequest();
Node* nodeWithAddress(sockaddr *senderAddress);
Node* nodeWithID(uint16_t nodeID);

View file

@ -11,7 +11,7 @@
#include <cmath>
#include <cstring>
#include <QDebug>
#include <QtCore/QDebug>
#include "SharedUtil.h"
#include "OctalCode.h"

View file

@ -8,7 +8,7 @@
#include <stdio.h>
#include <QDebug>
#include <QtCore/QDebug>
#include "PacketHeaders.h"

View file

@ -34,6 +34,8 @@ const PACKET_TYPE PACKET_TYPE_TRANSMITTER_DATA_V2 = 'T';
const PACKET_TYPE PACKET_TYPE_ENVIRONMENT_DATA = 'e';
const PACKET_TYPE PACKET_TYPE_DOMAIN_LIST_REQUEST = 'L';
const PACKET_TYPE PACKET_TYPE_DOMAIN_REPORT_FOR_DUTY = 'C';
const PACKET_TYPE PACKET_TYPE_REQUEST_ASSIGNMENT = 'r';
const PACKET_TYPE PACKET_TYPE_SEND_ASSIGNMENT = 's';
const PACKET_TYPE PACKET_TYPE_VOXEL_STATS = '#';
typedef char PACKET_VERSION;
@ -52,4 +54,6 @@ const int MAX_PACKET_HEADER_BYTES = sizeof(PACKET_TYPE) + sizeof(PACKET_VERSION)
#define ADD_SCENE_COMMAND "add scene"
#define TEST_COMMAND "a message"
const int ASSIGNMENT_SERVER_PORT = 7007;
#endif

View file

@ -14,7 +14,7 @@
#include <map>
#include <string>
#include <QDebug>
#include <QtCore/QDebug>
#include "PerfStat.h"

View file

@ -20,7 +20,7 @@
#include <CoreFoundation/CoreFoundation.h>
#endif
#include <QDebug>
#include <QtCore/QDebug>
#include "OctalCode.h"
#include "PacketHeaders.h"

View file

@ -13,7 +13,7 @@
#include <stdint.h>
#include <unistd.h>
#include <QDebug>
#include <QtCore/QDebug>
#ifdef _WIN32
#include "Systime.h"

View file

@ -20,7 +20,7 @@
#include <unistd.h>
#endif
#include <QDebug>
#include <QtCore/QDebug>
#include "UDPSocket.h"
@ -118,6 +118,17 @@ unsigned short loadBufferWithSocketInfo(char* addressBuffer, sockaddr* socket) {
}
}
sockaddr_in socketForHostname(const char* hostname) {
struct hostent* pHostInfo;
sockaddr_in newSocket;
if ((pHostInfo = gethostbyname(hostname))) {
memcpy(&newSocket.sin_addr, pHostInfo->h_addr_list[0], pHostInfo->h_length);
}
return newSocket;
}
UDPSocket::UDPSocket(int listeningPort) : listeningPort(listeningPort), blocking(true) {
init();
// create the socket

View file

@ -42,5 +42,6 @@ int packSocket(unsigned char* packStore, sockaddr* socketToPack);
int unpackSocket(unsigned char* packedData, sockaddr* unpackDestSocket);
int getLocalAddress();
unsigned short loadBufferWithSocketInfo(char* addressBuffer, sockaddr* socket);
sockaddr_in socketForHostname(const char* hostname);
#endif /* defined(__interface__UDPSocket__) */