00001 /* 00002 Copyright © 1998. The Regents of the University of California (Regents). 00003 All Rights Reserved. 00004 00005 Written by Matt Wright, The Center for New Music and Audio Technologies, 00006 University of California, Berkeley. 00007 00008 Permission to use, copy, modify, distribute, and distribute modified versions 00009 of this software and its documentation without fee and without a signed 00010 licensing agreement, is hereby granted, provided that the above copyright 00011 notice, this paragraph and the following two paragraphs appear in all copies, 00012 modifications, and distributions. 00013 00014 IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, 00015 SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING 00016 OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS 00017 BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00018 00019 REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 00020 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00021 PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED 00022 HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE 00023 MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 00024 00025 The OpenSound Control WWW page is 00026 http://www.cnmat.berkeley.edu/OpenSoundControl 00027 */ 00028 00029 00030 00031 /* 00032 OSC-receive.h 00033 Matt Wright, 11/18/97 00034 00035 include OSC-timetag.h and NetworkReturnAddress.h before this file. 00036 */ 00037 00038 00039 /************************************************** 00040 Initialization and memory pre-allocation 00041 **************************************************/ 00042 00043 /* The memory model used by this module is pre-allocation of fixed-size 00044 objects for network buffers and other internal objects. This preallocated 00045 memory is dynamically managed internally by a custom high-performance memory 00046 allocator. When the preallocated memory runs out, this module calls an 00047 optional realtime memory allocator that you provide. If your memory 00048 allocator gives this module more memory, it will add it to the pool of 00049 objects and never free the memory. If your system does not have a realtime 00050 memory allocator, provide a procedure that always returns 0. 00051 00052 You will fill an OSCReceiveMemoryTuner struct with the parameters that 00053 determine how memory will be allocated. 00054 00055 The MemoryAllocator fields are procedures you will provide that allocate 00056 memory. Like malloc(), they take the number of bytes as arguments and return 00057 either a pointer to the new memory or 0 for failure. This memory will never 00058 be freed. 00059 00060 - The InitTimeMemoryAllocator will be called only at initialization time, 00061 i.e., before OSCInitAddressSpace() returns. If it ever returns 0, that's 00062 a fatal error. 00063 00064 - The RealTimeMemoryAllocator will be called if, while the application is 00065 running, the address space grows larger than can fit in what was allocated 00066 at initialization time. If the RealTimeMemoryAllocator() returns 0, the 00067 operation attempting to grow the address space will fail. If your system 00068 does not have real-time memory allocation, RealTimeMemoryAllocator should 00069 be a procedure that always returns 0. 00070 00071 The remaining fields say how much memory to allocate at initialization time: 00072 00073 - receiveBufferSize is the maximum packet size that can be received. Is the 00074 maximum UDP packet size 4096? OSC clients can send a query to this system 00075 asking for this maximum packet size. 00076 00077 - numReceiveBuffers determines how many packets at a time can be sitting 00078 on the scheduler with messages waiting to take effect. If all the 00079 receive buffers are tied up like this, you won't be able to receive 00080 new packets. 00081 00082 - numQueuedObjects is the number of messages and packets that can be sitting 00083 on the scheduler waiting to take effect. 00084 00085 - Because a message pattern may be dispatched before the message takes effect, 00086 we need memory to store the callback pointers corresponding to a message. 00087 numCallbackListNodes is the number of callbacks that may be stored in this 00088 fashion. It must be at least as large as the maximum number of methods that 00089 any one message pattern may match, but if you want to take advantage of 00090 pre-dispatching, this should be large enough to hold all the callbacks for 00091 all the messages waiting in the scheduler. 00092 00093 */ 00094 00095 00096 struct OSCReceiveMemoryTuner { 00097 void *(*InitTimeMemoryAllocator)(int numBytes); 00098 void *(*RealTimeMemoryAllocator)(int numBytes); 00099 int receiveBufferSize; 00100 int numReceiveBuffers; 00101 int numQueuedObjects; 00102 int numCallbackListNodes; 00103 }; 00104 00105 /* Given an OSCReceiveMemoryTuner, return the number of bytes of 00106 memory that would be allocated if OSCInitReceive() were called 00107 on it. */ 00108 int OSCReceiveMemoryThatWouldBeAllocated(struct OSCReceiveMemoryTuner *t); 00109 00110 /* Returns FALSE if it fails to initialize */ 00111 Boolean OSCInitReceive(struct OSCReceiveMemoryTuner *t); 00112 00113 /************************************************** 00114 Managing packet data structures 00115 **************************************************/ 00116 00117 00118 /* You don't get to know what's in an OSCPacketBuffer. */ 00119 typedef struct OSCPacketBuffer_struct *OSCPacketBuffer; 00120 00121 /* Get an unused packet. Returns 0 if none are free. If you get a packet 00122 with this procedure, it is your responsibility either to call 00123 OSCAcceptPacket() on it (in which case the internals of the OSC Kit free 00124 the OSCPacketBuffer after the last message in it takes effect) or to call 00125 OSCFreePacket() on it. */ 00126 OSCPacketBuffer OSCAllocPacketBuffer(void); 00127 00128 /* Free. This is called automatically after the last message that was 00129 in the packet is invoked. You shouldn't need to call this unless 00130 you get a packet with OSCAllocPacketBuffer() and then for some reason 00131 decide not to call OSCAcceptPacket() on it. */ 00132 void OSCFreePacket(OSCPacketBuffer p); 00133 00134 /* Whatever code actually gets packets from the network should use these 00135 three selectors to access the fields in the packet structure that need 00136 to be filled in with the data from the network. */ 00137 00138 /* Selector to get the buffer from a packet. This buffer's size will be 00139 equal to the receiveBufferSize you passed to OSCInitReceive(). */ 00140 char *OSCPacketBufferGetBuffer(OSCPacketBuffer p); 00141 00142 /* Selector to get a pointer to the int that's the size count for the 00143 data currently in a packet. (Not the capacity of the packet's buffer, 00144 but the size of the packet that's actually stored in the buffer.) */ 00145 int *OSCPacketBufferGetSize(OSCPacketBuffer); 00146 00147 /* Selector to get the client's network address from a packet. This buffer's 00148 size will be equal to the clientAddrSize you passed to OSCInitReceive(). 00149 Note that the NetworkReturnAddressPtr type is full of "const"s, so your 00150 code that fills in the return address will probably have to cast the return 00151 value of this procedure to some non-const type to be able to write into it. */ 00152 NetworkReturnAddressPtr OSCPacketBufferGetClientAddr(OSCPacketBuffer p); 00153 00154 /* Returns the capacity of packet buffers (the receiveBufferSize you passed 00155 to OSCInitReceive()). */ 00156 int OSCGetReceiveBufferSize(void); 00157 00158 00159 /************************************************** 00160 Dealing with OpenSoundControl packets and 00161 making the messages take effect. 00162 **************************************************/ 00163 00164 /* Call this as soon as a packet comes in from the network. 00165 It will take care of anything that has to happen immediately, 00166 but put off as much as possible of the work of parsing the 00167 packet. (This tries to be as fast as possible in case a 00168 lot of packets come in.) */ 00169 void OSCAcceptPacket(OSCPacketBuffer packet); 00170 00171 /* Call this during an otherwise idle time. It goes through 00172 everything that's sitting in the OSC scheduler waiting to 00173 happen and does some of the work of parsing, pattern 00174 matching, dispatching, etc., that will have to be done 00175 at some point before the scheduled messages can take 00176 effect. 00177 00178 The return value indicates whether there is more work of 00179 this sort that could be done. (Each time you call this, 00180 it does only a small unit of this kind of work. If it 00181 returns TRUE and you still have time before the next thing 00182 you have to do, call it again.) */ 00183 Boolean OSCBeProductiveWhileWaiting(void); 00184 00185 /* Call this whenever enough time has passed that you want to see which 00186 messages are now ready and have them take effect. (For example, in a 00187 synthesizer, you might call this once per synthesis frame, just before 00188 synthesizing the audio for that frame.) 00189 00190 This procedure finds the earliest time tag of all the queued messages 00191 and invokes *all* of the queued messages with that time tag. (OSC 00192 guarantees that messages with the same tag take effect atomically.) 00193 If there are more messages that are ready, but with a different time 00194 tag, this procedure does not invoke them, but returns TRUE to indicate 00195 that more messages are ready. 00196 */ 00197 Boolean OSCInvokeMessagesThatAreReady(OSCTimeTag now); 00198 00199 /* Same thing, but invokes all of the messages whose time has come. */ 00200 void OSCInvokeAllMessagesThatAreReady(OSCTimeTag now); 00201 00202 00203 00204 /************************************************** 00205 How to use this stuff 00206 **************************************************/ 00207 00208 /* Here's a gross approximation of how your application will invoke the 00209 procedures in this module: 00210 00211 while (1) { 00212 OSCTimeTag now = CurrentTime(); 00213 do { 00214 if (WeAreSoLateThatWeNeedToDelayOSCMessagesToAvoidACrisis()) break; 00215 } while (OSCInvokeMessagesThatAreReady(now) == TRUE); 00216 00217 SynthesizeSomeSound(); 00218 if (NetworkPacketWaiting()) { 00219 OSCPacketBuffer p = OSCAllocPacketBuffer(); 00220 if (!p) { 00221 Bummer(); 00222 } else { 00223 NetworkReceivePacket(p); 00224 OSCAcceptPacket(p); 00225 } 00226 } 00227 while (TimeLeftBeforeWeHaveDoSomething()) { 00228 if (!OSCBeProductiveWhileWaiting()) break; 00229 } 00230 } 00231 00232 */ 00233
1.5.8