mirror of
https://github.com/game-stop/veejay.git
synced 2025-12-18 22:00:00 +01:00
Initial checkin of veejay 1.4
git-svn-id: svn://code.dyne.org/veejay/trunk@1172 eb8d1916-c9e9-0310-b8de-cf0c9472ead5
This commit is contained in:
1
veejay-current/veejay-server/libOSC/AUTHORS
Normal file
1
veejay-current/veejay-server/libOSC/AUTHORS
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
16
veejay-current/veejay-server/libOSC/Makefile.am
Normal file
16
veejay-current/veejay-server/libOSC/Makefile.am
Normal file
@@ -0,0 +1,16 @@
|
||||
INCLUDES = -I$(top_srcdir)/libOSC -I$(includedir)
|
||||
AM_CFLAGS=$(OP_CFLAGS)
|
||||
OSC_LIB_FILE = libOSC.la
|
||||
noinst_LTLIBRARIES = $(OSC_LIB_FILE)
|
||||
libOSC_la_CFLAGS = $(AM_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
|
||||
|
||||
0
veejay-current/veejay-server/libOSC/NEWS
Normal file
0
veejay-current/veejay-server/libOSC/NEWS
Normal file
58
veejay-current/veejay-server/libOSC/NetworkReturnAddress.c
Normal file
58
veejay-current/veejay-server/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/veejay-server/libOSC/NetworkReturnAddress.h
Normal file
52
veejay-current/veejay-server/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/veejay-server/libOSC/NetworkUDP.h
Normal file
7
veejay-current/veejay-server/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/veejay-server/libOSC/OSC-address-space.c
Normal file
599
veejay-current/veejay-server/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/veejay-server/libOSC/OSC-address-space.h
Normal file
364
veejay-current/veejay-server/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/veejay-server/libOSC/OSC-callbacklist.c
Normal file
95
veejay-current/veejay-server/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/veejay-server/libOSC/OSC-callbacklist.h
Normal file
49
veejay-current/veejay-server/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);
|
||||
|
||||
|
||||
87
veejay-current/veejay-server/libOSC/OSC-common.c
Normal file
87
veejay-current/veejay-server/libOSC/OSC-common.c
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
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>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdint.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/veejay-server/libOSC/OSC-common.h
Normal file
60
veejay-current/veejay-server/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/veejay-server/libOSC/OSC-dispatch.h
Normal file
52
veejay-current/veejay-server/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);
|
||||
|
||||
58
veejay-current/veejay-server/libOSC/OSC-drop.c
Normal file
58
veejay-current/veejay-server/libOSC/OSC-drop.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
|
||||
*/
|
||||
|
||||
|
||||
/* OSC-drop.c
|
||||
|
||||
This implementation just prints a warning.
|
||||
|
||||
Matt Wright, 3/16/98
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <netinet/in.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-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/veejay-server/libOSC/OSC-drop.h
Normal file
43
veejay-current/veejay-server/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/veejay-server/libOSC/OSC-internal-messages.h
Normal file
70
veejay-current/veejay-server/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);
|
||||
193
veejay-current/veejay-server/libOSC/OSC-pattern-match.c
Normal file
193
veejay-current/veejay-server/libOSC/OSC-pattern-match.c
Normal file
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
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>
|
||||
#include <stdint.h>
|
||||
#include <sys/time.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/veejay-server/libOSC/OSC-pattern-match.h
Normal file
35
veejay-current/veejay-server/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);
|
||||
|
||||
190
veejay-current/veejay-server/libOSC/OSC-priority-queue.c
Normal file
190
veejay-current/veejay-server/libOSC/OSC-priority-queue.c
Normal file
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
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>
|
||||
#include <stdint.h>
|
||||
#include <sys/time.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/veejay-server/libOSC/OSC-priority-queue.h
Normal file
90
veejay-current/veejay-server/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);
|
||||
893
veejay-current/veejay-server/libOSC/OSC-receive.c
Normal file
893
veejay-current/veejay-server/libOSC/OSC-receive.c
Normal file
@@ -0,0 +1,893 @@
|
||||
/*
|
||||
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 <stdint.h>
|
||||
#include <sys/time.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
|
||||
|
||||
static int use_mcast_ = 0;
|
||||
static char mcast_groupname[200];
|
||||
|
||||
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);
|
||||
if( globals.TheQueue ) free( globals.TheQueue );
|
||||
}
|
||||
|
||||
|
||||
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( use_mcast_ )
|
||||
// {
|
||||
fd_set fds;
|
||||
struct timeval no_wait;
|
||||
int status;
|
||||
memset( &no_wait, 0, sizeof(no_wait));
|
||||
FD_ZERO(&fds);
|
||||
FD_SET( na->sockfd , &fds );
|
||||
status = select( na->sockfd + 1, &fds, 0, 0, &no_wait );
|
||||
if(status <= 0)
|
||||
return FALSE;
|
||||
if(FD_ISSET( na->sockfd, &fds ))
|
||||
return TRUE;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if( ioctl( na->sockfd, FIONREAD, &n, 0)==-1) return FALSE;
|
||||
// if( n==0 ) return FALSE;
|
||||
// }
|
||||
// return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Boolean NetworkReceivePacket( OSCPacketBuffer packet ) {
|
||||
int n;
|
||||
NetworkReturnAddressPtr na = OSCPacketBufferGetClientAddr(packet);
|
||||
|
||||
if( use_mcast_ )
|
||||
{
|
||||
n = recv( na->sockfd, packet->buf, 100, 0 );
|
||||
if( n<= 0)
|
||||
return FALSE;
|
||||
packet->n = n;
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
void GoMultiCast( const char *group_name )
|
||||
{
|
||||
use_mcast_ = 1;
|
||||
strncpy( mcast_groupname, group_name, strlen(group_name ));
|
||||
}
|
||||
|
||||
int IsMultiCast( char *dst )
|
||||
{
|
||||
if(use_mcast_)
|
||||
sprintf(dst, "%s", mcast_groupname );
|
||||
return use_mcast_;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if( use_mcast_ )
|
||||
{
|
||||
struct ip_mreq mcast_req;
|
||||
int on = 1;
|
||||
int err= 0;
|
||||
memset( &mcast_req, 0, sizeof(mcast_req));
|
||||
packet->returnAddr->sockfd = socket( AF_INET, SOCK_DGRAM, 0);
|
||||
#ifdef SO_REUSEADDR
|
||||
setsockopt( packet->returnAddr->sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
|
||||
#endif
|
||||
#ifdef SO_REUSEPORT
|
||||
setsockopt( packet->returnAddr->sockfd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on));
|
||||
#endif
|
||||
err = bind( packet->returnAddr->sockfd, (struct sockaddr*) &my_addr, sizeof( my_addr ));
|
||||
if( err < 0 )
|
||||
return FALSE;
|
||||
|
||||
mcast_req.imr_multiaddr.s_addr = inet_addr( mcast_groupname );
|
||||
mcast_req.imr_interface.s_addr = htonl( INADDR_ANY );
|
||||
setsockopt( packet->returnAddr->sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
||||
&mcast_req, sizeof(mcast_req) );
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
242
veejay-current/veejay-server/libOSC/OSC-receive.h
Normal file
242
veejay-current/veejay-server/libOSC/OSC-receive.h
Normal file
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
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);
|
||||
|
||||
void GoMultiCast(const char *groupname);
|
||||
|
||||
int IsMultiCast( char *dst);
|
||||
|
||||
/**************************************************
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
123
veejay-current/veejay-server/libOSC/OSC-string-help.c
Normal file
123
veejay-current/veejay-server/libOSC/OSC-string-help.c
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
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 */
|
||||
#include <stdint.h>
|
||||
#include <sys/time.h>
|
||||
#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/veejay-server/libOSC/OSC-string-help.h
Normal file
70
veejay-current/veejay-server/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/veejay-server/libOSC/OSC-struct.h
Normal file
56
veejay-current/veejay-server/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
|
||||
174
veejay-current/veejay-server/libOSC/OSC-timetag.c
Normal file
174
veejay-current/veejay-server/libOSC/OSC-timetag.c
Normal file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
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>
|
||||
#include <stdint.h>
|
||||
#include <sys/time.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/veejay-server/libOSC/OSC-timetag.h
Normal file
91
veejay-current/veejay-server/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 */
|
||||
26
veejay-current/veejay-server/libOSC/libosc.h
Normal file
26
veejay-current/veejay-server/libOSC/libosc.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef _LIBOSC_H_INCLUDED
|
||||
#define _LIBOSC_H_INCLUDED
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#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>
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user