/* * TimeCastSrvr.c (c) Bob Quinn 3/15/97 * * Released to the public domain * * Description: * Sample multicast server (sender) application that multicasts the * system time for clients (receivers) to use to set their clocks. */ #include #include #include #include #include "filefinder.h" #define BUFSIZE 1024 #define MAXADDRSTR 16 #define TIMECAST_ADDR "234.5.6.7" #define TIMECAST_PORT 8910 #define TIMECAST_TTL 2 #define TIMECAST_INTRVL 0 char achMCAddr[MAXADDRSTR] = TIMECAST_ADDR; u_long lMCAddr; u_short nPort = TIMECAST_PORT; u_long lTTL = TIMECAST_TTL; u_short nInterval = TIMECAST_INTRVL; SYSTEMTIME stSysTime; class MyStream : public sf::SoundStream { public: std::vector m_samples; std::size_t m_currentSample; HANDLE sem; void load(sf::Int16* buffer, size_t sampleCount, size_t sampleRate, size_t channelCount) { sem = CreateSemaphore(NULL, 1, 1, NULL); // extract the audio samples from the sound buffer to our own container m_samples.assign(buffer, buffer + sampleCount); // reset the current playing position m_currentSample = 0; // initialize the base class initialize(channelCount, sampleRate); } void add(sf::Int16* buffer, size_t size) { // check semaphore WaitForSingleObject(sem, INFINITE); for (int i = 0; i < size; i++) { m_samples.push_back(buffer[i]); } ReleaseSemaphore(sem, 1, NULL); } private: virtual bool onGetData(Chunk& data) { // number of samples to stream every time the function is called; // in a more robust implementation, it would rather be a fixed // amount of time rather than an arbitrary number of samples const int samplesToStream = 50000; //check semaphore WaitForSingleObject(sem, INFINITE); // set the pointer to the next audio samples to be played data.samples = &m_samples[m_currentSample]; // have we reached the end of the sound? if (m_currentSample + samplesToStream <= m_samples.size()) { // end not reached: stream the samples and continue data.sampleCount = samplesToStream; m_currentSample += samplesToStream; ReleaseSemaphore(sem, 1, NULL); return true; } else { // end of stream reached: stream the remaining samples and stop playback data.sampleCount = m_samples.size() - m_currentSample; m_currentSample = m_samples.size(); ReleaseSemaphore(sem, 1, NULL); return false; } } virtual void onSeek(sf::Time timeOffset) { // compute the corresponding sample index according to the sample rate and channel count m_currentSample = static_cast(timeOffset.asSeconds() * getSampleRate() * getChannelCount()); } }; int main(int argc, char *argv[]) { int nRet, i; BOOL fFlag; SOCKADDR_IN stLclAddr, stDstAddr; struct ip_mreq stMreq; /* Multicast interface structure */ SOCKET hSocket; WSADATA stWSAData; filefinder(); /* Display program banner */ printf("------------------------------------------------------\n"); printf(" AudioStreamSrvr - multicast audio server\n"); printf("------------------------------------------------------\n"); /* Init WinSock */ nRet = WSAStartup(0x0202, &stWSAData); if (nRet) { printf ("WSAStartup failed: %d\r\n", nRet); exit (1); } /* Display current settings */ printf ("Multicast Address:%s, Port:%d, IP TTL:%d, Interval:%d\n", achMCAddr, nPort, lTTL, nInterval); /* Get a datagram socket */ hSocket = socket(AF_INET, SOCK_DGRAM, 0); if (hSocket == INVALID_SOCKET) { printf ("socket() failed, Err: %d\n", WSAGetLastError()); exit(1); } /* Bind the socket * * NOTE: Normally, we wouldn't need to call bind unless we were * assigning a local port number explicitly (naming the socket), * however Microsoft requires that a socket be bound before it * can join a multicast group with setsockopt() IP_ADD_MEMBERSHIP * (or fails w/ WSAEINVAL). */ stLclAddr.sin_family = AF_INET; stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* any interface */ stLclAddr.sin_port = 0; /* any port */ nRet = bind(hSocket, (struct sockaddr*) &stLclAddr, sizeof(stLclAddr)); if (nRet == SOCKET_ERROR) { printf ("bind() port: %d failed, Err: %d\n", nPort, WSAGetLastError()); } /* Join the multicast group * * NOTE: According to RFC 1112, a sender does not need to join the * group, however Microsoft requires a socket to join a group in * order to use setsockopt() IP_MULTICAST_TTL (or fails with error * WSAEINVAL). */ stMreq.imr_multiaddr.s_addr = inet_addr(achMCAddr); stMreq.imr_interface.s_addr = INADDR_ANY; nRet = setsockopt(hSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&stMreq, sizeof(stMreq)); if (nRet == SOCKET_ERROR) { printf ( "setsockopt() IP_ADD_MEMBERSHIP address %s failed, Err: %d\n", achMCAddr, WSAGetLastError()); } /* Set IP TTL to traverse up to multiple routers */ nRet = setsockopt(hSocket, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&lTTL, sizeof(lTTL)); if (nRet == SOCKET_ERROR) { printf ("setsockopt() IP_MULTICAST_TTL failed, Err: %d\n", WSAGetLastError()); } /* Disable loopback */ fFlag = FALSE; nRet = setsockopt(hSocket, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&fFlag, sizeof(fFlag)); if (nRet == SOCKET_ERROR) { printf ("setsockopt() IP_MULTICAST_LOOP failed, Err: %d\n", WSAGetLastError()); } /* Assign our destination address */ stDstAddr.sin_family = AF_INET; stDstAddr.sin_addr.s_addr = inet_addr(achMCAddr); stDstAddr.sin_port = htons(nPort); int count = 0; // load an audio buffer from a sound file sf::SoundBuffer buffer; const sf::Int16* pSample; sf::Int16 * pSound; sf::Int16 * temp; size_t sampleCount, sampleRate, channelCount; buffer.loadFromFile("test.wav"); sampleRate = buffer.getSampleRate(); channelCount = buffer.getChannelCount(); pSample = buffer.getSamples(); sampleCount = buffer.getSampleCount(); pSound = const_cast(pSample); temp = const_cast(pSample); char * test; MyStream stream; //stream.load(pSound, 250000, sampleRate, channelCount); //stream.play(); //stream.setVolume(10); Sleep(1000); // initialize and play our custom stream for (;;) { test = (char *)&temp[count * 30000]; printf("%d\n", &temp[count * 30000]); Sleep(10); /*--------------------------------------- Read File ----------------------------------------*/ /* Send the time to our multicast group! */ nRet = sendto(hSocket, test, 60000, 0, (struct sockaddr*)&stDstAddr, sizeof(stDstAddr)); if (nRet < 0) { printf ("sendto() failed, Error: %d\n", WSAGetLastError()); exit(1); } sf::Int16 * derp = reinterpret_cast(test); //stream.add(derp, sampleRate); printf("Sent...\n"); count++; //*temp = count*44100; /* Wait for the specified interval */ //Sleep(nInterval*1000); if(count * 30000 >= sampleCount - (sampleRate*2)) { while(true) { } count = 0; Sleep(1000); printf("count reset"); } } /* end for(;;) */ /* Close the socket */ closesocket(hSocket); /* Tell WinSock we're leaving */ WSACleanup(); return (0); } /* end main() */