Merge branch 'master' of github.com:worklist/hifi

This commit is contained in:
Stephen Birarda 2013-02-12 11:34:23 -08:00
commit 0bd62be1c3
13 changed files with 189 additions and 316 deletions

View file

@ -43,6 +43,8 @@ struct AgentList {
int num_agents = 0; int num_agents = 0;
int lastActiveCount = 0;
double diffclock(timeval clock1,timeval clock2) double diffclock(timeval clock1,timeval clock2)
{ {
double diffms = (clock2.tv_sec - clock1.tv_sec) * 1000.0; double diffms = (clock2.tv_sec - clock1.tv_sec) * 1000.0;
@ -115,7 +117,8 @@ void update_agent_list(timeval now) {
for (i = 0; i < num_agents; i++) { for (i = 0; i < num_agents; i++) {
if ((diffclock(agents[i].time, now) > LOGOFF_CHECK_INTERVAL) && if ((diffclock(agents[i].time, now) > LOGOFF_CHECK_INTERVAL) &&
agents[i].active) { agents[i].active) {
std::cout << "Expired Agent #" << i+1 << "\n"; std::cout << "Expired Agent from " <<
inet_ntoa(agents[i].sin_addr) << ":" << agents[i].port << "\n";
agents[i].active = false; agents[i].active = false;
} }
} }
@ -127,7 +130,8 @@ void send_agent_list(int handle, sockaddr_in * dest_address) {
char buffer[MAX_PACKET_SIZE]; char buffer[MAX_PACKET_SIZE];
char * address; char * address;
char portstring[10]; char portstring[10];
buffer[length++] = 'S'; int numSent = 0;
buffer[length++] = 'D';
//std::cout << "send list to: " << inet_ntoa(dest_address->sin_addr) << "\n"; //std::cout << "send list to: " << inet_ntoa(dest_address->sin_addr) << "\n";
for (i = 0; i < num_agents; i++) { for (i = 0; i < num_agents; i++) {
if (agents[i].active) { if (agents[i].active) {
@ -142,6 +146,7 @@ void send_agent_list(int handle, sockaddr_in * dest_address) {
length += strlen(portstring); length += strlen(portstring);
// Add comma separator between agents // Add comma separator between agents
buffer[length++] = ','; buffer[length++] = ',';
numSent++;
} }
} }
if (length > 1) { if (length > 1) {
@ -149,8 +154,10 @@ void send_agent_list(int handle, sockaddr_in * dest_address) {
0, (sockaddr *) dest_address, sizeof(sockaddr_in) ); 0, (sockaddr *) dest_address, sizeof(sockaddr_in) );
if (sent_bytes < length) if (sent_bytes < length)
std::cout << "Error sending agent list!\n"; std::cout << "Error sending agent list!\n";
else else if (numSent != lastActiveCount) {
std::cout << "Agent list sent: " << buffer << "\n"; std::cout << numSent << " Active Agents\n";
lastActiveCount = numSent;
}
} }
} }
@ -167,7 +174,7 @@ int main(int argc, const char * argv[])
std::cout << "Failed to create network.\n"; std::cout << "Failed to create network.\n";
return 0; return 0;
} else { } else {
std::cout << "DomainServer Started. Waiting for packets.\n"; std::cout << "DomainServer started, listening on port " << LISTENING_UDP_PORT << "\n";
} }
gettimeofday(&last_time, NULL); gettimeofday(&last_time, NULL);
@ -179,9 +186,9 @@ int main(int argc, const char * argv[])
//<< " " << packet_data << "\n"; //<< " " << packet_data << "\n";
float x,y,z; float x,y,z;
sscanf(packet_data, "%f,%f,%f", &x, &y, &z); sscanf(packet_data, "%f,%f,%f", &x, &y, &z);
if (addAgent(dest_address.sin_addr.s_addr, dest_address.sin_port, x, y, z)) { if (addAgent(dest_address.sin_addr.s_addr, ntohs(dest_address.sin_port), x, y, z)) {
std::cout << "Added agent from IP, port: " << std::cout << "Added Agent from " <<
inet_ntoa(dest_address.sin_addr) << "," << dest_address.sin_port << "\n"; inet_ntoa(dest_address.sin_addr) << ":" << ntohs(dest_address.sin_port) << "\n";
} }
// Reply with packet listing nearby active agents // Reply with packet listing nearby active agents
send_agent_list(handle, &dest_address); send_agent_list(handle, &dest_address);

View file

@ -10,36 +10,47 @@
#include "Agent.h" #include "Agent.h"
#include "Head.h" #include "Head.h"
// Structure to hold references to other agents that are nearby // Structure to hold references to other agents that are nearby
const int MAX_AGENTS = 100; const int MAX_AGENTS = 100;
struct AgentList { struct AgentList {
in_addr sin_addr; char address[255];
unsigned short port;
Head head; Head head;
} agents[MAX_AGENTS]; } agents[MAX_AGENTS];
int num_agents = 0; int num_agents = 0;
// //
// Process an incoming domainserver packet telling you about other nearby agents // Process an incoming domainserver packet telling you about other nearby agents,
// and returns the number of agents that were reported.
// //
void update_agents(char * data, int length) { int update_agents(char * data, int length) {
int numAgents = 0;
std::string packet(data, length); std::string packet(data, length);
//std::cout << " Update Agents, string: " << packet << "\n";
size_t spot; size_t spot;
size_t start_spot = 0; size_t start_spot = 0;
std::string address, port;
unsigned short nPort = 0;
spot = packet.find_first_of (",", 0); spot = packet.find_first_of (",", 0);
while (spot != std::string::npos) { while (spot != std::string::npos) {
std::string IPstring = packet.substr(start_spot, spot-start_spot); std::string thisAgent = packet.substr(start_spot, spot-start_spot);
//std::cout << "Found " << num_agents << if (thisAgent.find_first_of(":", 0) != std::string::npos) {
//" with IP " << IPstring << " from " << start_spot << " to " << spot << "\n"; address = thisAgent.substr(0, thisAgent.find_first_of(":", 0));
// Add the IP address to the agent table port = thisAgent.substr(thisAgent.find_first_of(":", 0) + 1,
add_agent(&IPstring); thisAgent.length() - thisAgent.find_first_of(":", 0));
nPort = atoi(port.c_str());
}
//std::cout << "IP: " << address << ", port: " << nPort << "\n";
add_agent((char *)address.c_str(), nPort);
numAgents++;
start_spot = spot + 1; start_spot = spot + 1;
if (start_spot < packet.length()) if (start_spot < packet.length())
spot = packet.find_first_of (",", start_spot); spot = packet.find_first_of (",", start_spot);
else spot = std::string::npos; else spot = std::string::npos;
} }
return numAgents;
} }
void render_agents() { void render_agents() {
@ -55,11 +66,11 @@ void render_agents() {
// //
// Update a single agent with data received from that agent's IP address // Update a single agent with data received from that agent's IP address
// //
void update_agent(in_addr addr, char * data, int length) void update_agent(char * address, unsigned short port, char * data, int length)
{ {
std::cout << "Looking for agent: " << inet_ntoa(addr) << "\n"; //printf("%s:%d\n", address, port);
for (int i = 0; i < num_agents; i++) { for (int i = 0; i < num_agents; i++) {
if (agents[i].sin_addr.s_addr == addr.s_addr) { if ((strcmp(address, agents[i].address) == 0) && (agents[i].port == port)) {
// Update the agent // Update the agent
agents[i].head.recvBroadcastData(data, length); agents[i].head.recvBroadcastData(data, length);
} }
@ -69,19 +80,19 @@ void update_agent(in_addr addr, char * data, int length)
// //
// Look for an agent by it's IP number, add if it does not exist in local list // Look for an agent by it's IP number, add if it does not exist in local list
// //
int add_agent(std::string * IP) { int add_agent(char * address, unsigned short port) {
in_addr_t addr = inet_addr(IP->c_str());
//std::cout << "Checking for " << IP->c_str() << " "; //std::cout << "Checking for " << IP->c_str() << " ";
for (int i = 0; i < num_agents; i++) { for (int i = 0; i < num_agents; i++) {
if (agents[i].sin_addr.s_addr == addr) { if ((strcmp(address, agents[i].address) == 0) && (agents[i].port == port)) {
//std::cout << "Found!\n"; std::cout << "Found agent!\n";
return 0; return 0;
} }
} }
if (num_agents < MAX_AGENTS) { if (num_agents < MAX_AGENTS) {
agents[num_agents].sin_addr.s_addr = addr; strcpy(agents[num_agents].address, address);
std::cout << "Added Agent # " << num_agents << " with IP " << agents[num_agents].port = port;
inet_ntoa(agents[num_agents].sin_addr) << "\n"; std::cout << "Added Agent # " << num_agents << " with Address " <<
agents[num_agents].address << ":" << agents[num_agents].port << "\n";
num_agents++; num_agents++;
return 1; return 1;
} else { } else {
@ -91,18 +102,22 @@ int add_agent(std::string * IP) {
} }
// //
// Broadcast data to all the other agents you are aware of, returns 1 for success // Broadcast data to all the other agents you are aware of, returns 1 if success
// //
int broadcast_to_agents(int handle, char * data, int length) { int broadcast_to_agents(UDPSocket *handle, char * data, int length) {
sockaddr_in dest_address;
dest_address.sin_family = AF_INET;
dest_address.sin_port = htons( (unsigned short) AGENT_UDP_PORT );
int sent_bytes; int sent_bytes;
//printf("broadcasting to %d agents\n", num_agents);
for (int i = 0; i < num_agents; i++) { for (int i = 0; i < num_agents; i++) {
dest_address.sin_addr.s_addr = agents[i].sin_addr.s_addr; //printf("bcast to %s\n", agents[i].address);
sent_bytes = sendto( handle, (const char*)data, length, //
0, (sockaddr*)&dest_address, sizeof(sockaddr_in) ); // STUPID HACK: For some reason on OSX with NAT translation packets sent to localhost are
// received as from the NAT translated port but have to be sent to the local port number.
//
//if (1) //(strcmp("192.168.1.53",agents[i].address) == 0)
// sent_bytes = handle->send(agents[i].address, 40103, data, length);
//else
sent_bytes = handle->send(agents[i].address, agents[i].port, data, length);
if (sent_bytes != length) { if (sent_bytes != length) {
std::cout << "Broadcast packet fail!\n"; std::cout << "Broadcast packet fail!\n";
return 0; return 0;

View file

@ -15,12 +15,13 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#include <fcntl.h> #include <fcntl.h>
#include <string.h> #include <string.h>
#include "Network.h" #include "UDPSocket.h"
void update_agents(char * data, int length);
int add_agent(std::string * IP); int update_agents(char * data, int length);
int broadcast_to_agents(int handle, char * data, int length); int add_agent(char * address, unsigned short port);
void update_agent(in_addr addr, char * data, int length); int broadcast_to_agents(UDPSocket * handle, char * data, int length);
void update_agent(char * address, unsigned short port, char * data, int length);
void render_agents(); void render_agents();
#endif #endif

View file

@ -87,6 +87,16 @@ int audioCallback (const void *inputBuffer,
if (inputLeft != NULL) { if (inputLeft != NULL) {
data->audioSocket->send((char *) EC2_WEST_AUDIO_SERVER, 55443, (void *)inputLeft, BUFFER_LENGTH_BYTES); data->audioSocket->send((char *) EC2_WEST_AUDIO_SERVER, 55443, (void *)inputLeft, BUFFER_LENGTH_BYTES);
//
// Measure the loudness of the signal from the microphone and store in audio object
//
float loudness = 0;
for (int i = 0; i < BUFFER_LENGTH_SAMPLES; i++) {
loudness += abs(inputLeft[i]);
}
loudness /= BUFFER_LENGTH_SAMPLES;
data->lastInputLoudness = loudness;
data->averagedInputLoudness = 0.66*data->averagedInputLoudness + 0.33*loudness;
} }
int16_t *outputLeft = ((int16_t **) outputBuffer)[0]; int16_t *outputLeft = ((int16_t **) outputBuffer)[0];
@ -366,6 +376,11 @@ void Audio::render()
} }
} }
void Audio::getInputLoudness(float * lastLoudness, float * averageLoudness) {
*lastLoudness = data->lastInputLoudness;
*averageLoudness = data->averagedInputLoudness;
}
void Audio::render(int screenWidth, int screenHeight) void Audio::render(int screenWidth, int screenHeight)
{ {
if (initialized && ECHO_SERVER_TEST) { if (initialized && ECHO_SERVER_TEST) {

View file

@ -23,6 +23,8 @@ public:
static void render(); static void render();
static void render(int screenWidth, int screenHeight); static void render(int screenWidth, int screenHeight);
static void getInputLoudness(float * lastLoudness, float * averageLoudness);
// terminates audio I/O // terminates audio I/O
static bool terminate(); static bool terminate();
private: private:

View file

@ -32,6 +32,9 @@ class AudioData {
float measuredJitter; float measuredJitter;
float jitterBuffer; float jitterBuffer;
int wasStarved; int wasStarved;
float lastInputLoudness;
float averagedInputLoudness;
AudioData(int bufferLength); AudioData(int bufferLength);
AudioData(int numberOfSources, int bufferLength); AudioData(int numberOfSources, int bufferLength);

View file

@ -12,6 +12,7 @@
#include "Head.h" #include "Head.h"
#include "Util.h" #include "Util.h"
#include "SerialInterface.h" #include "SerialInterface.h"
#include "Audio.h"
float skinColor[] = {1.0, 0.84, 0.66}; float skinColor[] = {1.0, 0.84, 0.66};
float browColor[] = {210.0/255.0, 105.0/255.0, 30.0/255.0}; float browColor[] = {210.0/255.0, 105.0/255.0, 30.0/255.0};
@ -275,12 +276,13 @@ void Head::render(int faceToFace)
// Mouth // Mouth
glPushMatrix(); glPushMatrix();
glTranslatef(0,-0.3,0.75); glTranslatef(0,-0.3,0.75);
glColor3fv(mouthColor); glColor3f(loudness/1000.0,0,0);
glRotatef(MouthPitch, 1, 0, 0); glRotatef(MouthPitch, 1, 0, 0);
glRotatef(MouthYaw, 0, 0, 1); glRotatef(MouthYaw, 0, 0, 1);
glScalef(MouthWidth, MouthHeight, 1); glScalef(MouthWidth*(.5 + averageLoudness/3000.0), MouthHeight*(1.0 + averageLoudness/6000.0), 1);
glutSolidCube(0.5); glutSolidCube(0.5);
glPopMatrix(); glPopMatrix();
@ -338,14 +340,19 @@ void Head::render(int faceToFace)
int Head::getBroadcastData(char* data) int Head::getBroadcastData(char* data)
{ {
// Copy data for transmission to the buffer, return length of data // Copy data for transmission to the buffer, return length of data
sprintf(data, "H%f,%f,%f,%f,%f,%f", Pitch + getRenderPitch(), Yaw + getRenderYaw(), Roll, position.x, position.y, position.z); sprintf(data, "H%f,%f,%f,%f,%f,%f,%f,%f", Pitch + getRenderPitch(), Yaw + getRenderYaw(), Roll,
position.x, position.y, position.z,
loudness, averageLoudness);
//printf("x: %3.1f\n", position.x); //printf("x: %3.1f\n", position.x);
return strlen(data); return strlen(data);
} }
void Head::recvBroadcastData(char * data, int size) void Head::recvBroadcastData(char * data, int size)
{ {
sscanf(data, "H%f,%f,%f,%f,%f,%f", &Pitch, &Yaw, &Roll, &position.x, &position.y, &position.z); sscanf(data, "%f,%f,%f,%f,%f,%f,%f,%f", &Pitch, &Yaw, &Roll,
&position.x, &position.y, &position.z,
&loudness, &averageLoudness);
//printf("%f,%f,%f,%f,%f,%f\n", Pitch, Yaw, Roll, position.x, position.y, position.z);
} }
void Head::SetNewHeadTarget(float pitch, float yaw) void Head::SetNewHeadTarget(float pitch, float yaw)

View file

@ -45,6 +45,11 @@ class Head {
float NoiseEnvelope; float NoiseEnvelope;
float PupilConverge; float PupilConverge;
float scale; float scale;
// Sound loudness information
float loudness;
float averageLoudness;
glm::vec3 position; glm::vec3 position;
int eyeContact; int eyeContact;
eyeContactTargets eyeContactTarget; eyeContactTargets eyeContactTarget;
@ -80,6 +85,12 @@ public:
// Send and receive network data // Send and receive network data
int getBroadcastData(char* data); int getBroadcastData(char* data);
void recvBroadcastData(char * data, int size); void recvBroadcastData(char * data, int size);
float getLoudness() {return loudness;};
float getAverageLoudness() {return averageLoudness;};
float setAverageLoudness(float al) {averageLoudness = al;};
float setLoudness(float l) {loudness = l;};
void SetNewHeadTarget(float, float); void SetNewHeadTarget(float, float);
glm::vec3 getPos() { return position; }; glm::vec3 getPos() { return position; };
void setPos(glm::vec3 newpos) { position = newpos; }; void setPos(glm::vec3 newpos) { position = newpos; };

View file

@ -1,156 +0,0 @@
//
// Network.cpp
// interface
//
// Created by Philip Rosedale on 8/27/12.
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
//
#include <iostream>
#include <stdio.h>
#include <cstring>
#include "Network.h"
// Implementation of optional delay behavior using a ring buffer
const int MAX_DELAY_PACKETS = 300;
char delay_buffer[MAX_PACKET_SIZE*MAX_DELAY_PACKETS];
timeval delay_time_received[MAX_DELAY_PACKETS];
int delay_size_received[MAX_DELAY_PACKETS];
int next_to_receive = 0;
int next_to_send = 0;
sockaddr_in address, dest_address, domainserver_address, from;
socklen_t fromLength = sizeof( from );
int network_init()
{
// Create socket
int handle = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
if ( handle <= 0 )
{
printf( "failed to create socket\n" );
return false;
}
// Bind socket to port
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( (unsigned short) SENDING_UDP_PORT );
if ( bind( handle, (const sockaddr*) &address, sizeof(sockaddr_in) ) < 0 )
{
printf( "failed to bind socket\n" );
return false;
}
// Set socket as non-blocking
int nonBlocking = 1;
if ( fcntl( handle, F_SETFL, O_NONBLOCK, nonBlocking ) == -1 )
{
printf( "failed to set non-blocking socket\n" );
return false;
}
// Setup desination address
/*unsigned int ip_address;
if (!inet_pton(AF_INET, DESTINATION_IP, &ip_address))
{
printf("failed to translate destination IP address\n");
return false;
}*/
dest_address.sin_family = AF_INET;
dest_address.sin_addr.s_addr = inet_addr(DESTINATION_IP);
//dest_address.sin_port = htons( (unsigned short) UDP_PORT );
domainserver_address.sin_family = AF_INET;
domainserver_address.sin_addr.s_addr = inet_addr(DOMAINSERVER_IP);
domainserver_address.sin_port = htons( (unsigned short) DOMAINSERVER_PORT );
from.sin_family = AF_INET;
//from.sin_addr.s_addr = htonl(ip_address);
//from.sin_port = htons( (unsigned short) UDP_PORT );
return handle;
}
// Send a ping packet and mark the time sent
timeval network_send_ping(int handle) {
timeval check;
char packet_data[] = "P";
sendto(handle, (const char*)packet_data, 1,
0, (sockaddr*)&dest_address, sizeof(sockaddr_in) );
gettimeofday(&check, NULL);
return check;
}
int notify_domainserver(int handle, float x, float y, float z) {
char data[100];
sprintf(data, "%f,%f,%f", x, y, z);
int packet_size = strlen(data);
//std::cout << "sending: " << data << " of size: " << packet_size << "\n";
int sent_bytes = sendto( handle, (const char*)data, packet_size,
0, (sockaddr*)&domainserver_address, sizeof(sockaddr_in) );
if ( sent_bytes != packet_size )
{
printf( "failed to send to domainserver: return value = %d\n", sent_bytes );
return false;
}
return sent_bytes;
}
int network_send(int handle, char * packet_data, int packet_size)
{
int sent_bytes = 0;
sent_bytes = sendto( handle, (const char*)packet_data, packet_size,
0, (sockaddr*)&dest_address, sizeof(sockaddr_in) );
if ( sent_bytes != packet_size )
{
printf( "failed to send packet to address, port: %s, %d, returned = %d\n", inet_ntoa(dest_address.sin_addr), dest_address.sin_port, sent_bytes );
return false;
}
return sent_bytes;
}
int network_receive(int handle, in_addr * from_addr, char * packet_data, int delay /*msecs*/)
{
int received_bytes = recvfrom(handle, (char*)packet_data, MAX_PACKET_SIZE,
0, (sockaddr*)&dest_address, &fromLength );
from_addr->s_addr = dest_address.sin_addr.s_addr;
if (!delay) {
// No delay set, so just return packets immediately!
return received_bytes;
} else {
timeval check;
gettimeofday(&check, NULL);
if (received_bytes > 0) {
// First write received data into ring buffer
delay_time_received[next_to_receive] = check;
delay_size_received[next_to_receive] = received_bytes;
memcpy(&delay_buffer[next_to_receive*MAX_PACKET_SIZE], packet_data, received_bytes);
next_to_receive++;
if (next_to_receive == MAX_DELAY_PACKETS) next_to_receive = 0;
}
// Then check if next to be sent is past due, send if so
if ((next_to_receive != next_to_send) &&
(diffclock(&delay_time_received[next_to_send], &check) > delay)) {
int returned_bytes = delay_size_received[next_to_send];
memcpy(packet_data,
&delay_buffer[next_to_send*MAX_PACKET_SIZE],
returned_bytes);
next_to_send++;
if (next_to_send == MAX_DELAY_PACKETS) next_to_send = 0;
return returned_bytes;
} else {
return 0;
}
}
}

View file

@ -1,41 +0,0 @@
//
// Network.h
// interface
//
// Created by Philip Rosedale on 8/27/12.
// Copyright (c) 2012 High Fidelity, Inc. All rights reserved.
//
#ifndef __interface__Network__
#define __interface__Network__
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/time.h>
#include "Util.h"
// Port to use for communicating UDP with other nearby agents
const int MAX_PACKET_SIZE = 1500;
const int SENDING_UDP_PORT = 40100;
const int AGENT_UDP_PORT = 40103;
const char DESTINATION_IP[] = "127.0.0.1";
// Address and port of domainserver process to advertise other agents
const char DOMAINSERVER_IP[] = "127.0.0.1";
const int DOMAINSERVER_PORT = 40102;
// Randomly send a ping packet every N packets sent
const int PING_PACKET_COUNT = 20;
int network_init();
int network_send(int handle, char * packet_data, int packet_size);
int network_receive(int handle, in_addr * from_addr, char * packet_data, int delay /*msecs*/);
timeval network_send_ping(int handle);
int notify_domainserver(int handle, float x, float y, float z);
#endif

View file

@ -55,6 +55,7 @@ UDPSocket::~UDPSocket() {
close(handle); close(handle);
} }
// Receive data on this socket with retrieving address of sender
bool UDPSocket::receive(void *receivedData, int *receivedBytes) { bool UDPSocket::receive(void *receivedData, int *receivedBytes) {
*receivedBytes = recvfrom(handle, receivedData, MAX_BUFFER_LENGTH_BYTES, *receivedBytes = recvfrom(handle, receivedData, MAX_BUFFER_LENGTH_BYTES,
@ -63,6 +64,15 @@ bool UDPSocket::receive(void *receivedData, int *receivedBytes) {
return (*receivedBytes > 0); return (*receivedBytes > 0);
} }
// Receive data on this socket with the address of the sender
bool UDPSocket::receive(sockaddr_in *senderAddress, void *receivedData, int *receivedBytes) {
*receivedBytes = recvfrom(handle, receivedData, MAX_BUFFER_LENGTH_BYTES,
0, (sockaddr *)senderAddress, &addLength);
return (*receivedBytes > 0);
}
int UDPSocket::send(char * destAddress, int destPort, const void *data, int byteLength) { int UDPSocket::send(char * destAddress, int destPort, const void *data, int byteLength) {
// change address and port on reusable global to passed variables // change address and port on reusable global to passed variables

View file

@ -20,7 +20,8 @@ class UDPSocket {
~UDPSocket(); ~UDPSocket();
int send(char *destAddress, int destPort, const void *data, int byteLength); int send(char *destAddress, int destPort, const void *data, int byteLength);
bool receive(void *receivedData, int *receivedBytes); bool receive(void *receivedData, int *receivedBytes);
private: bool receive(sockaddr_in *senderAddress, void *receivedData, int *receivedBytes);
private:
int handle; int handle;
UDPSocket(); // private default constructor UDPSocket(); // private default constructor

View file

@ -34,7 +34,6 @@
#include "Field.h" #include "Field.h"
#include "world.h" #include "world.h"
#include "Util.h" #include "Util.h"
#include "Network.h"
#include "Audio.h" #include "Audio.h"
#include "Head.h" #include "Head.h"
#include "Hand.h" #include "Hand.h"
@ -51,14 +50,19 @@ using namespace std;
int audio_on = 1; // Whether to turn on the audio support int audio_on = 1; // Whether to turn on the audio support
int simulate_on = 1; int simulate_on = 1;
// Network Socket Stuff //
// Network Socket and network constants
//
const int MAX_PACKET_SIZE = 1500;
const int AGENT_UDP_PORT = 40103;
char DOMAINSERVER_IP[] = "192.168.1.53";
const int DOMAINSERVER_PORT = 40102;
UDPSocket agentSocket(AGENT_UDP_PORT);
// For testing, add milliseconds of delay for received UDP packets // For testing, add milliseconds of delay for received UDP packets
int UDP_socket;
int delay = 0;
char* incoming_packet; char* incoming_packet;
timeval ping_start;
int ping_count = 0;
float ping_msecs = 0.0;
int packetcount = 0; int packetcount = 0;
int packets_per_second = 0; int packets_per_second = 0;
int bytes_per_second = 0; int bytes_per_second = 0;
@ -68,7 +72,7 @@ int bytescount = 0;
int target_x, target_y; int target_x, target_y;
int target_display = 0; int target_display = 0;
int head_mirror = 1; // Whether to mirror the head when viewing it int head_mirror = 1; // Whether to mirror own head when viewing it
int WIDTH = 1200; int WIDTH = 1200;
int HEIGHT = 800; int HEIGHT = 800;
@ -76,8 +80,8 @@ int fullscreen = 0;
#define HAND_RADIUS 0.25 // Radius of in-world 'hand' of you #define HAND_RADIUS 0.25 // Radius of in-world 'hand' of you
Head myHead; // The rendered head of oneself or others Head myHead; // The rendered head of oneself or others
Head dummyHead; // Test Head to render Head dummyHead; // Test Head to render
int showDummyHead = 1; int showDummyHead = 0;
Hand myHand(HAND_RADIUS, Hand myHand(HAND_RADIUS,
glm::vec3(0,1,1)); // My hand (used to manipulate things in world) glm::vec3(0,1,1)); // My hand (used to manipulate things in world)
@ -91,10 +95,9 @@ ParticleSystem balls(0,
0.0 // Gravity 0.0 // Gravity
); );
Cloud cloud(0, // Particles Cloud cloud(0, // Particles
box, // Bounding Box box, // Bounding Box
false // Wrap false // Wrap
); );
VoxelSystem voxels(0, box); VoxelSystem voxels(0, box);
@ -146,6 +149,7 @@ int head_lean_x, head_lean_y;
int mouse_x, mouse_y; // Where is the mouse int mouse_x, mouse_y; // Where is the mouse
int mouse_pressed = 0; // true if mouse has been pressed (clear when finished) int mouse_pressed = 0; // true if mouse has been pressed (clear when finished)
int nearbyAgents = 0; // How many other people near you is the domain server reporting?
int speed; int speed;
@ -220,9 +224,15 @@ void Timer(int extra)
glutTimerFunc(1000,Timer,0); glutTimerFunc(1000,Timer,0);
gettimeofday(&timer_start, NULL); gettimeofday(&timer_start, NULL);
// Send a message to the domainserver telling it we are ALIVE // Send a message to the domainserver telling it we are ALIVE
notify_domainserver(UDP_socket, location[0], location[1], location[2]); char output[100];
sprintf(output, "%f,%f,%f", location[0], location[1], location[2]);
int packet_size = strlen(output);
agentSocket.send(DOMAINSERVER_IP, DOMAINSERVER_PORT, output, packet_size);
// Send a message to ourselves
//char test[]="T";
//agentSocket.send("127.0.0.1", AGENT_UDP_PORT, test, 1);
} }
void display_stats(void) void display_stats(void)
@ -232,13 +242,13 @@ void display_stats(void)
drawtext(10, 15, 0.10, 0, 1.0, 0, legend); drawtext(10, 15, 0.10, 0, 1.0, 0, legend);
char stats[200]; char stats[200];
sprintf(stats, "FPS = %3.0f, Ping = %4.1f Pkts/s = %d, Bytes/s = %d", sprintf(stats, "FPS = %3.0f, Pkts/s = %d, Bytes/s = %d",
FPS, ping_msecs, packets_per_second, bytes_per_second); FPS, packets_per_second, bytes_per_second);
drawtext(10, 30, 0.10, 0, 1.0, 0, stats); drawtext(10, 30, 0.10, 0, 1.0, 0, stats);
if (serial_on) { if (serial_on) {
sprintf(stats, "ADC samples = %d, LED = %d", sprintf(stats, "ADC samples = %d, LED = %d",
serialPort.getNumSamples(), serialPort.getLED()); serialPort.getNumSamples(), serialPort.getLED());
drawtext(500, 30, 0.10, 0, 1.0, 0, stats); drawtext(500, 30, 0.10, 0, 1.0, 0, stats);
} }
char adc[200]; char adc[200];
@ -247,8 +257,7 @@ void display_stats(void)
angle_to(myHead.getPos()*-1.f, glm::vec3(0,0,0), myHead.getRenderYaw(), myHead.getYaw()), angle_to(myHead.getPos()*-1.f, glm::vec3(0,0,0), myHead.getRenderYaw(), myHead.getYaw()),
myHead.getYaw(), myHead.getRenderYaw()); myHead.getYaw(), myHead.getRenderYaw());
drawtext(10, 50, 0.10, 0, 1.0, 0, adc); drawtext(10, 50, 0.10, 0, 1.0, 0, adc);
} }
void initDisplay(void) void initDisplay(void)
@ -262,7 +271,7 @@ void initDisplay(void)
glEnable(GL_LIGHT0); glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
load_png_as_texture(texture_filename); //load_png_as_texture(texture_filename);
if (fullscreen) glutFullScreen(); if (fullscreen) glutFullScreen();
} }
@ -499,16 +508,24 @@ void update_pos(float frametime)
myHead.setRenderYaw(myHead.getRenderYaw() + render_yaw_rate); myHead.setRenderYaw(myHead.getRenderYaw() + render_yaw_rate);
myHead.setRenderPitch(render_pitch); myHead.setRenderPitch(render_pitch);
myHead.setPos(glm::vec3(location[0], location[1], location[2])); myHead.setPos(glm::vec3(location[0], location[1], location[2]));
// Get audio loudness data from audio input device
float loudness, averageLoudness;
Audio::getInputLoudness(&loudness, &averageLoudness);
myHead.setLoudness(loudness);
myHead.setAverageLoudness(averageLoudness);
// Update all this stuff to any agents that are nearby and need to see it! // Send my streaming head data to agents that are nearby and need to see it!
const int MAX_BROADCAST_STRING = 200; const int MAX_BROADCAST_STRING = 200;
char broadcast_string[MAX_BROADCAST_STRING]; char broadcast_string[MAX_BROADCAST_STRING];
int broadcast_bytes = myHead.getBroadcastData(broadcast_string); int broadcast_bytes = myHead.getBroadcastData(broadcast_string);
dummyHead.recvBroadcastData(broadcast_string, broadcast_bytes); broadcast_to_agents(&agentSocket, broadcast_string, broadcast_bytes);
//printf("-> %s\n", broadcast_string);
//dummyHead.recvBroadcastData(broadcast_string, broadcast_bytes);
//printf("head bytes: %d\n", broadcast_bytes); //printf("head bytes: %d\n", broadcast_bytes);
broadcast_to_agents(UDP_socket, broadcast_string, broadcast_bytes);
} }
int render_test_spot = WIDTH/2; int render_test_spot = WIDTH/2;
@ -641,6 +658,12 @@ void display(void)
// Display miscellaneous text stats onscreen // Display miscellaneous text stats onscreen
if (stats_on) display_stats(); if (stats_on) display_stats();
// Draw number of nearby people always
char agents[100];
sprintf(agents, "Agents nearby: %d\n", nearbyAgents);
drawtext(WIDTH-200,20, 0.10, 0, 1.0, 0, agents, 1, 1, 0);
#ifdef MARKER_CAPTURE #ifdef MARKER_CAPTURE
/* Render marker acquisition stuff */ /* Render marker acquisition stuff */
@ -743,14 +766,15 @@ void key(unsigned char k, int x, int y)
} }
} }
// //
// Check for and process incoming network packets // Receive packets from other agents/servers and decide what to do with them!
// //
void read_network() void read_network()
{ {
// Receive packets sockaddr_in senderAddress;
in_addr from_addr; int bytes_recvd;
int bytes_recvd = network_receive(UDP_socket, &from_addr, incoming_packet, delay); agentSocket.receive(&senderAddress, (void *)incoming_packet, &bytes_recvd);
if (bytes_recvd > 0) if (bytes_recvd > 0)
{ {
packetcount++; packetcount++;
@ -763,23 +787,19 @@ void read_network()
sscanf(incoming_packet, "M %d %d", &target_x, &target_y); sscanf(incoming_packet, "M %d %d", &target_x, &target_y);
target_display = 1; target_display = 1;
//printf("X = %d Y = %d\n", target_x, target_y); //printf("X = %d Y = %d\n", target_x, target_y);
} else if (incoming_packet[0] == 'P') { } else if (incoming_packet[0] == 'D') {
//
// Ping packet - check time and record
// //
timeval check; // Message from domainserver
gettimeofday(&check, NULL);
ping_msecs = (float)diffclock(&ping_start, &check);
} else if (incoming_packet[0] == 'S') {
// //
// Message from domainserver //printf("agent list received!\n");
// nearbyAgents = update_agents(&incoming_packet[1], bytes_recvd - 1);
update_agents(&incoming_packet[1], bytes_recvd - 1);
} else if (incoming_packet[0] == 'H') { } else if (incoming_packet[0] == 'H') {
// //
// Broadcast packet from another agent // Broadcast packet from another agent
// //
update_agent(from_addr, &incoming_packet[1], bytes_recvd - 1); update_agent(inet_ntoa(senderAddress.sin_addr), ntohs(senderAddress.sin_port), &incoming_packet[1], bytes_recvd - 1);
} else if (incoming_packet[0] == 'T') {
printf("Got test! From port %d\n", senderAddress.sin_port);
} }
} }
} }
@ -808,12 +828,6 @@ void idle(void)
if (!step_on) glutPostRedisplay(); if (!step_on) glutPostRedisplay();
last_frame = check; last_frame = check;
// Every 30 frames or so, check ping time
ping_count++;
if (ping_count >= 30) {
ping_start = network_send_ping(UDP_socket);
ping_count = 0;
}
} }
// Read network packets // Read network packets
@ -872,7 +886,7 @@ void motionFunc( int x, int y)
// Send network packet containing mouse location // Send network packet containing mouse location
char mouse_string[20]; char mouse_string[20];
sprintf(mouse_string, "M %d %d\n", mouse_x, mouse_y); sprintf(mouse_string, "M %d %d\n", mouse_x, mouse_y);
network_send(UDP_socket, mouse_string, strlen(mouse_string)); //network_send(UDP_socket, mouse_string, strlen(mouse_string));
} }
lattice.mouseClick((float)x/(float)WIDTH,(float)y/(float)HEIGHT); lattice.mouseClick((float)x/(float)WIDTH,(float)y/(float)HEIGHT);
@ -902,20 +916,10 @@ void *poll_marker_capture(void *threadarg){
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
// Create network socket and buffer // Create network socket and buffer
UDP_socket = network_init();
if (UDP_socket) printf( "Created UDP socket.\n" );
incoming_packet = new char[MAX_PACKET_SIZE]; incoming_packet = new char[MAX_PACKET_SIZE];
// Test network loopback
in_addr from_addr;
char test_data[] = "Test!";
int bytes_sent = network_send(UDP_socket, test_data, 5);
if (bytes_sent) printf("%d bytes sent.", bytes_sent);
int test_recv = network_receive(UDP_socket, &from_addr, incoming_packet, delay);
printf("Received %i bytes\n", test_recv);
// //
printf("Testing math... standard deviation.\n"); printf("Testing stats math... ");
StDev stdevtest; StDev stdevtest;
stdevtest.reset(); stdevtest.reset();
stdevtest.addValue(1345); stdevtest.addValue(1345);
@ -929,20 +933,15 @@ int main(int argc, char** argv)
stdevtest.addValue(1303); stdevtest.addValue(1303);
stdevtest.addValue(1299); stdevtest.addValue(1299);
if (stdevtest.getSamples() == 10) if (stdevtest.getSamples() != 10)
printf("Samples=PASS ");
else
printf("Samples=FAIL "); printf("Samples=FAIL ");
if (floor(stdevtest.getAverage()*100.0) == 132859.0) if (floor(stdevtest.getAverage()*100.0) != 132859.0)
printf("Average=PASS "); printf("Average=FAIL ");
else
printf("Average=FAIL, avg reported = %5.3f ", floor(stdevtest.getAverage()*100.0));
if (floor(stdevtest.getStDev()*100.0) == 2746.0) if (floor(stdevtest.getStDev()*100.0) != 2746.0)
printf("Stdev=PASS \n"); printf("Stdev=FAIL ");
else printf("\n");
printf("Stdev=FAIL \n");
// //
// Try to connect the serial port I/O // Try to connect the serial port I/O
@ -957,7 +956,6 @@ int main(int argc, char** argv)
serial_on = 1; serial_on = 1;
} }
glutInit(&argc, argv); glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(WIDTH, HEIGHT); glutInitWindowSize(WIDTH, HEIGHT);