# HG changeset patch # User Giulio Moro # Date 1455336552 0 # Node ID c42a6b4dc2d46771fe3a3c208cf7e995902a6e95 # Parent 869f5e703844c2d0e4247ed4210b354a12dd5863 Recovered some files from ClockSync diff -r 869f5e703844 -r c42a6b4dc2d4 core/NetworkSend.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/NetworkSend.cpp Sat Feb 13 04:09:12 2016 +0000 @@ -0,0 +1,294 @@ +#include "NetworkSend.h" + +#ifdef USE_JUCE +#else +//initialize the static members of NetworkSend +bool NetworkSend::staticConstructed=false; +int NetworkSend::sleepTimeMs; +bool NetworkSend::threadIsExiting; +bool NetworkSend::threadRunning; +std::vector NetworkSend::objAddrs(0); +AuxiliaryTask NetworkSend::sendDataTask=NULL; + +void sendData(){ + NetworkSend::run(); +} +void NetworkSend::staticConstructor(){ + if(staticConstructed==true) + return; + staticConstructed=true; + threadIsExiting=false; + threadRunning=false; + sendDataTask = BeagleRT_createAuxiliaryTask(::sendData, 95, "sendDataTask"); //TODO: allow variable priority +} +void NetworkSend::sendAllData(){ + for(unsigned int n=0; nsendData(); + } +} +int NetworkSend::getNumInstances(){ + return objAddrs.size(); +} +void NetworkSend::startThread(){ + BeagleRT_scheduleAuxiliaryTask(sendDataTask); +} +void NetworkSend::stopThread(){ + threadIsExiting=true; +} +bool NetworkSend::threadShouldExit(){ + return(gShouldStop || threadIsExiting); +} +bool NetworkSend::isThreadRunning(){ + return threadRunning; +} +#endif /* USE_JUCE */ + +#ifdef USE_JUCE +NetworkSend::NetworkSend(const String &threadName): + Thread(threadName) +#else +NetworkSend::NetworkSend() +#endif /* USE_JUCE */ +{ + channel.buffers=NULL; + channel.doneOnTime=NULL; + channel.readyToBeSent=NULL; + channel.enabled=false; + sleepTimeMs=2; //This should actually be initialized in the staticConstructor for non-Juce code, but doing it here makes it more portable + channel.sampleCount=0; +} + +NetworkSend::~NetworkSend(){ +#ifdef USE_JUCE + stopThread(1000); +#else + stopThread(); + for(unsigned int n=0; n4*channel.bufferLength ? blockSize*4 : 4*channel.bufferLength; + channel.numBuffers= 1+numSamples/channel.bufferLength; //the +1 takes the ceil() of the division + channel.buffers=(float**)malloc(channel.numBuffers*sizeof(float*)); + printf("NumBuffers: %d\n", channel.numBuffers); + if(channel.buffers==NULL) + return; + for(int n=0; n( t3 - t1 ).count(); + // auto duration2 = std::chrono::duration_cast( t2 - t1 ).count(); + // if(duration2>0) + // std::cout << "Duration is: " << duration2 <<". Whole loop is: " << duration1 << "\n"; + sleep(1); + } +#else + threadRunning=true; + while(threadShouldExit()==false){ + sendAllData(); + usleep(sleepTimeMs*1000); + } + threadRunning=false; +#endif +} +#ifdef USE_JUCE +#else +Scope::Scope(int aNumChannels): + channels(aNumChannels) +{}; +Scope::~Scope(){}; + +void Scope::log(int channel, float value){ + if(channel>=getNumChannels()) //TODO: assert this + return; + channels[channel].log(value); +} + +void Scope::setup(){ + setup(44100, 9999, "127.0.0.1"); +} + +void Scope::setup(float sampleRate, int aPort, const char* aServer){ + for(int n=0; n ReceiveAudioThread::objAddrs(0); +bool ReceiveAudioThread::threadRunning; +bool ReceiveAudioThread::threadIsExiting; +int ReceiveAudioThread::sleepTime; + +void receiveData(){ + ReceiveAudioThread::run(); +} +void ReceiveAudioThread::staticConstructor(){ + if(staticConstructed==true) + return; + staticConstructed=true; + threadIsExiting=false; + receiveDataTask=BeagleRT_createAuxiliaryTask(receiveData, 90, "receiveDataTask"); //TODO: allow different priorities +} +#endif /* USE_JUCE */ + +void ReceiveAudioThread::dealloc(){ + free(buffer); + buffer=NULL; + free(stackBuffer); + stackBuffer=NULL; +} +void ReceiveAudioThread::wrapWritePointer(){ + //this is not quite a simple wrapping as you would do in a circular buffer, + //as there is no guarantee the buffer will be full at all times, given that there must alwas be enough space at the end of it + //to hold a full payload + // lastValidPointer indicates the last pointer in the buffer containing valid data + // + if(writePointer+payloadLength+headerLength>bufferLength){ //if we are going to exceed the length of the buffer with the next reading + // lastValidPointer=writePointer+headerLength; //remember where the last valid data are + // for(int n=headerLength;n>5, the +#ifdef USE_JUCE +#else + lastTime=rt_timer_read(); +// rt_printf("lastTimeread= %llu\n", lastTime); +#endif /* USE_JUCE */ + // destructor (always or sometimes) never actually gets called, despite run() returns ...see issue #1381 + pushPayload(writePointer); //backup headerLength samples. This could be skipped if writePointer==0 + //read header+payload + int numBytes=socket.read(buffer+writePointer, bytesToRead, true); //read without waiting. + //TODO: (if using variable-length payload) validate the actual numBytes read against the size declared in the header + if(numBytes<0){ + printf("error numBytes1\n"); + return -3; //TODO: something went wrong, you have to discard the rest of the packet! + } + if(numBytes==0){//TODO: this should not happen unless you actually receive a packet of size zero (is it at all possible?) +// printf("received 0 bytes\n"); + return 0; + } + if(numBytes != bytesToRead){ //this is equivalent to (numBytesbufferLength) + return NULL; + readPointer+=length; + if(readPointer>lastValidPointer){ + readPointer=headerLength; + } + return buffer+(int)readPointer; +}; +int ReceiveAudioThread::getSamplesSrc(float *destination, int length, + float samplingRateRatio, int numChannelsInDestination, + int channelToWriteTo) +{ + if (!(samplingRateRatio>0 && samplingRateRatio<=2)) + return -2; + if(isListening()==false) + return -1; + static int numCalls=0; + if(writePointer<0 /*|| (numCalls&16383)==0*/){ //if writePointer has not been initalized yet ... +#ifdef USE_JUCE +#else //debug + rt_printf("reinit the writePointer, readPointer: %f;\n",readPointer); + readPointer=0; +#endif /* USE_JUCE */ + writePointer=2*length; // do it, so that it starts writing at a safety margin from where we write. + // This will help keeping them in sync. + //TODO: handle what happens when the remote stream is interrupted and then restarted + } + numCalls++; + if(length>lastValidPointer) { + //not enough samples available, we fill the buffer with what is available, but the destination buffer will not be filled completely + //at this very moment the other thread might be writing at most one payload into the buffer. + //To avoid a race condition, we need to let alone the buffer where we are currently writing + //as writing the payload also temporarily overwrites the previous headerLength samples, we need to account for them as well + //TODO: This assumes that the writePointer and readPointer do not drift. When doing clock synchronization we will find out that it is not true! + length=lastValidPointer-payloadLength-headerLength; + if(length<0) //no samples available at all! + return 0; + } + for(int n=0; n=lastValidPointer){ + readPointer=readPointer-lastValidPointer+headerLength; + } + } + return length; +} +int ReceiveAudioThread::getSamplesSrc(float *destination, int length, float samplingRateRatio){ + return getSamplesSrc(destination, length, samplingRateRatio, 1,0); + // TODO: rewriting this so that it does not call the override method we can save a multiply and add + // for each sample. +} +bool ReceiveAudioThread::isBufferReady(){ + return bufferReady; +} +#ifdef USE_JUCE +#else +void ReceiveAudioThread::startThread(){ + BeagleRT_scheduleAuxiliaryTask(receiveDataTask); +} +void ReceiveAudioThread::stopThread(){ + threadIsExiting=true; +} +bool ReceiveAudioThread::threadShouldExit(){ + return(gShouldStop || threadIsExiting ); +} +RTIME ReceiveAudioThread::getLastTime(){ + return lastTime; +} +#endif /* USE_JUCE */ +int ReceiveAudioThread::getTimestamp(){ + return timestamp; +} +void ReceiveAudioThread::run(){ + // fd2=fopen("buffer.m","w"); //DEBUG + // fprintf(fd2, "buf=["); //DEBUG + threadRunning=true; + int maxCount=10; + int count=0; + // Clean the socket from anything that is currently in it. +#ifdef USE_JUCE + // this is borrowed from BeagleRT's UdpServer class. + int n; + do { + float waste; + if(socket.waitUntilReady(true, 0)==0) + break; + n=socket.read((void*)&waste, sizeof(float), false); + count++; + if(n<0){ + printf("error\n"); + break; + } + printf("n: %d\n",n); + } while (n>0 && (maxCount<=0 || countsocket.empty(maxCount); + } +#endif /* USE_JUCE */ + printf("socket emptied with %d reads\n", count); + + while(!threadShouldExit()){ //TODO: check that the socket buffer is empty before starting +#ifdef USE_JUCE + readUdpToBuffer(); // read into the oldBuffer + sleep(sleepTime); +#else + for(unsigned int n=0; nreadUdpToBuffer(); + } + usleep(sleepTime); //TODO: use rt_task_sleep instead +#endif /* USE_JUCE */ + } + threadRunning=false; + printf("Thread is not running \n"); + // fprintf(fd,"];readPointer,writePointer,lastValidPointer,destination]=deal(var(:,1), var(:,2), var(:,3), var(:,4));"); //DEBUG + // fclose(fd);//DEBUG + // fprintf(fd2,"];");//DEBUG + // fclose(fd2); //DEBUG +} diff -r 869f5e703844 -r c42a6b4dc2d4 core/UdpClient.cpp --- a/core/UdpClient.cpp Sat Feb 13 01:51:01 2016 +0000 +++ b/core/UdpClient.cpp Sat Feb 13 04:09:12 2016 +0000 @@ -1,57 +1,77 @@ -/* - * udpClient.cpp - * - * Created on: 19 May 2015 - * Author: giulio moro - */ -#include "../include/UdpClient.h" - - UdpClient::UdpClient(){ - outSocket=socket(AF_INET, SOCK_DGRAM, 0); - isSetPort=false; - isSetServer=false; - enabled=false; - } - UdpClient::UdpClient(int aPort, const char* aServerName){ - outSocket=socket(AF_INET, SOCK_DGRAM, 0); - if(outSocket<0){ - enabled=false; - return; - } - setPort(aPort); - setServer(aServerName); - isSetPort=true; - isSetServer=true; - enabled=true; - } - UdpClient::~UdpClient(){ - close(outSocket); - } - void UdpClient::setPort(int aPort){ - port=aPort; - destinationServer.sin_port = htons(port); - destinationServer.sin_family = AF_INET; - isSetPort=true; - if(isSetServer){ - enabled=true; - } - }; - void UdpClient::setServer(const char* aServerName){ - inet_pton(AF_INET,aServerName,&destinationServer.sin_addr); - isSetServer=true; - if(isSetPort){ - enabled=true; - } - }; - int UdpClient::send(void * message, int size){ - if(!enabled) - return -1; - unsigned int length; - length=sizeof(struct sockaddr_in); - int n=sendto(outSocket,message,size,0,(const struct sockaddr *)&destinationServer,length); - if (n < 0){ - return n; - } - return 1; - }; - +/* + * udpClient.cpp + * + * Created on: 19 May 2015 + * Author: giulio moro + */ +#include "UdpClient.h" + + UdpClient::UdpClient(){ + outSocket=socket(AF_INET, SOCK_DGRAM, 0); + isSetPort=false; + isSetServer=false; + enabled=false; + } + UdpClient::UdpClient(int aPort, const char* aServerName){ + outSocket=socket(AF_INET, SOCK_DGRAM, 0); + if(outSocket<0){ + enabled=false; + return; + } + setPort(aPort); + setServer(aServerName); + isSetPort=true; + isSetServer=true; + enabled=true; + memset(&stTimeOut, 0, sizeof(struct timeval)); + } + UdpClient::~UdpClient(){ + close(outSocket); + } + void UdpClient::setPort(int aPort){ + port=aPort; + destinationServer.sin_port = htons(port); + destinationServer.sin_family = AF_INET; + isSetPort=true; + if(isSetServer){ + enabled=true; + } + }; + void UdpClient::setServer(const char* aServerName){ + inet_pton(AF_INET,aServerName,&destinationServer.sin_addr); + isSetServer=true; + if(isSetPort){ + enabled=true; + } + }; + int UdpClient::send(void * message, int size){ + if(!enabled) + return -1; + unsigned int length; + length=sizeof(struct sockaddr_in); + int n=sendto(outSocket,message,size,0,(const struct sockaddr *)&destinationServer,length); + if (n < 0){ + return n; + } + return 1; + }; + int UdpClient::write(const char* remoteHostname, int remotePortNumber, void* sourceBuffer, int numBytesToWrite){ + setServer(remoteHostname); + setPort(remotePortNumber); + send(sourceBuffer, numBytesToWrite); + } + int UdpClient::waitUntilReady(bool readyForReading, int timeoutMsecs){ +// If the socket is ready on return, this returns 1. If it times-out before the socket becomes ready, it returns 0. If an error occurs, it returns -1. + if(enabled==false) + return -1; + if(timeoutMsecs<0) + return select(outSocket+1, NULL, &stWriteFDS, NULL, NULL); //calling this with a NULL timeout will block indefinitely + FD_ZERO(&stWriteFDS); + FD_SET(outSocket, &stWriteFDS); + float timeOutSecs=timeoutMsecs*0.001; + stTimeOut.tv_sec=(int)timeOutSecs; + timeOutSecs-=(int)timeOutSecs; + stTimeOut.tv_usec=(int)(timeOutSecs*1000000); + int descriptorReady= select(outSocket+1, NULL, &stWriteFDS, NULL, &stTimeOut); + return descriptorReady>0? 1 : descriptorReady; + } \ No newline at end of file diff -r 869f5e703844 -r c42a6b4dc2d4 core/UdpServer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/UdpServer.cpp Sat Feb 13 04:09:12 2016 +0000 @@ -0,0 +1,119 @@ +/* + * udpServer.cpp + * + * Created on: 19 May 2015 + * Author: giulio moro + */ +#include "UdpServer.h" + +UdpServer::UdpServer(int aPort){ + init(aPort); +}; +UdpServer::UdpServer(){ + init(0); +} +UdpServer::~UdpServer(){ + close(); +}; +bool UdpServer::init(int aPort){ + enabled=true; + stZeroTimeOut.tv_sec = 0; //set timeout to 0 + stZeroTimeOut.tv_usec = 0; + inSocket=socket(AF_INET, SOCK_DGRAM, 0); + if (inSocket < 0){ + enabled=false; + } + length = sizeof(server); + server.sin_family=AF_INET; + server.sin_addr.s_addr=INADDR_ANY; + enabled=bindToPort(aPort); + wasteBufferSize=2048; + wasteBuffer=malloc(wasteBufferSize); + memset(&stTimeOut,0,sizeof(struct timeval)); + return enabled; +} + +bool UdpServer::bindToPort(int aPort){ + port=aPort; + if(port<1){ + enabled=false; + return false; + } + server.sin_port=htons(port); + if (bind(inSocket,(struct sockaddr *)&server,length)<0){ + enabled=false; + return false; + } + enabled=true; + return true; +} + +void UdpServer::close(){ + int ret=::close(inSocket); + if(ret != 0) + printf("Error while closing socket, errno: %d\n", errno);//Stop receiving data for this socket. If further data arrives, reject it. + inSocket=0; +} + +int UdpServer::waitUntilReady(bool readyForReading, int timeoutMsecs){ +// If the socket is ready on return, this returns 1. If it times-out before the socket becomes ready, it returns 0. If an error occurs, it returns -1. + if(enabled==false) + return -1; + if(timeoutMsecs<0) + return select(inSocket+1, &stReadFDS, NULL, NULL, NULL); //calling this with a NULL timeout will block indefinitely + FD_ZERO(&stReadFDS); + FD_SET(inSocket, &stReadFDS); + float timeOutSecs=timeoutMsecs*0.001; + stTimeOut.tv_sec=(long int)timeOutSecs; + timeOutSecs-=(int)timeOutSecs; + long int timeOutUsecs=timeOutSecs*1000000; + stTimeOut.tv_usec=timeOutUsecs; + int descriptorReady= select(inSocket+1, &stReadFDS, NULL, NULL, &stTimeOut); +// printf("stTimeOut.tv_sec=%ld, stTimeOut.tv_usec=%ld, descriptorReady: \n",stTimeOut.tv_sec,stTimeOut.tv_usec, descriptorReady); +// return descriptorReady>0 ? (timeOutUsecs-stTimeOut.tv_usec) : descriptorReady; + return descriptorReady>0 ? 1 : descriptorReady; +} + +int UdpServer::read(//Returns the number of bytes read, or -1 if there was an error. + void *destBuffer, + int maxBytesToRead, + bool blockUntilSpecifiedAmountHasArrived) +{ + if(enabled==false) + return -1; + FD_ZERO(&stReadFDS); + FD_SET(inSocket, &stReadFDS); + int descriptorReady= select(inSocket+1, &stReadFDS, NULL, NULL, &stZeroTimeOut); //TODO: this is not JUCE-compliant + if(descriptorReady<0){ //an error occurred + return -1; + } + int numberOfBytes=0; +// do + { + if (FD_ISSET(inSocket, &stReadFDS)) + { + // numberOfBytes=recvfrom(inSocket,destBuffer,maxBytesToRead,0,(struct sockaddr *)&from,&fromLength); + numberOfBytes+=recv(inSocket,destBuffer,maxBytesToRead-numberOfBytes,0); + if(numberOfBytes<0) + return -1; + } + } +// while (blockUntilSpecifiedAmountHasArrived && numberOfBytes==maxBytesToRead); + return numberOfBytes; +} +int UdpServer::empty(){ + return empty(0); +} +int UdpServer::empty(int maxCount){ + int count=0; + int n; + do { + if(waitUntilReady(true, 0)==0) + return 0; + float waste; + n=read(&waste, sizeof(float), false); + count++; + } while (n>0 && (maxCount<=0 || maxCount +#else +#include +#include +#include +#include +#include +#include +extern bool gShouldStop; +#endif /* USE_JUCE */ + +#define NETWORK_AUDIO_BUFFER_SIZE 302 +#define UDP_BUFFER_HEADER_CHANNEL_INDEX 0 +#define UDP_BUFFER_HEADER_TIMESTAMP_INDEX 1 +#define UDP_BUFFER_HEADER_LENGTH 2 + +struct NetworkBuffer{ + int channelNumber; + int numBuffers; + int writeBuffer; + int readBuffer; + int writePointer; + float** buffers; + bool* doneOnTime; + bool* readyToBeSent; + bool enabled; + int sampleCount; + static const int bufferLength=NETWORK_AUDIO_BUFFER_SIZE; + static const int headerLength=UDP_BUFFER_HEADER_LENGTH; + static const int headerChannelIndex=UDP_BUFFER_HEADER_CHANNEL_INDEX; + static const int headerTimestampIndex=UDP_BUFFER_HEADER_TIMESTAMP_INDEX; +}; + +#ifdef USE_JUCE +class NetworkSend: public Thread { +#else +class NetworkSend { +#endif /* USE_JUCE */ + float sampleRate; +#ifdef USE_JUCE + DatagramSocket udpClient; + int sleepTimeMs; + String remoteHostname; + int remotePortNumber; +#else + UdpClient udpClient; + bool isThreadRunning(); + static int sleepTimeMs; + static bool threadShouldExit(); + static bool threadIsExiting; + static bool threadRunning; + static bool staticConstructed; + static void staticConstructor(); + static AuxiliaryTask sendDataTask; //TODO: allow different AuxiliaryTasks for different priorities (e.g.: audio vs scope) + static std::vector objAddrs; +#endif /* USE_JUCE */ + void dealloc(); +public: + NetworkBuffer channel; +#ifdef USE_JUCE + NetworkSend(const String &threadName); +#else + NetworkSend(); +#endif + ~NetworkSend(); + void setup(float aSampleRate, int blockSize, int aChannelNumber, int aPort, const char *aServer); + void cleanup(); + void sendData(); + void log(float value); + void setPort(int aPort); + void setServer(const char* aServer); + void setChannelNumber(int aChannelNumber); + int getChannelNumber(); + int getTimestamp(); +#ifdef USE_JUCE + void run(); +#else + static int getNumInstances(); + static void sendAllData(); + static void startThread(); + static void stopThread(); + static void run(); +#endif /* USE_JUCE */ +}; + +#ifdef USE_JUCE +#else +/** + * An array of NetworkSend objects with some default parameters + * + * All sending on the same port (defaults to 9999) + * All sending to the same server (defaults to 127.0.0.1) +*/ +class Scope { + std::vector channels; + void deallocate(); +public: + Scope(int aNumChannels); + ~Scope(); + void log(int channel, float value); + void setup(); + void setup(float sampleRate, int aPort, const char* aServer); + void sendData(); + void setPort(int port); + void setPort(int channel, int port); + int getNumChannels(); +}; +#endif /* USE_JUCE */ + +#endif /* SCOPE_H */ diff -r 869f5e703844 -r c42a6b4dc2d4 include/ReceiveAudioThread.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/ReceiveAudioThread.h Sat Feb 13 04:09:12 2016 +0000 @@ -0,0 +1,105 @@ +#ifndef RECEIVEAUDIOTHREAD_H_INCLUDED +#define RECEIVEAUDIOTHREAD_H_INCLUDED + +#ifdef USE_JUCE +#include +#else +#include +#include +#include +#include +#include +#include +#include + +#endif /*USE_JUCE*/ + +#ifdef USE_JUCE +class ReceiveAudioThread : public Thread { +#else +class ReceiveAudioThread{ +#endif /* USE_JUCE */ +private: + // FILE *fd; //DEBUG + // FILE *fd2; //DEBUG +#ifdef USE_JUCE + DatagramSocket socket; +#else + UdpServer socket; +#endif /* USE_JUCE */ + bool listening; + bool bufferReady; +#ifdef USE_JUCE + bool threadRunning; //do we really need this ? +#else + static bool threadRunning; + static bool threadIsExiting; +#endif + float *buffer; + float *stackBuffer; + int bufferLength; + float readPointer; + int writePointer; + int lastValidPointer; +#ifdef USE_JUCE + int sleepTime; +#else + static int sleepTime; +#endif + int waitForSocketTime; + int payloadLength; //size of the payload of each datagram + int headerLength; //size of the header of each datagram + int bytesToRead; + int threadPriority; + int channel; + int timestamp; + void dealloc(); + void wrapWritePointer(); + void pushPayload(int startIndex); + void popPayload(int startIndex); + int readUdpToBuffer(); +#ifdef USE_JUCE +#else + RTIME lastTime; // Used for clock synchronization + static bool threadShouldExit(); + static bool staticConstructed; + static void staticConstructor(); + static AuxiliaryTask receiveDataTask; //TODO: allow different AuxiliaryTasks for different priorities (e.g.: audio vs scope) + static std::vector objAddrs; +#endif +public: +#ifdef USE_JUCE + ReceiveAudioThread(const String &threadName); +#else + ReceiveAudioThread(); +#endif + ~ReceiveAudioThread(); + void init(int port, int aSamplesPerBlock, int channel); + void bindToPort(int aPort); + bool isListening(); + float* getCurrentBuffer(int length); + /** + * Copies the samples to a non-interleaved buffer. + */ + int getSamplesSrc(float *destination, int length, float samplingRateRatio); + /** + * Copies the samples to an interleaved buffer. + */ + int getSamplesSrc(float *destination, int length, + float samplingRateRatio, int numChannelsInDestination, + int channelToWriteTo); + bool isBufferReady(); + int getTimestamp(); +#ifdef USE_JUCE // if we are in Juce, then we run a separate thread for each receiver + // (as each of them are typically receiving on a mono or stereo track) + void run(); +#else + RTIME getLastTime(); + void static run(); //while in BeagleRT we have a single thread that receives for all the instances. + //TODO: make run() private in BeagleRT + static void startThread(); + static void stopThread(); + static int getNumInstances(); +#endif // USE_JUCE +}; +#endif // RECEIVEAUDIOTHREAD_H_INCLUDED diff -r 869f5e703844 -r c42a6b4dc2d4 include/Scope.h --- a/include/Scope.h Sat Feb 13 01:51:01 2016 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -//scope.cpp -#include -#include -#include -#include - -#define BUILD_FOR_UDPRECEIVE_PLUGIN -#define NETWORK_AUDIO_BUFFER_SIZE 302 -struct networkAudio{ - int timestamp; - int currentBuffer; - int index; - float buffers[2][NETWORK_AUDIO_BUFFER_SIZE]; - int doneOnTime; - bool toBeSent; - UdpClient udpClient; -}; - -#define NUM_SCOPE_CHANNELS 6 - -static void SendScopeData(); - -class Scope { - int sampleCount; - float sampleRate; - AuxiliaryTask scopeTask; - public: - int numChannels; - networkAudio channel[NUM_SCOPE_CHANNELS]; - Scope(){ - numChannels = NUM_SCOPE_CHANNELS; - sampleCount = 0; -#ifdef BUILD_FOR_UDPRECEIVE_PLUGIN - char server[]="192.168.7.1"; -#else - char server[]="127.0.0.1"; -#endif /* BUILD_FOR_UDPRECEIVE_PLUGIN */ - printf("Sending messages to : %s\n", server); - for(int n=0; nnumChannels; n++){ - if(gOscilloscopeInstance->channel[n].toBeSent){ - gOscilloscopeInstance->channel[n].toBeSent=false; - gOscilloscopeInstance->channel[n].udpClient.send( - gOscilloscopeInstance->channel[n].buffers[!gOscilloscopeInstance->channel[n].currentBuffer], - NETWORK_AUDIO_BUFFER_SIZE*sizeof(float) - ); - gOscilloscopeInstance->channel[n].doneOnTime=1; - } - } -} diff -r 869f5e703844 -r c42a6b4dc2d4 include/UdpClient.h --- a/include/UdpClient.h Sat Feb 13 01:51:01 2016 +0000 +++ b/include/UdpClient.h Sat Feb 13 04:09:12 2016 +0000 @@ -23,6 +23,8 @@ int port; int enabled; int outSocket; + struct timeval stTimeOut; + fd_set stWriteFDS; bool isSetPort; bool isSetServer; struct sockaddr_in destinationServer; @@ -33,6 +35,8 @@ void setPort(int aPort); void setServer(const char* aServerName); int send(void* message, int size); + int write(const char* remoteHostname, int remotePortNumber, void* sourceBuffer, int numBytesToWrite); + int waitUntilReady(bool readyForReading, int timeoutMsecs); }; diff -r 869f5e703844 -r c42a6b4dc2d4 include/UdpServer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/UdpServer.h Sat Feb 13 04:09:12 2016 +0000 @@ -0,0 +1,70 @@ +/* + * udpServer.h + * + * Created on: 19 May 2015 + * Author: giulio moro + */ + +#ifndef UDPSERVER_H_ +#define UDPSERVER_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class UdpServer{ + private: + int port; + int enabled; + int inSocket; + struct sockaddr_in server; + struct timeval stTimeOut; + struct timeval stZeroTimeOut; + fd_set stReadFDS; + int size; + void *wasteBuffer; + int wasteBufferSize; + int length; + socklen_t fromLength; + struct sockaddr_in from; + public: + UdpServer(); + UdpServer(int aPort); + ~UdpServer(); + bool init(int aPort); + bool bindToPort(int aPort); + int getBoundPort() const; + /* + * Reads bytes from the socket. + * + * Drop-in replacement for JUCE DatagramSocket::read() + * + If blockUntilSpecifiedAmountHasArrived is true, the method will block until maxBytesToRead + bytes have been read, (or until an error occurs). If this flag is false, the method will + return as much data as is currently available without blocking. + */ + int read(void* destBuffer, int maxBytesToRead, bool blockUntilSpecifiedAmountHasArrived); + void close(); + int empty(); + int empty(int maxCount); + /* + * Waits until the socket is ready for reading or writing. + * + Drop-in replacement for JUCE DatagramSocket::waitUntilReady. + If readyForReading is true, it will wait until the socket is ready for reading; if false, it will wait until it's ready for writing. + If the timeout is < 0, it will wait forever, or else will give up after the specified time. + If the socket is ready on return, this returns 1. If it times-out before the socket becomes ready, it returns 0. If an error occurs, it returns -1. + */ + int waitUntilReady(bool readyForReading, int timeoutMsecs); +}; + + + +#endif /* UDPSERVER_H_ */