Using raw binary data in a patch

$Adam's icon

Hello Developers,

I'm writing an external that prepares raw binary information that should be sent directly to a device using TCP and UDP (I need to send data on both kind of sockets). Since I don't want to spend time with implementing my own TCP and UDP sender/receiver objects, I though I would send the raw binary output over net.tcp.send and udpsend, respectively. My problem is that I don't know how to send out raw binary data on an outlet (what kind of atoms are designed for this and how should I create the right outlet). First I though I could send the data as a string in the symbol list, but this fails as the binary data will be truncated at the first NULL byte appearing in the stream.

Do you have any suggestions?

Thanks,
Adam

Peter Castine's icon

Take a look at the FullPacket message for udpsend & udpreceive.

For TCP I think you'll need to roll your own way to handle arbitrary buffers. Java provides APIs for TCP that are very convenient to use. I did something like this once, and as I recall the TCP was easy; getting arbitrary buffers in and out of Java was a little tricky but do-able. Unfortunately it's been a long time since I did this and I don't have more details at my fingertips.

Hope this is a little helpful anyway.

-- P.

$Adam's icon

Hm. I just checked the documentation for the FullPacket message. This is what it says:

'The udpsend object and its counterpart the udpreceive object provide support for third-party Max objects that work with the Open Sound Control (OSC) protocol developed by the Center for New Music and Audio Technologies (CNMAT) at the University of California, Berkeley. The FullPacket message toggles support for the 'FullPacket' message used by the CNMAT Open Sound Control externals or the Max udpreceive object--when set, the udpsend object will send UDP buffers in the form of OSC 'FullPacket' messages.'

One problem is that I don't need the OSC protocol (I have a specification of the device describing byte-by-byte the data it is accepting and it is not using OSC), the other is that it is not clear how I should build a FullPacket message for [udpsend]. Is there a more detailed description about the FullPacket message?

Thanks,
Adam

Jesse's icon

If you can I'd suggest implementing your external in Java altogether, unless there's a reason you need it to be in C. Creating TCP and UDP sending mechanisms in Java is fairly trivial, and you won't have to deal with OSC or symbol formatting at all.

Peter Castine's icon

FullPacket really doesn't have anything to do with OSC.

The message was reasonably well-documented with the (now defunct) otudp object. As I recall (and this is from a very long time ago), the message format was 'FullPacket ' where the first long was the size of a buffer and the second long was the address at which the buffer begins (ie, a pointer address).

Here's sample code I used in the bixpack object for generating a FullPacket message

static void
FullPacketOut(
    myObj*    me,
    long    iSize,        // Size of buffer
    void*    iBuf)        // Address where the buffered data are stored

    {
    const short kArgCount    = 2;

    Atom    args[kArgCount];

    AtomSetLong(&args[0], iSize);
    AtomSetLong(&args[1], (long) iBuf);

    outlet_anything(MainOutlet(me), gensym("FullPacket"), kArgCount, args);
    }

MainOutlet() is just an inline function that gets a pointer to an the o_outlet component of the t_object component that is the beginning of every Max object.

$Adam's icon

Since I am sure this kind of problem will occur again and again in my life (I already had some trouble with binary stuff other times as well), finally I decided to solve this by implementing a separate "binary stream" object that could be accessed directly by other objects I would implement in the near future (for example a new TCP sender and also the stuff that creates my binary data for this particular device). I'd like to get a mechanism similar to the one achieved by colls and tables, which are also accessible by other objects even if they are not connected by patchcords.

I though I'd create a static hashmap containing my streams in the class describing my stream object, and other objects would access somehow this static hashmap. I figured out that there are methods like class_findbyname which would return a pointer to my stream class, but now I'm stuck with the problem of accessing a (public) static field of this same class. I also though about a possible 'tweak', that is, I could store the difference between my class pointer and the address of my static hashmap with class_obexoffset_set and then retrieve the same information by any other object using class_obexoffset_get for the class pointer (which can be retrieved from any object using class_findbyname), but I find this solution a bit dangerous, since Max would think that there is an obex at an address where actually there is no obex at all.

Do you have any other idea to solve this?

Timothy Place's icon

Not sure if this will help, but you could bind instances of your class to symbols like it's done in this article: http://blog.74objects.com/2009/04/07/custom-data-types-3/ .

Cheers

dhjdhjdhj's icon

Is this message still needed? If so, what are the appropriate parameter values?

-------------------
'FullPacket ' where the first long was the size of a buffer and the second long was the address at which the buffer begins (ie, a pointer address).