long osc_bundle_u_nformat(char *buf, long n, t_osc_bndl_u *bndl, int nindent) { if(!bndl || osc_bundle_u_getMsgCount(bndl) == 0){ return 0; } t_osc_bndl_it_u *it = osc_bndl_it_u_get(bndl); long offset = 0; if(!buf){ while(osc_bndl_it_u_hasNext(it)){ t_osc_msg_u *m = osc_bndl_it_u_next(it); offset += osc_message_u_nformat(NULL, 0, m, nindent); if(osc_bndl_it_u_hasNext(it)){ offset += snprintf(NULL, 0, ",\n"); } } }else{ while(osc_bndl_it_u_hasNext(it) && offset < n){ t_osc_msg_u *m = osc_bndl_it_u_next(it); offset += osc_message_u_nformat(buf + offset, n - offset, m, nindent); if(osc_bndl_it_u_hasNext(it)){ offset += snprintf(buf + offset, n - offset, ",\n"); } } } osc_bndl_it_u_destroy(it); return offset; }
t_osc_err osc_bundle_u_intersection(t_osc_bndl_u *bndl1, t_osc_bndl_u *bndl2, t_osc_bndl_u **bndl_out) { if(!(*bndl_out)){ *bndl_out = osc_bundle_u_alloc(); } int argc1 = osc_bundle_u_getMsgCount(bndl1); int argc2 = osc_bundle_u_getMsgCount(bndl2); if(argc1 == 0 || argc2 == 0){ return OSC_ERR_NONE; } t_osc_bndl_it_u *it = osc_bndl_it_u_get(bndl1); while(osc_bndl_it_u_hasNext(it)){ t_osc_msg_u *m = osc_bndl_it_u_next(it); char *address = osc_message_u_getAddress(m); int res = 0; osc_bundle_u_addressExists(bndl2, address, 1, &res); if(res != 0){ int res = 0; osc_bundle_u_addressExists(*bndl_out, address, 1, &res); if(res == 0){ t_osc_msg_u *mcopy = NULL; osc_message_u_deepCopy(&mcopy, m); osc_bundle_u_addMsg(*bndl_out, mcopy); } } } osc_bndl_it_u_destroy(it); return OSC_ERR_NONE; }
t_osc_err osc_bundle_u_addressExists(t_osc_bndl_u *bndl, char *address, int fullmatch, int *res) { *res = 0; t_osc_bndl_it_u *it = osc_bndl_it_u_get(bndl); while(osc_bndl_it_u_hasNext(it)){ t_osc_msg_u *m = osc_bndl_it_u_next(it); int po, ao; char *a = osc_message_u_getAddress(m); if(!a){ continue; } int r = osc_match(address, osc_message_u_getAddress(m), &po, &ao); if(fullmatch){ if(r != (OSC_MATCH_ADDRESS_COMPLETE | OSC_MATCH_PATTERN_COMPLETE)){ continue; } }else{ if(r == 0 || (((r & OSC_MATCH_PATTERN_COMPLETE) == 0) && address[po] != '/')){ continue; } } *res = 1; break; } osc_bndl_it_u_destroy(it); return OSC_ERR_NONE; }
t_osc_err osc_bundle_u_getMessagesWithCallback(t_osc_bndl_u *bndl, void (*f)(t_osc_msg_u*, void *), void *context) { t_osc_bndl_it_u *it = osc_bndl_it_u_get(bndl); while(osc_bndl_it_u_hasNext(it)){ t_osc_msg_u *m = osc_bndl_it_u_next(it); f(m, context); } osc_bndl_it_u_destroy(it); return OSC_ERR_NONE; }
t_osc_err osc_bundle_u_explode(t_osc_bndl_u **dest, t_osc_bndl_u *src, int maxlevel, char *sep) { if(!src){ return OSC_ERR_NOBUNDLE; } if(!(*dest)){ *dest = osc_bundle_u_alloc(); } t_osc_bndl_it_u *it = osc_bndl_it_u_get(src); while(osc_bndl_it_u_hasNext(it)){ t_osc_msg_u *m = osc_bndl_it_u_next(it); t_osc_err ret = osc_message_u_explode(*dest, m, maxlevel, sep); if(ret){ return ret; } } osc_bndl_it_u_destroy(it); return OSC_ERR_NONE; }
t_osc_msg_ar_u *osc_bundle_u_lookupAddress(t_osc_bndl_u *bndl, const char *address, int fullmatch) { int matchbuflen = 16, n = 0; //t_osc_msg_u **matches = osc_mem_alloc(matchbuflen * sizeof(t_osc_msg_u *)); t_osc_msg_ar_u *ar = osc_message_array_u_alloc(matchbuflen); osc_array_clear(ar); //memset(matches, '\0', matchbuflen * sizeof(t_osc_msg_u *)); t_osc_bndl_it_u *it = osc_bndl_it_u_get(bndl); while(osc_bndl_it_u_hasNext(it)){ if(n >= matchbuflen){ //matches = osc_mem_resize(matches, (matchbuflen + 16) * sizeof(t_osc_msg_u *)); t_osc_err e = osc_array_resize(ar, matchbuflen + 16); if(e){ return NULL; } matchbuflen += 16; } t_osc_msg_u *current_message = osc_bndl_it_u_next(it); int po, ao; int r = osc_match(address, osc_message_u_getAddress(current_message), &po, &ao); if(fullmatch){ if(r != (OSC_MATCH_ADDRESS_COMPLETE | OSC_MATCH_PATTERN_COMPLETE)){ continue; } }else{ if(r == 0 || (((r & OSC_MATCH_PATTERN_COMPLETE) == 0) && address[po] != '/')){ continue; } } //osc_message_u_copy(matches + n++, current_message); t_osc_msg_u *p = osc_array_get(ar, n++); osc_message_u_deepCopy(&p, current_message); } osc_bndl_it_u_destroy(it); osc_array_resize(ar, n); return ar; }
size_t osc_bundle_u_nserialize(char *buf, size_t n, t_osc_bndl_u *b) { size_t _n = 0; t_osc_bndl_it_u *it = osc_bndl_it_u_get(b); if(!buf){ _n += OSC_HEADER_SIZE; while(osc_bndl_it_u_hasNext(it)){ t_osc_msg_u *m = osc_bndl_it_u_next(it); _n += osc_message_u_nserialize(NULL, 0, m); } }else{ if(n < OSC_HEADER_SIZE){ return 0; } memcpy(buf, OSC_EMPTY_HEADER, OSC_HEADER_SIZE); _n += OSC_HEADER_SIZE; while(osc_bndl_it_u_hasNext(it) && _n < n){ t_osc_msg_u *m = osc_bndl_it_u_next(it); _n += osc_message_u_nserialize(buf + _n, n - _n, m); } } osc_bndl_it_u_destroy(it); return _n; }
static t_osc_err osc_bundle_u_flatten_impl(t_osc_bndl_u **dest, t_osc_bndl_u *src, int maxlevel, int level, char *prefix, char *sep, int remove_enclosing_address_if_empty) { if(!sep){ sep = ""; } if(!(*dest)){ *dest = osc_bundle_u_alloc(); } t_osc_bndl_it_u *bit = osc_bndl_it_u_get(src); while(osc_bndl_it_u_hasNext(bit)){ t_osc_msg_u *m = osc_bndl_it_u_next(bit); t_osc_msg_u *mcopy = NULL; osc_message_u_deepCopy(&mcopy, m); if((level < maxlevel) || (maxlevel <= 0)){ t_osc_msg_it_u *mit = osc_msg_it_u_get(mcopy); while(osc_msg_it_u_hasNext(mit)){ t_osc_atom_u *a = osc_msg_it_u_next(mit); if(osc_atom_u_getTypetag(a) == OSC_BUNDLE_TYPETAG){ osc_message_u_removeAtom(mcopy, a); t_osc_bndl_u *bu = osc_atom_u_getBndl(a); /* t_osc_bndl_u *bu = NULL; osc_bundle_s_deserialize(osc_bundle_s_getLen(b), osc_bundle_s_getPtr(b), &bu); */ t_osc_err e; if(prefix){ int prefixlen = strlen(prefix) + strlen(osc_message_u_getAddress(mcopy)) + strlen(sep); char pfx[prefixlen + 1]; sprintf(pfx, "%s%s%s", prefix, sep, osc_message_u_getAddress(mcopy)); e = osc_bundle_u_flatten_impl(dest, bu, maxlevel, level + 1, pfx, sep, remove_enclosing_address_if_empty); }else{ e = osc_bundle_u_flatten_impl(dest, bu, maxlevel, level + 1, osc_message_u_getAddress(mcopy), sep, remove_enclosing_address_if_empty); } if(e){ return e; } osc_atom_u_free(a); } } osc_msg_it_u_destroy(mit); } if(!remove_enclosing_address_if_empty || osc_message_u_getArgCount(mcopy) > 0){ if(prefix){ int newaddresslen = strlen(prefix) + strlen(osc_message_u_getAddress(mcopy)) + strlen(sep); char newaddress[newaddresslen + 1]; sprintf(newaddress, "%s%s%s", prefix, sep, osc_message_u_getAddress(mcopy)); osc_message_u_setAddress(mcopy, newaddress); } osc_bundle_u_addMsgWithoutDups(*dest, mcopy); }else{ osc_message_u_free(mcopy); } } osc_bndl_it_u_destroy(bit); return OSC_ERR_NONE; }
int main(int argc, char **argv) { // create a bundle and add messages to it t_osc_bndl_u *bndl_u = osc_bundle_u_alloc(); t_osc_msg_u *m1 = osc_message_u_alloc(); osc_message_u_setAddress(m1, "/foo"); osc_message_u_appendFloat(m1, 3.14); osc_bundle_u_addMsg(bndl_u, m1); t_osc_msg_u *m2 = osc_message_u_allocWithString("/bar", "whatevs"); osc_bundle_u_addMsg(bndl_u, m2); t_osc_msg_u *m3 = osc_message_u_allocWithAddress("/bloo"); t_osc_atom_u *a = osc_atom_u_allocWithInt32(12); osc_message_u_appendAtom(m3, a); osc_bundle_u_addMsg(bndl_u, m3); // serialize the bundle long len = osc_bundle_u_nserialize(NULL, 0, bndl_u); char bndl_s[len]; osc_bundle_u_nserialize(bndl_s, len, bndl_u); // free the original unserialized bundle osc_bundle_u_free(bndl_u); bndl_u = NULL; // deserialize the serialized bundle osc_bundle_s_deserialize(len, bndl_s, &bndl_u); // iterate over messages in a serialized bundle t_osc_bndl_it_s *b_it_s = osc_bndl_it_s_get(len, bndl_s); while(osc_bndl_it_s_hasNext(b_it_s)){ t_osc_msg_s *m = osc_bndl_it_s_next(b_it_s); printf("%s\n", osc_message_s_getAddress(m)); } osc_bndl_it_s_destroy(b_it_s); // turn a serialized bundle into printable text long tlen = osc_bundle_s_nformat(NULL, 0, len, bndl_s, 0); char text[tlen + 1]; osc_bundle_s_nformat(text, tlen, len, bndl_s, 0); printf("\nBUNDLE:\n"); printf("%s\n", text); printf("\n"); // turn text into an unserialized bundle t_osc_bndl_u *bndl_u_2 = NULL; char *text2 = "/jean : [1, 2, 3], /john : 6.66, /jeremy : \"is cool\""; osc_parser_parseString(strlen(text2), text2, &bndl_u_2); // iterate over messages in an unserialized bundle t_osc_bndl_it_u *b_it_u = osc_bndl_it_u_get(bndl_u_2); while(osc_bndl_it_u_hasNext(b_it_u)){ t_osc_msg_u *m = osc_bndl_it_u_next(b_it_u); printf("%s has typetags ", osc_message_u_getAddress(m)); // iterate over atoms in list t_osc_msg_it_u *m_it_u = osc_msg_it_u_get(m); while(osc_msg_it_u_hasNext(m_it_u)){ t_osc_atom_u *a = osc_msg_it_u_next(m_it_u); printf("%c", osc_atom_u_getTypetag(a)); } osc_msg_it_u_destroy(m_it_u); printf("\n"); } osc_bndl_it_u_destroy(b_it_u); }
//void odowncast_fullPacket(t_odowncast *x, long len, long ptr) void odowncast_fullPacket(t_odowncast *x, t_symbol *msg, int argc, t_atom *argv) { OMAX_UTIL_GET_LEN_AND_PTR; t_osc_bndl_u *b = osc_bundle_s_deserialize(len, ptr); if(!b){ object_error((t_object *)x, "invalid OSC packet"); return; } /* if(x->flatten_nested_bundles){ t_osc_bndl_u *bf = NULL; e = osc_bundle_u_flatten(&bf, b } */ t_osc_bndl_u **nestedbundles = NULL; int nnestedbundles = 0, nestedbundles_buflen = 0; t_osc_bndl_it_u *bit = osc_bndl_it_u_get(b); t_osc_timetag timetag = OSC_TIMETAG_NULL; while(osc_bndl_it_u_hasNext(bit)){ t_osc_msg_u *m = osc_bndl_it_u_next(bit); t_osc_msg_it_u *mit = osc_msg_it_u_get(m); while(osc_msg_it_u_hasNext(mit)){ t_osc_atom_u *a = osc_msg_it_u_next(mit); int i = 0; switch(osc_atom_u_getTypetag(a)){ case 'c': case 'C': case 'I': case 'h': case 'H': case 'u': case 'U': case 'N': case 'T': case 'F': if(x->ints){ osc_atom_u_setInt32(a, osc_atom_u_getInt32(a)); } break; case 'd': if(x->doubles){ osc_atom_u_setFloat(a, osc_atom_u_getFloat(a)); } break; case OSC_BUNDLE_TYPETAG: if(x->bundles){ if(!nestedbundles || nnestedbundles == nestedbundles_buflen){ nestedbundles = (t_osc_bndl_u **)osc_mem_resize(nestedbundles, (nestedbundles_buflen + 16) * sizeof(char *)); } nestedbundles[nnestedbundles++] = osc_atom_u_getBndl(a); osc_message_u_removeAtom(m, a); } break; case OSC_TIMETAG_TYPETAG: #if OSC_TIMETAG_FORMAT == OSC_TIMETAG_NTP if(x->timetags){ t_osc_timetag tt = osc_atom_u_getTimetag(a); if(x->timetag_address){ char *address = osc_message_u_getAddress(m); if(!strcmp(address, x->timetag_address->s_name)){ timetag = tt; } } t_osc_atom_u *aa = osc_atom_u_alloc(); int32_t tt1, tt2; //tt1 = (tt & 0xffffffff00000000) >> 32; //tt2 = tt & 0xffffffff; tt1 = osc_timetag_ntp_getSeconds(tt); tt2 = osc_timetag_ntp_getFraction(tt); osc_atom_u_setInt32(aa, ntoh32(tt1)); osc_atom_u_setInt32(a, ntoh32(tt2)); osc_message_u_insertAtom(m, aa, ++i); } #else object_error((t_object *)x, "o.downcast only supports NTP timetags"); #endif break; } i++; } osc_msg_it_u_destroy(mit); } osc_bndl_it_u_destroy(bit); t_osc_bndl_s *bs1 = osc_bundle_u_serialize(b); if(bs1){ long l = osc_bundle_s_getLen(bs1); char *p = osc_bundle_s_getPtr(bs1); memcpy(p + OSC_ID_SIZE, &timetag, sizeof(t_osc_timetag)); for(int i = 0; i < nnestedbundles; i++){ t_osc_bndl_s *bs2 = osc_bundle_u_serialize(nestedbundles[i]); if(bs2){ long ll = osc_bundle_s_getLen(bs2); char *pp = osc_bundle_s_getPtr(bs2); p = osc_mem_resize(p, l + ll); memcpy(p + l, pp, ll); l += ll; osc_bundle_s_deepFree(bs2); } } //if(x->bundle){ omax_util_outletOSC(x->outlet, l, p); /* }else{ t_osc_bndl_it_s *bit = osc_bndl_it_s_get(l, p); while(osc_bndl_it_s_hasNext(bit)){ t_osc_msg_s *m = osc_bndl_it_s_next(bit); long ml = osc_message_s_getSize(m); char *mp = osc_message_s_getAddress(m); omax_util_outletOSC(x->outlet, ml, mp); } osc_bndl_it_s_destroy(bit); } */ osc_bundle_s_deepFree(bs1); } osc_bundle_u_free(b); }