ZOSC(3)
๐ ZOSC(3) ๐
okay so bestie, welcome to the CZMQ Manual page for zosc, and I am so ready to walk you through this. grab a strawberry drink ๐, sit down, and let's get into it.
๐ธ NAME ๐ธ
zosc โ a whole class for working with Open Sound Control messages โจ
๐ SYNOPSIS ๐
๐จ DRAFT ALERT ๐จ this is a draft class, and it may change without notice. it's disabled in stable builds by default. if you use this in applications, please ask for it to be pushed to stable state. flip it on with --enable-drafts.
everything below lives inside this guard:
#ifdef CZMQ_BUILD_DRAFT_API
๐ง the constructors & destructor ๐ง
๐ zosc_new
โ ๏ธ * Draft method, for development use, may change without warning *
CZMQ_EXPORT zosc_t *
zosc_new (const char *address);
makes you a brand-new, totally empty OSC message with the address string you pass in. ๐ซถ
๐ zosc_fromframe
โ ๏ธ * Draft method, for development use, may change without warning *
CZMQ_EXPORT zosc_t *
zosc_fromframe (zframe_t *frame);
builds a new OSC message out of a zframe. it takes ownership of the zframe, so likeโฆ it's yours no more, bestie. ๐
๐ zosc_frommem
โ ๏ธ * Draft method, for development use, may change without warning *
CZMQ_EXPORT zosc_t *
zosc_frommem (char *data, size_t size);
creates a new zosc message straight from memory. it takes ownership of the memory, and you call free on the data after construction. ๐ง โจ
๐ zosc_create
โ ๏ธ * Draft method, for development use, may change without warning *
CZMQ_EXPORT zosc_t *
zosc_create (const char *address, const char *format, ...);
creates a new OSC message from the format you give it plus the arguments. the format type tags are, and I quote, exactly these:
i - 32bit integer
h - 64bit integer
f - 32bit floating point number (IEEE)
d - 64bit (double) floating point number
s - string (NULL terminated)
t = timetag: an OSC timetag in NTP format (uint64_t)
S - symbol
c - char
m - 4 byte midi packet (8 digits hexadecimal)
T - TRUE (no value required)
F - FALSE (no value required)
N - NIL (no value required)
I - Impulse (for triggers) or INFINITUM (no value required)
b - binary blob
๐ zosc_destroy
โ ๏ธ * Draft method, for development use, may change without warning *
CZMQ_EXPORT void
zosc_destroy (zosc_t **self_p);
bye bye, OSC message. ๐๏ธ it's gone, it's done, it's destroyed.
๐ getters & the format life ๐
๐ zosc_size
โ ๏ธ * Draft method, for development use, may change without warning *
CZMQ_EXPORT size_t
zosc_size (zosc_t *self);
hands you the chunk data size. ๐
๐ zosc_data
โ ๏ธ * Draft method, for development use, may change without warning *
CZMQ_EXPORT byte *
zosc_data (zosc_t *self);
returns the OSC chunk data. the caller does NOT own the data! read it, love it, don't free it. ๐
๐ zosc_address
โ ๏ธ * Draft method, for development use, may change without warning *
CZMQ_EXPORT const char *
zosc_address (zosc_t *self);
gives you the OSC address string. ๐ฎ
๐ zosc_format
โ ๏ธ * Draft method, for development use, may change without warning *
CZMQ_EXPORT const char *
zosc_format (zosc_t *self);
returns the OSC format of the message. and the type tags, once again, because we love a rerun:
i - 32bit integer
h - 64bit integer
f - 32bit floating point number (IEEE)
d - 64bit (double) floating point number
s - string (NULL terminated)
t = timetag: an OSC timetag in NTP format (uint64_t)
S - symbol
c - char
m - 4 byte midi packet (8 digits hexadecimal)
T - TRUE (no value required)
F - FALSE (no value required)
N - NIL (no value required)
I - Impulse (for triggers) or INFINITUM (no value required)
b - binary blob
๐ zosc_append
โ ๏ธ * Draft method, for development use, may change without warning *
CZMQ_EXPORT int
zosc_append (zosc_t *self, const char *format, ...);
appends data to the OSC message. the format describes what needs to be appended. heads up: this essentially relocates all data! ๐ซจ
the format type tags are:
i - 32bit integer
h - 64bit integer
f - 32bit floating point number (IEEE)
d - 64bit (double) floating point number
s - string (NULL terminated)
t = timetag: an OSC timetag in NTP format (uint64_t)
S - symbol
c - char
m - 4 byte midi packet (8 digits hexadecimal)
T - TRUE (no value required)
F - FALSE (no value required)
N - NIL (no value required)
I - Impulse (for triggers) or INFINITUM (no value required)
b - binary blob
๐ zosc_retr
โ ๏ธ * Draft method, for development use, may change without warning *
CZMQ_EXPORT int
zosc_retr (zosc_t *self, const char *format, ...);
retrieves the values described by the given format. important things, bestie, don't skip:
zosc_retrcreates the objects, and the caller must destroy them when finished. ๐- the supplied pointers do not need to be initialized.
- returns
0if successful, or-1if it failed to retrieve a value โ and in that failure case, the pointers are not modified. - if an argument pointer is
NULL, it skips that value. - want the full list of type tags for the format string? see the format method. ๐
๐ zosc_dup
โ ๏ธ * Draft method, for development use, may change without warning *
CZMQ_EXPORT zosc_t *
zosc_dup (zosc_t *self);
makes a copy of the message as a new chunk object. returns a fresh zosc_t, or null if there wasn't enough heap memory. if the chunk is null, it returns null. the caller owns the return value and must destroy it when done. ๐ซถ
๐ฆ pack / unpack ๐ฆ
๐ zosc_pack
โ ๏ธ * Draft method, for development use, may change without warning *
CZMQ_EXPORT zframe_t *
zosc_pack (zosc_t *self);
transforms a zosc into a zframe that can be sent in a message. the caller owns the return value and must destroy it when done. ๐ฆ
๐ zosc_packx
โ ๏ธ * Draft method, for development use, may change without warning *
CZMQ_EXPORT zframe_t *
zosc_packx (zosc_t **self_p);
also transforms a zosc into a zframe that can be sent in a message โ but this one takes ownership of the chunk. the caller owns the return value and must destroy it when done. โจ
๐ zosc_unpack
โ ๏ธ * Draft method, for development use, may change without warning *
CZMQ_EXPORT zosc_t *
zosc_unpack (zframe_t *frame);
turns a zframe back into a zosc. the caller owns the return value and must destroy it when done. ๐
๐ debug & identity ๐
๐ zosc_print
โ ๏ธ * Draft method, for development use, may change without warning *
CZMQ_EXPORT void
zosc_print (zosc_t *self);
dumps the OSC message to stdout, for debugging and tracing. ๐จ๏ธ
๐ zosc_is
โ ๏ธ * Draft method, for development use, may change without warning *
CZMQ_EXPORT bool
zosc_is (void *self);
probes the object you hand it and reports back whether it looks like a zosc_t. vibe check for types. ๐ต๏ธโโ๏ธ
๐ธ walking the message ๐ธ
๐ zosc_first
โ ๏ธ * Draft method, for development use, may change without warning *
CZMQ_EXPORT const void *
zosc_first (zosc_t *self, char *type);
returns a pointer to the item at the head of the OSC data. it sets the given char argument to the type tag of the data. if the message is empty, it returns NULL and sets the given char to NULL. ๐
๐ zosc_next
โ ๏ธ * Draft method, for development use, may change without warning *
CZMQ_EXPORT const void *
zosc_next (zosc_t *self, char *type);
returns the next item of the OSC message. if the list is empty, returns NULL. to move back to the start of the OSC message, call zosc_first (). ๐ฆ
๐ zosc_last
โ ๏ธ * Draft method, for development use, may change without warning *
CZMQ_EXPORT const void *
zosc_last (zosc_t *self, char *type);
returns a pointer to the item at the tail of the OSC message. it sets the given char argument to the type tag of the data. if the message is empty, returns NULL. ๐
โญ the pop girlies โญ
๐ zosc_pop_int32
โ ๏ธ * Draft method, for development use, may change without warning *
CZMQ_EXPORT int
zosc_pop_int32 (zosc_t *self, int *val);
sets the provided 32 bit integer from the value at the current cursor position in the message. if the type tag at the current position doesn't correspond, it fails and returns -1. returns 0 on success. โจ
๐ zosc_pop_int64
โ ๏ธ * Draft method, for development use, may change without warning *
CZMQ_EXPORT int
zosc_pop_int64 (zosc_t *self, int64_t *val);
sets the provided 64 bit integer from the value at the current cursor position in the message. if the type tag at the current position doesn't correspond, it fails and returns -1. returns 0 on success. โจ
๐ zosc_pop_float
โ ๏ธ * Draft method, for development use, may change without warning *
CZMQ_EXPORT int
zosc_pop_float (zosc_t *self, float *val);
sets the provided float from the value at the current cursor position in the message. if the type tag at the current position doesn't correspond, it fails and returns -1. returns 0 on success. โจ
๐ zosc_pop_double
โ ๏ธ * Draft method, for development use, may change without warning *
CZMQ_EXPORT int
zosc_pop_double (zosc_t *self, double *val);
sets the provided double from the value at the current cursor position in the message. if the type tag at the current position doesn't correspond, it fails and returns -1. returns 0 on success. โจ
๐ zosc_pop_string
โ ๏ธ * Draft method, for development use, may change without warning *
CZMQ_EXPORT int
zosc_pop_string (zosc_t *self, char **val);
sets the provided string from the value at the current cursor position in the message. if the type tag at the current position doesn't correspond, it fails and returns -1. returns 0 on success. the caller owns the string! ๐ซถ
๐ zosc_pop_char
โ ๏ธ * Draft method, for development use, may change without warning *
CZMQ_EXPORT int
zosc_pop_char (zosc_t *self, char *val);
sets the provided char from the value at the current cursor position in the message. if the type tag at the current position doesn't correspond, it fails and returns -1. returns 0 on success. โจ
๐ zosc_pop_bool
โ ๏ธ * Draft method, for development use, may change without warning *
CZMQ_EXPORT int
zosc_pop_bool (zosc_t *self, bool *val);
sets the provided boolean from the type tag in the message. important: booleans are not represented in the data in the message, only in the type tag. if the type tag at the current position doesn't correspond, it fails and returns -1. returns 0 on success. ๐
๐ zosc_pop_midi
โ ๏ธ * Draft method, for development use, may change without warning *
CZMQ_EXPORT int
zosc_pop_midi (zosc_t *self, uint32_t *val);
sets the provided 4 bytes (unsigned 32bit int) from the value at the current cursor position in the message. if the type tag at the current position doesn't correspond, it fails and returns -1. returns 0 on success. ๐น
๐ง self test ๐ง
๐ zosc_test
โ ๏ธ * Draft method, for development use, may change without warning *
CZMQ_EXPORT void
zosc_test (bool verbose);
the self test of this class. ๐งช
and that's a wrap on the guard:
#endif // CZMQ_BUILD_DRAFT_API
๐ psst โ the source is asking for you: Please add '@interface' section in './../src/zosc.c'.
๐ฆ DESCRIPTION ๐ฆ
zosc โ work with Open Sound Control messages ๐
๐ also from the source: Please add @discuss section in ./../src/zosc.c.
๐ EXAMPLE ๐
okay bestie this is the whole vibe, straight from zosc_test method. it's long, it's chaotic, it's iconic, and we're going through it together piece by piece. grab a snack. ๐
first up: heap packets only, because that's how we roll.
// we need to have packets on the heap
char *p1 = (char *)malloc(40);
memcpy(p1, oscpacket, 40);
zosc_t *self = zosc_frommem(p1, 40);
assert (self);
assert ( zosc_is( self ));
assert(streq ( zosc_address(self), "/sample/address"));
assert(streq ( zosc_format(self), "iTfs"));
// check value
uint32_t test = 0;
bool b = false;
float f = 0.f;
char *s = "BLA";
zosc_retr(self, "iTfs", &test, &b, &f, &s);
assert(test == 1);
assert(b);
assert(fabsf(f - 3.14f) < FLT_EPSILON); // float equal
assert(streq(s, "hello"));
zstr_free(&s);
zosc_destroy (&self);
not the float comparison using FLT_EPSILON instead of == ๐ญ that's the correct way to do it, no cap.
next: frames!! ๐ฆ
zframe_t *frame = zframe_new(oscpacket, 40);
assert(frame);
assert(zframe_size(frame) == 40);
zosc_t *fosc = zosc_fromframe(frame);
assert (fosc);
assert(streq ( zosc_address(fosc), "/sample/address"));
assert(streq ( zosc_format(fosc), "iTfs"));
// test skipping retrieving values
zosc_retr(fosc, "iTfs", NULL, NULL, NULL, NULL);
char *fstr = "";
zosc_retr(fosc, "iTfs", NULL, NULL, NULL, &fstr);
assert( streq(fstr, "hello") );
zstr_free(&fstr);
zosc_destroy (&fosc);
the way that you can pass NULL for the args you don't care about and it just skips them โ lowkey obsessed.
now we're duplicating and checking values. and yeah, zosc_dup(NULL) gives you NULL back, we test that too because we're thorough like that. ๐
// to the heap, otherwise we can't destroy
char *p2 = (char *)malloc(48);
memcpy(p2, testpack, 48);
zosc_t *testmsg = zosc_frommem(p2, 48);
assert( testmsg );
assert(streq ( zosc_address(testmsg), "/test"));
assert(streq ( zosc_format(testmsg), "ihTfds" ) );
// test duplicate
zosc_t *testmsgdup = zosc_dup(NULL);
assert( testmsgdup == NULL );
testmsgdup = zosc_dup(testmsg);
assert( testmsgdup );
assert(streq ( zosc_address(testmsgdup), "/test"));
assert(streq ( zosc_format(testmsgdup), "ihTfds" ) );
zosc_destroy(&testmsgdup);
// check value
int itest = -1;
int64_t ltest = -1;
bool btest = false;
float ftest = -1.f;
double dtest = -1.;
char *stest;
const char *format = zosc_format(testmsg);
zosc_retr(testmsg, format, &itest, <est, &btest, &ftest, &dtest, &stest);
assert( itest == 2 );
assert( ltest == 1844674407370 );
assert( btest );
assert( fabsf(ftest - 3.14f) < FLT_EPSILON ); // float equal
assert( fabs(dtest - 3.1415926535897932) < DBL_EPSILON );
assert( streq(stest, "hello") );
zstr_free(&stest);
zosc_destroy(&testmsg);
constructing messages!!! ๐ซถ this is the part where we make stuff.
// test constructing messages
int64_t prez = 3;
zosc_t* conm = zosc_create("/construct", "iihfdscF", -2,2, prez, 3.14,6.283185307179586, "greetings", 'q');
assert(conm);
assert(streq(zosc_address(conm), "/construct"));
assert(streq(zosc_format(conm), "iihfdscF"));
if (verbose) zosc_print(conm);
int x,y;
int64_t z;
float zz;
double zzz;
char *ss = "aliens";
char q = 'z';
bool Ftest = true;
zosc_retr(conm, "iihfdscF", &x, &y, &z, &zz, &zzz, &ss, &q, &Ftest);
assert( x==-2 );
assert( y==2 );
assert( z==3 );
assert( fabsf(zz-3.14f) < FLT_EPSILON );
assert( fabs(zzz-6.283185307179586) < DBL_EPSILON );
assert( streq( ss, "greetings") );
assert( q == 'q');
assert( !Ftest );
zstr_free(&ss);
ngl the Ftest = true then assert( !Ftest ) is such a plot twist. the bool got flipped by the round trip. iykyk.
iterating! โจ walk through every type tag one by one, and watch the 'h' case deliberately fail with int32 first (that's the // this will fail line, it's supposed to return -1) before succeeding with int64.
// test iterating
char type = '0';
const void *data = zosc_first(conm, &type);
while ( data )
{
if (verbose)
zsys_info("type tag is %c", type);
switch (type)
{
case('i'):
{
int32_t test = 9;
int rc = zosc_pop_int32(conm, &test);
assert(rc == 0);
assert( test == -2 || test == 2);
break;
}
case('h'):
{
int32_t fail = 9;
int rc = zosc_pop_int32(conm, &fail); // this will fail
assert(rc == -1);
int64_t test = 9;
rc = zosc_pop_int64(conm, &test);
assert(rc == 0);
assert( test == 3 );
break;
}
case('f'):
{
float flt_v = 0.f;
int rc = zosc_pop_float(conm, &flt_v);
assert(rc == 0);
assert( fabsf(flt_v-3.14f) < FLT_EPSILON );
break;
}
case 'd':
{
double dbl_v = 0.;
int rc = zosc_pop_double(conm, &dbl_v);
assert(rc == 0);
assert( fabs(dbl_v-6.283185307179586) < DBL_EPSILON );
break;
}
case 's':
{
char *str;
int rc = zosc_pop_string(conm, &str);
assert(rc == 0);
assert(streq(str, "greetings"));
zstr_free(&str);
break;
}
case 'c':
{
char chr;
int rc = zosc_pop_char(conm, &chr);
assert(rc == 0);
assert(chr == 'q');
break;
}
case 'F':
{
bool bl;
int rc = zosc_pop_bool(conm, &bl);
assert(rc == 0);
assert( !bl );
break;
}
default:
assert(0);
}
data = zosc_next(conm, &type);
}
that default: assert(0); is giving "unknown type tag? absolutely not, we die" energy ๐
appending!! ๐ฅ shove two more values on the end and re-read the whole thing with the extended format string.
// test append
int64_t preal = -80000;
zosc_append(conm, "ih", -200, preal);
int ax,ay;
int64_t az;
float azz;
double azzz;
char *ass = "aliens";
char aq = 'z';
bool aFtest = true;
int ai = 0;
int64_t al = 0;
zosc_retr(conm, "iihfdscFih", &ax, &ay, &az, &azz, &azzz, &ass, &aq, &aFtest, &ai, &al);
assert( ax==-2 );
assert( ay==2 );
assert( az==3 );
assert( fabsf(azz-3.14f) < FLT_EPSILON );
assert( fabs(azzz-6.283185307179586) < DBL_EPSILON );
assert( streq( ass, "greetings") );
assert( aq == 'q');
assert( !aFtest );
assert( ai==-200 );
assert( al==-80000 );
zstr_free(&ass);
and finally, yeeting it over UDP. ๐ there's a ZMQ_DGRAM branch and a plain-socket fallback branch, and a __WINDOWS__ variant inside that, because of course there is.
#ifdef ZMQ_DGRAM
zsock_t *dgrams = zsock_new_dgram("udp://*:*");
assert (dgrams);
zframe_t *t = zosc_pack(conm);
zstr_sendm( dgrams, "127.0.0.1:7777" );
zframe_send( &t, dgrams, 0);
zclock_sleep(10); // slow down, otherwise we've cleaned up before async send
zsock_destroy( &dgrams );
#else
int sockfd;
struct sockaddr_in servaddr;
// Creating socket file descriptor
if ( (sockfd = (int)socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
zsys_error("socket creation failed");
}
memset(&servaddr, 0, sizeof(servaddr));
// Filling server information
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(7777);
servaddr.sin_addr.s_addr = INADDR_ANY;
#ifdef __WINDOWS__
sendto(sockfd, (const char *)zosc_data(conm), (int)zosc_size(conm),
0, (const struct sockaddr *) &servaddr,
sizeof(servaddr));
#else
sendto(sockfd, zosc_data(conm), zosc_size(conm),
0, (const struct sockaddr *) &servaddr,
sizeof(servaddr));
#endif
#endif
zosc_destroy(&conm);
#ifdef __WINDOWS__
zsys_shutdown();
#endif
note the little zclock_sleep(10) with the comment // slow down, otherwise we've cleaned up before async send โ that's not decorative bestie, that's load-bearing. do not delete it. ๐
๐ซถ AUTHORS ๐ซถ
The czmq manual was written by the authors in the AUTHORS file.
๐ RESOURCES ๐
Main web site:
Report bugs to the email <zeromq-dev@lists.zeromq.org[1]>
๐ COPYRIGHT ๐
Copyright (c) the Contributors as noted in the AUTHORS file. This file is part of CZMQ, the high-level C binding for 0MQ: http://czmq.zeromq.org. This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. LICENSE included with the czmq distribution.
๐ NOTES ๐
- zeromq-dev@lists.zeromq.org mailto:zeromq-dev@lists.zeromq.org
and that's the whole page bestie, you made it to the end ๐ this was CZMQ 4.2.1, dated 01/16/2026, and honestly? she ate. go forth and encode some OSC. ๐โจ๐ฆ
๐ฆ where this page comes from
- fedora 44: czmq-devel 4.2.1-24.fc44 ยท MPL-2.0
- fedora 44: czmq-devel 4.2.1-24.fc44 ยท MPL-2.0
- ubuntu resolute: libczmq-dev 4.2.1-3build1 ยท MPL-2.0
- ubuntu stonking: libczmq-dev 4.2.1-3build1 ยท MPL-2.0
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms