Back to index

libsfml  1.6+dfsg2
Server.cpp
Go to the documentation of this file.
00001 
00003 // Headers
00005 #include <SFML/Audio.hpp>
00006 #include <SFML/Network.hpp>
00007 #include <iomanip>
00008 #include <iostream>
00009 
00010 
00011 const sf::Uint8 AudioData   = 1;
00012 const sf::Uint8 EndOfStream = 2;
00013 
00014 
00019 class NetworkAudioStream : public sf::SoundStream
00020 {
00021 public :
00022 
00027     NetworkAudioStream() :
00028     myOffset     (0),
00029     myHasFinished(false)
00030     {
00031         // Set the sound parameters
00032         Initialize(1, 44100);
00033     }
00034 
00039     ~NetworkAudioStream()
00040     {
00041         // Close the sockets
00042         myClient.Close();
00043         myListener.Close();
00044     }
00045 
00050     void Start(unsigned short Port)
00051     {
00052         if (!myHasFinished)
00053         {
00054             // Listen to the given port for incoming connections
00055             if (!myListener.Listen(Port))
00056                 return;
00057             std::cout << "Server is listening to port " << Port << ", waiting for connections... " << std::endl;
00058 
00059             // Wait for a connection
00060             sf::IPAddress ClientAddress;
00061             myListener.Accept(myClient, &ClientAddress);
00062             std::cout << "Client connected : " << ClientAddress << std::endl;
00063 
00064             // Start playback
00065             Play();
00066 
00067             // Start receiving audio data
00068             ReceiveLoop();
00069         }
00070         else
00071         {
00072             // Start playback
00073             Play();
00074         }
00075     }
00076 
00077 private :
00078 
00083     virtual bool OnStart()
00084     {
00085         // Reset the playing offset
00086         myOffset = 0;
00087 
00088         return true;
00089     }
00090 
00095     virtual bool OnGetData(sf::SoundStream::Chunk& Data)
00096     {
00097         // We have reached the end of the buffer and all audio data have been played : we can stop playback
00098         if ((myOffset == mySamples.size()) && myHasFinished)
00099             return false;
00100 
00101         // No new data has arrived since last update : wait until we get some
00102         while ((myOffset == mySamples.size()) && !myHasFinished)
00103             sf::Sleep(0.01f);
00104 
00105         // Copy samples into a local buffer to avoid synchronization problems
00106         // (don't forget that we run in two separate threads)
00107         {
00108             sf::Lock Lock(myMutex);
00109             myTempBuffer.assign(mySamples.begin() + myOffset, mySamples.end());
00110         }
00111 
00112         // Fill audio data to pass to the stream
00113         Data.Samples   = &myTempBuffer[0];
00114         Data.NbSamples = myTempBuffer.size();
00115 
00116         // Update the playing offset
00117         myOffset += myTempBuffer.size();
00118 
00119         return true;
00120     }
00121 
00126     void ReceiveLoop()
00127     {
00128         while (!myHasFinished)
00129         {
00130             // Get waiting audio data from the network
00131             sf::Packet PacketIn;
00132             if (myClient.Receive(PacketIn) != sf::Socket::Done)
00133                 break;
00134 
00135             // Extract the message ID
00136             sf::Uint8 Id;
00137             PacketIn >> Id;
00138 
00139             if (Id == AudioData)
00140             {
00141                 // Extract audio samples from the packet, and append it to our samples buffer
00142                 const sf::Int16* Samples   = reinterpret_cast<const sf::Int16*>(PacketIn.GetData() + 1);
00143                 std::size_t      NbSamples = (PacketIn.GetDataSize() - 1) / sizeof(sf::Int16);
00144 
00145                 // Don't forget that the other thread can access the samples array at any time
00146                 // (so we protect any operation on it with the mutex)
00147                 {
00148                     sf::Lock Lock(myMutex);
00149                     std::copy(Samples, Samples + NbSamples, std::back_inserter(mySamples));
00150                 }
00151             }
00152             else if (Id == EndOfStream)
00153             {
00154                 // End of stream reached : we stop receiving audio data
00155                 std::cout << "Audio data has been 100% received !" << std::endl;
00156                 myHasFinished = true;
00157             }
00158             else
00159             {
00160                 // Something's wrong...
00161                 std::cout << "Invalid packet received..." << std::endl;
00162                 myHasFinished = true;
00163             }
00164         }
00165     }
00166 
00168     // Member data
00170     sf::SocketTCP          myListener;
00171     sf::SocketTCP          myClient;
00172     sf::Mutex              myMutex;
00173     std::vector<sf::Int16> mySamples;
00174     std::vector<sf::Int16> myTempBuffer;
00175     std::size_t            myOffset;
00176     bool                   myHasFinished;
00177 };
00178 
00179 
00185 void DoServer(unsigned short Port)
00186 {
00187     // Build an audio stream to play sound data as it is received through the network
00188     NetworkAudioStream AudioStream;
00189     AudioStream.Start(Port);
00190 
00191     // Loop until the sound playback is finished
00192     while (AudioStream.GetStatus() != sf::SoundStream::Stopped)
00193     {
00194         // Leave some CPU time for other threads
00195         sf::Sleep(0.1f);
00196     }
00197 
00198     std::cin.ignore(10000, '\n');
00199 
00200     // Wait until the user presses 'enter' key
00201     std::cout << "Press enter to replay the sound..." << std::endl;
00202     std::cin.ignore(10000, '\n');
00203 
00204     // Replay the sound (just to make sure replaying the received data is OK)
00205     AudioStream.Play();
00206 
00207     // Loop until the sound playback is finished
00208     while (AudioStream.GetStatus() != sf::SoundStream::Stopped)
00209     {
00210         // Leave some CPU time for other threads
00211         sf::Sleep(0.1f);
00212     }
00213 }