cinder / Cinder

Cinder is a community-developed, free and open source library for professional-quality creative coding in C++.
http://libcinder.org
Other
5.3k stars 940 forks source link

Add Blob arguments in OSC block #663

Open indefinit opened 9 years ago

indefinit commented 9 years ago

Feature request. I'd like to send and receive blob arguments in the OSC Block. Since osc/OscTypes.h already defines a Blob type, I feel like it should be relatively trivial to implement the arguments in the Block wrapper. I've started working on it in my own fork but depending on general consensus (i.e. if others think they'd benefit from a blob data type in OSC) maybe I could present that here? Thanks!

pizthewiz commented 9 years ago

The OSC blob type is one of the four types required by the OSC 1.0 spec, so a PR sounds good to me.

Relatedly, I think there was some discussion of ASIO-based OSC handling on the forum and possibly even a CinderBlock, but I can't seem to find it.

pizthewiz commented 9 years ago

The block I was thinking of might be djmike/OscDev, but it doesn't appear to be very active.

indefinit commented 9 years ago

hmm interesting about the ASIO OSC handling.

I'm happy to open up a PR. One quick question though. in the osc::ReceivedMessageArgument class I see two methods for receiving blobs, but I'm a little confused as to what to actually pass as parameters to these methods since the other ReceivedMessageArgument methods take no parameters.

void ReceivedMessageArgument::AsBlob( const void*& data, osc_bundle_element_size_t& size ) const
{
    if( !typeTagPtr_ )
        throw MissingArgumentException();
    else if( *typeTagPtr_ == BLOB_TYPE_TAG )
        AsBlobUnchecked( data, size );
    else
        throw WrongArgumentTypeException();
}
void ReceivedMessageArgument::AsBlobUnchecked( const void*& data, osc_bundle_element_size_t& size ) const
{
    // read blob size as an unsigned int then validate
    osc_bundle_element_size_t sizeResult = (osc_bundle_element_size_t)ToUInt32( argumentPtr_ );
    if( !IsValidElementSizeValue(sizeResult) )
        throw MalformedMessageException("invalid blob size");

    size = sizeResult;
    data = (void*)(argumentPtr_+ osc::OSC_SIZEOF_INT32);
}

If I extend the ProcessMessage method in OscListener it would look something like:

else if(arg->IsBlob())
    // where do I reference data and generic bundle element size?
    message->addBlobArg(arg->AsBlobUnchecked(const void *&data, osc_bundle_element_size_t &size);
pizthewiz commented 9 years ago

I haven't worked with oscpack directly but I would tend to think the blob should be exposed as a ci::Buffer on the Cinder side.

indefinit commented 9 years ago

Ah ok cool. I think I get it now. Very similar to how oscpack works in OF. This would be appended to the method above:

...
else if(arg->IsBlob()){
            const char *data;
            ::osc::osc_bundle_element_size_t size = 0;
            arg->AsBlobUnchecked((const void *&) data, size);
            ci::Buffer buffer(&data, size);
            message->addBlobArg(buffer);
        }