KetaiSensor & OscP5: sending OSC messages directly from within an event handler

edited April 2016 in Android Mode

Hello,

I'm trying to implement a sensor based OSC controller. So far I've set up a handler for accelerometer events and I can see from the console output that accelerometer data is being captured properly in an onAccelerometerEvent handler. However, I haven't been able to send OSC directly from within the handler. I've seen e.g. in this example that, even though all necessary data is available within the handler, actual sending is done in the draw function. I've been able to do it like that in my own sketch as well but preferably I'd like to do it in the handler and not be dependant on the framerate at which the draw function executes. Why is it not possible to send OSC from within a sensor event handler? (or, if it is possible, what am I doing wrong?)

example code (I've moved over to AndroidStudio, so the below is translated back to processing - hope my code makes sense...)

import ketai.sensors.*;
import oscP5.*;

OscP5 oscP5;
NetAddress broadcastLoc;
OscMessage oscAcc;
KetaiSensor sensor;

void setup() {
    oscP5 = new OscP5(this, 32000);
    broadcastLoc = new NetAddress("192.168.1.5", 57120);
    sensor = new KetaiSensor(this);
}

void draw() {

}

void onAccelerometerEvent(float x, float y, float z, long time, int accuracy) {
    println("x: " + x + "\ny: " + y + "\nz: " + z + "\naccuracy: " + accuracy);
    oscAcc = new OscMessage("/acc");
    oscAcc.add(x);
    oscAcc.add(y);
    oscAcc.add(z);
    println("broadcastLoc: " + broadcastLoc + "\nOSC msg: " + oscAcc + "\noscP5: " + oscP5);
    try {
        oscP5.send(oscAcc, broadcastLoc);
    } catch(Exception e) {
        // prints just "sending failed: null"
        println("sending failed: " + e.getMessage());
    }
}

Answers

  • edited January 2016 Answer ✓

    Why is it not possible to send OSC from within a sensor event handler?

    Most hardware-based libraries create their own Thread in order to be run asynchronously.
    In your example above, at the very least, both KetaiSensor & OscP5 got their own threads.

    When onAccelerometerEvent() triggers, it's run under KetaiSensor's Thread I believe.
    Then you instantiate a new OscMessage.

    BtW, I wonder whether it would be better to just do it once within setup(), rather than creating new 1s on-the-fly for each trigger under a foreign Thread? :-/

    The problem w/ asynchronous execution is that we may end up interfering w/ another Thread at the wrong time. For example, by modifying its state when it's busy doing the same!

    All Processing libraries expect the actual action to happen under the "Animation" Thread.
    That's why accessing other threads from there is safest. O:-)

    My advise is, rather than dealing w/ OscP5 under any foreign Thread, just flag that the action happened.
    Then have an if () block inside sketch's draw() to check that boolean flag, reset that flag, and execute the task. *-:)

  • Thanks a lot for that explanation. I already suspected something like that. Maybe it's a good hint that you gave me about instantiating new OSC messages. I'll take a look. However, always having to send my OSC messages from within draw() isn't exactly satisfying, though I understand that's the concept behind processing and makes working with it easy for non (java) programmers. I'll investigate further...

  • ... always having to send my OSC messages from within draw()...

    Of course we can always create a separate function for it and call it from within draw(). ;;)

  • edited January 2016

    @Stefan=== i tried your code (some errors in it, i had to import also netP5 && start the sensor in setup) && i have seen that you cannot send osc inside the sensor handler, probably for the excellent reasons given by @GoToLoop; so i created a method called in draw() and everything works fine;

    @GoToLoop ===

    • if you instantiate the oscmessage only in set up each time you calll the method it adds the new values to its array which becomes quickly very memory expansive...

    • i dont know if it could be useful or useless to declare this method (in draw) as synchronized: i have tried the twos but seen no difference. Can you tell me? Thanks in advance.

    1. Dunno specifically about this library so I didn't know about the memory accumulation.
      But after quickly perusing its docs, I've found it's got a clear() method: :-bd
      http://www.Sojamo.de/libraries/oscp5/reference/oscP5/OscMessage.html#clear()
    2. synchronized is an advanced Java keyword feature. A very big topic! :-S
      But aFaIK, unless OscMessage's add() method is synchronized as well, placing them inside some synchronized () block is 100% useless and just make them a lil' slower! :-&
      However, if by some miracle they happen to be synchronized (), we have to use its instance reference as mutex for it.
  • @GoToLoop===

    right; using clear() (or clearArguments() rather) is probably a good solution && the best one if you want to save till a certain number of values (for reuse or...) from the oscMess; as for synchronized, looking to oscP5 source confirms that there is no "miracle"... So, as you say, it's useless in this kind of case! ;) Thanks!

Sign In or Register to comment.