static callbackListEnds DispatchSubMessage(char *pattern, OSCcontainer c) { callbackListEnds result; char *nextSlash, *restOfPattern; char offendingAddr[LONG_ADDR_LEN]; int i; result.begin = result.end = 0; nextSlash = NextSlashOrNull(pattern); if (*nextSlash == '\0') { /* Base case: the pattern names methods of this container. */ for (i = 0; i < c->numMethods; i++) { if (PatternMatch(pattern, c->methodNames[i])) { callbackList node = AllocCallbackListNode(c->methods[i]->callback, c->methods[i]->context, result.begin); if (node == 0) { /* Excuse the hairyness of the code to generate the error message. */ if (OSCGetAddressString(offendingAddr, LONG_ADDR_LEN-strlen(c->methodNames[i]), c)) { strcat(offendingAddr, c->methodNames[i]); } else { strcpy(offendingAddr, c->methodNames[i]); } OSCWarning("No memory for callback node; not invoking %s", offendingAddr); } else { if (result.end == 0) { result.end = node; } result.begin = node; } } } } else { /* Recursive case: in the middle of an address, so the job at this step is to look for containers that match. We temporarily turn the next slash into a null so pattern will be a null-terminated string of the stuff between the slashes. */ *nextSlash = '\0'; restOfPattern = nextSlash + 1; for (i = 0; i < c->numChildren; ++i) { if (PatternMatch(pattern, c->childrenNames[i])) { callbackListEnds subResult = DispatchSubMessage(restOfPattern, c->children[i]); if (result.end == 0) { result = subResult; } else { subResult.end->next = result.begin; result.begin = subResult.begin; } } } *nextSlash = '/'; } return result; }
static void routeOSC_doanything(t_routeOSC *x, t_symbol *s, int argc, t_atom *argv) { char *pattern, *nextSlash; int i, pattern_depth = 0, matchedAnything = 0; int noPath = 0; // nonzero if we are dealing with a simple list (as from a previous [routeOSC]) pattern = s->s_name; if (x->x_verbosity) post("routeOSC_doanything(%p): pattern is %s", x, pattern); if (pattern[0] != '/') { // make a path '/'. Now s is actually the first item in the arguments list pattern = gensym("/")->s_name; noPath = 1; if (x->x_verbosity) post("routeOSC_doanything(%p): message pattern \"%s\" does not begin with /, setting path to %s", x, s->s_name, pattern); } pattern_depth = routeOSC_count_slashes(pattern); if (x->x_verbosity) post("routeOSC_doanything(%p): pattern_depth is %i", x, pattern_depth); nextSlash = NextSlashOrNull(pattern+1); if (*nextSlash == '\0') { /* pattern_depth == 1 */ /* last level of the address, so we'll output the argument list */ for (i = 0; i < x->x_num; ++i) { if ( (x->x_prefix_depth[i] <= pattern_depth) && (MyPatternMatch(pattern+1, x->x_prefixes[i]+1)) ) { ++matchedAnything; if (noPath) { // just a list starting with a symbol // The special symbol is s outlet_anything(x->x_outlets[i], s, argc, argv); } else // normal OSC path { // I hate stupid Max lists with a special first element if (argc == 0) { outlet_bang(x->x_outlets[i]); } else if (argv[0].a_type == A_SYMBOL) { // Promote the symbol that was argv[0] to the special symbol outlet_anything(x->x_outlets[i], argv[0].a_w.w_symbol, argc-1, argv+1); } else if (argc > 1) { // Multiple arguments starting with a number, so naturally we have // to use a special function to output this "list", since it's what // Max originally meant by "list". outlet_list(x->x_outlets[i], 0L, argc, argv); } else { // There was only one argument, and it was a number, so we output it // not as a list if (argv[0].a_type == A_FLOAT) { outlet_float(x->x_outlets[i], argv[0].a_w.w_float); } else { pd_error(x, "* routeOSC: unrecognized atom type!"); } } } } } } else { /* There's more address after this part, so our output list will begin with the next slash. */ t_symbol *restOfPattern = 0; /* avoid the gensym unless we have to output */ char patternBegin[1000]; /* Get the incoming pattern to match against all our prefixes */ for (i = 0; i < x->x_num; ++i) { restOfPattern = 0; if (x->x_prefix_depth[i] <= pattern_depth) { StrCopyUntilNthSlash(patternBegin, pattern+1, x->x_prefix_depth[i]); if (x->x_verbosity) post("routeOSC_doanything(%p): (%d) patternBegin is %s", x, i, patternBegin); if (MyPatternMatch(patternBegin, x->x_prefixes[i]+1)) { if (x->x_verbosity) post("routeOSC_doanything(%p): (%d) matched %s depth %d", x, i, x->x_prefixes[i], x->x_prefix_depth[i]); ++matchedAnything; nextSlash = NthSlashOrNull(pattern+1, x->x_prefix_depth[i]); if (x->x_verbosity) post("routeOSC_doanything(%p): (%d) nextSlash %s", x, i, nextSlash); if (restOfPattern == 0) restOfPattern = gensym(nextSlash); outlet_anything(x->x_outlets[i], restOfPattern, argc, argv); } } } } if (!matchedAnything) { // output unmatched data on rightmost outlet a la normal 'route' object, jdl 20020908 outlet_anything(x->x_outlets[x->x_num], s, argc, argv); } }
void OSCroute_doanything(t_OSCroute *x, t_symbol *s, int argc, t_atom *argv) { char *pattern, *nextSlash; int i; int matchedAnything; // post("*** OSCroute_anything(s %s, argc %ld)", s->s_name, (long) argc); pattern = s->s_name; if (pattern[0] != '/') { post("* OSC-route: invalid message pattern %s does not begin with /", s->s_name); outlet_anything(x->x_outlets[x->x_num], s, argc, argv); return; } matchedAnything = 0; nextSlash = NextSlashOrNull(pattern+1); if (*nextSlash == '\0') { /* last level of the address, so we'll output the argument list */ #ifdef NULL_IS_DIFFERENT_FROM_BANG if (argc==0) { post("* OSC-route: why are you matching one level pattern %s with no args?", pattern); return; } #endif for (i = 0; i < x->x_num; ++i) { if (MyPatternMatch(pattern+1, x->x_prefixes[i]+1)) { ++matchedAnything; // I hate stupid Max lists with a special first element if (argc == 0) { outlet_bang(x->x_outlets[i]); } else if (argv[0].a_type == A_SYMBOL) { // Promote the symbol that was argv[0] to the special symbol outlet_anything(x->x_outlets[i], argv[0].a_w.w_symbol, argc-1, argv+1); } else if (argc > 1) { // Multiple arguments starting with a number, so naturally we have // to use a special function to output this "list", since it's what // Max originally meant by "list". outlet_list(x->x_outlets[i], 0L, argc, argv); } else { // There was only one argument, and it was a number, so we output it // not as a list /* if (argv[0].a_type == A_LONG) { */ /* outlet_int(x->x_outlets[i], argv[0].a_w.w_long); */ // } else if (argv[0].a_type == A_FLOAT) { outlet_float(x->x_outlets[i], argv[0].a_w.w_float); } else { post("* OSC-route: unrecognized atom type!"); } } } } } else { /* There's more address after this part, so our output list will begin with the next slash. */ t_symbol *restOfPattern = 0; /* avoid the gensym unless we have to output */ char patternBegin[1000]; /* Get the first level of the incoming pattern to match against all our prefixes */ StrCopyUntilSlash(patternBegin, pattern+1); for (i = 0; i < x->x_num; ++i) { if (MyPatternMatch(patternBegin, x->x_prefixes[i]+1)) { ++matchedAnything; if (restOfPattern == 0) { restOfPattern = gensym(nextSlash); } outlet_anything(x->x_outlets[i], restOfPattern, argc, argv); } } } if (x->x_complainmode) { if (!matchedAnything) { post("* OSC-route: pattern %s did not match any prefixes", pattern); } } // output unmatched data on rightmost outlet a la normal 'route' object, jdl 20020908 if (!matchedAnything) { outlet_anything(x->x_outlets[x->x_num], s, argc, argv); } }