OscP5 can't draw anything

edited September 2015 in Library Questions

Hi. I'm using OscP5 to receive data from PureData. I want to draw something on the screen everytime an OSC message is received. What is going to be drawn depends on the message pattern.

On the code bellow i'm trying to draw a random ellipse everytime any message is received, just for illustrating my problem.

The problem is: nothing is drawn. The function i'm calling IS running, as you can see in the console. But nothing is being drawn most of the times. An ellipse is drawn like every 100 times the function is called.

import oscP5.*;
import netP5.*;
float count=1;

OscP5 oscP5;
NetAddress myRemoteLocation;

void setup() {
  size(400,400);
  oscP5 = new OscP5(this,12000);
  myRemoteLocation = new NetAddress("127.0.0.1",12000);
}

void draw() {
}

public void randomEllipse() {
  ellipse(random(0,width),random(0,height),20,20);
  println("randomEllipse() ran "+count+" times");
  count++;
}


public void oscEvent(OscMessage theOscMessage) {
  randomEllipse();
}

// This sends the message to this same Sketch when any key is pressed. Don't forget to click the sketch for focus!
void keyPressed() {
  OscMessage myMessage = new OscMessage("/test");  
  oscP5.send(myMessage, myRemoteLocation);
}

My theory is:

oscEvent works well when setting public variables that will be used as parameters for stuff in draw(). So i'm guessing that for something to be drawn, it must be run at the time a frame is beeing processed. So if you receive a oscMsg but no frame is beeing drawn, the ellipse() inside the function won't be scheduled to the next frame. On the rare case that the oscMsg is receive when a frame is beeing drawn, then the ellipse will appear.

I've thought about using oscEvent to assing somevalue to a array, then reading that array every frame with draw() to know what actions were scheduled.

But this will be a lot of extra work, since i will have lots of different things to drawn depending of lots of osc patters received. So some messages would use strings, others floats, others lists of floats. This way i would have to use an array to everykind of input i receive from the Osc, or save everything as a string, use a second typeTag array and convert everything on the fly.

My question is: There is another way to draw something when an Osc message is being received without having to save stuff on variables? Something like

public void oscEvent(OscMessage theOscMessage) {
  ellipse(random(0,width),random(0,height),20,20);
}

Answers

  • edited September 2015 Answer ✓

    Your problem is exactly the same as this guy had w/ serialEvent(): @-)
    http://forum.Processing.org/two/discussion/12550/line-not-drawing-anything

  • There is another way to draw something when an OscP5 message is being received without having to save stuff on variables?

    AFAIK we need "global" variables so both draw() & oscEvent() can share them. 8-|

  • edited September 2015

    I also found that your idea to draw something directly in the oscEvent function will work with Processing version 2.2.1, but not on version 3+. This is why you will sometimes found some examples on the Web using this methodology.
    I’m not familiar with the difference and the benefits of independent threads. There might be a reason to do so, like to not interfere with drawing during the data reading process of the event. And I see that the link proposed by GoToLoop at first answer is a good start to understand what’s going on. He himself do some nice digging of this subject.

  • edited September 2015

    Thanks for the fast reply, guys!

    It happens indeed because the data is beeing processed in different threads. As i suspected the only way is saving everything in variables and using then inside draw().

    (It does makes sense that this stuff have separated threads)

    I've managed to work it out. Basically i'm using oscP5.plug method to call functions that will store received data on an array, then on draw() i read those messages and send them to theirs respective functions. Took me some good 4 hours, but it's working, and i will share it here so it may help somebody else.

    First we get the information we want

    import oscP5.*;
    import netP5.*;
    
    OscP5 oscP5;
    NetAddress myRemoteLocation;
    String OscSchedule[] = new String[2000];
    int SchNum = -1;
    
    void setup() {
      oscP5 = new OscP5(this, 12000);
      myRemoteLocation = new NetAddress("127.0.0.1", 12000);
    
       oscP5.plug(this."drawSquares","/drawSquares"); //routes the messages
    
    }
    

    Then we save it on a Array

    //incoming data is "drawSquares 30 30". we need drawSquares
    //because in pd you might be sending other data, like drawCircles
    void drawSquaresWrite()(String str, int xPos, int yPos){
      SchNum++;
      OscSchedule[SchNum]="drawSquares"+str+" "+i+" "+i;
    }
    
    //note that we are writing everything as a string here. That is because the array can't store strings and floats. Some methods will need the strings.
    
    Let's say you also have a class Trees and this class have a method for creating or deleting apples on it. You might want to receive "/tree delete apples" from puredata. So it's best to use a string array and then get the numbers out of it.
    
    You can later use parseInt( yourString.substring(i,j) ) when needed, for methods that use numbers. Like "/drawCircles 30 50" where 30 and 50 are x and y positions.
    

    Then we get this informations inside draw()

    void draw() {
      for(int i=0;i<=SchNum;i++){
        OscRoute(OscSchedule[i]);
      }
      SchNum=-1;
    }
    

    And send it to a function that will analyze it and call the apropriate function, depending on what kind of data you received through OSC.

    OscRoute(String input){
       inputTest = getFirstWord(input); //this returns "drawSquares", so you know where to send your message. In this case drawSquares()
       input = removeFirstWord(input); //we are not going to need that prefix anymore
    
       if(inputTest.equals("drawSquares")==true) {
            drawSquares(input);
       }
    
        if(inputTest.equals("drawCircles")==true){
            drawCircles(input);
       }
    
      //note that you can't use switch/cases here because it doesn't work with strings.
    
    }
    

    Then on the adequate function we parse the string and work our magic

    drawCircles(String input){
    
       //code to parse the x and y positions out of the string
    
       //code to draw the circles
    
    }
    

    That's it! Hope that will be useful. I've made a small collections of functions to process those strings. (including those used in my sketch). Do you guys know if there are already any library like that or it would be good if i shared them?

Sign In or Register to comment.