mirror of
https://github.com/game-stop/veejay.git
synced 2025-12-13 03:09:59 +01:00
243 lines
9.7 KiB
C
243 lines
9.7 KiB
C
/*
|
|
Copyright © 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;
|
|
}
|
|
}
|
|
|
|
*/
|
|
|