mirror of
https://github.com/game-stop/veejay.git
synced 2025-12-22 15:50:01 +01:00
moved
git-svn-id: svn://code.dyne.org/veejay/trunk@52 eb8d1916-c9e9-0310-b8de-cf0c9472ead5
This commit is contained in:
1
veejay-current/libOSC/AUTHORS
Normal file
1
veejay-current/libOSC/AUTHORS
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
25
veejay-current/libOSC/Makefile.am
Normal file
25
veejay-current/libOSC/Makefile.am
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
DEBUG_CFLAGS =
|
||||||
|
|
||||||
|
INCLUDES = -I$(top_srcdir)/libOSC -I$(includedir)
|
||||||
|
|
||||||
|
OSC_LIB_FILE = libOSC.la
|
||||||
|
ALL_LIB_OPTS = -release $(LT_RELEASE) -export-dynamic
|
||||||
|
|
||||||
|
noinst_LTLIBRARIES = $(OSC_LIB_FILE)
|
||||||
|
|
||||||
|
|
||||||
|
libOSC_la_CFLAGS = $(DEBUG_CFLAGS)
|
||||||
|
|
||||||
|
libOSC_la_SOURCES = OSC-address-space.c \
|
||||||
|
OSC-callbacklist.c \
|
||||||
|
OSC-drop.c \
|
||||||
|
OSC-pattern-match.c \
|
||||||
|
OSC-priority-queue.c \
|
||||||
|
OSC-receive.c \
|
||||||
|
OSC-string-help.c \
|
||||||
|
OSC-common.c \
|
||||||
|
OSC-timetag.c \
|
||||||
|
NetworkReturnAddress.c
|
||||||
|
|
||||||
|
libOSC_la_LDFLAGS = $(ALL_LIB_OPTS) -DDYNAMIC -O2 -Wall -rdynamic
|
||||||
|
|
||||||
0
veejay-current/libOSC/NEWS
Normal file
0
veejay-current/libOSC/NEWS
Normal file
58
veejay-current/libOSC/NetworkReturnAddress.c
Normal file
58
veejay-current/libOSC/NetworkReturnAddress.c
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||||
|
University of California, Berkeley.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||||
|
of this software and its documentation without fee and without a signed
|
||||||
|
licensing agreement, is hereby granted, provided that the above copyright
|
||||||
|
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||||
|
modifications, and distributions.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||||
|
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||||
|
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||||
|
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
The OpenSound Control WWW page is
|
||||||
|
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
NetworkReturnAddress.c
|
||||||
|
|
||||||
|
This version implements UDP return addresses on SGI
|
||||||
|
|
||||||
|
Matt Wright,
|
||||||
|
9/11/98
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <libOSC/OSC-common.h>
|
||||||
|
#include <libOSC/OSC-timetag.h>
|
||||||
|
#include <libOSC/OSC-address-space.h>
|
||||||
|
#include <libOSC/NetworkReturnAddress.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <libOSC/NetworkUDP.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int SizeOfNetworkReturnAddress(void) {
|
||||||
|
return sizeof(struct NetworkReturnAddressStruct);
|
||||||
|
}
|
||||||
|
|
||||||
|
Boolean NetworkSendReturnMessage(NetworkReturnAddressPtr addr,
|
||||||
|
int n,
|
||||||
|
void *buf) {
|
||||||
|
if (addr == 0) return FALSE;
|
||||||
|
|
||||||
|
return n == sendto(addr->sockfd, buf, n, 0, &(addr->cl_addr), addr->clilen);
|
||||||
|
}
|
||||||
52
veejay-current/libOSC/NetworkReturnAddress.h
Normal file
52
veejay-current/libOSC/NetworkReturnAddress.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||||
|
University of California, Berkeley.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||||
|
of this software and its documentation without fee and without a signed
|
||||||
|
licensing agreement, is hereby granted, provided that the above copyright
|
||||||
|
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||||
|
modifications, and distributions.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||||
|
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||||
|
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||||
|
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
The OpenSound Control WWW page is
|
||||||
|
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
NetworkReturnAddress.h
|
||||||
|
|
||||||
|
API that the OSC Kit uses to deal with network return addresses. You will
|
||||||
|
fill in parts of this file and write NetworkReturnAddress.c to implement
|
||||||
|
this API via whatever network services you use.
|
||||||
|
|
||||||
|
NB: This API is the only interface the Kit uses for dealing with network
|
||||||
|
addresses, but of course the part of the application that accepts incoming
|
||||||
|
packets needs to know about network return addresses so it can fill in the
|
||||||
|
correct return address when it receives a packet.
|
||||||
|
|
||||||
|
Matt Wright,
|
||||||
|
6/3/98
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Return sizeof(struct NetworkReturnAddressStruct). */
|
||||||
|
int SizeOfNetworkReturnAddress(void);
|
||||||
|
|
||||||
|
/* Send a packet back to the client, or do nothing if addr==0 */
|
||||||
|
Boolean NetworkSendReturnMessage(NetworkReturnAddressPtr addr,
|
||||||
|
int n,
|
||||||
|
void *buf);
|
||||||
7
veejay-current/libOSC/NetworkUDP.h
Normal file
7
veejay-current/libOSC/NetworkUDP.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
struct NetworkReturnAddressStruct {
|
||||||
|
struct sockaddr_in cl_addr;
|
||||||
|
int clilen;
|
||||||
|
int sockfd;
|
||||||
|
};
|
||||||
599
veejay-current/libOSC/OSC-address-space.c
Normal file
599
veejay-current/libOSC/OSC-address-space.c
Normal file
@@ -0,0 +1,599 @@
|
|||||||
|
/*
|
||||||
|
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||||
|
University of California, Berkeley.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||||
|
of this software and its documentation without fee and without a signed
|
||||||
|
licensing agreement, is hereby granted, provided that the above copyright
|
||||||
|
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||||
|
modifications, and distributions.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||||
|
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||||
|
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||||
|
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
The OpenSound Control WWW page is
|
||||||
|
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
OSC-address-space.c
|
||||||
|
Matt Wright, 3/16/98
|
||||||
|
*/
|
||||||
|
#include <config.h>
|
||||||
|
#include <libOSC/OSC-common.h>
|
||||||
|
#include <libOSC/OSC-timetag.h>
|
||||||
|
#include <libOSC/OSC-address-space.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define MAX_ALIASES_PER_CONTAINER 3
|
||||||
|
#define MAX_CHILDREN_PER_CONTAINER 20
|
||||||
|
#define MAX_METHODS_PER_CONTAINER 30
|
||||||
|
#define BASE_NUM_TO_REALLOCATE 10
|
||||||
|
|
||||||
|
|
||||||
|
struct OSCContainerStruct {
|
||||||
|
struct OSCContainerStruct *parent;
|
||||||
|
int numChildren;
|
||||||
|
Name childrenNames[MAX_CHILDREN_PER_CONTAINER];
|
||||||
|
struct OSCContainerStruct *children[MAX_CHILDREN_PER_CONTAINER];
|
||||||
|
int numMethods;
|
||||||
|
Name methodNames[MAX_METHODS_PER_CONTAINER];
|
||||||
|
OSCMethod methods[MAX_METHODS_PER_CONTAINER];
|
||||||
|
struct OSCContainerQueryResponseInfoStruct QueryResponseInfo;
|
||||||
|
struct OSCContainerStruct *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OSCMethodStruct {
|
||||||
|
methodCallback callback;
|
||||||
|
void *context;
|
||||||
|
struct OSCMethodQueryResponseInfoStruct QueryResponseInfo;
|
||||||
|
struct OSCMethodStruct *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Globals */
|
||||||
|
static Boolean Initialized = FALSE;
|
||||||
|
static OSCcontainer OSCTopLevelContainer;
|
||||||
|
static OSCcontainer freeContainers; /* Linked list via next field. */
|
||||||
|
static OSCMethod freeMethods; /* Linked list via next field. */
|
||||||
|
static void *(*RealTimeMemoryAllocator)(int numBytes);
|
||||||
|
|
||||||
|
|
||||||
|
/* Note: The free list of containers should actually be a "free forest", so
|
||||||
|
that all the subcontainers recursively under a freed container are
|
||||||
|
automatically freed.
|
||||||
|
|
||||||
|
FREE: just stick the freed subtree on the front of the list.
|
||||||
|
|
||||||
|
ALLOC: Take all the children of the first container on the list and
|
||||||
|
insert them in the free list, then return that first container.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/************************ Initialization and Memory ************************/
|
||||||
|
|
||||||
|
static void MakeFreeContainersList(int n) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i+1 < n; ++i) {
|
||||||
|
freeContainers[i].next = &(freeContainers[i+1]);
|
||||||
|
}
|
||||||
|
freeContainers[n-1].next = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MakeFreeMethodsList(int n) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i+1 < n; ++i) {
|
||||||
|
freeMethods[i].next = &(freeMethods[i+1]);
|
||||||
|
}
|
||||||
|
freeMethods[n-1].next = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
OSCcontainer OSCInitAddressSpace(struct OSCAddressSpaceMemoryTuner *t) {
|
||||||
|
int bytesNeeded;
|
||||||
|
|
||||||
|
if (Initialized)
|
||||||
|
fatal_error("OSCInitAddressSpace: already initialized!");
|
||||||
|
Initialized = TRUE;
|
||||||
|
|
||||||
|
RealTimeMemoryAllocator = t->RealTimeMemoryAllocator;
|
||||||
|
|
||||||
|
bytesNeeded = (1 + t->initNumContainers) * sizeof(*freeContainers);
|
||||||
|
freeContainers = (OSCcontainer) (*(t->InitTimeMemoryAllocator))(bytesNeeded);
|
||||||
|
if (freeContainers == 0) {
|
||||||
|
fatal_error("OSCInitAddressSpace: couldn't allocate %d bytes for %d containers",
|
||||||
|
bytesNeeded, t->initNumContainers);
|
||||||
|
}
|
||||||
|
|
||||||
|
OSCTopLevelContainer = &freeContainers[t->initNumContainers];
|
||||||
|
MakeFreeContainersList(t->initNumContainers);
|
||||||
|
|
||||||
|
bytesNeeded = t->initNumMethods * sizeof(*freeMethods);
|
||||||
|
freeMethods = (OSCMethod) (*(t->InitTimeMemoryAllocator))(bytesNeeded);
|
||||||
|
if (freeMethods == 0) {
|
||||||
|
fatal_error("OSCInitAddressSpace: couldn't allocate %d bytes for %d methods",
|
||||||
|
bytesNeeded, t->initNumMethods);
|
||||||
|
}
|
||||||
|
MakeFreeMethodsList(t->initNumMethods);
|
||||||
|
|
||||||
|
/* Initialize the top-level container */
|
||||||
|
OSCTopLevelContainer->parent = 0;
|
||||||
|
OSCTopLevelContainer->numChildren = 0;
|
||||||
|
OSCTopLevelContainer->numMethods = 0;
|
||||||
|
OSCTopLevelContainer->QueryResponseInfo.comment = "OSC top-level container";
|
||||||
|
OSCTopLevelContainer->next = 0;
|
||||||
|
|
||||||
|
return OSCTopLevelContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Container and method memory management: linked lists of free objects */
|
||||||
|
|
||||||
|
static OSCcontainer AllocContainer(void) {
|
||||||
|
static int numExtraAllocs = 0;
|
||||||
|
|
||||||
|
OSCcontainer result;
|
||||||
|
if (freeContainers != 0) {
|
||||||
|
result = freeContainers;
|
||||||
|
freeContainers = freeContainers->next;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
OSCWarning("Out of memory for containers; trying to allocate more in real time");
|
||||||
|
{
|
||||||
|
int num = BASE_NUM_TO_REALLOCATE * ++numExtraAllocs;
|
||||||
|
freeContainers = (*RealTimeMemoryAllocator)(num * sizeof(*freeContainers));
|
||||||
|
if (freeContainers == 0) {
|
||||||
|
OSCWarning("Real-time allocation failed");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
MakeFreeContainersList(num);
|
||||||
|
return AllocContainer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//static void FreeContainer(OSCcontainer c) {
|
||||||
|
// c->next = freeContainers;
|
||||||
|
// freeContainers = c;
|
||||||
|
//}
|
||||||
|
|
||||||
|
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 void FreeMethod(OSCMethod c) {
|
||||||
|
// c->next = freeMethods;
|
||||||
|
// freeMethods = c;
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************** Containers ****************************/
|
||||||
|
|
||||||
|
/* Managing the tree of containers and subcontainers, with aliases */
|
||||||
|
|
||||||
|
void AddSubContainer(OSCcontainer parent, OSCcontainer child, Name name) {
|
||||||
|
if (parent->numChildren >= MAX_CHILDREN_PER_CONTAINER) {
|
||||||
|
fatal_error("AddSubContainer: exceeded MAX_CHILDREN_PER_CONTAINER (%d)\n"
|
||||||
|
"Increase the value in OSC-address-space.c and recompile.",
|
||||||
|
MAX_CHILDREN_PER_CONTAINER);
|
||||||
|
}
|
||||||
|
|
||||||
|
parent->childrenNames[parent->numChildren] = name;
|
||||||
|
parent->children[parent->numChildren] = child;
|
||||||
|
++(parent->numChildren);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Boolean OSCAddContainerAlias(OSCcontainer container, Name otherName) {
|
||||||
|
if (container->parent->numChildren >= MAX_CHILDREN_PER_CONTAINER) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
AddSubContainer(container->parent, container, otherName);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveSubContainer(OSCcontainer parent, OSCcontainer child) {
|
||||||
|
int i, numRemoved;
|
||||||
|
|
||||||
|
/* Remove every pointer to the container, even if it has multiple aliases */
|
||||||
|
|
||||||
|
numRemoved = 0;
|
||||||
|
for (i = 0; i < parent->numChildren; ++i) {
|
||||||
|
if (parent->children[i] != child) {
|
||||||
|
parent->children[i-numRemoved] = parent->children[i];
|
||||||
|
parent->childrenNames[i-numRemoved] = parent->childrenNames[i];
|
||||||
|
} else {
|
||||||
|
++numRemoved;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parent->numChildren -= numRemoved;
|
||||||
|
|
||||||
|
if (numRemoved == 0) {
|
||||||
|
fatal_error("RemoveSubContainer: subcontainer not found!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
OSCcontainer OSCNewContainer(Name name, OSCcontainer parent,
|
||||||
|
struct OSCContainerQueryResponseInfoStruct *QueryResponseInfo) {
|
||||||
|
OSCcontainer me;
|
||||||
|
|
||||||
|
me = AllocContainer();
|
||||||
|
if (me == 0) return 0;
|
||||||
|
|
||||||
|
if (strchr(name, '/') != NULL) {
|
||||||
|
OSCProblem("Container name \"%s\" contains a slash --- not good.",
|
||||||
|
name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
me->parent = parent;
|
||||||
|
AddSubContainer(me->parent, me, name);
|
||||||
|
me->numChildren = 0;
|
||||||
|
me->numMethods = 0;
|
||||||
|
me->QueryResponseInfo = (*QueryResponseInfo);
|
||||||
|
return me;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const char *ContainerName(OSCcontainer c) {
|
||||||
|
/* Return the first name associated with me in my parent's child list.
|
||||||
|
(Assume all later ones are aliases.) */
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < c->parent->numChildren; ++i) {
|
||||||
|
if (c->parent->children[i] == c) {
|
||||||
|
return c->parent->childrenNames[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fatal_error("ContainerName: Container %p isn't in its parent's child list.", c);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gasHelp(char *target, int maxlength, OSCcontainer c );
|
||||||
|
|
||||||
|
Boolean OSCGetAddressString(char *target, int maxLength, OSCcontainer c) {
|
||||||
|
int lenNeeded;
|
||||||
|
|
||||||
|
if (maxLength <= 1) return FALSE;
|
||||||
|
|
||||||
|
lenNeeded = gasHelp(target, maxLength-1, c) + 1; /* -1, +1 are for null char. */
|
||||||
|
if (lenNeeded > maxLength) {
|
||||||
|
OSCProblem("Address string too long (room for %d chars; need %d)",
|
||||||
|
maxLength, lenNeeded);
|
||||||
|
target[0] = '\0';
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gasHelp(char *target, int maxLength, OSCcontainer c) {
|
||||||
|
int sublength, length;
|
||||||
|
const char *myName;
|
||||||
|
|
||||||
|
/* printf("*** gasHelp %s %d %p %s\n", target, maxLength, c, c->name); */
|
||||||
|
|
||||||
|
if (c == OSCTopLevelContainer) {
|
||||||
|
target[0] = '/';
|
||||||
|
target[1] = '\0';
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
myName = ContainerName(c);
|
||||||
|
sublength = gasHelp(target, maxLength, c->parent);
|
||||||
|
length = sublength + strlen(myName) + 1; /* +1 is for trailing slash */
|
||||||
|
if (length > maxLength) {
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(target+sublength, myName);
|
||||||
|
target[length-1] = '/';
|
||||||
|
target[length] = '\0';
|
||||||
|
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************** Methods ****************************/
|
||||||
|
|
||||||
|
#define LONG_ADDR_SIZE 1000 /* Just for error messages */
|
||||||
|
|
||||||
|
OSCMethod OSCNewMethod(Name name, OSCcontainer me, methodCallback callback,
|
||||||
|
void *context, struct OSCMethodQueryResponseInfoStruct *QueryResponseInfo) {
|
||||||
|
|
||||||
|
char addr[LONG_ADDR_SIZE];
|
||||||
|
OSCMethod m;
|
||||||
|
|
||||||
|
if (strchr(name, '/') != NULL) {
|
||||||
|
OSCProblem("Method name \"%s\" contains a slash --- not good.",
|
||||||
|
name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (me->numMethods >= MAX_METHODS_PER_CONTAINER) {
|
||||||
|
addr[0] = '\0';
|
||||||
|
OSCGetAddressString(addr, LONG_ADDR_SIZE, me);
|
||||||
|
OSCProblem("OSCNewMethod: container %s already has %d methods; can't add another\n"
|
||||||
|
"Change MAX_METHODS_PER_CONTAINER in OSC-address-space.c and recompile.",
|
||||||
|
addr, me->numMethods);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m = AllocMethod();
|
||||||
|
if (!m) return 0;
|
||||||
|
|
||||||
|
m->callback = callback;
|
||||||
|
m->context = context;
|
||||||
|
m->QueryResponseInfo = *QueryResponseInfo;
|
||||||
|
|
||||||
|
me->methodNames[me->numMethods] = name;
|
||||||
|
me->methods[me->numMethods] = m;
|
||||||
|
++(me->numMethods);
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************** Queries ****************************/
|
||||||
|
|
||||||
|
void OSCInitContainerQueryResponseInfo(struct OSCContainerQueryResponseInfoStruct *i) {
|
||||||
|
i->comment = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSCInitMethodQueryResponseInfo(struct OSCMethodQueryResponseInfoStruct *i) {
|
||||||
|
i->description = 0;
|
||||||
|
i->pvq = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************* Debug ********************************/
|
||||||
|
|
||||||
|
|
||||||
|
static int ContainerAliases(OSCcontainer c, char *target) {
|
||||||
|
/* Write a space-delimited list of alias names in the given string,
|
||||||
|
and return the number */
|
||||||
|
int i, n;
|
||||||
|
|
||||||
|
if (c == OSCTopLevelContainer) return 0;
|
||||||
|
target[0] = '\0';
|
||||||
|
n = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < c->parent->numChildren; ++i) {
|
||||||
|
if (c->parent->children[i] == c) {
|
||||||
|
if (n > 0) {
|
||||||
|
strcat(target, " ");
|
||||||
|
strcat(target, c->parent->childrenNames[i]);
|
||||||
|
}
|
||||||
|
++n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (n == 0) fatal_error("ContainerAliases: internal inconsistency");
|
||||||
|
|
||||||
|
return n-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BIG_ADDRESS 50
|
||||||
|
|
||||||
|
static void PrintHelp(OSCcontainer c) {
|
||||||
|
char addr[BIG_ADDRESS];
|
||||||
|
char aliasNames[1000];
|
||||||
|
|
||||||
|
int i, j, numAliases;
|
||||||
|
|
||||||
|
if (OSCGetAddressString(addr, BIG_ADDRESS, c) == FALSE) {
|
||||||
|
printf(" /.../%s", ContainerName(c));
|
||||||
|
} else {
|
||||||
|
printf(" %s", addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
numAliases = ContainerAliases(c, aliasNames);
|
||||||
|
if (numAliases > 0) {
|
||||||
|
printf(" (%d aliases:%s)", numAliases, aliasNames);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
for (i = 0; i < c->numMethods; ++i) {
|
||||||
|
printf(" %s%s: %s\n", addr, c->methodNames[i],
|
||||||
|
c->methods[i]->QueryResponseInfo.description);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Forgive this quadratic kludge: */
|
||||||
|
for (i = 0; i < c->numChildren; ++i) {
|
||||||
|
int matches = 0;
|
||||||
|
for (j = 0; j < i; ++j) {
|
||||||
|
if (c->children[j] == c->children[i]) {
|
||||||
|
/* c->children[i] is just an alias to c->children[j],
|
||||||
|
which we already printed, so ignore it. */
|
||||||
|
matches ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(matches == 0 ) PrintHelp(c->children[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSCPrintWholeAddressSpace(void) {
|
||||||
|
printf("\n----- The OSC address space -----\n");
|
||||||
|
PrintHelp(OSCTopLevelContainer);
|
||||||
|
printf("...end of OSC address space.\n\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***************************** Dispatching *****************************/
|
||||||
|
|
||||||
|
#include <libOSC/OSC-dispatch.h>
|
||||||
|
#include <libOSC/OSC-callbacklist.h>
|
||||||
|
#include <libOSC/OSC-pattern-match.h>
|
||||||
|
|
||||||
|
/* To do quick concatenation of singly-linked lists, we pass around
|
||||||
|
this data structure that points to the first and last elements: */
|
||||||
|
|
||||||
|
typedef struct callbackListEnds_struct {
|
||||||
|
callbackList begin;
|
||||||
|
callbackList end;
|
||||||
|
} callbackListEnds;
|
||||||
|
|
||||||
|
/* Helper proc. declarations */
|
||||||
|
static callbackListEnds DispatchSubMessage(char *pattern, OSCcontainer c);
|
||||||
|
static char *NextSlashOrNull(char *p);
|
||||||
|
|
||||||
|
|
||||||
|
callbackList OSCDispatchMessage(char *pattern) {
|
||||||
|
callbackListEnds result;
|
||||||
|
|
||||||
|
if (pattern[0] != '/') {
|
||||||
|
OSCProblem("Invalid address \"%s\" does not begin with /", pattern);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = DispatchSubMessage(pattern+1, OSCTopLevelContainer);
|
||||||
|
|
||||||
|
return result.begin;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LONG_ADDR_LEN 100
|
||||||
|
|
||||||
|
|
||||||
|
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 char *NextSlashOrNull(char *p) {
|
||||||
|
while (*p != '/' && *p != '\0') {
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
364
veejay-current/libOSC/OSC-address-space.h
Normal file
364
veejay-current/libOSC/OSC-address-space.h
Normal file
@@ -0,0 +1,364 @@
|
|||||||
|
/*
|
||||||
|
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||||
|
University of California, Berkeley.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||||
|
of this software and its documentation without fee and without a signed
|
||||||
|
licensing agreement, is hereby granted, provided that the above copyright
|
||||||
|
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||||
|
modifications, and distributions.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||||
|
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||||
|
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||||
|
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
The OpenSound Control WWW page is
|
||||||
|
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
OSC-address-space.h
|
||||||
|
Matt Wright, 11/20/97
|
||||||
|
Version 2.0 5/28/98
|
||||||
|
|
||||||
|
C interface for registering the nodes in the OSC address space for an
|
||||||
|
application.
|
||||||
|
|
||||||
|
include OSC-timetag.h before this file
|
||||||
|
|
||||||
|
****************************** Introduction ******************************
|
||||||
|
|
||||||
|
|
||||||
|
The model is based on our original C++ design and consists of two kinds of
|
||||||
|
objects:
|
||||||
|
|
||||||
|
methods are the leaf nodes of the address space hierarchy. A complete OSC
|
||||||
|
address corresponds to a particular method, which has a corresponding
|
||||||
|
callback procedure that will be invoked to implement commands sent by an
|
||||||
|
OSC client.
|
||||||
|
|
||||||
|
containers are branch nodes of the address space hierarchy, and contain
|
||||||
|
methods and other containers. Each container has a single namespace;
|
||||||
|
it cannot contain a method and a subcontainer with the same name.
|
||||||
|
|
||||||
|
For example, let's examine the OSC message "/resonators/foo/decay 2.5". The
|
||||||
|
address of this message is "/resonators/foo/decay" and the message has a
|
||||||
|
single argument, 2.5. We'd say that the object corresponding to the prefix
|
||||||
|
"/resonators" is a container, and that it contains another container whose
|
||||||
|
address is "/resonators/foo". The "/resonators/foo" container has a method
|
||||||
|
"decay".
|
||||||
|
|
||||||
|
The memory model used by this module is pre-allocation of fixed-size objects
|
||||||
|
for containers, methods, and other internal objects. This preallocated
|
||||||
|
memory is dynamically managed internally by a custom high-performance memory
|
||||||
|
allocator. When the preallocated memory runs out, this module calls an
|
||||||
|
optional realtime memory allocator that you provide. If your memory allocator
|
||||||
|
gives this module more memory, it will add it to the pool of objects and
|
||||||
|
never free the memory. If your system does not have a realtime memory
|
||||||
|
allocator, provide a procedure that always returns 0.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*************************** Type Definitions ******************************/
|
||||||
|
|
||||||
|
/* Users of this module don't get to see what's inside these objects */
|
||||||
|
typedef struct OSCContainerStruct *OSCcontainer;
|
||||||
|
typedef struct OSCMethodStruct *OSCMethod;
|
||||||
|
|
||||||
|
/* This makes it easy to change the way we represent symbolic names: */
|
||||||
|
typedef const char *Name;
|
||||||
|
|
||||||
|
|
||||||
|
/************************ Initialization and Memory ************************/
|
||||||
|
|
||||||
|
/* You will fill an OSCAddressSpaceMemoryTuner struct with the parameters that
|
||||||
|
determine how memory will be allocated.
|
||||||
|
|
||||||
|
initNumContainers is the number of containers that will be allocated at
|
||||||
|
initialization time. This should be the maximum number of containers you
|
||||||
|
ever expect to have in your address space.
|
||||||
|
|
||||||
|
initNumMethods is the number of methods that will be allocated at
|
||||||
|
initialization time. If you register the same method callback procedure
|
||||||
|
multiple times at different places in the address space, each of these
|
||||||
|
locations counts as a separate method as far as memory allocation is
|
||||||
|
concerned.
|
||||||
|
|
||||||
|
The MemoryAllocator fields are procedures you will provide that allocate
|
||||||
|
memory. Like malloc(), they take the number of bytes as arguments and return
|
||||||
|
either a pointer to the new memory or 0 for failure. This memory will never
|
||||||
|
be freed.
|
||||||
|
|
||||||
|
The InitTimeMemoryAllocator will be called only at initialization time,
|
||||||
|
i.e., before OSCInitAddressSpace() returns. If it ever returns 0, that's
|
||||||
|
a fatal error.
|
||||||
|
|
||||||
|
The RealTimeMemoryAllocator will be called if, while the application is
|
||||||
|
running, the address space grows larger than can fit in what was allocated
|
||||||
|
at initialization time. If the RealTimeMemoryAllocator() returns 0, the
|
||||||
|
operation attempting to grow the address space will fail. If your system
|
||||||
|
does not have real-time memory allocation, RealTimeMemoryAllocator should
|
||||||
|
be a procedure that always returns 0.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct OSCAddressSpaceMemoryTuner {
|
||||||
|
int initNumContainers;
|
||||||
|
int initNumMethods;
|
||||||
|
void *(*InitTimeMemoryAllocator)(int numBytes);
|
||||||
|
void *(*RealTimeMemoryAllocator)(int numBytes);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Given an OSCAddressSpaceMemoryTuner, return the number of bytes of
|
||||||
|
memory that would be allocated if OSCInitAddressSpace() were called
|
||||||
|
on it. */
|
||||||
|
int OSCAddressSpaceMemoryThatWouldBeAllocated(struct OSCAddressSpaceMemoryTuner *t);
|
||||||
|
|
||||||
|
|
||||||
|
/* Call this before you call anything else. It returns the container that
|
||||||
|
corresponds to the address "/" and is the root of the address space tree.
|
||||||
|
*/
|
||||||
|
OSCcontainer OSCInitAddressSpace(struct OSCAddressSpaceMemoryTuner *t);
|
||||||
|
|
||||||
|
|
||||||
|
/**************************** Containers ****************************/
|
||||||
|
|
||||||
|
/* Here's how this system deals with the standard OSC queries addressed to
|
||||||
|
containers. This module handles the details of listening for these queries
|
||||||
|
and returning a correctly-formatted answer; all it needs from you is the
|
||||||
|
actual data that constitute the answers to these queries.
|
||||||
|
|
||||||
|
You pass this data in an OSCContainerQueryResponseInfo structure. Future versions
|
||||||
|
of this module may have new kinds of queries that they can deal with, so
|
||||||
|
the list of fields in this structure may grow. That's why your code should
|
||||||
|
call OSCInitContainerQueryResponseInfo() on your struct before putting new values
|
||||||
|
into it; this procedure will initialize all of the fields to 0, meaning
|
||||||
|
"don't have that information", which will cause the associated queries to
|
||||||
|
fail.
|
||||||
|
|
||||||
|
The "null" message, i.e., a message with a trailing slash, requesting the
|
||||||
|
list of addresses under a given container, is handled automatically.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct OSCContainerQueryResponseInfoStruct {
|
||||||
|
char *comment;
|
||||||
|
/* Other fields may go here */
|
||||||
|
};
|
||||||
|
|
||||||
|
void OSCInitContainerQueryResponseInfo(struct OSCContainerQueryResponseInfoStruct *i);
|
||||||
|
|
||||||
|
|
||||||
|
/* Allocate a new container and initialize it. Returns 0 if it cannot
|
||||||
|
allocate a new container, e.g., if you've exceeded the initNumContainers
|
||||||
|
limit of the OSCAddressSpaceMemoryTuner() and the RealTimeMemoryAllocator()
|
||||||
|
didn't return any new memory.
|
||||||
|
|
||||||
|
This procedure doesn't make a copy of the name string or any of the
|
||||||
|
contents of the OSCContainerQueryResponseInfoStruct. It does copy the fields
|
||||||
|
of the OSCContainerQueryResponseInfoStruct.
|
||||||
|
*/
|
||||||
|
OSCcontainer OSCNewContainer(Name name, OSCcontainer parent,
|
||||||
|
struct OSCContainerQueryResponseInfoStruct *queryInfo);
|
||||||
|
|
||||||
|
|
||||||
|
/* Remove a container from the address space. This also removes all the
|
||||||
|
container's methods and recursively removes all sub-containers. Memory
|
||||||
|
freed by removing a container is kept in this module's internal pool.
|
||||||
|
*/
|
||||||
|
void OSCRemoveContainer(OSCcontainer container);
|
||||||
|
|
||||||
|
|
||||||
|
/* Given a pointer to a container, and another name for that container, add or
|
||||||
|
remove that name as an alias for the container. Return FALSE for failure. */
|
||||||
|
Boolean OSCAddContainerAlias(OSCcontainer container, Name otherName);
|
||||||
|
Boolean OSCRemoveContainerAlias(OSCcontainer container, Name otherName);
|
||||||
|
|
||||||
|
|
||||||
|
/* Write the OSC address of the given container into the given string.
|
||||||
|
Return FALSE if the address won't fit in the string. */
|
||||||
|
Boolean OSCGetAddressString(char *target, int maxLength, OSCcontainer c);
|
||||||
|
|
||||||
|
|
||||||
|
/* Given an address (not a pattern!), return the single OSCcontainer it names,
|
||||||
|
or 0 if there is no container at that address */
|
||||||
|
OSCcontainer OSCLookUpContainer(Name address);
|
||||||
|
|
||||||
|
|
||||||
|
/**************************** Methods ****************************/
|
||||||
|
|
||||||
|
/* A methodCallback is a procedure that you write that will be called at the
|
||||||
|
time that an OSC message is to take effect. It will be called with 5
|
||||||
|
arguments:
|
||||||
|
- A context pointer that was registered with the methodNode
|
||||||
|
this is a method of. (Something like the C++ "this" pointer.)
|
||||||
|
- The number of bytes of argument data
|
||||||
|
- A pointer to the argument portion of the OSC message
|
||||||
|
- The time tag at which this message is supposed to take effect.
|
||||||
|
- A "return address" object you can use to send a message back to the
|
||||||
|
client that sent this message. This return channel is guaranteed
|
||||||
|
to be usable only during the invocation of your method, so your method
|
||||||
|
must use the return address immediately or ignore it, not store it away
|
||||||
|
for later use.
|
||||||
|
*/
|
||||||
|
typedef struct NetworkReturnAddressStruct *NetworkReturnAddressPtr;
|
||||||
|
/* removed const */
|
||||||
|
|
||||||
|
typedef void (*methodCallback)(void *context, int arglen, const void *args,
|
||||||
|
OSCTimeTag when, NetworkReturnAddressPtr returnAddr);
|
||||||
|
|
||||||
|
|
||||||
|
/* A ParamValQuerier is a procedure that the OSC system will call when the
|
||||||
|
user wants to know the current value of a parameter. It will be passed the
|
||||||
|
same context pointer as the associated method. It should write its return
|
||||||
|
value in the given buffer in the same format as the associated
|
||||||
|
methodCallback would expect its "args" argument, and should return the
|
||||||
|
length of data just like the method would expect in its "arglen" argument.
|
||||||
|
It doesn't have to worry about the address portion of the OSC message.
|
||||||
|
*/
|
||||||
|
typedef char OSCData; /* For pointers to OSC-formatted data */
|
||||||
|
typedef int (*ParamValQuerier)(OSCData *result, void *context);
|
||||||
|
|
||||||
|
|
||||||
|
/* This system deals with other standard per-method queries, such as
|
||||||
|
documentation, valid parameter types and ranges, units, default values,
|
||||||
|
etc., pretty much just like per-container queries.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct OSCMethodQueryResponseInfoStruct {
|
||||||
|
char *description;
|
||||||
|
ParamValQuerier pvq;
|
||||||
|
/* For each argument of the method:
|
||||||
|
min, max, default, units */
|
||||||
|
};
|
||||||
|
|
||||||
|
void OSCInitMethodQueryResponseInfo(struct OSCMethodQueryResponseInfoStruct *i);
|
||||||
|
|
||||||
|
|
||||||
|
/* Allocate a new method, initialize it, and add it to a container. Returns 0
|
||||||
|
for failure, e.g., if you've exceeded the initNumMethods limit of the
|
||||||
|
OSCAddressSpaceMemoryTuner() and the RealTimeMemoryAllocator() didn't return any
|
||||||
|
new memory.
|
||||||
|
|
||||||
|
This procedure doesn't make a copy of the name string or any of the
|
||||||
|
contents of the OSCMethodQueryResponseInfoStruct.
|
||||||
|
*/
|
||||||
|
|
||||||
|
OSCMethod OSCNewMethod(Name name, OSCcontainer container, methodCallback meth,
|
||||||
|
void *context, struct OSCMethodQueryResponseInfoStruct *queryInfo);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/******************************* Debug ********************************/
|
||||||
|
|
||||||
|
|
||||||
|
void OSCPrintWholeAddressSpace(void);
|
||||||
|
|
||||||
|
|
||||||
|
/**************************** Sample Code *****************************/
|
||||||
|
|
||||||
|
/* Here's a gross approximation of how your application will invoke the
|
||||||
|
procedures in this module. It registers an address space with
|
||||||
|
containers with addresses "/foo", "/foo/foochild", and "/bar",
|
||||||
|
and gives each of them "play" and "shuddup" messages.
|
||||||
|
|
||||||
|
|
||||||
|
#include "OSC-common.h"
|
||||||
|
#include "OSC-timetag.h"
|
||||||
|
#include "OSC-address-space.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int playing;
|
||||||
|
int param;
|
||||||
|
float otherParam;
|
||||||
|
} Player;
|
||||||
|
|
||||||
|
void PlayCallback(void *context, int arglen, const void *vargs,
|
||||||
|
OSCTimeTag when, NetworkReturnAddressPtr ra) {
|
||||||
|
Player *p = context;
|
||||||
|
const int *args = vargs;
|
||||||
|
|
||||||
|
|
||||||
|
p->playing = 1;
|
||||||
|
if (arglen >= 4) {
|
||||||
|
p->param = args[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShuddupCallback(void *context, int arglen, const void *vargs,
|
||||||
|
OSCTimeTag when, NetworkReturnAddressPtr ra) {
|
||||||
|
Player *p = context;
|
||||||
|
const float *args = vargs;
|
||||||
|
|
||||||
|
|
||||||
|
p->playing = 0;
|
||||||
|
if (arglen >= 4) {
|
||||||
|
p->otherParam = args[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *InitTimeMalloc(int numBytes) {
|
||||||
|
return malloc(numBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *NoRealTimeMalloc(int numBytes) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
struct OSCAddressSpaceMemoryTuner oasmt;
|
||||||
|
OSCcontainer topLevelContainer, foo, foochild, bar;
|
||||||
|
struct OSCContainerQueryResponseInfoStruct ocqris;
|
||||||
|
struct OSCMethodQueryResponseInfoStruct omqris;
|
||||||
|
|
||||||
|
Player *players;
|
||||||
|
|
||||||
|
players = (Player *) malloc(3 * sizeof(*players));
|
||||||
|
if (!players) exit(1);
|
||||||
|
|
||||||
|
oasmt.initNumContainers = 10;
|
||||||
|
oasmt.initNumMethods = 10;
|
||||||
|
oasmt.InitTimeMemoryAllocator = InitTimeMalloc;
|
||||||
|
oasmt.RealTimeMemoryAllocator = NoRealTimeMalloc;
|
||||||
|
|
||||||
|
topLevelContainer = OSCInitAddressSpace(&oasmt);
|
||||||
|
|
||||||
|
OSCInitContainerQueryResponseInfo(&ocqris);
|
||||||
|
ocqris.comment = "Foo for you";
|
||||||
|
foo = OSCNewContainer("foo", topLevelContainer, &ocqris);
|
||||||
|
|
||||||
|
OSCInitContainerQueryResponseInfo(&ocqris);
|
||||||
|
ocqris.comment = "Beware the son of foo!";
|
||||||
|
foochild = OSCNewContainer("foochild", foo, &ocqris);
|
||||||
|
|
||||||
|
OSCInitContainerQueryResponseInfo(&ocqris);
|
||||||
|
ocqris.comment = "Belly up to the bar";
|
||||||
|
bar = OSCNewContainer("bar", topLevelContainer, &ocqris);
|
||||||
|
|
||||||
|
if (foo == 0 || foochild == 0 || bar == 0) {
|
||||||
|
fprintf(stderr, "Problem!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
OSCInitMethodQueryResponseInfo(&omqris);
|
||||||
|
OSCNewMethod("play", foo, PlayCallback, &(players[0]), &omqris);
|
||||||
|
OSCNewMethod("shuddup", foo, ShuddupCallback, &(players[0]), &omqris);
|
||||||
|
|
||||||
|
OSCNewMethod("play", foochild, PlayCallback, &(players[1]), &omqris);
|
||||||
|
OSCNewMethod("shuddup", foochild, ShuddupCallback, &(players[1]), &omqris);
|
||||||
|
|
||||||
|
OSCNewMethod("play", bar, PlayCallback, &(players[2]), &omqris);
|
||||||
|
OSCNewMethod("shuddup", bar, ShuddupCallback, &(players[2]), &omqris);
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
95
veejay-current/libOSC/OSC-callbacklist.c
Normal file
95
veejay-current/libOSC/OSC-callbacklist.c
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||||
|
University of California, Berkeley.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||||
|
of this software and its documentation without fee and without a signed
|
||||||
|
licensing agreement, is hereby granted, provided that the above copyright
|
||||||
|
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||||
|
modifications, and distributions.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||||
|
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||||
|
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||||
|
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
The OpenSound Control WWW page is
|
||||||
|
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
OSC-callbacklist.c
|
||||||
|
Linked lists of methods
|
||||||
|
|
||||||
|
Matt Wright, 11/20/97
|
||||||
|
|
||||||
|
Allocator is a simple linked list of free nodes.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <libOSC/OSC-common.h>
|
||||||
|
#include <libOSC/OSC-timetag.h>
|
||||||
|
#include <libOSC/OSC-address-space.h>
|
||||||
|
#include <libOSC/OSC-dispatch.h>
|
||||||
|
#include <libOSC/OSC-callbacklist.h>
|
||||||
|
|
||||||
|
static callbackList allNodes;
|
||||||
|
static callbackList freeNodes;
|
||||||
|
|
||||||
|
/* Call this before you call anything else */
|
||||||
|
Boolean InitCallbackListNodes(int numNodes, void *(*InitTimeMalloc)(int numBytes)) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
allNodes = (*InitTimeMalloc)(numNodes * sizeof(*allNodes));
|
||||||
|
if (allNodes == 0) return FALSE;
|
||||||
|
|
||||||
|
/* Initialize list of freeNodes */
|
||||||
|
freeNodes = &(allNodes[0]);
|
||||||
|
for (i = 0; i < numNodes-1; ++i) {
|
||||||
|
allNodes[i].next = &(allNodes[i+1]);
|
||||||
|
}
|
||||||
|
allNodes[numNodes-1].next = 0;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
callbackList AllocCallbackListNode(methodCallback callback, void *context,
|
||||||
|
struct callbackListNode *next) {
|
||||||
|
callbackList result;
|
||||||
|
if (freeNodes == 0) {
|
||||||
|
/* OSCProblem("Out of memory for callback lists!"); */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = freeNodes;
|
||||||
|
freeNodes = freeNodes->next;
|
||||||
|
|
||||||
|
result->callback = callback;
|
||||||
|
result->context = context;
|
||||||
|
result->next = next;
|
||||||
|
#ifdef DEBUG_CBL
|
||||||
|
printf("AllocCallbackListNode: returning %p (cb %p, context %p, next %p)\n",
|
||||||
|
result, result->callback, result->context, result->next);
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FreeCallbackListNode(callbackList cb) {
|
||||||
|
#ifdef DEBUG_CBL
|
||||||
|
printf("FreeCallbackListNode(%p)\n", cb);
|
||||||
|
#endif
|
||||||
|
cb->next = freeNodes;
|
||||||
|
freeNodes = cb;
|
||||||
|
}
|
||||||
49
veejay-current/libOSC/OSC-callbacklist.h
Normal file
49
veejay-current/libOSC/OSC-callbacklist.h
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||||
|
University of California, Berkeley.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||||
|
of this software and its documentation without fee and without a signed
|
||||||
|
licensing agreement, is hereby granted, provided that the above copyright
|
||||||
|
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||||
|
modifications, and distributions.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||||
|
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||||
|
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||||
|
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
The OpenSound Control WWW page is
|
||||||
|
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
OSC-callbacklist.h
|
||||||
|
Linked lists of methods
|
||||||
|
|
||||||
|
Matt Wright, 3/13/98
|
||||||
|
|
||||||
|
include "OSC-dispatch.h" before this file.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Call this before you call anything else. */
|
||||||
|
Boolean InitCallbackListNodes(int numNodes, void *(*InitTimeMalloc)(int numBytes));
|
||||||
|
|
||||||
|
callbackList AllocCallbackListNode(methodCallback callback, void *context,
|
||||||
|
struct callbackListNode *next);
|
||||||
|
|
||||||
|
void FreeCallbackListNode(callbackList);
|
||||||
|
|
||||||
|
|
||||||
82
veejay-current/libOSC/OSC-common.c
Normal file
82
veejay-current/libOSC/OSC-common.c
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||||
|
University of California, Berkeley.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||||
|
of this software and its documentation without fee and without a signed
|
||||||
|
licensing agreement, is hereby granted, provided that the above copyright
|
||||||
|
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||||
|
modifications, and distributions.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||||
|
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||||
|
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||||
|
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
The OpenSound Control WWW page is
|
||||||
|
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* OSC-system-dependent.c
|
||||||
|
|
||||||
|
Matt Wright, 3/13/98
|
||||||
|
|
||||||
|
File of procedures OSC has to call that are not part of the OSC package
|
||||||
|
and that you, the developer adding OSC addressability to an application,
|
||||||
|
must write in a way that makes sense in the context of your system.
|
||||||
|
|
||||||
|
You should also look at OSC-timetag.c and see if there's a better way
|
||||||
|
to handle time tags on your system.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <libOSC/OSC-common.h>
|
||||||
|
|
||||||
|
/* Printing stuff: for now, use stderr. Some cleverer stuff we could do:
|
||||||
|
|
||||||
|
- Make a silent mode where these don't do anything.
|
||||||
|
- Return error messages via OSC to some client
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
void fatal_error(char *s, ...) {
|
||||||
|
va_list ap;
|
||||||
|
fprintf(stderr, "Fatal error: ");
|
||||||
|
va_start(ap, s);
|
||||||
|
vfprintf(stderr, s, ap);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
va_end(ap);
|
||||||
|
exit(-321);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSCProblem(char *s, ...) {
|
||||||
|
va_list ap;
|
||||||
|
fprintf(stderr, "OSC Problem: ");
|
||||||
|
va_start(ap, s);
|
||||||
|
vfprintf(stderr, s, ap);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSCWarning(char *s, ...) {
|
||||||
|
va_list ap;
|
||||||
|
fprintf(stderr, "OSC Warning: ");
|
||||||
|
va_start(ap, s);
|
||||||
|
vfprintf(stderr, s, ap);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
60
veejay-current/libOSC/OSC-common.h
Normal file
60
veejay-current/libOSC/OSC-common.h
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||||
|
University of California, Berkeley.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||||
|
of this software and its documentation without fee and without a signed
|
||||||
|
licensing agreement, is hereby granted, provided that the above copyright
|
||||||
|
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||||
|
modifications, and distributions.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||||
|
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||||
|
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||||
|
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
The OpenSound Control WWW page is
|
||||||
|
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* OSC-common.h
|
||||||
|
Simple stuff to #include everywhere in the OSC package
|
||||||
|
|
||||||
|
by Matt Wright, 3/13/98
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Boolean type */
|
||||||
|
|
||||||
|
#ifndef TRUE
|
||||||
|
typedef int Boolean;
|
||||||
|
#define TRUE 1
|
||||||
|
#define FALSE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Fixed byte width types */
|
||||||
|
typedef int int4; /* 4 byte int */
|
||||||
|
|
||||||
|
/* Printing type procedures. All take printf-style format string */
|
||||||
|
|
||||||
|
/* Catastrophic failure: print message and halt system */
|
||||||
|
void fatal_error(char *s, ...);
|
||||||
|
|
||||||
|
/* Error message for user */
|
||||||
|
void OSCProblem(char *s, ...);
|
||||||
|
|
||||||
|
/* Warning for user */
|
||||||
|
void OSCWarning(char *s, ...);
|
||||||
|
|
||||||
|
|
||||||
52
veejay-current/libOSC/OSC-dispatch.h
Normal file
52
veejay-current/libOSC/OSC-dispatch.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||||
|
University of California, Berkeley.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||||
|
of this software and its documentation without fee and without a signed
|
||||||
|
licensing agreement, is hereby granted, provided that the above copyright
|
||||||
|
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||||
|
modifications, and distributions.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||||
|
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||||
|
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||||
|
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
The OpenSound Control WWW page is
|
||||||
|
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* OSC-dispatch.h
|
||||||
|
|
||||||
|
Given an OSC message pattern from an incoming message, match the
|
||||||
|
pattern against the OSC address space and produce a list of the
|
||||||
|
callbacks corresponding to all the addresses that were matched.
|
||||||
|
|
||||||
|
Matt Wright, 6/5/98
|
||||||
|
*/
|
||||||
|
|
||||||
|
/***************************** Dispatching *****************************/
|
||||||
|
|
||||||
|
typedef struct callbackListNode {
|
||||||
|
methodCallback callback;
|
||||||
|
void *context;
|
||||||
|
struct callbackListNode *next;
|
||||||
|
} *callbackList;
|
||||||
|
|
||||||
|
|
||||||
|
/* Given an OSC message pattern from an incoming message, match the
|
||||||
|
pattern against the OSC address space and produce a list of the
|
||||||
|
callbacks corresponding to all the addresses that were matched. */
|
||||||
|
callbackList OSCDispatchMessage(char *pattern);
|
||||||
|
|
||||||
56
veejay-current/libOSC/OSC-drop.c
Normal file
56
veejay-current/libOSC/OSC-drop.c
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||||
|
University of California, Berkeley.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||||
|
of this software and its documentation without fee and without a signed
|
||||||
|
licensing agreement, is hereby granted, provided that the above copyright
|
||||||
|
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||||
|
modifications, and distributions.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||||
|
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||||
|
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||||
|
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
The OpenSound Control WWW page is
|
||||||
|
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* OSC-drop.c
|
||||||
|
|
||||||
|
This implementation just prints a warning.
|
||||||
|
|
||||||
|
Matt Wright, 3/16/98
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <libOSC/OSC-common.h>
|
||||||
|
#include <libOSC/OSC-timetag.h>
|
||||||
|
#include <libOSC/OSC-address-space.h>
|
||||||
|
#include <libOSC/NetworkReturnAddress.h>
|
||||||
|
#include <libOSC/OSC-receive.h>
|
||||||
|
#include <libOSC/OSC-drop.h>
|
||||||
|
|
||||||
|
|
||||||
|
void DropPacket(OSCPacketBuffer p) {
|
||||||
|
OSCWarning("Packet dropped.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void DropBundle(char *buf, int n, OSCPacketBuffer p) {
|
||||||
|
OSCWarning("Bundle dropped.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void DropMessage(char *buf, int n, OSCPacketBuffer p) {
|
||||||
|
OSCWarning("Message dropped.");
|
||||||
|
}
|
||||||
|
|
||||||
43
veejay-current/libOSC/OSC-drop.h
Normal file
43
veejay-current/libOSC/OSC-drop.h
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||||
|
University of California, Berkeley.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||||
|
of this software and its documentation without fee and without a signed
|
||||||
|
licensing agreement, is hereby granted, provided that the above copyright
|
||||||
|
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||||
|
modifications, and distributions.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||||
|
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||||
|
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||||
|
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
The OpenSound Control WWW page is
|
||||||
|
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* OSC-drop.h
|
||||||
|
|
||||||
|
These procedures will be called on a packet, bundle, or message that's
|
||||||
|
being dropped for whatever reason. They can do nothing, print (or
|
||||||
|
otherwise inform the user of) a warning, save the offending data somewhere,
|
||||||
|
etc.
|
||||||
|
|
||||||
|
Matt Wright, 3/16/98
|
||||||
|
*/
|
||||||
|
|
||||||
|
void DropPacket(OSCPacketBuffer p);
|
||||||
|
void DropBundle(char *buf, int n, OSCPacketBuffer p);
|
||||||
|
void DropMessage(char *buf, int n, OSCPacketBuffer p);
|
||||||
|
|
||||||
70
veejay-current/libOSC/OSC-internal-messages.h
Normal file
70
veejay-current/libOSC/OSC-internal-messages.h
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||||
|
University of California, Berkeley.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||||
|
of this software and its documentation without fee and without a signed
|
||||||
|
licensing agreement, is hereby granted, provided that the above copyright
|
||||||
|
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||||
|
modifications, and distributions.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||||
|
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||||
|
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||||
|
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
The OpenSound Control WWW page is
|
||||||
|
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* OSC-internal-messages.h
|
||||||
|
|
||||||
|
Interface for having an application send OSC messages to itself
|
||||||
|
internally.
|
||||||
|
|
||||||
|
All these procedures return FALSE if unable to deliver the message.
|
||||||
|
|
||||||
|
Matt Wright, 3/17/98
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Send a message immediately, with no return address. This procedure
|
||||||
|
returns after the message has been sent (or has failed to be sent),
|
||||||
|
so the memory for address and args can be on the stack. Returns FALSE
|
||||||
|
if there's a problem; TRUE otherwise. */
|
||||||
|
Boolean OSCSendInternalMessage(char *address, int arglen, void *args);
|
||||||
|
|
||||||
|
|
||||||
|
/* Same thing, but with a return address supplied. */
|
||||||
|
Boolean OSCSendInternalMessageWithRSVP(char *address, int arglen, void *args,
|
||||||
|
NetworkReturnAddressPtr returnAddr);
|
||||||
|
|
||||||
|
|
||||||
|
/* Schedule some messages to occur at a given time. This allocates one of the
|
||||||
|
OSCPacketBuffer structures (see OSC-receive.h) to hold the addresses and argument
|
||||||
|
data until the messages take effect, so if you're going to call this, you
|
||||||
|
should take this use of packets into account in setting the
|
||||||
|
numReceiveBuffers argument to OSCInitReceive().
|
||||||
|
|
||||||
|
This provides an less general interface than OSC's bundle mechanism, because
|
||||||
|
the bundle of messages you provide cannot include subbundles.
|
||||||
|
|
||||||
|
The addresses, arglens, and args arguments are arrays of size numMessages.
|
||||||
|
|
||||||
|
There's no return address argument because you're not allowed to save a network
|
||||||
|
return address for later use.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Boolean OSCScheduleInternalMessages(OSCTimeTag when, int numMessages,
|
||||||
|
char **addresses, int *arglens,
|
||||||
|
void **args);
|
||||||
192
veejay-current/libOSC/OSC-pattern-match.c
Normal file
192
veejay-current/libOSC/OSC-pattern-match.c
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
/*
|
||||||
|
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||||
|
University of California, Berkeley.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||||
|
of this software and its documentation without fee and without a signed
|
||||||
|
licensing agreement, is hereby granted, provided that the above copyright
|
||||||
|
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||||
|
modifications, and distributions.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||||
|
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||||
|
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||||
|
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
The OpenSound Control WWW page is
|
||||||
|
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
OSC-pattern-match.c
|
||||||
|
Matt Wright, 3/16/98
|
||||||
|
Adapted from oscpattern.c, by Matt Wright and Amar Chaudhury
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <libOSC/OSC-common.h>
|
||||||
|
#include <libOSC/OSC-pattern-match.h>
|
||||||
|
|
||||||
|
static const char *theWholePattern; /* Just for warning messages */
|
||||||
|
|
||||||
|
static Boolean MatchBrackets (const char *pattern, const char *test);
|
||||||
|
static Boolean MatchList (const char *pattern, const char *test);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* we know that pattern[0] == '[' and test[0] != 0 */
|
||||||
|
|
||||||
|
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 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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
35
veejay-current/libOSC/OSC-pattern-match.h
Normal file
35
veejay-current/libOSC/OSC-pattern-match.h
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||||
|
University of California, Berkeley.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||||
|
of this software and its documentation without fee and without a signed
|
||||||
|
licensing agreement, is hereby granted, provided that the above copyright
|
||||||
|
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||||
|
modifications, and distributions.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||||
|
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||||
|
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||||
|
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
The OpenSound Control WWW page is
|
||||||
|
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
OSC-pattern-match.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
Boolean PatternMatch (const char *pattern, const char *test);
|
||||||
|
|
||||||
189
veejay-current/libOSC/OSC-priority-queue.c
Normal file
189
veejay-current/libOSC/OSC-priority-queue.c
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
/*
|
||||||
|
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||||
|
University of California, Berkeley.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||||
|
of this software and its documentation without fee and without a signed
|
||||||
|
licensing agreement, is hereby granted, provided that the above copyright
|
||||||
|
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||||
|
modifications, and distributions.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||||
|
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||||
|
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||||
|
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
The OpenSound Control WWW page is
|
||||||
|
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* OSC-priority-queue.c
|
||||||
|
Priority queue used by OSC time tag scheduler
|
||||||
|
|
||||||
|
This is the most trivial implementation, an unsorted array of queued
|
||||||
|
objects, mostly for debug purposes.
|
||||||
|
|
||||||
|
Matt Wright, 9/17/98
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <libOSC/OSC-common.h>
|
||||||
|
#include <libOSC/OSC-timetag.h>
|
||||||
|
#include <libOSC/OSC-priority-queue.h>
|
||||||
|
|
||||||
|
#define PRINT_PRIORITY_QUEUE
|
||||||
|
|
||||||
|
#ifdef DEBUG_OSC_PRIORITY_QUEUE
|
||||||
|
#define PRINT_PRIORITY_QUEUE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(PRINT_PRIORITY_QUEUE) || defined(DEBUG_OSC_PRIORITY_QUEUE)
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
void OSCQueuePrint(OSCQueue q);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define CAPACITY 1000
|
||||||
|
|
||||||
|
|
||||||
|
struct OSCQueueStruct {
|
||||||
|
OSCSchedulableObject list[CAPACITY];
|
||||||
|
int n;
|
||||||
|
int scanIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
OSCQueue OSCNewQueue(int maxItems, void *(*InitTimeMalloc)(int numBytes)) {
|
||||||
|
OSCQueue result;
|
||||||
|
|
||||||
|
if (maxItems > CAPACITY) fatal_error("Increase CAPACITY in OSC-priority-queue.c");
|
||||||
|
|
||||||
|
result = (*InitTimeMalloc)(sizeof(*result));
|
||||||
|
if (result == 0) return 0;
|
||||||
|
|
||||||
|
result->n = 0;
|
||||||
|
|
||||||
|
#ifdef DEBUG_OSC_PRIORITY_QUEUE
|
||||||
|
OSCQueuePrint(result);
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int OSCQueueInsert(OSCQueue q, OSCSchedulableObject new) {
|
||||||
|
if (q->n == CAPACITY) return FALSE;
|
||||||
|
|
||||||
|
q->list[q->n] = new;
|
||||||
|
++(q->n);
|
||||||
|
#ifdef DEBUG_OSC_PRIORITY_QUEUE
|
||||||
|
printf("OSCQueueInsert: just inserted %p\n", new);
|
||||||
|
OSCQueuePrint(q);
|
||||||
|
#endif
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
OSCTimeTag OSCQueueEarliestTimeTag(OSCQueue q) {
|
||||||
|
int i;
|
||||||
|
OSCTimeTag smallest = OSCTT_BiggestPossibleTimeTag();
|
||||||
|
|
||||||
|
for (i = 0; i < q->n; ++i) {
|
||||||
|
if (OSCTT_Compare(smallest, q->list[i]->timetag) > 0) {
|
||||||
|
smallest = q->list[i]->timetag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_OSC_PRIORITY_QUEUE
|
||||||
|
printf("OSCQueueEarliestTimeTag: about to return %llx\n", smallest);
|
||||||
|
OSCQueuePrint(q);
|
||||||
|
#endif
|
||||||
|
return smallest;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void RemoveElement(int goner, OSCQueue q) {
|
||||||
|
int i;
|
||||||
|
--(q->n);
|
||||||
|
|
||||||
|
for (i = goner; i < q->n; ++i) {
|
||||||
|
q->list[i] = q->list[i+1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OSCSchedulableObject OSCQueueRemoveEarliest(OSCQueue q) {
|
||||||
|
OSCSchedulableObject result;
|
||||||
|
int i, smallestIndex;
|
||||||
|
|
||||||
|
if (q->n == 0) {
|
||||||
|
OSCWarning("OSCQueueRemoveEarliest: empty queue");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_OSC_PRIORITY_QUEUE
|
||||||
|
printf("OSCQueueRemoveEarliest: begin\n");
|
||||||
|
OSCQueuePrint(q);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
smallestIndex = 0;
|
||||||
|
for (i = 1; i < q->n; ++i) {
|
||||||
|
if (OSCTT_Compare(q->list[smallestIndex]->timetag, q->list[i]->timetag) > 0) {
|
||||||
|
smallestIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = q->list[smallestIndex];
|
||||||
|
|
||||||
|
RemoveElement(smallestIndex, q);
|
||||||
|
|
||||||
|
#ifdef DEBUG_OSC_PRIORITY_QUEUE
|
||||||
|
printf("OSCQueueRemoveEarliest: done\n");
|
||||||
|
OSCQueuePrint(q);
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PRINT_PRIORITY_QUEUE
|
||||||
|
|
||||||
|
void OSCQueuePrint(OSCQueue q) {
|
||||||
|
int i;
|
||||||
|
printf("OSC Priority queue at %p has %d elements:\n", q, q->n);
|
||||||
|
|
||||||
|
for (i = 0; i < q->n; ++i) {
|
||||||
|
printf(" list[%2d] is %p, timetag = %llx\n", i, q->list[i], q->list[i]->timetag);
|
||||||
|
}
|
||||||
|
printf("\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void OSCQueueScanStart(OSCQueue q) {
|
||||||
|
q->scanIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
OSCSchedulableObject OSCQueueScanNext(OSCQueue q) {
|
||||||
|
if (q->scanIndex >= q->n) return 0;
|
||||||
|
|
||||||
|
return (q->list[(q->scanIndex)++]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSCQueueRemoveCurrentScanItem(OSCQueue q) {
|
||||||
|
/* Remember that q->scanIndex is the index of the *next*
|
||||||
|
item that will be returned, so the "current" item, i.e.,
|
||||||
|
the one most recently returned by OSCQueueScanNext(),
|
||||||
|
is q->scanIndex-1. */
|
||||||
|
|
||||||
|
RemoveElement(q->scanIndex-1, q);
|
||||||
|
--(q->scanIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckWholeQueue(void) {
|
||||||
|
}
|
||||||
90
veejay-current/libOSC/OSC-priority-queue.h
Normal file
90
veejay-current/libOSC/OSC-priority-queue.h
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||||
|
University of California, Berkeley.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||||
|
of this software and its documentation without fee and without a signed
|
||||||
|
licensing agreement, is hereby granted, provided that the above copyright
|
||||||
|
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||||
|
modifications, and distributions.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||||
|
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||||
|
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||||
|
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
The OpenSound Control WWW page is
|
||||||
|
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* OSC-priority-queue.h
|
||||||
|
Interface to priority queue used by OSC time tag scheduler
|
||||||
|
|
||||||
|
Matt Wright, 3/13/98
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* include OSC-timetag.h before this file. */
|
||||||
|
|
||||||
|
/* This queue manages pointers to data objects. It doesn't care what's in the
|
||||||
|
objects except that the first element has to be an OSCTimeTag. So whatever
|
||||||
|
data you want to store, cast your pointer to it to a pointer to this type. */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
OSCTimeTag timetag;
|
||||||
|
/* There will be other stuff... */
|
||||||
|
} *OSCSchedulableObject;
|
||||||
|
|
||||||
|
typedef struct OSCQueueStruct *OSCQueue;
|
||||||
|
|
||||||
|
/* Make a new queue, or return 0 for failure. */
|
||||||
|
OSCQueue OSCNewQueue(int maxItems, void *(*InitTimeMalloc)(int numBytes));
|
||||||
|
|
||||||
|
/* Put something into the queue. Return FALSE if quque is full. */
|
||||||
|
Boolean OSCQueueInsert(OSCQueue q, OSCSchedulableObject o);
|
||||||
|
|
||||||
|
/* What's the time tag of the earliest item in the queue?
|
||||||
|
Return OSCTT_BiggestPossibleTimeTag() if queue is empty. */
|
||||||
|
OSCTimeTag OSCQueueEarliestTimeTag(OSCQueue q);
|
||||||
|
|
||||||
|
/* Remove the item from the front of the queue. Fatal error
|
||||||
|
if the queue is empty. */
|
||||||
|
OSCSchedulableObject OSCQueueRemoveEarliest(OSCQueue q);
|
||||||
|
|
||||||
|
|
||||||
|
/* Interface for examining items currently stored on the queue:
|
||||||
|
|
||||||
|
- To start, call OSCQueueScanStart().
|
||||||
|
|
||||||
|
- Then each subsequent call to OSCQueueScanNext() returns a pointer to an
|
||||||
|
OSCSchedulableObject that is stored on the queue, until
|
||||||
|
OSCQueueScanNext() returns 0 to indicate that all objects on the queue
|
||||||
|
have been scanned.
|
||||||
|
|
||||||
|
The objects returned by OSCQueueScanNext() come in chronological order (or
|
||||||
|
approximately chronological order, depending on the underlying queue data
|
||||||
|
structure).
|
||||||
|
|
||||||
|
If you call OSCQueueRemoveCurrentScanItem(), the object most recently
|
||||||
|
returned by OSCQueueScanNext() will be removed from the queue.
|
||||||
|
|
||||||
|
If there are any insertions or deletions to the queue, the sequence of
|
||||||
|
scanned objects must still include every object in the queue. This may
|
||||||
|
cause a particular object to be returned more than once by
|
||||||
|
OSCQueueScanNext().
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
void OSCQueueScanStart(OSCQueue q);
|
||||||
|
OSCSchedulableObject OSCQueueScanNext(OSCQueue q);
|
||||||
|
void OSCQueueRemoveCurrentScanItem(OSCQueue q);
|
||||||
823
veejay-current/libOSC/OSC-receive.c
Normal file
823
veejay-current/libOSC/OSC-receive.c
Normal file
@@ -0,0 +1,823 @@
|
|||||||
|
/*
|
||||||
|
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||||
|
University of California, Berkeley.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||||
|
of this software and its documentation without fee and without a signed
|
||||||
|
licensing agreement, is hereby granted, provided that the above copyright
|
||||||
|
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||||
|
modifications, and distributions.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||||
|
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||||
|
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||||
|
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
The OpenSound Control WWW page is
|
||||||
|
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define PARANOID 0
|
||||||
|
/*
|
||||||
|
OSC-receive.c
|
||||||
|
Matt Wright, 3/13/98, 6/3/98
|
||||||
|
|
||||||
|
Adapted from OSC-addressability.c (and seriously cleaned up!)
|
||||||
|
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <libOSC/OSC-common.h>
|
||||||
|
#include <libOSC/OSC-timetag.h>
|
||||||
|
#include <libOSC/OSC-address-space.h>
|
||||||
|
#include <libOSC/NetworkReturnAddress.h>
|
||||||
|
#include <libOSC/OSC-receive.h>
|
||||||
|
#include <libOSC/OSC-priority-queue.h>
|
||||||
|
#include <libOSC/OSC-string-help.h>
|
||||||
|
#include <libOSC/OSC-drop.h>
|
||||||
|
#include <libOSC/OSC-dispatch.h>
|
||||||
|
#include <libOSC/NetworkUDP.h>
|
||||||
|
#include <libOSC/OSC-callbacklist.h>
|
||||||
|
#if defined(DEBUG_INTERNAL) || defined(DEBUG) || defined(DEBUG_PACKET_MEM) || defined(DEBUG_QD_MEM) || defined(DEBUG_8BYTE_ALIGN) || defined(SUSPECT_QD_PROB)
|
||||||
|
#include <stdio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct {
|
||||||
|
OSCQueue TheQueue; /* The Priority Queue */
|
||||||
|
OSCTimeTag lastTimeTag; /* Best approximation to current time */
|
||||||
|
Boolean timePassed; /* TRUE if OSCInvokeMessagesThatAreReady() has been
|
||||||
|
called since the last time OSCBeProductiveWhileWaiting() was. */
|
||||||
|
int recvBufSize; /* Size of all receive buffers */
|
||||||
|
void *(*InitTimeMalloc)(int numBytes);
|
||||||
|
void *(*RealTimeMemoryAllocator)(int numBytes);
|
||||||
|
} globals;
|
||||||
|
|
||||||
|
|
||||||
|
/* Data structures */
|
||||||
|
|
||||||
|
struct OSCPacketBuffer_struct {
|
||||||
|
char *buf; /* Contents of network packet go here */
|
||||||
|
int n; /* Overall size of packet */
|
||||||
|
int refcount; /* # queued things using memory from this buffer */
|
||||||
|
struct OSCPacketBuffer_struct *nextFree; /* For linked list of free packets */
|
||||||
|
|
||||||
|
Boolean returnAddrOK; /* Because returnAddr points to memory we need to
|
||||||
|
store future return addresses, we set this
|
||||||
|
field to FALSE in situations where a packet
|
||||||
|
buffer "has no return address" instead of
|
||||||
|
setting returnAddr to 0 */
|
||||||
|
|
||||||
|
NetworkReturnAddressPtr returnAddr;
|
||||||
|
//void *returnAddr; /* Addr of client this packet is from */
|
||||||
|
/* This was of type NetworkReturnAddressPtr, but the constness
|
||||||
|
was making it impossible for me to initialize it. There's
|
||||||
|
probably a better way that I don't understand. */
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/* These are the data objects that are inserted and removed from the
|
||||||
|
scheduler. The idea is that we can insert a single message or
|
||||||
|
an entire bundle on the scheduler, and we can leave it in various
|
||||||
|
states of being parsed and pattern matched. */
|
||||||
|
|
||||||
|
#define NOT_DISPATCHED_YET ((callbackList) -1)
|
||||||
|
|
||||||
|
typedef struct queuedDataStruct {
|
||||||
|
OSCTimeTag timetag; /* When this bundle or message is supposed to happen */
|
||||||
|
OSCPacketBuffer myPacket; /* Ptr. to buffer this is contained in */
|
||||||
|
|
||||||
|
enum {MESSAGE, BUNDLE} type;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
char *bytes;
|
||||||
|
int length;
|
||||||
|
} bundle;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
char *messageName; /* Ptr. into receive buffer */
|
||||||
|
int length; /* Includes name and arugments */
|
||||||
|
void *args; /* 0 if not yet parsed */
|
||||||
|
int argLength;
|
||||||
|
callbackList callbacks; /* May be NOT_DISPATCHED_YET */
|
||||||
|
} message;
|
||||||
|
} data;
|
||||||
|
|
||||||
|
struct queuedDataStruct *nextFree; /* For linked list of free structures */
|
||||||
|
} queuedData;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Static procedure declatations */
|
||||||
|
static Boolean InitPackets(int receiveBufferSize, int clientAddrSize, int numReceiveBuffers);
|
||||||
|
static Boolean InitQueuedData(int numQueuedObjects);
|
||||||
|
static queuedData *AllocQD(void);
|
||||||
|
static void FreeQD(queuedData *qd);
|
||||||
|
static void CallWholeCallbackList(callbackList l, int argLength, void *args, OSCTimeTag when, NetworkReturnAddressPtr returnAddr);
|
||||||
|
static void InsertBundleOrMessage(char *buf, int n, OSCPacketBuffer packet, OSCTimeTag enclosingTimeTag);
|
||||||
|
static void ParseBundle(queuedData *qd);
|
||||||
|
static Boolean ParseMessage(queuedData *qd);
|
||||||
|
/* static void CheckPacketRefcount(OSCPacketBuffer packet); */
|
||||||
|
static void PacketAddRef(OSCPacketBuffer packet);
|
||||||
|
static void PacketRemoveRef(OSCPacketBuffer packet);
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************
|
||||||
|
Initialization and memory pre-allocation
|
||||||
|
**************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
Boolean OSCInitReceive(struct OSCReceiveMemoryTuner *t) {
|
||||||
|
globals.recvBufSize = t->receiveBufferSize;
|
||||||
|
globals.InitTimeMalloc = t->InitTimeMemoryAllocator;
|
||||||
|
globals.RealTimeMemoryAllocator = t->RealTimeMemoryAllocator;
|
||||||
|
|
||||||
|
globals.TheQueue = OSCNewQueue(t->numQueuedObjects, t->InitTimeMemoryAllocator);
|
||||||
|
if (globals.TheQueue == 0) return FALSE;
|
||||||
|
|
||||||
|
globals.lastTimeTag = OSCTT_Immediately();
|
||||||
|
globals.timePassed = TRUE;
|
||||||
|
|
||||||
|
if (InitPackets(t->receiveBufferSize, SizeOfNetworkReturnAddress(),
|
||||||
|
t->numReceiveBuffers) == FALSE) return FALSE;
|
||||||
|
if (InitQueuedData(t->numQueuedObjects) == FALSE) return FALSE;
|
||||||
|
if (InitCallbackListNodes(t->numCallbackListNodes, t->InitTimeMemoryAllocator)
|
||||||
|
== FALSE) return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************
|
||||||
|
Managing packet data structures
|
||||||
|
**************************************************/
|
||||||
|
|
||||||
|
static struct OSCPacketBuffer_struct *freePackets;
|
||||||
|
|
||||||
|
#ifdef DEBUG_PACKET_MEM
|
||||||
|
static void PrintPacketFreeList(void) {
|
||||||
|
struct OSCPacketBuffer_struct *p;
|
||||||
|
printf("- freePackets:");
|
||||||
|
if (freePackets == 0) {
|
||||||
|
printf(" [none]");
|
||||||
|
}
|
||||||
|
for (p = freePackets; p != 0; p = p->nextFree) {
|
||||||
|
printf(" %p", p);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MIN_REASONABLE_RCV_BUFSIZE 128
|
||||||
|
|
||||||
|
void OSCFreeReceiver(void)
|
||||||
|
{
|
||||||
|
if( freePackets) free(freePackets);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static Boolean InitPackets(int receiveBufferSize, int clientAddrSize, int numReceiveBuffers) {
|
||||||
|
int i;
|
||||||
|
struct OSCPacketBuffer_struct *allPackets;
|
||||||
|
|
||||||
|
if (receiveBufferSize < MIN_REASONABLE_RCV_BUFSIZE) {
|
||||||
|
fatal_error("OSCInitReceive: receiveBufferSize of %d is unreasonably small.",
|
||||||
|
receiveBufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
allPackets = (*(globals.InitTimeMalloc))(numReceiveBuffers * sizeof(*allPackets));
|
||||||
|
if (allPackets == 0) return FALSE;
|
||||||
|
|
||||||
|
for (i = 0; i < numReceiveBuffers; ++i) {
|
||||||
|
allPackets[i].returnAddr = (*(globals.InitTimeMalloc))(clientAddrSize);
|
||||||
|
if (allPackets[i].returnAddr == 0) return FALSE;
|
||||||
|
|
||||||
|
allPackets[i].buf = (*(globals.InitTimeMalloc))(receiveBufferSize);
|
||||||
|
if (allPackets[i].buf == 0) return FALSE;
|
||||||
|
|
||||||
|
allPackets[i].nextFree = &(allPackets[i+1]);
|
||||||
|
}
|
||||||
|
allPackets[numReceiveBuffers-1].nextFree = ((struct OSCPacketBuffer_struct *) 0);
|
||||||
|
freePackets = allPackets;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *OSCPacketBufferGetBuffer(OSCPacketBuffer p) {
|
||||||
|
return p->buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
int *OSCPacketBufferGetSize(OSCPacketBuffer p) {
|
||||||
|
return &(p->n);
|
||||||
|
}
|
||||||
|
|
||||||
|
int OSCGetReceiveBufferSize(void) {
|
||||||
|
return globals.recvBufSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetworkReturnAddressPtr OSCPacketBufferGetClientAddr(OSCPacketBuffer p) {
|
||||||
|
return p->returnAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
void PrintPacket(OSCPacketBuffer p) {
|
||||||
|
printf("Packet %p. buf %p, n %d, refcount %d, nextFree %p\n",
|
||||||
|
p, p->buf, p->n, p->refcount, p->nextFree);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************
|
||||||
|
Dealing with OpenSoundControl packets and
|
||||||
|
making the messages take effect.
|
||||||
|
**************************************************/
|
||||||
|
|
||||||
|
static queuedData *freeQDList;
|
||||||
|
|
||||||
|
#ifdef DEBUG_QD_MEM
|
||||||
|
static void PrintQDFreeList(void) {
|
||||||
|
static queuedData *p;
|
||||||
|
printf("- freeQDList:");
|
||||||
|
if (freeQDList == 0) {
|
||||||
|
printf(" [none]");
|
||||||
|
}
|
||||||
|
for (p = freeQDList; p != 0; p = p->nextFree) {
|
||||||
|
printf(" %p", p);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static Boolean InitQueuedData(int numQueuedObjects) {
|
||||||
|
int i;
|
||||||
|
queuedData *allQD;
|
||||||
|
|
||||||
|
allQD = (*(globals.InitTimeMalloc))(numQueuedObjects * (sizeof(*allQD)));
|
||||||
|
if (allQD == 0) return FALSE;
|
||||||
|
|
||||||
|
for (i = 0; i < numQueuedObjects; ++i) {
|
||||||
|
allQD[i].nextFree = &(allQD[i+1]);
|
||||||
|
}
|
||||||
|
allQD[numQueuedObjects-1].nextFree = 0;
|
||||||
|
freeQDList = &(allQD[0]);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FreeQD(queuedData *qd) {
|
||||||
|
qd->nextFree = freeQDList;
|
||||||
|
freeQDList = qd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OSCAcceptPacket(OSCPacketBuffer packet) {
|
||||||
|
if ((packet->n % 4) != 0) {
|
||||||
|
OSCProblem("OSC packet size (%d bytes) not a multiple of 4.", packet->n);
|
||||||
|
DropPacket(packet);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf("OSCAcceptPacket(OSCPacketBuffer %p, buf %p, size %d)\n",
|
||||||
|
packet, packet->buf, packet->n);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* If the packet came from the user, it's return address is OK. */
|
||||||
|
packet->returnAddrOK = TRUE;
|
||||||
|
|
||||||
|
InsertBundleOrMessage(packet->buf, packet->n, packet, OSCTT_Immediately());
|
||||||
|
|
||||||
|
#ifdef PARANOID
|
||||||
|
if (packet->refcount == 0) {
|
||||||
|
if (freePackets != packet) {
|
||||||
|
fatal_error("OSCAcceptPacket: packet refcount 0, but it's not the head of the free list!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
OSCInvokeAllMessagesThatAreReady(globals.lastTimeTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
Boolean OSCBeProductiveWhileWaiting(void) {
|
||||||
|
/* Here's where we could be clever if an allocation fails.
|
||||||
|
(I.e., if we're out of QD objects, we should avoid
|
||||||
|
parsing bundles.) The code isn't that smart yet. */
|
||||||
|
|
||||||
|
queuedData *qd;
|
||||||
|
|
||||||
|
if (globals.timePassed) {
|
||||||
|
OSCQueueScanStart(globals.TheQueue);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
qd = (queuedData *) OSCQueueScanNext(globals.TheQueue);
|
||||||
|
if (qd == 0) return FALSE;
|
||||||
|
|
||||||
|
if (qd->type == BUNDLE) {
|
||||||
|
ParseBundle(qd);
|
||||||
|
OSCQueueRemoveCurrentScanItem(globals.TheQueue);
|
||||||
|
return TRUE;
|
||||||
|
} else {
|
||||||
|
if (qd->data.message.callbacks == NOT_DISPATCHED_YET) {
|
||||||
|
if (ParseMessage(qd) == FALSE) {
|
||||||
|
/* Problem with this message - flush it. */
|
||||||
|
DropMessage(qd->data.message.messageName,
|
||||||
|
qd->data.message.length,
|
||||||
|
qd->myPacket);
|
||||||
|
OSCQueueRemoveCurrentScanItem(globals.TheQueue);
|
||||||
|
PacketRemoveRef(qd->myPacket);
|
||||||
|
FreeQD(qd);
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
/* The item we found was an already-dispatched message,
|
||||||
|
so continue the while loop. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Boolean OSCInvokeMessagesThatAreReady(OSCTimeTag now) {
|
||||||
|
queuedData *x;
|
||||||
|
OSCTimeTag thisTimeTag;
|
||||||
|
|
||||||
|
globals.lastTimeTag = now;
|
||||||
|
globals.timePassed = TRUE;
|
||||||
|
|
||||||
|
thisTimeTag = OSCQueueEarliestTimeTag(globals.TheQueue);
|
||||||
|
|
||||||
|
if (OSCTT_Compare(thisTimeTag, now) > 0) {
|
||||||
|
/* No messages ready yet. */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf("OSCInvokeMessagesThatAreReady(%llx) - yes, some are ready; earliest %llx\n", now, thisTimeTag);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while (OSCTT_Compare(thisTimeTag, OSCQueueEarliestTimeTag(globals.TheQueue)) == 0) {
|
||||||
|
x = (queuedData *) OSCQueueRemoveEarliest(globals.TheQueue);
|
||||||
|
if (!x) return FALSE;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf("...Just removed earliest entry from queue: %p, TT %llx, %s\n",
|
||||||
|
x, x->timetag, x->type == MESSAGE ? "message" : "bundle");
|
||||||
|
if (x->type == MESSAGE) {
|
||||||
|
printf("...message %s, len %d, args %p, arglen %d, callbacks %p\n",
|
||||||
|
x->data.message.messageName, x->data.message.length, x->data.message.args,
|
||||||
|
x->data.message.argLength, x->data.message.callbacks);
|
||||||
|
} else {
|
||||||
|
if (x->data.bundle.length == 0) {
|
||||||
|
printf("...bundle is empty.\n");
|
||||||
|
} else {
|
||||||
|
printf("...bundle len %d, first count %d, first msg %s\n",
|
||||||
|
x->data.bundle.length, *((int *) x->data.bundle.bytes), x->data.bundle.bytes+4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PrintPacket(x->myPacket);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (x->type == BUNDLE) {
|
||||||
|
ParseBundle(x);
|
||||||
|
} else {
|
||||||
|
if (x->data.message.callbacks == NOT_DISPATCHED_YET) {
|
||||||
|
if (ParseMessage(x) == FALSE) {
|
||||||
|
/* Problem with this message - flush it. */
|
||||||
|
PacketRemoveRef(x->myPacket);
|
||||||
|
FreeQD(x);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CallWholeCallbackList(x->data.message.callbacks,
|
||||||
|
x->data.message.argLength,
|
||||||
|
x->data.message.args,
|
||||||
|
thisTimeTag,
|
||||||
|
x->myPacket->returnAddrOK ? x->myPacket->returnAddr : 0);
|
||||||
|
|
||||||
|
PacketRemoveRef(x->myPacket);
|
||||||
|
FreeQD(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef PARANOID
|
||||||
|
if (OSCTT_Compare(thisTimeTag, OSCQueueEarliestTimeTag(globals.TheQueue)) > 0) {
|
||||||
|
fatal_error("OSCInvokeMessagesThatAreReady: corrupt queue!\n"
|
||||||
|
" just did %llx; earliest in queue is now %llx",
|
||||||
|
thisTimeTag, OSCQueueEarliestTimeTag(globals.TheQueue));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return OSCTT_Compare(OSCQueueEarliestTimeTag(globals.TheQueue), now) <= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSCInvokeAllMessagesThatAreReady(OSCTimeTag now) {
|
||||||
|
while (OSCInvokeMessagesThatAreReady(now)) {
|
||||||
|
/* Do nothing */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CallWholeCallbackList(callbackList l, int argLength, void *args, OSCTimeTag when,
|
||||||
|
NetworkReturnAddressPtr returnAddr) {
|
||||||
|
/* In a multithreaded application, this might run in a different thread
|
||||||
|
than the thread that deals with the priority queue. */
|
||||||
|
|
||||||
|
callbackList next;
|
||||||
|
|
||||||
|
while (l != 0) {
|
||||||
|
(*(l->callback))(l->context, argLength, args, when, returnAddr);
|
||||||
|
next = l->next;
|
||||||
|
FreeCallbackListNode(l);
|
||||||
|
l = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void InsertBundleOrMessage(char *buf, int n, OSCPacketBuffer packet, OSCTimeTag enclosingTimeTag) {
|
||||||
|
Boolean IsBundle;
|
||||||
|
queuedData *qd;
|
||||||
|
|
||||||
|
/* We add the reference first thing so in case any of the upcoming
|
||||||
|
potential failure situations come we can call PacketRemoveRef, thereby
|
||||||
|
freeing the packet if necessary. */
|
||||||
|
PacketAddRef(packet);
|
||||||
|
|
||||||
|
if ((n % 4) != 0) {
|
||||||
|
OSCProblem("OSC message or bundle size (%d bytes) not a multiple of 4.", n);
|
||||||
|
DropMessage(buf, n, packet);
|
||||||
|
PacketRemoveRef(packet);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((n >= 8) && (strncmp(buf, "#bundle", 8) == 0)) {
|
||||||
|
IsBundle = TRUE;
|
||||||
|
|
||||||
|
if (n < 16) {
|
||||||
|
OSCProblem("Bundle message too small (%d bytes) for time tag.", n);
|
||||||
|
DropBundle(buf, n, packet);
|
||||||
|
PacketRemoveRef(packet);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
IsBundle = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
qd = AllocQD();
|
||||||
|
|
||||||
|
if (qd == 0) {
|
||||||
|
OSCProblem("Not enough memory for queued data!");
|
||||||
|
DropBundle(buf, n, packet);
|
||||||
|
PacketRemoveRef(packet);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qd->myPacket = packet;
|
||||||
|
qd->type = IsBundle ? BUNDLE : MESSAGE;
|
||||||
|
|
||||||
|
if (IsBundle) {
|
||||||
|
/* Be careful of 8-byte alignment when copying the time tag. Here's a good
|
||||||
|
way to get a bus error when buf happens not to be 8-byte aligned:
|
||||||
|
qd->timetag = *((OSCTimeTag *)(buf+8));
|
||||||
|
*/
|
||||||
|
memcpy(&(qd->timetag), buf+8, sizeof(OSCTimeTag));
|
||||||
|
|
||||||
|
if (OSCTT_Compare(qd->timetag, enclosingTimeTag) < 0) {
|
||||||
|
OSCProblem("Time tag of sub-bundle is before time tag of enclosing bundle.");
|
||||||
|
DropBundle(buf, n, packet);
|
||||||
|
PacketRemoveRef(packet);
|
||||||
|
FreeQD(qd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qd->data.bundle.bytes = buf + 16;
|
||||||
|
qd->data.bundle.length = n - 16;
|
||||||
|
} else {
|
||||||
|
qd->timetag = enclosingTimeTag;
|
||||||
|
qd->data.message.messageName = buf;
|
||||||
|
qd->data.message.length = n;
|
||||||
|
qd->data.message.callbacks = NOT_DISPATCHED_YET;
|
||||||
|
}
|
||||||
|
|
||||||
|
OSCQueueInsert(globals.TheQueue, (OSCSchedulableObject) qd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ParseBundle(queuedData *qd) {
|
||||||
|
/* A queued bundle has been removed from the scheduler queue, and now it's
|
||||||
|
time to parse all the stuff inside it and schedule the enclosed
|
||||||
|
messages and bundles. Once all the contents of the bundle have been
|
||||||
|
parsed and scheduled, we trash the bundle, decrementing the packet
|
||||||
|
count and freeing the QD. */
|
||||||
|
|
||||||
|
int size;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if (qd->type != BUNDLE) {
|
||||||
|
fatal_error("This can't happen: bundle isn't a bundle!");
|
||||||
|
}
|
||||||
|
|
||||||
|
while (i < qd->data.bundle.length) {
|
||||||
|
size = *((int *) (qd->data.bundle.bytes + i));
|
||||||
|
if ((size % 4) != 0) {
|
||||||
|
OSCProblem("Bad size count %d in bundle (not a multiple of 4).", size);
|
||||||
|
DropBundle(qd->data.bundle.bytes, qd->data.bundle.length, qd->myPacket);
|
||||||
|
goto bag;
|
||||||
|
}
|
||||||
|
if ((size + i + 4) > qd->data.bundle.length) {
|
||||||
|
OSCProblem("Bad size count %d in bundle (only %d bytes left in entire bundle).",
|
||||||
|
size, qd->data.bundle.length-i-4);
|
||||||
|
DropBundle(qd->data.bundle.bytes, qd->data.bundle.length, qd->myPacket);
|
||||||
|
goto bag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Recursively handle element of bundle */
|
||||||
|
InsertBundleOrMessage(qd->data.bundle.bytes+i+4, size, qd->myPacket, qd->timetag);
|
||||||
|
i += 4 + size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i != qd->data.bundle.length) {
|
||||||
|
fatal_error("This can't happen: internal logic error parsing bundle");
|
||||||
|
}
|
||||||
|
|
||||||
|
bag:
|
||||||
|
/* If we got here successfully, we've added to the packet's reference count for
|
||||||
|
each message or subbundle by calling InsertBundleOrMessage(), so we remove the one
|
||||||
|
reference for bundle that we just parsed. If we got here by "goto bag", there's a
|
||||||
|
problem with the bundle so we also want to lose the reference count. */
|
||||||
|
|
||||||
|
PacketRemoveRef(qd->myPacket);
|
||||||
|
FreeQD(qd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 void PacketAddRef(OSCPacketBuffer packet) {
|
||||||
|
++(packet->refcount);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PacketRemoveRef(OSCPacketBuffer packet) {
|
||||||
|
--(packet->refcount);
|
||||||
|
if (packet->refcount == 0) {
|
||||||
|
OSCFreePacket(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************
|
||||||
|
Implementation of procedures declared in
|
||||||
|
OSC-internal-messages.h
|
||||||
|
**************************************************/
|
||||||
|
|
||||||
|
#include <libOSC/OSC-internal-messages.h>
|
||||||
|
|
||||||
|
Boolean OSCSendInternalMessage(char *address, int arglen, void *args) {
|
||||||
|
return OSCSendInternalMessageWithRSVP(address, arglen, args, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Boolean OSCSendInternalMessageWithRSVP(char *address, int arglen, void *args,
|
||||||
|
NetworkReturnAddressPtr returnAddr) {
|
||||||
|
callbackList l = OSCDispatchMessage(address);
|
||||||
|
|
||||||
|
if (l == 0) return FALSE;
|
||||||
|
|
||||||
|
CallWholeCallbackList(l, arglen, args, OSCTT_Immediately(), returnAddr);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Boolean OSCScheduleInternalMessages(OSCTimeTag when, int numMessages,
|
||||||
|
char **addresses, int *arglens, void **args) {
|
||||||
|
int i, bufSizeNeeded;
|
||||||
|
OSCPacketBuffer p;
|
||||||
|
queuedData *qd;
|
||||||
|
char *bufPtr;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Figure out how big of a buffer we'll need to hold this huge bundle.
|
||||||
|
We don't store the "#bundle" string or the time tag, just the 4-byte
|
||||||
|
size counts, the addresses, possible extra null padding for the
|
||||||
|
addresses, and the arguments. */
|
||||||
|
|
||||||
|
bufSizeNeeded = 0;
|
||||||
|
for (i = 0; i < numMessages; ++i) {
|
||||||
|
bufSizeNeeded += 4 + OSCPaddedStrlen(addresses[i]) + arglens[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bufSizeNeeded > OSCGetReceiveBufferSize()) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Now try to allocate the data objects to hold these messages */
|
||||||
|
qd = AllocQD();
|
||||||
|
if (qd == 0) return FALSE;
|
||||||
|
|
||||||
|
p = OSCAllocPacketBuffer();
|
||||||
|
if (p == 0) {
|
||||||
|
FreeQD(qd);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now fill in the buffer with a fake #bundle message. This is almost like
|
||||||
|
putting a real #bundle message in the buffer and then calling OSCAcceptPacket,
|
||||||
|
except that we save a little time and memory by not writing "#bundle" or the time tag,
|
||||||
|
and by pre-parsing the messages a little. Thus, this code duplicates a lot
|
||||||
|
of what's in InsertBundleOrMessage() */
|
||||||
|
|
||||||
|
bufPtr = p->buf;
|
||||||
|
|
||||||
|
for (i = 0; i < numMessages; ++i) {
|
||||||
|
/* First the size count of this bundle element */
|
||||||
|
*((int4 *) bufPtr) = OSCPaddedStrlen(addresses[i]) + arglens[i];
|
||||||
|
bufPtr += sizeof(int4);
|
||||||
|
|
||||||
|
/* Then the address */
|
||||||
|
bufPtr = OSCPaddedStrcpy(bufPtr, addresses[i]);
|
||||||
|
|
||||||
|
/* Then the arguments */
|
||||||
|
memcpy(bufPtr, args[i], arglens[i]);
|
||||||
|
bufPtr += arglens[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PARANOID
|
||||||
|
if (bufPtr != p->buf+bufSizeNeeded) {
|
||||||
|
fatal_error("OSCScheduleInternalMessages: internal error");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Fill in the rest of the packet fields */
|
||||||
|
p->n = bufSizeNeeded;
|
||||||
|
p->returnAddrOK = FALSE;
|
||||||
|
PacketAddRef(p);
|
||||||
|
|
||||||
|
/* Now fill in the queuedData object */
|
||||||
|
qd->timetag = when;
|
||||||
|
qd->myPacket = p;
|
||||||
|
qd->type = BUNDLE;
|
||||||
|
qd->data.bundle.length = bufSizeNeeded;
|
||||||
|
qd->data.bundle.bytes = p->buf;
|
||||||
|
|
||||||
|
/* Now we can put it into the scheduling queue. */
|
||||||
|
OSCQueueInsert(globals.TheQueue, (OSCSchedulableObject) qd);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Boolean NetworkPacketWaiting(OSCPacketBuffer packet) {
|
||||||
|
int n;
|
||||||
|
NetworkReturnAddressPtr na = OSCPacketBufferGetClientAddr(packet);
|
||||||
|
if( ioctl( na->sockfd, FIONREAD, &n, 0)==-1) return FALSE;
|
||||||
|
if( n==0 ) return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Boolean NetworkReceivePacket( OSCPacketBuffer packet ) {
|
||||||
|
int n;
|
||||||
|
NetworkReturnAddressPtr na = OSCPacketBufferGetClientAddr(packet);
|
||||||
|
|
||||||
|
n = recvfrom( na->sockfd, packet->buf, 100, 0,
|
||||||
|
(struct sockaddr*) &(na->cl_addr), &(na->clilen));
|
||||||
|
if(n<=0) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
packet->n = n;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Boolean NetworkStartUDPServer(OSCPacketBuffer packet, int port_id) {
|
||||||
|
struct sockaddr_in my_addr;
|
||||||
|
my_addr.sin_family = AF_INET;
|
||||||
|
my_addr.sin_port = htons(port_id);
|
||||||
|
my_addr.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
|
||||||
|
memset( &(my_addr.sin_zero), 0, 8);
|
||||||
|
|
||||||
|
packet->returnAddr->sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if( bind( packet->returnAddr->sockfd,
|
||||||
|
(struct sockaddr*) &my_addr,
|
||||||
|
sizeof(struct sockaddr)) == -1) return FALSE;
|
||||||
|
|
||||||
|
packet->returnAddr->clilen = sizeof(struct sockaddr);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
245
veejay-current/libOSC/OSC-receive.h
Normal file
245
veejay-current/libOSC/OSC-receive.h
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
/*
|
||||||
|
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||||
|
University of California, Berkeley.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||||
|
of this software and its documentation without fee and without a signed
|
||||||
|
licensing agreement, is hereby granted, provided that the above copyright
|
||||||
|
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||||
|
modifications, and distributions.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||||
|
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||||
|
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||||
|
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
The OpenSound Control WWW page is
|
||||||
|
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
OSC-receive.h
|
||||||
|
Matt Wright, 11/18/97
|
||||||
|
|
||||||
|
include OSC-timetag.h and NetworkReturnAddress.h before this file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************
|
||||||
|
Initialization and memory pre-allocation
|
||||||
|
**************************************************/
|
||||||
|
|
||||||
|
/* The memory model used by this module is pre-allocation of fixed-size
|
||||||
|
objects for network buffers and other internal objects. This preallocated
|
||||||
|
memory is dynamically managed internally by a custom high-performance memory
|
||||||
|
allocator. When the preallocated memory runs out, this module calls an
|
||||||
|
optional realtime memory allocator that you provide. If your memory
|
||||||
|
allocator gives this module more memory, it will add it to the pool of
|
||||||
|
objects and never free the memory. If your system does not have a realtime
|
||||||
|
memory allocator, provide a procedure that always returns 0.
|
||||||
|
|
||||||
|
You will fill an OSCReceiveMemoryTuner struct with the parameters that
|
||||||
|
determine how memory will be allocated.
|
||||||
|
|
||||||
|
The MemoryAllocator fields are procedures you will provide that allocate
|
||||||
|
memory. Like malloc(), they take the number of bytes as arguments and return
|
||||||
|
either a pointer to the new memory or 0 for failure. This memory will never
|
||||||
|
be freed.
|
||||||
|
|
||||||
|
- The InitTimeMemoryAllocator will be called only at initialization time,
|
||||||
|
i.e., before OSCInitAddressSpace() returns. If it ever returns 0, that's
|
||||||
|
a fatal error.
|
||||||
|
|
||||||
|
- The RealTimeMemoryAllocator will be called if, while the application is
|
||||||
|
running, the address space grows larger than can fit in what was allocated
|
||||||
|
at initialization time. If the RealTimeMemoryAllocator() returns 0, the
|
||||||
|
operation attempting to grow the address space will fail. If your system
|
||||||
|
does not have real-time memory allocation, RealTimeMemoryAllocator should
|
||||||
|
be a procedure that always returns 0.
|
||||||
|
|
||||||
|
The remaining fields say how much memory to allocate at initialization time:
|
||||||
|
|
||||||
|
- receiveBufferSize is the maximum packet size that can be received. Is the
|
||||||
|
maximum UDP packet size 4096? OSC clients can send a query to this system
|
||||||
|
asking for this maximum packet size.
|
||||||
|
|
||||||
|
- numReceiveBuffers determines how many packets at a time can be sitting
|
||||||
|
on the scheduler with messages waiting to take effect. If all the
|
||||||
|
receive buffers are tied up like this, you won't be able to receive
|
||||||
|
new packets.
|
||||||
|
|
||||||
|
- numQueuedObjects is the number of messages and packets that can be sitting
|
||||||
|
on the scheduler waiting to take effect.
|
||||||
|
|
||||||
|
- Because a message pattern may be dispatched before the message takes effect,
|
||||||
|
we need memory to store the callback pointers corresponding to a message.
|
||||||
|
numCallbackListNodes is the number of callbacks that may be stored in this
|
||||||
|
fashion. It must be at least as large as the maximum number of methods that
|
||||||
|
any one message pattern may match, but if you want to take advantage of
|
||||||
|
pre-dispatching, this should be large enough to hold all the callbacks for
|
||||||
|
all the messages waiting in the scheduler.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
struct OSCReceiveMemoryTuner {
|
||||||
|
void *(*InitTimeMemoryAllocator)(int numBytes);
|
||||||
|
void *(*RealTimeMemoryAllocator)(int numBytes);
|
||||||
|
int receiveBufferSize;
|
||||||
|
int numReceiveBuffers;
|
||||||
|
int numQueuedObjects;
|
||||||
|
int numCallbackListNodes;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Given an OSCReceiveMemoryTuner, return the number of bytes of
|
||||||
|
memory that would be allocated if OSCInitReceive() were called
|
||||||
|
on it. */
|
||||||
|
int OSCReceiveMemoryThatWouldBeAllocated(struct OSCReceiveMemoryTuner *t);
|
||||||
|
|
||||||
|
/* Returns FALSE if it fails to initialize */
|
||||||
|
Boolean OSCInitReceive(struct OSCReceiveMemoryTuner *t);
|
||||||
|
|
||||||
|
/**************************************************
|
||||||
|
Managing packet data structures
|
||||||
|
**************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
/* You don't get to know what's in an OSCPacketBuffer. */
|
||||||
|
typedef struct OSCPacketBuffer_struct *OSCPacketBuffer;
|
||||||
|
|
||||||
|
/* Get an unused packet. Returns 0 if none are free. If you get a packet
|
||||||
|
with this procedure, it is your responsibility either to call
|
||||||
|
OSCAcceptPacket() on it (in which case the internals of the OSC Kit free
|
||||||
|
the OSCPacketBuffer after the last message in it takes effect) or to call
|
||||||
|
OSCFreePacket() on it. */
|
||||||
|
OSCPacketBuffer OSCAllocPacketBuffer(void);
|
||||||
|
|
||||||
|
/* Free. This is called automatically after the last message that was
|
||||||
|
in the packet is invoked. You shouldn't need to call this unless
|
||||||
|
you get a packet with OSCAllocPacketBuffer() and then for some reason
|
||||||
|
decide not to call OSCAcceptPacket() on it. */
|
||||||
|
void OSCFreePacket(OSCPacketBuffer p);
|
||||||
|
|
||||||
|
void OSCFreeReceiver(void);
|
||||||
|
|
||||||
|
/* Whatever code actually gets packets from the network should use these
|
||||||
|
three selectors to access the fields in the packet structure that need
|
||||||
|
to be filled in with the data from the network. */
|
||||||
|
|
||||||
|
/* Selector to get the buffer from a packet. This buffer's size will be
|
||||||
|
equal to the receiveBufferSize you passed to OSCInitReceive(). */
|
||||||
|
char *OSCPacketBufferGetBuffer(OSCPacketBuffer p);
|
||||||
|
|
||||||
|
/* Selector to get a pointer to the int that's the size count for the
|
||||||
|
data currently in a packet. (Not the capacity of the packet's buffer,
|
||||||
|
but the size of the packet that's actually stored in the buffer.) */
|
||||||
|
int *OSCPacketBufferGetSize(OSCPacketBuffer);
|
||||||
|
|
||||||
|
/* Selector to get the client's network address from a packet. This buffer's
|
||||||
|
size will be equal to the clientAddrSize you passed to OSCInitReceive().
|
||||||
|
Note that the NetworkReturnAddressPtr type is full of "const"s, so your
|
||||||
|
code that fills in the return address will probably have to cast the return
|
||||||
|
value of this procedure to some non-const type to be able to write into it. */
|
||||||
|
NetworkReturnAddressPtr OSCPacketBufferGetClientAddr(OSCPacketBuffer p);
|
||||||
|
|
||||||
|
/* Returns the capacity of packet buffers (the receiveBufferSize you passed
|
||||||
|
to OSCInitReceive()). */
|
||||||
|
int OSCGetReceiveBufferSize(void);
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************
|
||||||
|
Dealing with OpenSoundControl packets and
|
||||||
|
making the messages take effect.
|
||||||
|
**************************************************/
|
||||||
|
|
||||||
|
/* Call this as soon as a packet comes in from the network.
|
||||||
|
It will take care of anything that has to happen immediately,
|
||||||
|
but put off as much as possible of the work of parsing the
|
||||||
|
packet. (This tries to be as fast as possible in case a
|
||||||
|
lot of packets come in.) */
|
||||||
|
void OSCAcceptPacket(OSCPacketBuffer packet);
|
||||||
|
|
||||||
|
/* Call this during an otherwise idle time. It goes through
|
||||||
|
everything that's sitting in the OSC scheduler waiting to
|
||||||
|
happen and does some of the work of parsing, pattern
|
||||||
|
matching, dispatching, etc., that will have to be done
|
||||||
|
at some point before the scheduled messages can take
|
||||||
|
effect.
|
||||||
|
|
||||||
|
The return value indicates whether there is more work of
|
||||||
|
this sort that could be done. (Each time you call this,
|
||||||
|
it does only a small unit of this kind of work. If it
|
||||||
|
returns TRUE and you still have time before the next thing
|
||||||
|
you have to do, call it again.) */
|
||||||
|
Boolean OSCBeProductiveWhileWaiting(void);
|
||||||
|
|
||||||
|
/* Call this whenever enough time has passed that you want to see which
|
||||||
|
messages are now ready and have them take effect. (For example, in a
|
||||||
|
synthesizer, you might call this once per synthesis frame, just before
|
||||||
|
synthesizing the audio for that frame.)
|
||||||
|
|
||||||
|
This procedure finds the earliest time tag of all the queued messages
|
||||||
|
and invokes *all* of the queued messages with that time tag. (OSC
|
||||||
|
guarantees that messages with the same tag take effect atomically.)
|
||||||
|
If there are more messages that are ready, but with a different time
|
||||||
|
tag, this procedure does not invoke them, but returns TRUE to indicate
|
||||||
|
that more messages are ready.
|
||||||
|
*/
|
||||||
|
Boolean OSCInvokeMessagesThatAreReady(OSCTimeTag now);
|
||||||
|
|
||||||
|
/* Same thing, but invokes all of the messages whose time has come. */
|
||||||
|
void OSCInvokeAllMessagesThatAreReady(OSCTimeTag now);
|
||||||
|
|
||||||
|
Boolean NetworkReceivePacket(OSCPacketBuffer packet);
|
||||||
|
|
||||||
|
Boolean NetworkStartUDPServer(OSCPacketBuffer packet, int port_id);
|
||||||
|
|
||||||
|
Boolean NetworkPacketWaiting(OSCPacketBuffer packet);
|
||||||
|
|
||||||
|
/**************************************************
|
||||||
|
How to use this stuff
|
||||||
|
**************************************************/
|
||||||
|
|
||||||
|
/* Here's a gross approximation of how your application will invoke the
|
||||||
|
procedures in this module:
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
OSCTimeTag now = CurrentTime();
|
||||||
|
do {
|
||||||
|
if (WeAreSoLateThatWeNeedToDelayOSCMessagesToAvoidACrisis()) break;
|
||||||
|
} while (OSCInvokeMessagesThatAreReady(now) == TRUE);
|
||||||
|
|
||||||
|
SynthesizeSomeSound();
|
||||||
|
if (NetworkPacketWaiting()) {
|
||||||
|
OSCPacketBuffer p = OSCAllocPacketBuffer();
|
||||||
|
if (!p) {
|
||||||
|
Bummer();
|
||||||
|
} else {
|
||||||
|
NetworkReceivePacket(p);
|
||||||
|
OSCAcceptPacket(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (TimeLeftBeforeWeHaveDoSomething()) {
|
||||||
|
if (!OSCBeProductiveWhileWaiting()) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
122
veejay-current/libOSC/OSC-string-help.c
Normal file
122
veejay-current/libOSC/OSC-string-help.c
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||||
|
University of California, Berkeley.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||||
|
of this software and its documentation without fee and without a signed
|
||||||
|
licensing agreement, is hereby granted, provided that the above copyright
|
||||||
|
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||||
|
modifications, and distributions.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||||
|
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||||
|
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||||
|
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
The OpenSound Control WWW page is
|
||||||
|
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* OSC-string-help.c
|
||||||
|
Procedures that could be useful to programmers writing OSC methods that
|
||||||
|
take string arguments.
|
||||||
|
|
||||||
|
by Matt Wright, 3/19/98
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <libOSC/OSC-common.h> /* For Boolean */
|
||||||
|
|
||||||
|
#define STRING_ALIGN_PAD 4
|
||||||
|
|
||||||
|
char *OSCDataAfterAlignedString(const char *string, const char *boundary, char **errorMsg) {
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if ((boundary - string) %4 != 0) {
|
||||||
|
fatal_error("DataAfterAlignedString: bad boundary\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; string[i] != '\0'; i++) {
|
||||||
|
if (string + i >= boundary) {
|
||||||
|
(*errorMsg) = "DataAfterAlignedString: Unreasonably long string";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now string[i] is the first null character */
|
||||||
|
i++;
|
||||||
|
|
||||||
|
for (; (i % STRING_ALIGN_PAD) != 0; i++) {
|
||||||
|
if (string + i >= boundary) {
|
||||||
|
(*errorMsg) = "Unreasonably long string";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (string[i] != '\0') {
|
||||||
|
(*errorMsg) = "Incorrectly padded string.";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (char *) (string+i);
|
||||||
|
}
|
||||||
|
|
||||||
|
int OSCPaddedStrlen(const char *s) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; *s != '\0'; s++, i++) {
|
||||||
|
/* do nothing */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now i is the length with no null bytes. We need 1-4 null bytes,
|
||||||
|
to make the total length a multiple of 4. So we add 4, as if
|
||||||
|
we need 4 null bytes, then & 0xfffffffc to round down to the nearest
|
||||||
|
multiple of 4. */
|
||||||
|
|
||||||
|
return (i + 4) & 0xfffffffc;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *OSCPaddedStrcpy(char *target, const char *source) {
|
||||||
|
while ( (*target++) = (*source++)) {
|
||||||
|
/* do nothing */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* That copied one null byte */
|
||||||
|
while (((int) target) % 4 != 0) {
|
||||||
|
*target = '\0';
|
||||||
|
target++;
|
||||||
|
}
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
Boolean OSCParseStringList(const char *result[], int *numStrings, int maxStrings,
|
||||||
|
const char *args, int numBytes) {
|
||||||
|
int numFound;
|
||||||
|
const char *p;
|
||||||
|
const char *boundary = args + numBytes;
|
||||||
|
char *errorMessage;
|
||||||
|
|
||||||
|
p = args;
|
||||||
|
|
||||||
|
for (numFound = 0; numFound < maxStrings; ++numFound) {
|
||||||
|
if (p == boundary) {
|
||||||
|
*numStrings = numFound;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
result[numFound] = p;
|
||||||
|
p = OSCDataAfterAlignedString(p, boundary, &errorMessage);
|
||||||
|
if (p == 0) return FALSE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
70
veejay-current/libOSC/OSC-string-help.h
Normal file
70
veejay-current/libOSC/OSC-string-help.h
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||||
|
University of California, Berkeley.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||||
|
of this software and its documentation without fee and without a signed
|
||||||
|
licensing agreement, is hereby granted, provided that the above copyright
|
||||||
|
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||||
|
modifications, and distributions.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||||
|
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||||
|
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||||
|
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
The OpenSound Control WWW page is
|
||||||
|
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* OSC-string-help.h
|
||||||
|
Procedures that could be useful to programmers writing OSC methods that
|
||||||
|
take string arguments.
|
||||||
|
|
||||||
|
by Matt Wright, 3/19/98
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Use this to deal with OSC null-padded 4 byte-aligned strings
|
||||||
|
|
||||||
|
The argument is a block of data beginning with a string. The string
|
||||||
|
has (presumably) been padded with extra null characters so that the
|
||||||
|
overall length is a multiple of 4 bytes. Return a pointer to the next
|
||||||
|
byte after the null byte(s). The boundary argument points to the
|
||||||
|
character after the last valid character in the buffer---if the string
|
||||||
|
hasn't ended by there, something's wrong.
|
||||||
|
|
||||||
|
If the data looks wrong, return 0, and set *errorMsg */
|
||||||
|
|
||||||
|
char *OSCDataAfterAlignedString(const char *string, const char *boundary, char **errorMsg);
|
||||||
|
|
||||||
|
|
||||||
|
/* Given a normal C-style string with a single padding byte, return the
|
||||||
|
length of the string including the necessary 1-4 padding bytes.
|
||||||
|
(Basically strlen()+1 rounded up to the next multiple of 4.) */
|
||||||
|
int OSCPaddedStrlen(const char *s);
|
||||||
|
|
||||||
|
/* Copy a given C-style string into the given destination, including the
|
||||||
|
requisite padding byte(s). Unlike strcpy(), this returns a pointer to
|
||||||
|
the next character after the copied string's null bytes, like
|
||||||
|
what OSCDataAfterAlignedString() returns. */
|
||||||
|
char *OSCPaddedStrcpy(char *target, const char *source);
|
||||||
|
|
||||||
|
|
||||||
|
/* Given an args pointer that should be nothing but a list of strings, fill
|
||||||
|
result[] with pointers to the beginnings of each string, and set
|
||||||
|
*numStrings to be the number of strings found. maxStrings gives the size
|
||||||
|
of the result array. Return FALSE if any strings are malformatted or if
|
||||||
|
there are more than maxStrings many strings. */
|
||||||
|
|
||||||
|
Boolean OSCParseStringList(const char *result[], int *numStrings, int maxStrings,
|
||||||
|
const char *args, int numBytes);
|
||||||
56
veejay-current/libOSC/OSC-struct.h
Normal file
56
veejay-current/libOSC/OSC-struct.h
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#ifndef OSCH
|
||||||
|
#define OSCH
|
||||||
|
#ifndef TRUE
|
||||||
|
typedef int Boolean;
|
||||||
|
#define TRUE 1
|
||||||
|
#define FALSE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Fixed byte width types */
|
||||||
|
typedef int int4; /* 4 byte int */
|
||||||
|
typedef struct NetworkReturnAddressStruct_t {
|
||||||
|
struct sockaddr_in cl_addr; /* client information */
|
||||||
|
struct sockaddr_in my_addr; /* us */
|
||||||
|
int clilen;
|
||||||
|
int sockfd;
|
||||||
|
fd_set readfds;
|
||||||
|
struct timeval tv;
|
||||||
|
int fdmax;
|
||||||
|
} NetworkReturnAddressStruct;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct OSCPacketBuffer_struct {
|
||||||
|
char *buf; /* Contents of network packet go here */
|
||||||
|
int n; /* Overall size of packet */
|
||||||
|
int refcount; /* # queued things using memory from this buffer */
|
||||||
|
struct OSCPacketBuffer_struct *nextFree; /* For linked list of free packets */
|
||||||
|
|
||||||
|
Boolean returnAddrOK; /* Because returnAddr points to memory we need to
|
||||||
|
store future return addresses, we set this
|
||||||
|
field to FALSE in situations where a packet
|
||||||
|
buffer "has no return address" instead of
|
||||||
|
setting returnAddr to 0 */
|
||||||
|
|
||||||
|
void *returnAddr; /* Addr of client this packet is from */
|
||||||
|
/* This was of type NetworkReturnAddressPtr, but the constness
|
||||||
|
was making it impossible for me to initialize it. There's
|
||||||
|
probably a better way that I don't understand. */
|
||||||
|
|
||||||
|
} OSCPacketBuffer;
|
||||||
|
|
||||||
|
struct OSCReceiveMemoryTuner {
|
||||||
|
void *(*InitTimeMemoryAllocator)(int numBytes);
|
||||||
|
void *(*RealTimeMemoryAllocator)(int numBytes);
|
||||||
|
int receiveBufferSize;
|
||||||
|
int numReceiveBuffers;
|
||||||
|
int numQueuedObjects;
|
||||||
|
int numCallbackListNodes;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
173
veejay-current/libOSC/OSC-timetag.c
Normal file
173
veejay-current/libOSC/OSC-timetag.c
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
/*
|
||||||
|
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||||
|
University of California, Berkeley.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||||
|
of this software and its documentation without fee and without a signed
|
||||||
|
licensing agreement, is hereby granted, provided that the above copyright
|
||||||
|
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||||
|
modifications, and distributions.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||||
|
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||||
|
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||||
|
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
The OpenSound Control WWW page is
|
||||||
|
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
OSC_timeTag.c: library for manipulating OSC time tags
|
||||||
|
Matt Wright, 5/29/97
|
||||||
|
|
||||||
|
Version 0.2 (9/11/98): cleaned up so no explicit type names in the .c file.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <libOSC/OSC-timetag.h>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAS8BYTEINT
|
||||||
|
#define TWO_TO_THE_32_FLOAT 4294967296.0f
|
||||||
|
|
||||||
|
OSCTimeTag OSCTT_Immediately(void) {
|
||||||
|
return (OSCTimeTag) 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
OSCTimeTag OSCTT_BiggestPossibleTimeTag(void) {
|
||||||
|
return (OSCTimeTag) 0xffffffffffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
OSCTimeTag OSCTT_PlusSeconds(OSCTimeTag original, float secondsOffset) {
|
||||||
|
int8 offset = (int8) (secondsOffset * TWO_TO_THE_32_FLOAT);
|
||||||
|
|
||||||
|
/* printf("* OSCTT_PlusSeconds %llx plus %f seconds (i.e., %lld offset) is %llx\n", original,
|
||||||
|
secondsOffset, offset, original + offset); */
|
||||||
|
|
||||||
|
return original + offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
int OSCTT_Compare(OSCTimeTag left, OSCTimeTag right) {
|
||||||
|
#if 0
|
||||||
|
printf("***** OSCTT_Compare(%llx, %llx): %d\n", left, right,
|
||||||
|
(left<right) ? -1 : ((left == right) ? 0 : 1));
|
||||||
|
#endif
|
||||||
|
if (left < right) {
|
||||||
|
return -1;
|
||||||
|
} else if (left == right) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __sgi
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#define SECONDS_FROM_1900_to_1970 2208988800 /* 17 leap years */
|
||||||
|
#define TWO_TO_THE_32_OVER_ONE_MILLION 4295
|
||||||
|
|
||||||
|
|
||||||
|
OSCTimeTag OSCTT_CurrentTime(void) {
|
||||||
|
uint8 result;
|
||||||
|
uint4 usecOffset;
|
||||||
|
struct timeval tv;
|
||||||
|
struct timezone tz;
|
||||||
|
|
||||||
|
BSDgettimeofday(&tv, &tz);
|
||||||
|
|
||||||
|
/* First get the seconds right */
|
||||||
|
result = (unsigned) SECONDS_FROM_1900_to_1970 +
|
||||||
|
(unsigned) tv.tv_sec -
|
||||||
|
(unsigned) 60 * tz.tz_minuteswest +
|
||||||
|
(unsigned) (tz.tz_dsttime ? 3600 : 0);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* No timezone, no DST version ... */
|
||||||
|
result = (unsigned) SECONDS_FROM_1900_to_1970 +
|
||||||
|
(unsigned) tv.tv_sec;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* make seconds the high-order 32 bits */
|
||||||
|
result = result << 32;
|
||||||
|
|
||||||
|
/* Now get the fractional part. */
|
||||||
|
usecOffset = (unsigned) tv.tv_usec * (unsigned) TWO_TO_THE_32_OVER_ONE_MILLION;
|
||||||
|
/* printf("** %ld microsec is offset %x\n", tv.tv_usec, usecOffset); */
|
||||||
|
|
||||||
|
result += usecOffset;
|
||||||
|
|
||||||
|
/* printf("* OSCTT_CurrentTime is %llx\n", result); */
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* __sgi */
|
||||||
|
|
||||||
|
/* Instead of asking your operating system what time it is, it might be
|
||||||
|
clever to find out the current time at the instant your application
|
||||||
|
starts audio processing, and then keep track of the number of samples
|
||||||
|
output to know how much time has passed. */
|
||||||
|
|
||||||
|
/* Loser version for systems that have no ability to tell the current time: */
|
||||||
|
OSCTimeTag OSCTT_CurrentTime(void) {
|
||||||
|
return (OSCTimeTag) 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __sgi */
|
||||||
|
|
||||||
|
|
||||||
|
#else /* Not HAS8BYTEINT */
|
||||||
|
|
||||||
|
OSCTimeTag OSCTT_CurrentTime(void) {
|
||||||
|
OSCTimeTag result;
|
||||||
|
result.seconds = 0;
|
||||||
|
result.fraction = 1;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
OSCTimeTag OSCTT_BiggestPossibleTimeTag(void) {
|
||||||
|
OSCTimeTag result;
|
||||||
|
result.seconds = 0xffffffff;
|
||||||
|
result.fraction = 0xffffffff;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
OSCTimeTag OSCTT_Immediately(void) {
|
||||||
|
OSCTimeTag result;
|
||||||
|
result.seconds = 0;
|
||||||
|
result.fraction = 1;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
OSCTimeTag OSCTT_PlusSeconds(OSCTimeTag original, float secondsOffset) {
|
||||||
|
OSCTimeTag result;
|
||||||
|
result.seconds = 0;
|
||||||
|
result.fraction = 1;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int OSCTT_Compare(OSCTimeTag left, OSCTimeTag right) {
|
||||||
|
/* Untested! */
|
||||||
|
int highResult = left.seconds - right.seconds;
|
||||||
|
|
||||||
|
if (highResult != 0) return highResult;
|
||||||
|
|
||||||
|
return left.fraction - right.fraction;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* HAS8BYTEINT */
|
||||||
|
|
||||||
91
veejay-current/libOSC/OSC-timetag.h
Normal file
91
veejay-current/libOSC/OSC-timetag.h
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
Copyright <20> 1998. The Regents of the University of California (Regents).
|
||||||
|
All Rights Reserved.
|
||||||
|
|
||||||
|
Written by Matt Wright, The Center for New Music and Audio Technologies,
|
||||||
|
University of California, Berkeley.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and distribute modified versions
|
||||||
|
of this software and its documentation without fee and without a signed
|
||||||
|
licensing agreement, is hereby granted, provided that the above copyright
|
||||||
|
notice, this paragraph and the following two paragraphs appear in all copies,
|
||||||
|
modifications, and distributions.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||||
|
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
|
||||||
|
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
|
||||||
|
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
|
||||||
|
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
|
||||||
|
The OpenSound Control WWW page is
|
||||||
|
http://www.cnmat.berkeley.edu/OpenSoundControl
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
OSC_timeTag.h: library for manipulating OSC time tags
|
||||||
|
Matt Wright, 5/29/97
|
||||||
|
|
||||||
|
Time tags in OSC have the same format as in NTP: 64 bit fixed point, with the
|
||||||
|
top 32 bits giving number of seconds sinve midnight 1/1/1900 and the bottom
|
||||||
|
32 bits giving fractional parts of a second. We represent this by an 8-byte
|
||||||
|
unsigned long if possible, or else a struct.
|
||||||
|
|
||||||
|
NB: On many architectures with 8-byte ints, it's illegal (like maybe a bus error)
|
||||||
|
to dereference a pointer to an 8 byte int that's not 8-byte aligned.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef OSC_TIMETAG
|
||||||
|
#define OSC_TIMETAG
|
||||||
|
|
||||||
|
#ifdef __sgi
|
||||||
|
#define HAS8BYTEINT
|
||||||
|
/* You may have to change this typedef if there's some other
|
||||||
|
way to specify 8 byte ints on your system */
|
||||||
|
typedef long long int8;
|
||||||
|
typedef unsigned long long uint8;
|
||||||
|
typedef unsigned long uint4;
|
||||||
|
#else
|
||||||
|
/* You may have to redefine this typedef if ints on your system
|
||||||
|
aren't 4 bytes. */
|
||||||
|
typedef unsigned int uint4;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAS8BYTEINT
|
||||||
|
typedef uint8 OSCTimeTag;
|
||||||
|
#else
|
||||||
|
typedef struct {
|
||||||
|
uint4 seconds;
|
||||||
|
uint4 fraction;
|
||||||
|
} OSCTimeTag;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Return a time tag representing the current time (as of when this
|
||||||
|
procedure is called). */
|
||||||
|
OSCTimeTag OSCTT_CurrentTime(void);
|
||||||
|
|
||||||
|
/* Return the time tag 0x0000000000000001, indicating to the receiving device
|
||||||
|
that it should process the message immediately. */
|
||||||
|
OSCTimeTag OSCTT_Immediately(void);
|
||||||
|
|
||||||
|
/* Return the time tag 0xffffffffffffffff, a time so far in the future that
|
||||||
|
it's effectively infinity. */
|
||||||
|
OSCTimeTag OSCTT_BiggestPossibleTimeTag(void);
|
||||||
|
|
||||||
|
/* Given a time tag and a number of seconds to add to the time tag, return
|
||||||
|
the new time tag */
|
||||||
|
OSCTimeTag OSCTT_PlusSeconds(OSCTimeTag original, float secondsOffset);
|
||||||
|
|
||||||
|
/* Compare two time tags. Return negative if first is < second, 0 if
|
||||||
|
they're equal, and positive if first > second. */
|
||||||
|
int OSCTT_Compare(OSCTimeTag left, OSCTimeTag right);
|
||||||
|
|
||||||
|
#endif /* OSC_TIMETAG */
|
||||||
18
veejay-current/libOSC/libosc.h
Normal file
18
veejay-current/libOSC/libosc.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#ifndef _LIBOSC_H_
|
||||||
|
#define _LIBOSC_H_
|
||||||
|
|
||||||
|
#include <libOSC/OSC-common.h>
|
||||||
|
#include <libOSC/OSC-timetag.h>
|
||||||
|
#include <libOSC/OSC-address-space.h>
|
||||||
|
#include <libOSC/OSC-dispatch.h>
|
||||||
|
#include <libOSC/OSC-receive.h>
|
||||||
|
#include <libOSC/OSC-callbacklist.h>
|
||||||
|
#include <libOSC/OSC-drop.h>
|
||||||
|
#include <libOSC/OSC-internal-messages.h>
|
||||||
|
#include <libOSC/OSC-pattern-match.h>
|
||||||
|
#include <libOSC/OSC-priority-queue.h>
|
||||||
|
#include <libOSC/OSC-string-help.h>
|
||||||
|
#include <libOSC/NetworkReturnAddress.h>
|
||||||
|
#include <libOSC/NetworkUDP.h>
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user