mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 11:45:36 +02:00
Merge branch 'master' into 19095
This commit is contained in:
commit
4403f726bb
16 changed files with 241 additions and 135 deletions
|
@ -28,6 +28,7 @@
|
|||
#include <fcntl.h>
|
||||
#include <sys/time.h>
|
||||
#include "AgentList.h"
|
||||
#include "SharedUtil.h"
|
||||
|
||||
const int DOMAIN_LISTEN_PORT = 40102;
|
||||
|
||||
|
@ -41,33 +42,23 @@ const int LOGOFF_CHECK_INTERVAL = 5000;
|
|||
int lastActiveCount = 0;
|
||||
AgentList agentList(DOMAIN_LISTEN_PORT);
|
||||
|
||||
int listForBroadcast(unsigned char *listBuffer, sockaddr *agentPublicAddress, sockaddr *agentLocalAddress, char agentType) {
|
||||
unsigned char *currentBufferPos = listBuffer + 1;
|
||||
unsigned char *startPointer = currentBufferPos;
|
||||
|
||||
for(std::vector<Agent>::iterator agent = agentList.agents.begin(); agent != agentList.agents.end(); agent++) {
|
||||
|
||||
if (DEBUG_TO_SELF || !agent->matches(agentPublicAddress, agentLocalAddress, agentType)) {
|
||||
*currentBufferPos++ = agent->type;
|
||||
|
||||
currentBufferPos += packSocket(currentBufferPos, agent->publicSocket);
|
||||
currentBufferPos += packSocket(currentBufferPos, agent->localSocket);
|
||||
}
|
||||
}
|
||||
|
||||
return 1 + (currentBufferPos - startPointer); // 1 is added for the leading 'D'
|
||||
}
|
||||
|
||||
int main(int argc, const char * argv[])
|
||||
{
|
||||
ssize_t receivedBytes = 0;
|
||||
char agentType;
|
||||
|
||||
unsigned char *broadcastPacket = new unsigned char[MAX_PACKET_SIZE];
|
||||
*broadcastPacket = 'D';
|
||||
|
||||
unsigned char *currentBufferPos;
|
||||
unsigned char *startPointer;
|
||||
int packetBytesWithoutLeadingChar;
|
||||
|
||||
sockaddr_in agentPublicAddress, agentLocalAddress;
|
||||
agentLocalAddress.sin_family = AF_INET;
|
||||
|
||||
|
||||
agentList.startSilentAgentRemovalThread();
|
||||
|
||||
while (true) {
|
||||
if (agentList.getAgentSocket()->receive((sockaddr *)&agentPublicAddress, packetData, &receivedBytes)) {
|
||||
|
@ -76,13 +67,30 @@ int main(int argc, const char * argv[])
|
|||
|
||||
agentList.addOrUpdateAgent((sockaddr *)&agentPublicAddress, (sockaddr *)&agentLocalAddress, agentType);
|
||||
|
||||
int listBytes = listForBroadcast(broadcastPacket, (sockaddr *)&agentPublicAddress, (sockaddr *)&agentLocalAddress, agentType);
|
||||
currentBufferPos = broadcastPacket + 1;
|
||||
startPointer = currentBufferPos;
|
||||
|
||||
if (listBytes > 0) {
|
||||
agentList.getAgentSocket()->send((sockaddr *)&agentPublicAddress, broadcastPacket, listBytes);
|
||||
for(std::vector<Agent>::iterator agent = agentList.agents.begin(); agent != agentList.agents.end(); agent++) {
|
||||
|
||||
if (DEBUG_TO_SELF || !agent->matches((sockaddr *)&agentPublicAddress, (sockaddr *)&agentLocalAddress, agentType)) {
|
||||
*currentBufferPos++ = agent->type;
|
||||
|
||||
currentBufferPos += packSocket(currentBufferPos, agent->publicSocket);
|
||||
currentBufferPos += packSocket(currentBufferPos, agent->localSocket);
|
||||
} else {
|
||||
// this is the agent, just update last receive to now
|
||||
agent->lastRecvTimeUsecs = usecTimestampNow();
|
||||
}
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
if ((packetBytesWithoutLeadingChar = (currentBufferPos - startPointer))) {
|
||||
agentList.getAgentSocket()->send((sockaddr *)&agentPublicAddress, broadcastPacket, packetBytesWithoutLeadingChar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,8 +44,8 @@ const char EC2_WEST_MIXER[] = "54.241.92.53";
|
|||
const int AUDIO_UDP_LISTEN_PORT = 55444;
|
||||
|
||||
int starve_counter = 0;
|
||||
|
||||
StDev stdev;
|
||||
bool stopAudioReceiveThread = false;
|
||||
|
||||
#define LOG_SAMPLE_DELAY 1
|
||||
|
||||
|
@ -202,7 +202,7 @@ void *receiveAudioViaUDP(void *args) {
|
|||
delete[] filename;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
while (!stopAudioReceiveThread) {
|
||||
if (sharedAudioData->audioSocket->receive((void *)receivedData, &receivedBytes)) {
|
||||
|
||||
bool firstSample = (currentReceiveTime.tv_sec == 0);
|
||||
|
@ -262,6 +262,8 @@ void *receiveAudioViaUDP(void *args) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pthread_exit(0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -284,8 +286,6 @@ Audio::Audio(Oscilloscope * s)
|
|||
audioData->audioSocket = new UDPSocket(AUDIO_UDP_LISTEN_PORT);
|
||||
audioData->ringBuffer = new AudioRingBuffer(RING_BUFFER_SIZE_SAMPLES);
|
||||
|
||||
pthread_t audioReceiveThread;
|
||||
|
||||
AudioRecThreadStruct threadArgs;
|
||||
threadArgs.sharedAudioData = audioData;
|
||||
|
||||
|
@ -307,6 +307,7 @@ Audio::Audio(Oscilloscope * s)
|
|||
Pa_StartStream(stream);
|
||||
if (paError != paNoError) goto error;
|
||||
|
||||
|
||||
return;
|
||||
|
||||
error:
|
||||
|
@ -421,6 +422,9 @@ void Audio::render(int screenWidth, int screenHeight)
|
|||
*/
|
||||
bool Audio::terminate ()
|
||||
{
|
||||
stopAudioReceiveThread = true;
|
||||
pthread_join(audioReceiveThread, NULL);
|
||||
|
||||
if (initialized) {
|
||||
initialized = false;
|
||||
|
||||
|
@ -429,12 +433,11 @@ bool Audio::terminate ()
|
|||
|
||||
paError = Pa_Terminate();
|
||||
if (paError != paNoError) goto error;
|
||||
|
||||
delete audioData;
|
||||
|
||||
logFile.close();
|
||||
}
|
||||
|
||||
logFile.close();
|
||||
delete audioData;
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
|
|
|
@ -41,6 +41,9 @@ private:
|
|||
// audio stream handle
|
||||
PaStream *stream;
|
||||
|
||||
// audio receive thread
|
||||
pthread_t audioReceiveThread;
|
||||
|
||||
// give access to AudioData class from audioCallback
|
||||
friend int audioCallback (const void*, void*, unsigned long, const PaStreamCallbackTimeInfo*, PaStreamCallbackFlags, void*);
|
||||
};
|
||||
|
|
|
@ -8,33 +8,29 @@
|
|||
|
||||
#include "Hand.h"
|
||||
|
||||
const float DEFAULT_X = 0.0;
|
||||
const float DEFAULT_Y = 0.0;
|
||||
const float DEFAULT_Z = -7.0;
|
||||
const float PHI = 1.618;
|
||||
|
||||
Hand::Hand(float initradius, glm::vec3 initcolor)
|
||||
const float DEFAULT_X = 0;
|
||||
const float DEFAULT_Y = -1.5;
|
||||
const float DEFAULT_Z = 2.0;
|
||||
|
||||
Hand::Hand(glm::vec3 initcolor)
|
||||
{
|
||||
color = initcolor;
|
||||
radius = initradius;
|
||||
reset();
|
||||
noise = 0;
|
||||
noise = 0.2;
|
||||
scale.x = 0.07;
|
||||
scale.y = scale.x * 5.0;
|
||||
scale.z = scale.y * 1.0;
|
||||
}
|
||||
|
||||
void Hand::render()
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
if (isColliding) glColor3f(1,0,0);
|
||||
else glColor3f(color.x, color.y, color.z);
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(-0.05, -0.5, 0.0);
|
||||
glVertex3f(position.x, position.y, position.z);
|
||||
glVertex3f(0.05, -0.5, 0.0);
|
||||
glVertex3f(position.x, position.y, position.z);
|
||||
glEnd();
|
||||
glTranslatef(position.x, position.y, position.z);
|
||||
glutSolidSphere(radius, 15, 15);
|
||||
glColor3f(color.x, color.y, color.z);
|
||||
glScalef(scale.x, scale.y, scale.z);
|
||||
glutSolidSphere(1.5, 20, 20);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
@ -43,22 +39,17 @@ void Hand::reset()
|
|||
position.x = DEFAULT_X;
|
||||
position.y = DEFAULT_Y;
|
||||
position.z = DEFAULT_Z;
|
||||
setTarget(position);
|
||||
velocity.x = velocity.y = velocity.z = 0;
|
||||
isColliding = false;
|
||||
}
|
||||
|
||||
void Hand::simulate(float deltaTime)
|
||||
{
|
||||
position += velocity*deltaTime;
|
||||
|
||||
velocity *= (1.f - 4.0*deltaTime);
|
||||
|
||||
if ((noise) && (randFloat() < 0.1))
|
||||
{
|
||||
velocity.x += (randFloat() - 0.5)*noise;
|
||||
velocity.y += (randFloat() - 0.5)*noise;
|
||||
velocity.z += (randFloat() - 0.5)*noise;
|
||||
|
||||
// If noise, add wandering movement
|
||||
if (noise) {
|
||||
position += noise * 0.1f * glm::vec3(randFloat() - 0.5, randFloat() - 0.5, randFloat() - 0.5);
|
||||
}
|
||||
// Decay position of hand toward target
|
||||
position -= deltaTime*(position - target);
|
||||
|
||||
}
|
|
@ -16,26 +16,20 @@
|
|||
#include "world.h"
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
const float RADIUS_RANGE = 10.0;
|
||||
|
||||
class Hand {
|
||||
public:
|
||||
Hand(float initradius, glm::vec3 color);
|
||||
Hand(glm::vec3 color);
|
||||
void simulate (float deltaTime);
|
||||
void render ();
|
||||
void reset ();
|
||||
void setNoise (float mag) { noise = mag; };
|
||||
void addVel (glm::vec3 add) { velocity += add; };
|
||||
void addVel (glm::vec3 v) { velocity += v; };
|
||||
glm::vec3 getPos() { return position; };
|
||||
void setPos(glm::vec3 newpos) { position = newpos; };
|
||||
float getRadius() { return radius; };
|
||||
void setRadius(float newradius) { radius = newradius; };
|
||||
void setColliding(bool newcollide) { isColliding = newcollide; };
|
||||
void setPos(glm::vec3 p) { position = p; };
|
||||
void setTarget(glm::vec3 t) { target = t; };
|
||||
private:
|
||||
glm::vec3 position, velocity, color;
|
||||
glm::vec3 position, target, velocity, color, scale;
|
||||
float noise;
|
||||
float radius;
|
||||
bool isColliding;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ Head::Head()
|
|||
renderYaw = 0.0;
|
||||
renderPitch = 0.0;
|
||||
setNoise(0);
|
||||
hand = new Hand(glm::vec3(skinColor[0], skinColor[1], skinColor[2]));
|
||||
}
|
||||
|
||||
Head::~Head() {
|
||||
|
@ -205,6 +206,7 @@ void Head::simulate(float deltaTime)
|
|||
}
|
||||
|
||||
}
|
||||
hand->simulate(deltaTime);
|
||||
|
||||
|
||||
}
|
||||
|
@ -216,27 +218,34 @@ void Head::render(int faceToFace, float * myLocation)
|
|||
glm::vec3 cameraHead(myLocation[0], myLocation[1], myLocation[2]);
|
||||
float distanceToCamera = glm::distance(cameraHead, position);
|
||||
|
||||
//std::cout << distanceToCamera << "\n";
|
||||
// Always render own hand, but don't render head unless showing face2face
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glPushMatrix();
|
||||
|
||||
glScalef(scale, scale, scale);
|
||||
glTranslatef(leanSideways, 0.f, leanForward);
|
||||
|
||||
glRotatef(Yaw, 0, 1, 0);
|
||||
|
||||
hand->render();
|
||||
|
||||
// Don't render a head if it is really close to your location, because that is your own head!
|
||||
if ((distanceToCamera > 1.0) || faceToFace) {
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glPushMatrix();
|
||||
|
||||
glScalef(scale, scale, scale);
|
||||
glTranslatef(leanSideways, 0.f, leanForward);
|
||||
|
||||
glRotatef(Yaw, 0, 1, 0);
|
||||
|
||||
glRotatef(Pitch, 1, 0, 0);
|
||||
glRotatef(Roll, 0, 0, 1);
|
||||
|
||||
|
||||
// Overall scale of head
|
||||
if (faceToFace) glScalef(1.5, 2.0, 2.0);
|
||||
else glScalef(0.75, 1.0, 1.0);
|
||||
glColor3fv(skinColor);
|
||||
|
||||
|
||||
|
||||
// Head
|
||||
glutSolidSphere(1, 30, 30);
|
||||
glutSolidSphere(1, 30, 30);
|
||||
|
||||
//std::cout << distanceToCamera << "\n";
|
||||
|
||||
// Ears
|
||||
glPushMatrix();
|
||||
|
@ -326,9 +335,9 @@ void Head::render(int faceToFace, float * myLocation)
|
|||
glutSolidSphere(PupilSize, 15, 15);
|
||||
glPopMatrix();
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
// Transmit data to agents requesting it
|
||||
|
@ -336,18 +345,23 @@ void Head::render(int faceToFace, float * myLocation)
|
|||
int Head::getBroadcastData(char* data)
|
||||
{
|
||||
// Copy data for transmission to the buffer, return length of data
|
||||
sprintf(data, "H%f,%f,%f,%f,%f,%f,%f,%f", getRenderPitch() + Pitch, -getRenderYaw() + 180 -Yaw, Roll,
|
||||
sprintf(data, "H%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f",
|
||||
getRenderPitch() + Pitch, -getRenderYaw() + 180 -Yaw, Roll,
|
||||
position.x + leanSideways, position.y, position.z + leanForward,
|
||||
loudness, averageLoudness);
|
||||
loudness, averageLoudness,
|
||||
hand->getPos().x, hand->getPos().y, hand->getPos().z);
|
||||
return strlen(data);
|
||||
}
|
||||
|
||||
void Head::parseData(void *data, int size) {
|
||||
// parse head data for this agent
|
||||
sscanf((char *)data, "H%f,%f,%f,%f,%f,%f,%f,%f",
|
||||
glm::vec3 handPos(0,0,0);
|
||||
sscanf((char *)data, "H%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f",
|
||||
&Pitch, &Yaw, &Roll,
|
||||
&position.x, &position.y, &position.z,
|
||||
&loudness, &averageLoudness);
|
||||
&loudness, &averageLoudness,
|
||||
&handPos.x, &handPos.y, &handPos.z);
|
||||
if (glm::length(handPos) > 0.0) hand->setPos(handPos);
|
||||
}
|
||||
|
||||
void Head::SetNewHeadTarget(float pitch, float yaw)
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
#include "AgentData.h"
|
||||
#include "Field.h"
|
||||
#include "world.h"
|
||||
#include "Head.h"
|
||||
#include "Hand.h"
|
||||
#include "InterfaceConfig.h"
|
||||
#include "SerialInterface.h"
|
||||
|
||||
|
@ -95,7 +97,9 @@ class Head : public AgentData {
|
|||
int eyeContact;
|
||||
eyeContactTargets eyeContactTarget;
|
||||
void readSensors();
|
||||
float renderYaw, renderPitch; // Pitch from view frustum when this is own head.
|
||||
float renderYaw, renderPitch; // Pitch from view frustum when this is own head.
|
||||
|
||||
Hand * hand;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -61,10 +61,12 @@ int simulate_on = 1;
|
|||
|
||||
const int MAX_PACKET_SIZE = 1500;
|
||||
char DOMAIN_HOSTNAME[] = "highfidelity.below92.com";
|
||||
char DOMAIN_IP[100] = ""; // IP Address will be used first if not empty string
|
||||
char DOMAIN_IP[100] = "192.168.1.47"; // IP Address will be used first if not empty string
|
||||
const int DOMAINSERVER_PORT = 40102;
|
||||
|
||||
AgentList agentList;
|
||||
pthread_t networkReceiveThread;
|
||||
bool stopNetworkReceiveThread = false;
|
||||
|
||||
// For testing, add milliseconds of delay for received UDP packets
|
||||
int packetcount = 0;
|
||||
|
@ -90,8 +92,6 @@ Oscilloscope audioScope(512,200,true);
|
|||
#define HAND_RADIUS 0.25 // Radius of in-world 'hand' of you
|
||||
Head myHead; // The rendered head of oneself
|
||||
|
||||
Hand myHand(HAND_RADIUS,
|
||||
glm::vec3(0,1,1)); // My hand (used to manipulate things in world)
|
||||
|
||||
glm::vec3 box(WORLD_SIZE,WORLD_SIZE,WORLD_SIZE);
|
||||
ParticleSystem balls(0,
|
||||
|
@ -144,7 +144,6 @@ float noise = 1.0; // Overall magnitude scaling for random noi
|
|||
int step_on = 0;
|
||||
int display_levels = 0;
|
||||
int display_head = 0;
|
||||
int display_hand = 0;
|
||||
int display_field = 0;
|
||||
|
||||
int display_head_mouse = 1; // Display sample mouse pointer controlled by head movement
|
||||
|
@ -338,7 +337,6 @@ void init(void)
|
|||
|
||||
if (noise_on)
|
||||
{
|
||||
myHand.setNoise(noise);
|
||||
myHead.setNoise(noise);
|
||||
}
|
||||
|
||||
|
@ -366,6 +364,9 @@ void terminate () {
|
|||
//close(serial_fd);
|
||||
|
||||
audio.terminate();
|
||||
stopNetworkReceiveThread = true;
|
||||
pthread_join(networkReceiveThread, NULL);
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
|
@ -389,7 +390,6 @@ void reset_sensors()
|
|||
head_lean_y = HEIGHT/2;
|
||||
|
||||
myHead.reset();
|
||||
myHand.reset();
|
||||
|
||||
if (serialPort.active) {
|
||||
serialPort.resetTrailingAverages();
|
||||
|
@ -420,20 +420,6 @@ void update_pos(float frametime)
|
|||
head_mouse_y = max(head_mouse_y, 0);
|
||||
head_mouse_y = min(head_mouse_y, HEIGHT);
|
||||
|
||||
// Update hand/manipulator location for measured forces from serial channel
|
||||
/*
|
||||
const float MIN_HAND_ACCEL = 30.0;
|
||||
const float HAND_FORCE_SCALE = 0.5;
|
||||
glm::vec3 hand_accel(-(avg_adc_channels[6] - adc_channels[6]),
|
||||
-(avg_adc_channels[7] - adc_channels[7]),
|
||||
-(avg_adc_channels[5] - adc_channels[5]));
|
||||
|
||||
if (glm::length(hand_accel) > MIN_HAND_ACCEL)
|
||||
{
|
||||
myHand.addVel(frametime*hand_accel*HAND_FORCE_SCALE);
|
||||
}
|
||||
*/
|
||||
|
||||
// Update render direction (pitch/yaw) based on measured gyro rates
|
||||
const int MIN_YAW_RATE = 100;
|
||||
const float YAW_SENSITIVITY = 0.08;
|
||||
|
@ -511,9 +497,6 @@ void update_pos(float frametime)
|
|||
location[0] += fwd_vec[2]*-lateral_vel;
|
||||
location[2] += fwd_vec[0]*lateral_vel;
|
||||
|
||||
// Update manipulator objects with object with current location
|
||||
balls.updateHand(myHead.getPos() + myHand.getPos(), glm::vec3(0,0,0), myHand.getRadius());
|
||||
|
||||
// Update own head data
|
||||
myHead.setRenderYaw(myHead.getRenderYaw() + render_yaw_rate);
|
||||
myHead.setRenderPitch(render_pitch);
|
||||
|
@ -600,22 +583,18 @@ void display(void)
|
|||
}
|
||||
}
|
||||
|
||||
if (display_hand) myHand.render();
|
||||
|
||||
if (!display_head) balls.render();
|
||||
|
||||
// Render the world box
|
||||
if (!display_head && stats_on) render_world_box();
|
||||
|
||||
// Render my own head
|
||||
|
||||
if (display_head) {
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glTranslatef(0.f, 0.f, -7.f);
|
||||
myHead.render(1, &location[0]);
|
||||
glPopMatrix();
|
||||
}
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glTranslatef(0.f, 0.f, -7.f);
|
||||
myHead.render(display_head, &location[0]);
|
||||
glPopMatrix();
|
||||
|
||||
//glm::vec3 test(0.5, 0.5, 0.5);
|
||||
//render_vector(&test);
|
||||
|
||||
|
@ -721,18 +700,15 @@ void key(unsigned char k, int x, int y)
|
|||
noise_on = !noise_on; // Toggle noise
|
||||
if (noise_on)
|
||||
{
|
||||
myHand.setNoise(noise);
|
||||
myHead.setNoise(noise);
|
||||
}
|
||||
else
|
||||
{
|
||||
myHand.setNoise(0);
|
||||
myHead.setNoise(0);
|
||||
}
|
||||
|
||||
}
|
||||
if (k == 'h') display_head = !display_head;
|
||||
if (k == 'b') display_hand = !display_hand;
|
||||
if (k == 'm') head_mirror = !head_mirror;
|
||||
|
||||
if (k == 'f') display_field = !display_field;
|
||||
|
@ -769,7 +745,7 @@ void *networkReceive(void *args)
|
|||
ssize_t bytesReceived;
|
||||
char *incomingPacket = new char[MAX_PACKET_SIZE];
|
||||
|
||||
while (true) {
|
||||
while (!stopNetworkReceiveThread) {
|
||||
if (agentList.getAgentSocket()->receive(&senderAddress, incomingPacket, &bytesReceived)) {
|
||||
packetcount++;
|
||||
bytescount += bytesReceived;
|
||||
|
@ -795,7 +771,6 @@ void idle(void)
|
|||
if (simulate_on) {
|
||||
field.simulate(1.f/FPS);
|
||||
myHead.simulate(1.f/FPS);
|
||||
myHand.simulate(1.f/FPS);
|
||||
balls.simulate(1.f/FPS);
|
||||
cloud.simulate(1.f/FPS);
|
||||
lattice.simulate(1.f/FPS);
|
||||
|
@ -943,8 +918,10 @@ int main(int argc, char** argv)
|
|||
agentList.linkedDataCreateCallback = &attachNewHeadToAgent;
|
||||
agentList.audioMixerSocketUpdate = &audioMixerUpdate;
|
||||
|
||||
// start the thread which checks for silent agents
|
||||
agentList.startSilentAgentRemovalThread();
|
||||
|
||||
// create thread for receipt of data via UDP
|
||||
pthread_t networkReceiveThread;
|
||||
pthread_create(&networkReceiveThread, NULL, networkReceive, NULL);
|
||||
|
||||
glutInit(&argc, argv);
|
||||
|
@ -979,7 +956,6 @@ int main(int argc, char** argv)
|
|||
|
||||
glutMainLoop();
|
||||
|
||||
pthread_join(networkReceiveThread, NULL);
|
||||
::terminate();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -7,4 +7,11 @@ file(GLOB HIFI_SHARED_SRCS src/*.h src/*.cpp)
|
|||
|
||||
# create a library and set the property so it can be referenced later
|
||||
add_library(HifiShared ${HIFI_SHARED_SRCS})
|
||||
set(HIFI_SHARED_LIBRARY HifiShared)
|
||||
set(HIFI_SHARED_LIBRARY HifiShared)
|
||||
|
||||
# link required libraries on UNIX
|
||||
if (UNIX AND NOT APPLE)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
target_link_libraries(HifiShared ${CMAKE_THREAD_LIBS_INIT})
|
||||
endif (UNIX AND NOT APPLE)
|
|
@ -10,10 +10,9 @@
|
|||
#include <arpa/inet.h>
|
||||
#include <cstring>
|
||||
#include "UDPSocket.h"
|
||||
#include "SharedUtil.h"
|
||||
|
||||
Agent::Agent() {
|
||||
|
||||
}
|
||||
Agent::Agent() {}
|
||||
|
||||
Agent::Agent(sockaddr *agentPublicSocket, sockaddr *agentLocalSocket, char agentType) {
|
||||
publicSocket = new sockaddr;
|
||||
|
@ -23,6 +22,7 @@ Agent::Agent(sockaddr *agentPublicSocket, sockaddr *agentLocalSocket, char agent
|
|||
memcpy(localSocket, agentLocalSocket, sizeof(sockaddr));
|
||||
|
||||
type = agentType;
|
||||
lastRecvTimeUsecs = usecTimestampNow();
|
||||
|
||||
activeSocket = NULL;
|
||||
linkedData = NULL;
|
||||
|
@ -43,6 +43,7 @@ Agent::Agent(const Agent &otherAgent) {
|
|||
activeSocket = NULL;
|
||||
}
|
||||
|
||||
lastRecvTimeUsecs = otherAgent.lastRecvTimeUsecs;
|
||||
type = otherAgent.type;
|
||||
|
||||
// linked data is transient, gets re-assigned on next packet receive
|
||||
|
|
|
@ -28,6 +28,7 @@ class Agent {
|
|||
char type;
|
||||
timeval pingStarted;
|
||||
int pingMsecs;
|
||||
double lastRecvTimeUsecs;
|
||||
bool isSelf;
|
||||
AgentData *linkedData;
|
||||
|
||||
|
|
|
@ -8,6 +8,11 @@
|
|||
|
||||
#include "AgentList.h"
|
||||
#include <arpa/inet.h>
|
||||
#include <pthread.h>
|
||||
#include "SharedUtil.h"
|
||||
|
||||
bool stopAgentRemovalThread = false;
|
||||
pthread_mutex_t vectorChangeMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
AgentList::AgentList() : agentSocket(AGENT_SOCKET_LISTEN_PORT) {
|
||||
linkedDataCreateCallback = NULL;
|
||||
|
@ -15,7 +20,12 @@ AgentList::AgentList() : agentSocket(AGENT_SOCKET_LISTEN_PORT) {
|
|||
}
|
||||
|
||||
AgentList::AgentList(int socketListenPort) : agentSocket(socketListenPort) {
|
||||
|
||||
linkedDataCreateCallback = NULL;
|
||||
audioMixerSocketUpdate = NULL;
|
||||
}
|
||||
|
||||
AgentList::~AgentList() {
|
||||
stopSilentAgentRemovalThread();
|
||||
}
|
||||
|
||||
UDPSocket * AgentList::getAgentSocket() {
|
||||
|
@ -59,6 +69,8 @@ void AgentList::updateAgentWithData(sockaddr *senderAddress, void *packetData, s
|
|||
if (agentIndex != -1) {
|
||||
Agent *matchingAgent = &agents[agentIndex];
|
||||
|
||||
matchingAgent->lastRecvTimeUsecs = usecTimestampNow();
|
||||
|
||||
if (matchingAgent->linkedData == NULL) {
|
||||
if (linkedDataCreateCallback != NULL) {
|
||||
linkedDataCreateCallback(matchingAgent);
|
||||
|
@ -135,11 +147,20 @@ bool AgentList::addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket,
|
|||
|
||||
std::cout << "Added agent - " << &newAgent << "\n";
|
||||
|
||||
agents.push_back(newAgent);
|
||||
pthread_mutex_lock(&vectorChangeMutex);
|
||||
agents.push_back(newAgent);
|
||||
pthread_mutex_unlock(&vectorChangeMutex);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
// we had this agent already
|
||||
|
||||
if (agent->type == 'M') {
|
||||
// until the Audio class also uses our agentList, we need to update
|
||||
// the lastRecvTimeUsecs for the audio mixer so it doesn't get killed and re-added continously
|
||||
agent->lastRecvTimeUsecs = usecTimestampNow();
|
||||
}
|
||||
|
||||
// we had this agent already, do nothing for now
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -150,12 +171,11 @@ void AgentList::broadcastToAgents(char *broadcastData, size_t dataBytes) {
|
|||
// until the Audio class uses the AgentList
|
||||
if (agent->activeSocket != NULL && agent->type == 'I') {
|
||||
// we know which socket is good for this agent, send there
|
||||
agentSocket.send((sockaddr *)agent->activeSocket, broadcastData, dataBytes);
|
||||
agentSocket.send(agent->activeSocket, broadcastData, dataBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AgentList::pingAgents() {
|
||||
char payload[] = "P";
|
||||
|
||||
|
@ -163,7 +183,7 @@ void AgentList::pingAgents() {
|
|||
if (agent->type == 'I') {
|
||||
if (agent->activeSocket != NULL) {
|
||||
// we know which socket is good for this agent, send there
|
||||
agentSocket.send((sockaddr *)agent->activeSocket, payload, 1);
|
||||
agentSocket.send(agent->activeSocket, payload, 1);
|
||||
} else {
|
||||
// ping both of the sockets for the agent so we can figure out
|
||||
// which socket we can use
|
||||
|
@ -193,4 +213,39 @@ void AgentList::handlePingReply(sockaddr *agentAddress) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *removeSilentAgents(void *args) {
|
||||
std::vector<Agent> *agents = (std::vector<Agent> *)args;
|
||||
double checkTimeUSecs, sleepTime;
|
||||
|
||||
while (!stopAgentRemovalThread) {
|
||||
checkTimeUSecs = usecTimestampNow();
|
||||
|
||||
for(std::vector<Agent>::iterator agent = agents->begin(); agent != agents->end();) {
|
||||
if ((checkTimeUSecs - agent->lastRecvTimeUsecs) > AGENT_SILENCE_THRESHOLD_USECS) {
|
||||
std::cout << "Killing agent " << &(*agent) << "\n";
|
||||
pthread_mutex_lock(&vectorChangeMutex);
|
||||
agent = agents->erase(agent);
|
||||
pthread_mutex_unlock(&vectorChangeMutex);
|
||||
} else {
|
||||
agent++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sleepTime = AGENT_SILENCE_THRESHOLD_USECS - (usecTimestampNow() - checkTimeUSecs);
|
||||
usleep(sleepTime);
|
||||
}
|
||||
|
||||
pthread_exit(0);
|
||||
}
|
||||
|
||||
void AgentList::startSilentAgentRemovalThread() {
|
||||
pthread_create(&removeSilentAgentsThread, NULL, removeSilentAgents, (void *)&agents);
|
||||
}
|
||||
|
||||
void AgentList::stopSilentAgentRemovalThread() {
|
||||
stopAgentRemovalThread = true;
|
||||
pthread_join(removeSilentAgentsThread, NULL);
|
||||
}
|
|
@ -15,11 +15,13 @@
|
|||
#include "UDPSocket.h"
|
||||
|
||||
const unsigned short AGENT_SOCKET_LISTEN_PORT = 40103;
|
||||
const int AGENT_SILENCE_THRESHOLD_USECS = 2 * 1000000;
|
||||
|
||||
class AgentList {
|
||||
public:
|
||||
AgentList();
|
||||
AgentList(int socketListenPort);
|
||||
~AgentList();
|
||||
std::vector<Agent> agents;
|
||||
void(*linkedDataCreateCallback)(Agent *);
|
||||
void(*audioMixerSocketUpdate)(in_addr_t, in_port_t);
|
||||
|
@ -30,12 +32,16 @@ class AgentList {
|
|||
bool addOrUpdateAgent(sockaddr *publicSocket, sockaddr *localSocket, char agentType);
|
||||
void processAgentData(sockaddr *senderAddress, void *packetData, size_t dataBytes);
|
||||
void broadcastToAgents(char *broadcastData, size_t dataBytes);
|
||||
void sendToAgent(Agent *destAgent, void *packetData, size_t dataBytes);
|
||||
void pingAgents();
|
||||
void startSilentAgentRemovalThread();
|
||||
void stopSilentAgentRemovalThread();
|
||||
private:
|
||||
UDPSocket agentSocket;
|
||||
int indexOfMatchingAgent(sockaddr *senderAddress);
|
||||
void updateAgentWithData(sockaddr *senderAddress, void *packetData, size_t dataBytes);
|
||||
void handlePingReply(sockaddr *agentAddress);
|
||||
UDPSocket agentSocket;
|
||||
pthread_t removeSilentAgentsThread;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__AgentList__) */
|
||||
|
|
19
shared/src/SharedUtil.cpp
Normal file
19
shared/src/SharedUtil.cpp
Normal file
|
@ -0,0 +1,19 @@
|
|||
//
|
||||
// SharedUtil.cpp
|
||||
// hifi
|
||||
//
|
||||
// Created by Stephen Birarda on 2/22/13.
|
||||
//
|
||||
//
|
||||
|
||||
#include "SharedUtil.h"
|
||||
|
||||
double usecTimestamp(timeval *time) {
|
||||
return (time->tv_sec * 1000000.0);
|
||||
}
|
||||
|
||||
double usecTimestampNow() {
|
||||
timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
return (now.tv_sec * 1000000.0);
|
||||
}
|
18
shared/src/SharedUtil.h
Normal file
18
shared/src/SharedUtil.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
//
|
||||
// SharedUtil.h
|
||||
// hifi
|
||||
//
|
||||
// Created by Stephen Birarda on 2/22/13.
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef __hifi__SharedUtil__
|
||||
#define __hifi__SharedUtil__
|
||||
|
||||
#include <iostream>
|
||||
#include <sys/time.h>
|
||||
|
||||
double usecTimestamp(timeval *time);
|
||||
double usecTimestampNow();
|
||||
|
||||
#endif /* defined(__hifi__SharedUtil__) */
|
|
@ -81,6 +81,12 @@ UDPSocket::UDPSocket(int listeningPort) {
|
|||
return;
|
||||
}
|
||||
|
||||
// set timeout on socket recieve to 0.5 seconds
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 500000;
|
||||
setsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof tv);
|
||||
|
||||
printf("Created UDP socket listening on port %d.\n", listeningPort);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue