An Open Sound Control library for the mbed, created to be compatible with Recotana's OSCClass library (http://recotana.com) for the Arduino with Ethernet shield. It also uses parts of the OSC Transceiver(Sender/Receiver) code by xshige written by: Alvaro Cassinelli, October 2011 tweaked by: Toby Harris / *spark audio-visual, March 2012
Dependencies: NetServices mbed
Revision 11:853a9e887023, committed 2012-04-15
- Comitter:
- tobyspark
- Date:
- Sun Apr 15 15:05:19 2012 +0000
- Parent:
- 10:b4cc0df203b7
- Commit message:
Changed in this revision
main.cpp | Show annotated file Show diff for this revision Revisions of this file |
mbedOSC.h | Show annotated file Show diff for this revision Revisions of this file |
diff -r b4cc0df203b7 -r 853a9e887023 main.cpp --- a/main.cpp Sun Apr 15 13:26:47 2012 +0000 +++ b/main.cpp Sun Apr 15 15:05:19 2012 +0000 @@ -1,125 +1,143 @@ #include "mbed.h" #include "mbedOSC.h" -DigitalOut myled(LED1); +//// ETHERNET -// mbed IP address (server): +// Ethernet can be created with *either* an address assigned by DHCP or a static IP address. Uncomment the define line for DHCP +//#define DHCP #ifdef DHCP EthernetNetIf eth; #else EthernetNetIf eth( - IpAddr(10,0,0,2), //IP Address - IpAddr(255,255,255,0), //Network Mask - IpAddr(10,0,0,1), //Gateway - IpAddr(10,0,0,1) //DNS + IpAddr(10,0,0,2), //IP Address + IpAddr(255,255,255,0), //Network Mask + IpAddr(10,0,0,1), //Gateway + IpAddr(10,0,0,1) //DNS ); #endif -uint8_t serverIp[] = { 10, 0, 0, 2 }; // not needed perhaps! -int serverPort = 10000; - -uint8_t destIp[] = { 10, 0, 0, 1}; -int destPort = 12000; - -char *topAddress="/mbed"; -char *subAddress[3]={ "/test1" , "/test2" , "/test3" }; - +//// OSC + +// The object to do the work of sending and receiving +OSCClass osc; + +// The message objects to send and receive with OSCMessage recMes; OSCMessage sendMes; - -OSCClass osc; -//OSCClass osc(&recMes); // instantiate OSC communication object, and set the receiver container from the OSC packets - -Serial pc(USBTX, USBRX); - -void processOSC(); - -int main() { - - // make debug port: - pc.baud(115200); + +// Setting - The port we're listening to on the mbed for OSC messages +int mbedListenPort = 10000; + +// Setting - The address and port we're going to send to, from the mbed +uint8_t destIp[] = { 10, 0, 0, 1}; +int destPort = 12000; + +//// mbed input + +DigitalIn button(p21); +bool buttonLastState; - // Set the Ethernet port: - printf("Setting up...\r\n"); - EthernetErr ethErr = eth.setup(); - if(ethErr) - { - printf("Error %d in setup.\r\n", ethErr); - return -1; - } - printf("Setup OK\r\n"); - - - //(1) Sending message: - // Set IP and Port: - sendMes.setIp( destIp ); - sendMes.setPort( destPort ); - // Set data: - // sendMes.setTopAddress(topAddress); - - //setting osc functionnality: - //(2) Receiving: - // recMes.setIp( serverIp ); // not needed? - osc.setReceiveMessage(&recMes); // this sets the receiver container for the OSC packets (we can avoid doing this if we use osc.getMessage() to get messages) - osc.begin(serverPort); // binds the upd (osc) messages to an arbitrary listening port ("server" port), and callback function - osc.messageReceivedCallback.attach(&processOSC); - - //========================================== INFINITE LOOP (in USER PROGRAM CONTEXT) =================================================================== - while(true) { - Net::poll(); - - // ... Do whatever needs to be done (note: the osc processing is done in the processOSC function. - // BUT DO NOT FORGET to call osc.onUDPSocketEvent(e). This is messy... should find a better way to do it. - +//// Our messageReceivedCallback function +void processOSC() { + + // If this function has been called, the OSC message just received will have been parsed into our recMes OSCMessage object + // Note we can access recMes here, outside of the main loop, as we created it as a global variable. + + // TASK: If this message one we want, do something about it. + // In this example we're listening for messages with a top address of "mbed". + // Note the strcmp function returns 0 if identical, so !strcmp is true if the two strings are the same + if ( !strcmp( recMes.getAddress(0) , "mbed" ) ) { + printf("OSC Message received addressed to mbed \r\n"); + if ( !strcmp( recMes.getAddress(1) , "test1" ) ) + printf("Received subAddress= test1 \r\n"); + + // Send some osc message: + sendMes.setTopAddress("/working..."); + osc.sendOsc(&sendMes); } } -void processOSC() { +//// M A I N +int main() { + + //// TASK: Set up the Ethernet port + printf("Setting up ethernet...\r\n"); + EthernetErr ethErr = eth.setup(); + if (ethErr) { + printf("Ethernet Failed to setup. Error: %d\r\n", ethErr); + return -1; + } + printf("Ethernet OK\r\n"); + + //// TASK: Set up OSC message sending + + // In the OSC message container we've made for send messages, set where we want it to go: + sendMes.setIp( destIp ); + sendMes.setPort( destPort ); + + //// TASK: Set up OSC message receiving + + // In the OSC send/receive object... + // Set the OSC message container for it to parse received messages into + osc.setReceiveMessage(&recMes); + + // Tell it to begin listening for OSC messages at the port specified (the IP address we know already, it's the mbed's!). + osc.begin(mbedListenPort); - if (osc.newMessage) { // in fact, there is no need to check this if using the method of a global callback function - it is clear this is a new packet... however, it may be - // interesting to use a timer, and process data (answers, etc) only after a certain amount of time, so as to avoid blocking the program in IRQ context... - - //pc.printf("we received top address %s\n", recMes.getAddress(0) ); - - osc.newMessage=false; // note: if using: message=osc.getMessage(), then we don't need to do this explicitly. - - // Test: - if( !strcmp( recMes.getAddress(0) , "mbed" ) ) { - pc.printf("we received topAddress= mbed \n"); - if( !strcmp( recMes.getAddress(1) , "test1" ) ) - pc.printf("we received subAddress= test1 \n"); - - // Send some osc message: - sendMes.setTopAddress("/working..."); - osc.sendOsc(&sendMes); - } + // Rather than constantly checking to see whether there are new messages waiting, the object can call some code of ours to run when a message is received. + // This line does that, attaching a callback function we've written before getting to this point, in this case it's called processOSC + // For more info how this works, see http://mbed.org/cookbook/FunctionPointer + osc.messageReceivedCallback.attach(&processOSC); + + //// TASK: Prime button change detection + buttonLastState = button; + + //// TASK: GO! + + // We've finished setting up, now loop this forever... + while (true) { + // This polls the network connection for new activity, without keeping on calling this you won't receive any OSC! + Net::poll(); + + // Has the button changed? + if (button != buttonLastState) { + // If so, lets update the lastState variable and then send an OSC message + buttonLastState = button; + + sendMes.setTopAddress("/mbed"); + sendMes.setSubAddress("/button"); + sendMes.setArgs("i", (long)button); // The payload will be the button state as an integer, ie. 0 or 1. We need to cast to 'long' for ints (and 'double' for floats).// The payload will be the button state as an integer, ie. 0 or 1. We need to cast to 'long' for ints (and 'double' for floats). + osc.sendOsc(&sendMes); + + printf("Sent OSC message /mbed/button \r\n"); } - + + // ... Do whatever needs to be done by your mbed otherwise. If an OSC message is received, your messageReceivedCallback will run (in this case, processOSC()). + } } - /* EXAMPLE SEND/RECEIVE on PROCESSING: // oscP5sendreceive by andreas schlegel // example shows how to send and receive osc messages. // oscP5 website at http://www.sojamo.de/oscP5 - + import oscP5.*; import netP5.*; - + OscP5 oscP5; NetAddress myRemoteLocation; void setup() { size(400,400); frameRate(25); - // start oscP5, listening for incoming messages at port 12000 + // start oscP5, listening for incoming messages at port 12000 oscP5 = new OscP5(this,12000); - + // myRemoteLocation is a NetAddress. a NetAddress takes 2 parameters, // an ip address and a port number. myRemoteLocation is used as parameter in - // oscP5.send() when sending osc packets to another computer, device, + // oscP5.send() when sending osc packets to another computer, device, // application. usage see below. for testing purposes the listening port // and the port of the remote location address are the same, hence you will // send messages back to this sketch. @@ -128,23 +146,23 @@ void draw() { - background(0); + background(0); } void mousePressed() { - // in the following different ways of creating osc messages are shown by example + // in the following different ways of creating osc messages are shown by example OscMessage myMessage = new OscMessage("/mbed/test1"); - - myMessage.add(123); // add an int to the osc message + + myMessage.add(123); // add an int to the osc message - // send the message - oscP5.send(myMessage, myRemoteLocation); + // send the message + oscP5.send(myMessage, myRemoteLocation); } -// incoming osc message are forwarded to the oscEvent method. +// incoming osc message are forwarded to the oscEvent method. void oscEvent(OscMessage theOscMessage) { - // print the address pattern and the typetag of the received OscMessage + // print the address pattern and the typetag of the received OscMessage print("### received an osc message."); print(" addrpattern: "+theOscMessage.addrPattern()); println(" typetag: "+theOscMessage.typetag());
diff -r b4cc0df203b7 -r 853a9e887023 mbedOSC.h --- a/mbedOSC.h Sun Apr 15 13:26:47 2012 +0000 +++ b/mbedOSC.h Sun Apr 15 15:05:19 2012 +0000 @@ -1,15 +1,13 @@ /* mbed OSC Library This is an Open Sound Control library for the mbed, created to be compatible with Recotana's OSCClass library (http://recotana.com) for the - Arduino with Ethernet shield. I have also used parts of the OSC Transceiver(Sender/Receiver) code by xshige - written by: Alvaro Cassinelli, 7.10.2011 - tweaked by: Toby Harris / *spark audio-visual, 13.4.2012 + Arduino with Ethernet shield. It also uses parts of the OSC Transceiver(Sender/Receiver) code by xshige + written by: Alvaro Cassinelli, October 2011 + tweaked by: Toby Harris / *spark audio-visual, March 2012 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 2.1 as published by the Free Software Foundation. Open Sound Control http://opensoundcontrol.org/ - - */ #ifndef mbedOSC_h @@ -245,10 +243,14 @@ char tempAddress[MAX_ADDRESS][16]; uint8_t tempArg[MAX_ARG][4]; + void onUDPSocketEvent(UDPSocketEvent e); + void decodePacket( OSCMessage *_mes); // makes OSC message from packet public: + friend class UDPSocket; + /** Create an object to send and receive OSC messages */ OSCClass(); @@ -257,11 +259,6 @@ @param[in] _mes A pointer to the "receiveing" OSC message (OSCMessage *) */ OSCClass(OSCMessage *_mes); // set the receiver message container - -/** - Ignore: See messageReceivedCallback instead. This is called by the UDPSocket... and should be a protected function and we friend UDPSocket? - */ - void onUDPSocketEvent(UDPSocketEvent e); /** This initializes the OSC communication object with default receiving port (DEFAULT_REC_PORT) @@ -280,7 +277,7 @@ void stop(); /** - Returns whether there is new OSC data in the receiver message container + Returns whether there is new OSC data in the receiver message container. */ bool newMessage;