void veejay_bundle_add_blobs( void *osc, const char *msg, void *blub, void *blab, void *blib ) { oscclient_t *c = (oscclient_t*) osc; if(!c->bundle) { c->bundle = lo_bundle_new( LO_TT_IMMEDIATE ); } lo_message lmsg = lo_message_new(); lo_blob blob = (lo_blob) blub; lo_blob blob2 = (lo_blob) blab; lo_blob blob3 = (lo_blob) blib; lo_message_add_blob( lmsg, blob ); lo_message_add_blob( lmsg, blob2 ); lo_message_add_blob( lmsg, blob3 ); lo_bundle_add_message( c->bundle, msg, lmsg ); }
void OscTransmitter::sendByteArray(const char * path, const unsigned char * data, int length) { if(length == 0) return; lo_blob b = lo_blob_new(length, data); lo_message msg = lo_message_new(); lo_message_add_blob(msg, b); if(debugMessages_) { cout << path << " "; lo_message_pp(msg); } // Send message to everyone who's currently listening for(vector<lo_address>::iterator it = addresses_.begin(); it != addresses_.end(); it++) { lo_send_message(*it, path, msg); } lo_blob_free(b); }
//this is not a JACK process cylce int process() { if(shutdown_in_progress==1) { return 0; } if(process_enabled==1) { //as long as there is data ready to be sent, read and try to send //need: handle case where receiver can not read data fast enough // while(rb_can_read(rb) // >=input_port_count*bytes_per_sample*period_size) // { while(rb_can_read(rb) >=port_count*bytes_per_sample*period_size) { //fake consume // rb_advance_read_pointer(rb,port_count*bytes_per_sample*period_size); lo_message mm=lo_message_new(); //add message counter lo_message_add_int64(mm,message_number_out); //indicate how many xruns (in sender's JACK) lo_message_add_int64(mm,remote_xrun_counter); gettimeofday(&tv, NULL); lo_timetag tt; tt.sec=(long)tv.tv_sec; tt.frac=(long)tv.tv_usec; lo_message_add_timetag(mm,tt); lo_message_add_int32(mm,sample_rate); //blob array, holding one period per channel // lo_blob blob[input_port_count]; lo_blob blob[port_count]; void* membuf = malloc(period_size*bytes_per_sample); int i; for( i=0; i<port_count; i++ ) { //void* membuf = malloc(period_size*bytes_per_sample); rb_read (rb, (char*)membuf, period_size*bytes_per_sample); blob[i]=lo_blob_new(period_size*bytes_per_sample,membuf); lo_message_add_blob(mm,blob[i]); } int ret=lo_send_message(loa_tcp,"/audio",mm); last_lo_send_message_tcp_return=ret; if(ret<0) { // fprintf(stderr," TCP WARN: msg no: %" PRId64 " size: %" PRId64 " ret: %d ",message_number_out,lo_message_length(mm,"/audio"),ret); } else { total_bytes_successfully_sent+=ret; // fprintf(stderr," msg no: %" PRId64 " size: %" PRId64 " ret: %d ",message_number_out,lo_message_length(mm,"/audio"),ret); message_number_out++; } //free //lo_free(membuf); lo_message_free(mm); free(membuf); //free blobls ... for( i=0; i<port_count; i++ ) { free(blob[i]); } if(ret<0) { return ret; } }//end while has data return 0; }//end if process enabled //process not yet enabled, buffering else { if(relaxed_display_counter>=update_display_every_nth_cycle || last_test_cycle==1 ) { if((int)message_number<=0 && starting_transmission==0) { fprintf(stderr,"\rwaiting for audio input data..."); } fflush(stderr); relaxed_display_counter=0; } relaxed_display_counter++; return 0; }//end if process not enabled //return 0; } //end process
static int osc_send(CSOUND *csound, OSCSEND *p) { /* Types I allow at present: 0) int 1) float 2) string 3) double 4) char 5) table as blob */ char port[8]; char *pp = port; char *hh; if (*p->port<0) pp = NULL; else snprintf(port, 8, "%d", (int) MYFLT2LRND(*p->port)); hh = (char*) p->host->data; if (*hh=='\0') hh = NULL; if(p->addr != NULL) lo_address_free(p->addr); p->addr = lo_address_new(hh, pp); if (p->cnt++ ==0 || *p->kwhen!=p->last) { int i=0; int msk = 0x20; /* First argument */ lo_message msg = lo_message_new(); char *type = (char*)p->type->data; MYFLT **arg = p->arg; p->last = *p->kwhen; for (i=0; type[i]!='\0'; i++, msk <<=1) { /* Need to add type checks */ switch (type[i]) { case 'i': lo_message_add_int32(msg, (int32_t) MYFLT2LRND(*arg[i])); break; case 'l': case 'h': lo_message_add_int64(msg, (int64_t) MYFLT2LRND(*arg[i])); break; case 'c': lo_message_add_char(msg, (char) (*arg[i] + FL(0.5))); break; case 'm': { union a { int32_t x; uint8_t m[4]; } mm; mm.x = *arg[i]+FL(0.5); lo_message_add_midi(msg, mm.m); break; } case 'f': lo_message_add_float(msg, (float)(*arg[i])); break; case 'd': lo_message_add_double(msg, (double)(*arg[i])); break; case 's': lo_message_add_string(msg, ((STRINGDAT *)arg[i])->data); break; case 'b': /* Boolean */ if (*arg[i]==FL(0.0)) lo_message_add_true(msg); else lo_message_add_false(msg); break; case 't': /* timestamp */ { lo_timetag tt; tt.sec = (uint32_t)(*arg[i]+FL(0.5)); msk <<= 1; i++; if (UNLIKELY(type[i]!='t')) return csound->PerfError(csound, p->h.insdshead, Str("Time stamp is two values")); tt.frac = (uint32_t)(*arg[i]+FL(0.5)); lo_message_add_timetag(msg, tt); break; } //#ifdef SOMEFINEDAY case 'G': /* fGen Table/blob */ { lo_blob myblob; int len, olen; FUNC *ftp; void *data; /* make sure fn exists */ if (LIKELY((ftp=csound->FTnp2Find(csound,arg[i]))!=NULL)) { len = ftp->flen; /* and set it up */ data = csound->Malloc(csound, olen=sizeof(FUNC)-sizeof(MYFLT*)+ sizeof(MYFLT)*len); memcpy(data, ftp, sizeof(FUNC)-sizeof(MYFLT*)); memcpy(data+sizeof(FUNC)-sizeof(MYFLT*), ftp->ftable, sizeof(MYFLT)*len); } else { return csound->PerfError(csound, p->h.insdshead, Str("ftable %.2f does not exist"), *arg[i]); } myblob = lo_blob_new(olen, data); lo_message_add_blob(msg, myblob); csound->Free(csound, data); lo_blob_free(myblob); break; } //#endif case 'a': /* Audio as blob */ { lo_blob myblob; MYFLT *data = csound->Malloc(csound, sizeof(MYFLT)*(CS_KSMPS+1)); data[0] = CS_KSMPS; memcpy(&data[1], arg[i], data[0]); myblob = lo_blob_new(sizeof(MYFLT)*(CS_KSMPS+1), data); lo_message_add_blob(msg, myblob); csound->Free(csound, data); lo_blob_free(myblob); break; } case 'A': /* Array/blob */ { lo_blob myblob; int len = 1; ARRAYDAT *ss; /* make sure fn exists */ if (LIKELY((ss = (ARRAYDAT*)arg[i]) !=NULL && ss->data != NULL)) { int j, d; for (j=0,d=ss->dimensions; d>0; j++, d--) len *= ss->sizes[j]; len *= sizeof(MYFLT); } else { return csound->PerfError(csound, p->h.insdshead, Str("argument %d is not an array"), i); } // two parts needed { void *dd = malloc(len+sizeof(int)*(1+ss->dimensions)); memcpy(dd, &ss->dimensions, sizeof(int)); memcpy(dd+sizeof(int), ss->sizes, sizeof(int)*ss->dimensions); memcpy(dd+sizeof(int)*(1+ss->dimensions), ss->data, len); /* printf("dd length = %d dimensions = %d, %d %d %.8x %.8x %.8x %.8x\n", */ /* len+sizeof(int)*(1+ss->dimensions), ss->dimensions, */ /* ((int*)dd)[0], ((int*)dd)[1], ((int*)dd)[2], ((int*)dd)[3], */ /* ((int*)dd)[4], ((int*)dd)[5]); */ myblob = lo_blob_new(len, dd); free(dd); } lo_message_add_blob(msg, myblob); lo_blob_free(myblob); break; } case 'S': csound->Warning(csound, "S unimplemented"); break; //#endif default: csound->Warning(csound, Str("Unknown OSC type %c\n"), type[1]); } } lo_send_message(p->addr, (char*)p->dest->data, msg); lo_message_free(msg); } return OK; }
static int osc_send(CSOUND *csound, OSCSEND *p) { /* Types I allow at present: 0) int 1) float 2) string 3) double 4) char 5) table as blob */ if (p->cnt++ ==0 || *p->kwhen!=p->last) { int i=0; int msk = 0x20; /* First argument */ lo_message msg = lo_message_new(); char *type = (char*)p->type->data; MYFLT **arg = p->arg; p->last = *p->kwhen; for (i=0; type[i]!='\0'; i++, msk <<=1) { /* Need to add type checks */ switch (type[i]) { case 'i': lo_message_add_int32(msg, (int32_t) MYFLT2LRND(*arg[i])); break; case 'l': lo_message_add_int64(msg, (int64_t) MYFLT2LRND(*arg[i])); break; case 'c': lo_message_add_char(msg, (char) (*arg[i] + FL(0.5))); break; case 'm': { union a { int32_t x; uint8_t m[4]; } mm; mm.x = *arg[i]+FL(0.5); lo_message_add_midi(msg, mm.m); break; } case 'f': lo_message_add_float(msg, (float)(*arg[i])); break; case 'd': lo_message_add_double(msg, (double)(*arg[i])); break; case 's': lo_message_add_string(msg, ((STRINGDAT *)arg[i])->data); break; case 'b': /* Boolean */ if (*arg[i]==FL(0.0)) lo_message_add_true(msg); else lo_message_add_false(msg); break; case 't': /* timestamp */ { lo_timetag tt; tt.sec = (uint32_t)(*arg[i]+FL(0.5)); msk <<= 1; i++; if (UNLIKELY(type[i]!='t')) return csound->PerfError(csound, p->h.insdshead, Str("Time stamp is two values")); tt.frac = (uint32_t)(*arg[i]+FL(0.5)); lo_message_add_timetag(msg, tt); break; } //#ifdef SOMEFINEDAY case 'T': /* Table/blob */ { lo_blob myblob; int len; FUNC *ftp; void *data; /* make sure fn exists */ if (LIKELY((ftp=csound->FTnp2Find(csound,arg[i]))!=NULL)) { data = ftp->ftable; len = ftp->flen-1; /* and set it up */ } else { return csound->PerfError(csound, p->h.insdshead, Str("ftable %.2f does not exist"), *arg[i]); } myblob = lo_blob_new(sizeof(MYFLT)*len, data); lo_message_add_blob(msg, myblob); lo_blob_free(myblob); break; } //#endif default: csound->Warning(csound, Str("Unknown OSC type %c\n"), type[1]); } } lo_send_message(p->addr, (char*)p->dest->data, msg); lo_message_free(msg); } return OK; }
int lo_message_add_varargs_internal(lo_message msg, const char *types, va_list ap, const char *file, int line) { int count = 0; int ret = 0; while (types && *types) { count++; switch (*types++) { case LO_INT32:{ int32_t i = va_arg(ap, int32_t); lo_message_add_int32(msg, i); break; } case LO_FLOAT:{ float f = (float) va_arg(ap, double); lo_message_add_float(msg, f); break; } case LO_STRING:{ char *s = va_arg(ap, char *); #ifndef USE_ANSI_C if (s == (char *) LO_MARKER_A) { fprintf(stderr, "liblo error: lo_send or lo_message_add called with " "invalid string pointer for arg %d, probably arg mismatch\n" "at %s:%d, exiting.\n", count, file, line); } #endif lo_message_add_string(msg, s); break; } case LO_BLOB:{ lo_blob b = va_arg(ap, lo_blob); lo_message_add_blob(msg, b); break; } case LO_INT64:{ int64_t i64 = va_arg(ap, int64_t); lo_message_add_int64(msg, i64); break; } case LO_TIMETAG:{ lo_timetag tt = va_arg(ap, lo_timetag); lo_message_add_timetag(msg, tt); break; } case LO_DOUBLE:{ double d = va_arg(ap, double); lo_message_add_double(msg, d); break; } case LO_SYMBOL:{ char *s = va_arg(ap, char *); #ifndef USE_ANSI_C if (s == (char *) LO_MARKER_A) { fprintf(stderr, "liblo error: lo_send or lo_message_add called with " "invalid symbol pointer for arg %d, probably arg mismatch\n" "at %s:%d, exiting.\n", count, file, line); va_end(ap); return -2; } #endif lo_message_add_symbol(msg, s); break; } case LO_CHAR:{ char c = va_arg(ap, int); lo_message_add_char(msg, c); break; } case LO_MIDI:{ uint8_t *m = va_arg(ap, uint8_t *); lo_message_add_midi(msg, m); break; } case LO_TRUE: lo_message_add_true(msg); break; case LO_FALSE: lo_message_add_false(msg); break; case LO_NIL: lo_message_add_nil(msg); break; case LO_INFINITUM: lo_message_add_infinitum(msg); break; case '$': if (*types == '$') { // type strings ending in '$$' indicate not to perform // LO_MARKER checking va_end(ap); return 0; } // fall through to unknown type default:{ ret = -1; // unknown type fprintf(stderr, "liblo warning: unknown type '%c' at %s:%d\n", *(types - 1), file, line); break; } } } #ifndef USE_ANSI_C void *i = va_arg(ap, void *); if (((unsigned long)i & 0xFFFFFFFFUL) != ((unsigned long)LO_MARKER_A & 0xFFFFFFFFUL)) { ret = -2; // bad format/args fprintf(stderr, "liblo error: lo_send, lo_message_add, or lo_message_add_varargs called with " "mismatching types and data at\n%s:%d, exiting.\n", file, line); va_end(ap); return ret; } i = va_arg(ap, void *); if (((unsigned long)i & 0xFFFFFFFFUL) != ((unsigned long)LO_MARKER_B & 0xFFFFFFFFUL)) { ret = -2; // bad format/args fprintf(stderr, "liblo error: lo_send, lo_message_add, or lo_message_add_varargs called with " "mismatching types and data at\n%s:%d, exiting.\n", file, line); } #endif va_end(ap); return ret; }
void test_deserialise() { char *buf, *buf2, *tmp; const char *types = NULL, *path; lo_arg **argv = NULL; size_t len, size; char data[256]; int result = 0; lo_blob btest = lo_blob_new(sizeof(testdata), testdata); uint8_t midi_data[4] = {0xff, 0xf7, 0xAA, 0x00}; lo_timetag tt = {0x1, 0x80000000}; lo_blob b = NULL; // build a message lo_message msg = lo_message_new(); TEST(0 == lo_message_get_argc(msg)); lo_message_add_float(msg, 0.12345678f); // 0 f lo_message_add_int32(msg, 123); // 1 i lo_message_add_string(msg, "123"); // 2 s lo_message_add_blob(msg, btest); // 3 b lo_message_add_midi(msg, midi_data); // 4 m lo_message_add_int64(msg, 0x0123456789abcdefULL); // 5 h lo_message_add_timetag(msg, tt); // 6 t lo_message_add_double(msg, 0.9999); // 7 d lo_message_add_symbol(msg, "sym"); // 8 S lo_message_add_char(msg, 'X'); // 9 c lo_message_add_char(msg, 'Y'); // 10 c lo_message_add_true(msg); // 11 T lo_message_add_false(msg); // 12 F lo_message_add_nil(msg); // 13 N lo_message_add_infinitum(msg); // 14 I // test types, args TEST(15 == lo_message_get_argc(msg)); types = lo_message_get_types(msg); TEST(NULL != types); argv = lo_message_get_argv(msg); TEST(NULL != argv); TEST('f' == types[0] && fabs(argv[0]->f - 0.12345678f) < FLT_EPSILON); TEST('i' == types[1] && 123 == argv[1]->i); TEST('s' == types[2] && !strcmp(&argv[2]->s, "123")); TEST('b' == types[3]); b = (lo_blob)argv[3]; TEST(lo_blob_datasize(b) == sizeof(testdata)); TEST(12 == lo_blobsize(b)); TEST(!memcmp(lo_blob_dataptr(b), &testdata, sizeof(testdata))); TEST('m' == types[4] && !memcmp(&argv[4]->m, midi_data, 4)); TEST('h' == types[5] && 0x0123456789abcdefULL == argv[5]->h); TEST('t' == types[6] && 1 == argv[6]->t.sec && 0x80000000 == argv[6]->t.frac); TEST('d' == types[7] && fabs(argv[7]->d - 0.9999) < FLT_EPSILON); TEST('S' == types[8] && !strcmp(&argv[8]->s, "sym")); TEST('c' == types[9] && 'X' == argv[9]->c); TEST('c' == types[10] && 'Y' == argv[10]->c); TEST('T' == types[11] && NULL == argv[11]); TEST('F' == types[12] && NULL == argv[12]); TEST('N' == types[13] && NULL == argv[13]); TEST('I' == types[14] && NULL == argv[14]); // serialise it len = lo_message_length(msg, "/foo"); printf("serialise message_length=%d\n", (int)len); buf = calloc(len, sizeof(char)); size = 0; tmp = lo_message_serialise(msg, "/foo", buf, &size); TEST(tmp == buf && size == len && 92 == len); lo_message_free(msg); // deserialise it printf("deserialise\n"); path = lo_get_path(buf, len); TEST(NULL != path && !strcmp(path, "/foo")); msg = lo_message_deserialise(buf, size, NULL); TEST(NULL != msg); // repeat same test as above TEST(15 == lo_message_get_argc(msg)); types = lo_message_get_types(msg); TEST(NULL != types); argv = lo_message_get_argv(msg); TEST(NULL != argv); TEST('f' == types[0] && fabs(argv[0]->f - 0.12345678f) < FLT_EPSILON); TEST('i' == types[1] && 123 == argv[1]->i); TEST('s' == types[2] && !strcmp(&argv[2]->s, "123")); TEST('b' == types[3]); b = (lo_blob)argv[3]; TEST(lo_blob_datasize(b) == sizeof(testdata)); TEST(12 == lo_blobsize(b)); TEST(!memcmp(lo_blob_dataptr(b), &testdata, sizeof(testdata))); TEST('m' == types[4] && !memcmp(&argv[4]->m, midi_data, 4)); TEST('h' == types[5] && 0x0123456789abcdefULL == argv[5]->h); TEST('t' == types[6] && 1 == argv[6]->t.sec && 0x80000000 == argv[6]->t.frac); TEST('d' == types[7] && fabs(argv[7]->d - 0.9999) < FLT_EPSILON); TEST('S' == types[8] && !strcmp(&argv[8]->s, "sym")); TEST('c' == types[9] && 'X' == argv[9]->c); TEST('c' == types[10] && 'Y' == argv[10]->c); TEST('T' == types[11] && NULL == argv[11]); TEST('F' == types[12] && NULL == argv[12]); TEST('N' == types[13] && NULL == argv[13]); TEST('I' == types[14] && NULL == argv[14]); // serialise it again, compare len = lo_message_length(msg, "/foo"); printf("serialise message_length=%d\n", (int)len); buf2 = calloc(len, sizeof(char)); size = 0; tmp = lo_message_serialise(msg, "/foo", buf2, &size); TEST(tmp == buf2 && size == len && 92 == len); TEST(!memcmp(buf, buf2, len)); lo_message_free(msg); lo_blob_free(btest); free(buf); free(buf2); // deserialise failure tests with invalid message data msg = lo_message_deserialise(data, 0, &result); // 0 size TEST(NULL == msg && LO_ESIZE == result); snprintf(data, 256, "%s", "/foo"); // unterminated path string msg = lo_message_deserialise(data, 4, &result); TEST(NULL == msg && LO_EINVALIDPATH == result); snprintf(data, 256, "%s", "/f_o"); // non-0 in pad area msg = lo_message_deserialise(data, 4, &result); TEST(NULL == msg && LO_EINVALIDPATH == result); snprintf(data, 256, "%s", "/t__"); // types missing replace_char(data, 4, '_', '\0'); msg = lo_message_deserialise(data, 4, &result); TEST(NULL == msg && LO_ENOTYPE == result); snprintf(data, 256, "%s%s", "/t__", "____"); // types empty replace_char(data, 8, '_', '\0'); msg = lo_message_deserialise(data, 8, &result); TEST(NULL == msg && LO_EBADTYPE == result); snprintf(data, 256, "%s%s", "/t__", ",f_"); // short message replace_char(data, 7, '_', '\0'); msg = lo_message_deserialise(data, 7, &result); TEST(NULL == msg && LO_EINVALIDTYPE == result); snprintf(data, 256, "%s%s", "/t__", "ifi_"); // types missing comma replace_char(data, 8, '_', '\0'); msg = lo_message_deserialise(data, 8, &result); TEST(NULL == msg && LO_EBADTYPE == result); snprintf(data, 256, "%s%s", "/t__", ",ifi"); // types unterminated replace_char(data, 8, '_', '\0'); msg = lo_message_deserialise(data, 8, &result); TEST(NULL == msg && LO_EINVALIDTYPE == result); snprintf(data, 256, "%s%s", "/t__", ",ii_"); // not enough arg data replace_char(data, 8, '_', '\0'); msg = lo_message_deserialise(data, 12, &result); TEST(NULL == msg && LO_EINVALIDARG == result); snprintf(data, 256, "%s%s", "/t__", ",ii_"); // not enough arg data again replace_char(data, 8, '_', '\0'); msg = lo_message_deserialise(data, 15, &result); TEST(NULL == msg && LO_EINVALIDARG == result); snprintf(data, 256, "%s%s", "/t__", ",f__"); // too much arg data replace_char(data, 8, '_', '\0'); msg = lo_message_deserialise(data, 16, &result); TEST(NULL == msg && LO_ESIZE == result); snprintf(data, 256, "%s%s", "/t__", ",bs_"); // blob longer than msg length replace_char(data, 8, '_', '\0'); *(uint32_t *)(data + 8) = lo_htoo32((uint32_t)99999); msg = lo_message_deserialise(data, 256, &result); TEST(NULL == msg && LO_EINVALIDARG == result); }