Skip to content

Commit

Permalink
add fromstring method and split print into dump and print
Browse files Browse the repository at this point in the history
  • Loading branch information
sphaero committed Jul 2, 2024
1 parent f7f7649 commit 59c1a38
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 13 deletions.
11 changes: 11 additions & 0 deletions api/zosc.api
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@
<argument name = "size" type = "size" />
</constructor>

<constructor name = "fromstring" state = "draft">
Create a new zosc message from a string. This the same syntax as
zosc_create but written as a single line string.
<argument name = "oscstring" type = "string" />
</constructor>

<constructor name = "create">
Create a new zosc message from the given format and arguments.
The format type tags are as follows:
Expand Down Expand Up @@ -168,6 +174,11 @@
<return type = "zosc" fresh = "1" />
</method>

<method name = "dump">
Return a string describing the the OSC message. The returned string must be freed by the caller.
<return type = "string" fresh="1" />
</method>

<method name = "print">
Dump OSC message to stdout, for debugging and tracing.
</method>
Expand Down
12 changes: 12 additions & 0 deletions include/zosc.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ CZMQ_EXPORT zosc_t *
CZMQ_EXPORT zosc_t *
zosc_frommem (char *data, size_t size);

// *** Draft method, for development use, may change without warning ***
// Create a new zosc message from a string. This the same syntax as
// zosc_create but written as a single line string.
CZMQ_EXPORT zosc_t *
zosc_fromstring (const char *oscstring);

// *** Draft method, for development use, may change without warning ***
// Create a new zosc message from the given format and arguments.
// The format type tags are as follows:
Expand Down Expand Up @@ -161,6 +167,12 @@ CZMQ_EXPORT zframe_t *
CZMQ_EXPORT zosc_t *
zosc_unpack (zframe_t *frame);

// *** Draft method, for development use, may change without warning ***
// Return a string describing the the OSC message.
// Caller owns return value and must destroy it when done.
CZMQ_EXPORT char *
zosc_dump (zosc_t *self);

// *** Draft method, for development use, may change without warning ***
// Dump OSC message to stdout, for debugging and tracing.
CZMQ_EXPORT void
Expand Down
169 changes: 156 additions & 13 deletions src/zosc.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,110 @@ zosc_frommem (char *data, size_t size)
return self;
}


zosc_t *
zosc_fromstring (const char *oscstr)
{
// split spaces
char *input = strdup(oscstr);
char *address = strtok(input, " ");
if (address == NULL)
{
// no spaces return
zstr_free(&input);
return NULL;
}
char *format = strtok(NULL, " ");
if (format == NULL)
{
// no format
zstr_free(&input);
return NULL;
}
zosc_t *oscm = zosc_new(address);
int i = 0;
char type = *format;
while( type != 0 )
{
char *value = NULL;
if (type != 'F' && type != 'T' )
{
value = strtok(NULL, " ");
if (value == NULL)
goto error;
}

switch (type)
{
case('i'):
{
int32_t v = atoi(value);
zosc_append(oscm, "i", v);
break;
}
case('h'):
{
int64_t v = atol(value);
zosc_append(oscm, "h", v);
break;
}
case('f'):
{
float v = (float)atof(value);
zosc_append(oscm, "f", v);
break;
}
case('d'):
{
double v = atof(value);
zosc_append(oscm, "d", v);
break;
}
case('s'):
{
zosc_append(oscm, "s", value);
break;
}
case('c'):
{
zosc_append(oscm, "c", value[0]);
break;
}
case('m'):
{
// TODO midi
//zosc_append(oscm, "m", value);
break;
}
case('F'):
{
zosc_append(oscm, "F", NULL);
break;
}
case('T'):
{
zosc_append(oscm, "T", NULL);
break;
}
default:
{
zsys_info("type tag is %c", type);
break;
}
}
i++; // get next character
type = *(format+i);
}
zstr_free(&input);
return oscm;

error:
zstr_free(&input);
zosc_destroy(&oscm);
return NULL;
}


zosc_t *
zosc_create (const char *address, const char *format, ...)
{
Expand Down Expand Up @@ -590,15 +694,16 @@ zosc_unpack (zframe_t *frame)
}

