// // main.cpp // osc // // Created by Jorge Herrera on 2011-11-09. // // Exemplifies how to use a Thread to enable simultaneous sending/listening to OSC messages // based on the SimpleSend.cpp and SimpleReceive.cpp examples included in oscpack. // // Uses: // - oscpack 1.0.2 (http://www.audiomulch.com/~rossb/oscpack) // - Stk 4.4.3 (https://ccrma.stanford.edu/software/stk/) #include #include #include #include #include "osc/OscOutboundPacketStream.h" #include "osc/OscReceivedElements.h" #include "osc/OscPacketListener.h" #include "ip/UdpSocket.h" #include "Thread.h" // the remote endpoints shoud be listening on this port // (use 6998 for self testing and 7000 to test with receive.ck) #define REMOTE_PORT 7000 // we'll be listening on this port for incoming osc messages #define LOCAL_PORT 6998 // we'll be sending messages to theses address (could be more than one) #define ADDRESS "127.0.0.1" #define OUTPUT_BUFFER_SIZE 1024 #define randf() ( (float)rand()/RAND_MAX ) #define maybe() ( randf() < 0.5 ) using namespace std; //-------------------------------------------------------------------- // Class required by oscpack, to implement the // ProcessMessage() method //-------------------------------------------------------------------- class OSCListener : public osc::OscPacketListener { protected: // Implement the required ProcessMessage() virtual void ProcessMessage( const osc::ReceivedMessage& m, const IpEndpointName& remoteEndpoint ) { try{ if( strcmp( m.AddressPattern(), "/sndbuf/buf/rates" ) == 0 ){ // process messages to the "/sndbuf/buf/rates" address" osc::ReceivedMessageArgumentStream args = m.ArgumentStream(); float a1, a2; args >> a1 >> a2 >> osc::EndMessage; std::cout << "received '" << m.AddressPattern() << "' message with arguments: " << a1 << " " << a2 << "\n"; } else if( strcmp( m.AddressPattern(), "/message" ) == 0 ){ // process messages to the "/messages" address" osc::ReceivedMessageArgumentStream args = m.ArgumentStream(); const char * str; args >> str >> osc::EndMessage; std::cout << "received '" << m.AddressPattern() << "' message with arguments: " << str << "\n"; } }catch( osc::Exception& e ){ // any parsing errors such as unexpected argument types, or // missing arguments get thrown as exceptions. std::cout << "error while parsing message: " << m.AddressPattern() << ": " << e.what() << "\n"; } } }; //-------------------------------------------------------------------- // name: oscListener // desc: starts a separate thread to listen for incoming messages //-------------------------------------------------------------------- void * oscListener( void * userData ) { cerr << "Starting listening thread!" << endl; OSCListener listener; UdpListeningReceiveSocket s( IpEndpointName( IpEndpointName::ANY_ADDRESS, LOCAL_PORT ), &listener ); //s.RunUntilSigInt(); s.Run(); cerr << "Exiting thread!" << endl; } //-------------------------------------------------------------------- // name: sendOSCMessage // desc: exactly what the name says //-------------------------------------------------------------------- void sendOSCMessage() { UdpTransmitSocket transmitSocket( IpEndpointName( ADDRESS, REMOTE_PORT ) ); char buffer[OUTPUT_BUFFER_SIZE]; osc::OutboundPacketStream p( buffer, OUTPUT_BUFFER_SIZE ); // 80% persent of the time, send a new pair of rates if( randf() < 0.8 ) { // generate the arguments float rate1 = randf() * 2.0f; float rate2 = randf() * 200.0f + 260.0f; // form the message p << osc::BeginMessage( "/sndbuf/buf/rates" ) << rate1 << rate2 << osc::EndMessage; } // otherwise send a string message else { const char * msg; if ( maybe() ) msg = "A string message"; else msg = "Another message"; // form the message p << osc::BeginMessage( "/message" ) << msg << osc::EndMessage; } // send the OSC message transmitSocket.Send( p.Data(), p.Size() ); } //-------------------------------------------------------------------- // name: main // desc: entry point //-------------------------------------------------------------------- int main (int argc, char ** argv) { // seed random number generator srand( time(NULL) ); Thread listenerThread; // start the OSC listener thread bool success = listenerThread.start( oscListener, NULL ); if( !success ) { cerr << "Error when creating listener thread!" << endl; exit(1); } std::cout << "press ctrl-c to quit\n"; // loop (we'll use this main thread to send OSC messages) while( true ) { sendOSCMessage(); // advance quickly ... usleep( 20000 ); // rest every once in a while if( randf() < 0.02 ) usleep( 3000000 ); } listenerThread.wait( 10 ); return 0; }