static Boolean MatchBrackets (const char *pattern, const char *test) { Boolean result; Boolean negated = FALSE; const char *p = pattern; if (pattern[1] == 0) { OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern); return FALSE; } if (pattern[1] == '!') { negated = TRUE; p++; } while (*p != ']') { if (*p == 0) { OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern); return FALSE; } if (p[1] == '-' && p[2] != 0) { if (test[0] >= p[0] && test[0] <= p[2]) { result = !negated; goto advance; } } if (p[0] == test[0]) { result = !negated; goto advance; } p++; } result = negated; advance: if (!result) return FALSE; while (*p != ']') { if (*p == 0) { OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern); return FALSE; } p++; } return PatternMatch (p+1,test+1); }
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; }
void ScaleMethod(void *vs, int arglen, const void *vargs, OSCTimeTag when, NetworkReturnAddressPtr ra) { int i; OSCTimeTag now = OSCTT_CurrentTime(); Boolean r; float newarg[1]; float *ptrToArgs[1]; char *address = "/sine1/f"; int newarglen = 4; /* printf("*ScaleMethod (context %p, arglen %d, args %p, when %llx, ra %p)\n", vs, arglen, vargs, when, ra); */ ptrToArgs[0] = newarg; for (i = 0; i < 9; ++i) { newarg[0] = 100.f + i * 50.f; r = OSCScheduleInternalMessages(OSCTT_PlusSeconds(now, (float) i), 1, &address, &newarglen, ptrToArgs); if (r == FALSE) { OSCWarning("ScaleMethod: OSCScheduleInternalMessages returned FALSE"); } } }
Boolean OSCRemoveContainerAlias(OSCcontainer container, Name otherName) { int i, j; OSCcontainer parent = container->parent; Boolean found = FALSE; for (i = 0; i < parent->numChildren; ++i) { if (parent->childrenNames[i] == otherName) { if (parent->children[i] != container) { fatal_error("OSCRemoveContainerAlias: %s is actually a sibling's name!", otherName); } found = TRUE; for (j = i+1; j < parent->numChildren; ++j) { parent->children[j-1] = parent->children[j]; parent->childrenNames[j-1] = parent->childrenNames[j]; --(parent->numChildren); } } } if (!found) { fatal_error("OSCRemoveContainerAlias: %s not found!", otherName); } /* Now make sure the child still exists under another name */ for (i = 0; i < parent->numChildren; ++i) { if (parent->children[i] == container) return TRUE; } OSCWarning("OSCRemoveContainerAlias: %s was the last name for that subcontainer"); /* xxx should recursively free the container and its children... */ return TRUE; }
void GainMethod(void *vs, int arglen, const void *vargs, OSCTimeTag when, NetworkReturnAddressPtr ra) { SynthState *s = vs; const float *args = vargs; if (arglen == 4) { s->g = args[0]; } else { OSCWarning("Wrong arglen to GainMethod: %d", arglen); } }
void FreqMethod(void *vs, int arglen, const void *vargs, OSCTimeTag when, NetworkReturnAddressPtr ra) { SynthState *s = vs; const float *args = vargs; if (arglen == 4) { /* printf("*** FreqMethod arg %f, when %llx\n", args[0], when); */ s->f = args[0]; } else { OSCWarning("Wrong arglen to FreqMethod: %d", arglen); } }
static OSCMethod AllocMethod(void) { static int numExtraAllocs = 0; OSCMethod result; if (freeMethods != 0) { result = freeMethods; freeMethods = freeMethods->next; return result; } OSCWarning("Out of memory for methods; trying to allocate more in real time"); { int num = BASE_NUM_TO_REALLOCATE * ++numExtraAllocs; freeMethods = (*RealTimeMemoryAllocator)(num * sizeof(*freeMethods)); if (freeMethods == 0) { OSCWarning("Real-time allocation failed"); return 0; } MakeFreeMethodsList(num); return AllocMethod(); } }
static queuedData *AllocQD(void) { queuedData *result; if (freeQDList == 0) { /* Could try to call realtime malloc() */ OSCWarning("AllocQD: no QD objects free now; returning 0."); return 0; } result = freeQDList; freeQDList = freeQDList->nextFree; return result; }
void OSCFreePacket(OSCPacketBuffer p) { #ifdef PARANOID if (p->refcount != 0) { OSCWarning("OSCFreePacket: %p's refcount is %d!\n", p, p->refcount); } #endif p->nextFree = freePackets; freePackets = p; #ifdef DEBUG_PACKET_MEM printf("OSCFreePacket: freed %p ", p); PrintPacketFreeList(); #endif }
Boolean PatternMatch (const char * pattern, const char * test) { theWholePattern = pattern; if (pattern == 0 || pattern[0] == 0) { return test[0] == 0; } if (test[0] == 0) { if (pattern[0] == '*') return PatternMatch (pattern+1,test); else return FALSE; } switch (pattern[0]) { case 0 : return test[0] == 0; case '?' : return PatternMatch (pattern + 1, test + 1); case '*' : if (PatternMatch (pattern+1, test)) { return TRUE; } else { return PatternMatch (pattern, test+1); } case ']' : case '}' : OSCWarning("Spurious %c in pattern \".../%s/...\"",pattern[0], theWholePattern); return FALSE; case '[' : return MatchBrackets (pattern,test); case '{' : return MatchList (pattern,test); case '\\' : if (pattern[1] == 0) { return test[0] == 0; } else if (pattern[1] == test[0]) { return PatternMatch (pattern+2,test+1); } else { return FALSE; } default : if (pattern[0] == test[0]) { return PatternMatch (pattern+1,test+1); } else { return FALSE; } } }
void AllMyStringsMethod(void *dummy, int arglen, const void *args, OSCTimeTag when, NetworkReturnAddressPtr ra) { char *strings[MAX_NUM_STRINGS]; int numFound; Boolean r; int i; r = OSCParseStringList(strings, &numFound, MAX_NUM_STRINGS, args, arglen); if (!r) { OSCWarning("AllMyStringsMethod: OSCParseStringList() returned FALSE"); return; } printf("\nAll My Strings:\n"); for (i = 0; i < numFound; ++i) { printf(" strings[%d] is %p: \"%s\"\n", i, strings[i], strings[i]); } }
static Boolean ParseMessage(queuedData *qd) { /* Fill in all the information we'll need to execute the message as quickly as possible when the time comes. This means figuring out where the address ends and the arguments begin, and also pattern matching the address to find the callbacks associated with it. The message may be something we have to invoke now, or it may be some message scheduled for the future that's just waiting on the queue; this procedure doesn't care. */ char *args; /* char * so we can do pointer subtraction */ int messageLen; char *DAAS_errormsg; if (qd->type != MESSAGE) { fatal_error("This can't happen: message isn't a message!"); } args = OSCDataAfterAlignedString(qd->data.message.messageName, qd->data.message.messageName+qd->data.message.length, &DAAS_errormsg); if (args == 0) { OSCProblem("Bad message name string: %s\n", DAAS_errormsg); DropMessage(qd->data.message.messageName, qd->data.message.length, qd->myPacket); return FALSE; } qd->data.message.args = args; messageLen = args - qd->data.message.messageName; qd->data.message.argLength = qd->data.message.length - messageLen; qd->data.message.callbacks = OSCDispatchMessage(qd->data.message.messageName); if (qd->data.message.callbacks == 0) { OSCWarning("Message pattern \"%s\" did not correspond to any address in the synth.", qd->data.message.messageName); return FALSE; } return TRUE; }
static Boolean MatchList (const char *pattern, const char *test) { const char *restOfPattern, *tp = test; for(restOfPattern = pattern; *restOfPattern != '}'; restOfPattern++) { if (*restOfPattern == 0) { OSCWarning("Unterminated { in pattern \".../%s/...\"", theWholePattern); return FALSE; } } restOfPattern++; /* skip close curly brace */ pattern++; /* skip open curly brace */ while (1) { if (*pattern == ',') { if (PatternMatch (restOfPattern, tp)) { return TRUE; } else { tp = test; ++pattern; } } else if (*pattern == '}') { return PatternMatch (restOfPattern, tp); } else if (*pattern == *tp) { ++pattern; ++tp; } else { tp = test; while (*pattern != ',' && *pattern != '}') { pattern++; } if (*pattern == ',') { pattern++; } } } }
void ReceivePacket(int sockfd) { OSCPacketBuffer pb; struct NetworkReturnAddressStruct *ra; int maxclilen=sizeof(struct sockaddr_in); int n; int capacity = OSCGetReceiveBufferSize(); int morePackets = 1; char *buf; while(morePackets) { pb = OSCAllocPacketBuffer(); if (!pb) { OSCWarning("Out of memory for packet buffers---had to drop a packet!"); /* How do I actually gobble down the packet? */ return; } buf = OSCPacketBufferGetBuffer(pb); /* The type NetworkReturnAddressPtr is const in two ways, so that callback procedures that are passed the pointer can neither change the pointer itself or the data the pointer points to. But here's where we fill in the return address, so we do a cast to a non-const type. */ ra = (struct NetworkReturnAddressStruct *) OSCPacketBufferGetClientAddr(pb); ra->clilen = maxclilen; ra->sockfd = sockfd; /* printf("* recvfrom(sockfd %d, buf %p, capacity %d)\n", sockfd, buf, capacity); */ n = recvfrom(sockfd, buf, capacity, 0, &(ra->cl_addr), &(ra->clilen)); if (n > 0) { int *sizep = OSCPacketBufferGetSize(pb); *sizep = n; OSCAcceptPacket(pb); if (time_to_quit) return; } else { OSCFreePacket(pb); morePackets = 0; } } }
OSCPacketBuffer OSCAllocPacketBuffer(void) { OSCPacketBuffer result; if (freePackets == 0) { /* Could try to call the real-time memory allocator here */ OSCWarning("OSCAllocPacketBuffer: no free packets!"); return 0; } result = freePackets; freePackets = result->nextFree; result->refcount = 0; #ifdef DEBUG_PACKET_MEM printf("OSCAllocPacketBuffer: allocating %p ", result); PrintPacketFreeList(); #endif return result; }