// Dump OSC message to stdout, for debugging and tracing.
void
zosc_print (zosc_t *self)
char *
zosc_dump (zosc_t *self)
{
assert(self);
assert(self->format);
char *out = (char *)malloc(1024);

size_t needle = self->data_begin;
int i=0;
fprintf(stdout, "%s %s", self->address, self->format);
sprintf(out, "%s %s", self->address, self->format);
while(self->format[i])
{
switch (self->format[i])
Expand All @@ -607,38 +712,38 @@ zosc_print (zosc_t *self)
{
void *data = zchunk_data( self->chunk ) + needle;
int32_t int_v = (int32_t)ntohl(*(uint32_t *)data);
fprintf(stdout, " %i", int_v);
sprintf(out, "%s %i", out, int_v);
needle += sizeof (uint32_t);
break;
}
case 'h':
{
uint64_t int_v = ntohll(*(uint64_t*)(zchunk_data( self->chunk ) + (needle * sizeof (char) )));
fprintf(stdout, " %ld", (long)int_v);
sprintf(out, "%s %ld", out, (long)int_v);
needle += sizeof (uint64_t);
break;
}
case 'f':
{
uint32_t flt_v = ntohl(*(uint32_t*)(zchunk_data( self->chunk ) + needle));
float *v = (float *)&flt_v; // hackish
fprintf(stdout, " %.6f", (double)*v);
sprintf(out, "%s %.6f", out, (double)*v);
needle += sizeof (float);
break;
}
case 'd':
{
uint64_t dbl_v = ntohll(*(uint64_t*)(zchunk_data( self->chunk ) + needle));
double *v = (double *)&dbl_v;
fprintf(stdout, " %f", *v);
sprintf(out, "%s %f", out, *v);
needle += sizeof (double);
break;
}
case 's':
{
// not sure if the double pointer is the way to go
char *str = (char*)(zchunk_data( self->chunk ) + needle);
fprintf(stdout, " %s", str);
sprintf(out, "%s %s", out, str);
size_t l = strlen((char*)(zchunk_data( self->chunk ) + needle));
needle += l + 1;
needle = (needle + 3) & (size_t)~0x03;
Expand All @@ -650,26 +755,26 @@ zosc_print (zosc_t *self)
{
char chr = (*(char*)(zchunk_data( self->chunk ) +
needle + 3));
fprintf(stdout, " %c", chr);
sprintf(out, "%s %c", out, chr);
needle += sizeof (int); // advance multitude of 4!
break;
}
case 'm':
{
uint32_t midi = ntohl(*(uint32_t *)(zchunk_data( self->chunk ) + needle));
fprintf(stdout, " 0x%08x", midi);
sprintf(out, "%s 0x%08x", out, midi);
needle += sizeof (uint32_t);
break;
}
case 'T':
{
// value only determined based on the format!
fprintf(stdout, " True");
//sprintf(out, "%s True", out);
break;
}
case 'F':
{
fprintf(stdout, " False");
//sprintf(out, "%s False", out);
break;
}
case 'N': // never used???
Expand All @@ -685,9 +790,18 @@ zosc_print (zosc_t *self)
}
i++;
}
fprintf(stdout, "\n");
return out;
}

void
zosc_print (zosc_t *self)
{
char *s = zosc_dump(self);
zsys_debug("%s", s);
zstr_free(&s);
}


bool
zosc_is (void *self)
{
Expand Down Expand Up @@ -1036,6 +1150,35 @@ zosc_test (bool verbose)
zstr_free(&stest);
zosc_destroy(&testmsg);

// test contructing from string
zosc_t* strm = zosc_fromstring("/stringmsg ihfdscF 32 64 1.100000 3.140000 hello q");
assert(strm);
assert(streq(zosc_address(strm), "/stringmsg"));
assert(streq(zosc_format(strm), "ihfdscF"));
char *sd = zosc_dump(strm);
assert(streq(sd, "/stringmsg ihfdscF 32 64 1.100000 3.140000 hello q"));
zstr_free(&sd);
{
int32_t test = 0;
int64_t test64 = 0;
float testf = 0.0f;
double testd = 0.0;
char * tests = "robots";
char c = 'a';
bool b = true;
zosc_retr(strm, zosc_format(strm), &test, &test64, &testf, &testd, &tests, &c, &b);
assert( test == 32 );
assert( test64 == 64 );
assert( fabsf(testf-1.1f) < FLT_EPSILON );
assert( fabs(testd-3.14) < DBL_EPSILON );
assert( streq(tests, "hello") );
zstr_free( &tests );
assert( c == 'q' );
}
// test print
zosc_print(strm);
zosc_destroy(&strm);

// test constructing messages
int64_t prez = 3;
zosc_t* conm = zosc_create("/construct", "iihfdscF", -2,2, prez, 3.14,6.283185307179586, "greetings", 'q');
Expand Down

0 comments on commit 59c1a38

Please sign in to comment.