From 189c0787586602185fea7dcbc3ef37665b75ba45 Mon Sep 17 00:00:00 2001 From: jdl Date: Tue, 6 Aug 2002 12:13:57 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r75, which included commits to RCS files with non-trunk default branches. svn path=/trunk/externals/OSCx/; revision=76 --- libOSC/LIBOSC.001 | 94 +++++++++ libOSC/LIBOSC.002 | 100 +++++++++ libOSC/LIBOSC.DSP | 100 +++++++++ libOSC/LIBOSC.DSW | 29 +++ libOSC/LIBOSC.PLG | 29 +++ libOSC/Makefile | 21 ++ libOSC/OSC-client.c | 473 ++++++++++++++++++++++++++++++++++++++++++ libOSC/OSC-client.c.pre-htonl | 303 +++++++++++++++++++++++++++ libOSC/OSC-client.h | 181 ++++++++++++++++ libOSC/OSC-timetag.c | 175 ++++++++++++++++ libOSC/OSC-timetag.h | 93 +++++++++ libOSC/test_OSC.c | 149 +++++++++++++ libOSC/test_OSC_timeTag.c | 36 ++++ 13 files changed, 1783 insertions(+) create mode 100644 libOSC/LIBOSC.001 create mode 100644 libOSC/LIBOSC.002 create mode 100644 libOSC/LIBOSC.DSP create mode 100644 libOSC/LIBOSC.DSW create mode 100644 libOSC/LIBOSC.PLG create mode 100644 libOSC/Makefile create mode 100644 libOSC/OSC-client.c create mode 100644 libOSC/OSC-client.c.pre-htonl create mode 100644 libOSC/OSC-client.h create mode 100644 libOSC/OSC-timetag.c create mode 100644 libOSC/OSC-timetag.h create mode 100644 libOSC/test_OSC.c create mode 100644 libOSC/test_OSC_timeTag.c (limited to 'libOSC') diff --git a/libOSC/LIBOSC.001 b/libOSC/LIBOSC.001 new file mode 100644 index 0000000..d1b40cc --- /dev/null +++ b/libOSC/LIBOSC.001 @@ -0,0 +1,94 @@ +# Microsoft Developer Studio Project File - Name="LIBOSC" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=LIBOSC - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "LIBOSC.MAK". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "LIBOSC.MAK" CFG="LIBOSC - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "LIBOSC - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "LIBOSC - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe + +!IF "$(CFG)" == "LIBOSC - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "LIBOSC - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "LIBOSC - Win32 Release" +# Name "LIBOSC - Win32 Debug" +# Begin Source File + +SOURCE=".\OSC-client.c" +# End Source File +# Begin Source File + +SOURCE=".\OSC-client.h" +# End Source File +# Begin Source File + +SOURCE=".\OSC-timetag.c" +# End Source File +# Begin Source File + +SOURCE=".\OSC-timetag.h" +# End Source File +# End Target +# End Project diff --git a/libOSC/LIBOSC.002 b/libOSC/LIBOSC.002 new file mode 100644 index 0000000..d2c0fe8 --- /dev/null +++ b/libOSC/LIBOSC.002 @@ -0,0 +1,100 @@ +# Microsoft Developer Studio Project File - Name="LIBOSC" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=LIBOSC - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "LIBOSC.MAK". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "LIBOSC.MAK" CFG="LIBOSC - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "LIBOSC - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "LIBOSC - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe + +!IF "$(CFG)" == "LIBOSC - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE RSC /l 0x409 +# ADD RSC /l 0x409 +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../pd/src" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"..\..\..\pd\lib\LIBOSC.lib" + +!ELSEIF "$(CFG)" == "LIBOSC - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE RSC /l 0x409 +# ADD RSC /l 0x409 +# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /Z7 /Od /I "../../pd/src" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "LIBOSC - Win32 Release" +# Name "LIBOSC - Win32 Debug" +# Begin Source File + +SOURCE=".\OSC-client.c" +# End Source File +# Begin Source File + +SOURCE=".\OSC-client.h" +# End Source File +# Begin Source File + +SOURCE=".\OSC-timetag.c" +# End Source File +# Begin Source File + +SOURCE=".\OSC-timetag.h" +# End Source File +# End Target +# End Project diff --git a/libOSC/LIBOSC.DSP b/libOSC/LIBOSC.DSP new file mode 100644 index 0000000..99e661a --- /dev/null +++ b/libOSC/LIBOSC.DSP @@ -0,0 +1,100 @@ +# Microsoft Developer Studio Project File - Name="LIBOSC" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=LIBOSC - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "LIBOSC.MAK". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "LIBOSC.MAK" CFG="LIBOSC - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "LIBOSC - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "LIBOSC - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "LIBOSC - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "../../pd/src" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE RSC /l 0x409 +# ADD RSC /l 0x409 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"..\..\..\pd\lib\LIBOSC.lib" + +!ELSEIF "$(CFG)" == "LIBOSC - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /Z7 /Od /I "../../pd/src" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE RSC /l 0x409 +# ADD RSC /l 0x409 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "LIBOSC - Win32 Release" +# Name "LIBOSC - Win32 Debug" +# Begin Source File + +SOURCE=".\OSC-client.c" +# End Source File +# Begin Source File + +SOURCE=".\OSC-client.h" +# End Source File +# Begin Source File + +SOURCE=".\OSC-timetag.c" +# End Source File +# Begin Source File + +SOURCE=".\OSC-timetag.h" +# End Source File +# End Target +# End Project diff --git a/libOSC/LIBOSC.DSW b/libOSC/LIBOSC.DSW new file mode 100644 index 0000000..ef47907 --- /dev/null +++ b/libOSC/LIBOSC.DSW @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "LIBOSC"=.\LIBOSC.DSP - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/libOSC/LIBOSC.PLG b/libOSC/LIBOSC.PLG new file mode 100644 index 0000000..d011835 --- /dev/null +++ b/libOSC/LIBOSC.PLG @@ -0,0 +1,29 @@ + + +
+

Build Log

+

+--------------------Configuration: LIBOSC - Win32 Release-------------------- +

+

Command Lines

+Creating temporary file "C:\DOCUME~1\gustav\LOCALS~1\Temp\RSPB.tmp" with contents +[ +/nologo /ML /W3 /GX /O2 /I "../../pd/src" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Fp"Release/LIBOSC.pch" /YX /Fo"Release/" /Fd"Release/" /FD /c +"D:\pd\OSC\LIBOSC\OSC-client.c" +"D:\pd\OSC\LIBOSC\OSC-timetag.c" +] +Creating command line "cl.exe @C:\DOCUME~1\gustav\LOCALS~1\Temp\RSPB.tmp" +Creating command line "link.exe -lib /nologo /out:"..\..\..\pd\lib\LIBOSC.lib" ".\Release\OSC-client.obj" ".\Release\OSC-timetag.obj" " +

Output Window

+Compiling... +OSC-client.c +OSC-timetag.c +Creating library... + + + +

Results

+LIBOSC.lib - 0 error(s), 0 warning(s) +
+ + diff --git a/libOSC/Makefile b/libOSC/Makefile new file mode 100644 index 0000000..6261b37 --- /dev/null +++ b/libOSC/Makefile @@ -0,0 +1,21 @@ +CFLAGS= -O2 +LIB=libOSC.a + +LIBOBJS= ${LIB}(OSC-client.o) ${LIB}(OSC-timetag.o) + +all: ${LIBOBJS} + +.c.a: + ${CC} -c ${CFLAGS} $< + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +test_OSC: test_OSC.o ${LIB} + cc -o test_OSC test_OSC.o ${LIB} + +test_OSC_timeTag: test_OSC_timeTag.o OSC-timetag.o + cc -o test_OSC_timeTag test_OSC_timeTag.o OSC-timetag.o + + +clean: + rm -f ${LIB} *.o diff --git a/libOSC/OSC-client.c b/libOSC/OSC-client.c new file mode 100644 index 0000000..27b07d0 --- /dev/null +++ b/libOSC/OSC-client.c @@ -0,0 +1,473 @@ +/* +Copyright (c) 1996. The Regents of the University of California (Regents). +All Rights Reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation for educational, research, and not-for-profit purposes, 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. Contact The Office of +Technology Licensing, UC Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, +CA 94720-1620, (510) 643-7201, for commercial licensing opportunities. + +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. + + 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. +*/ + + +/* + Author: Matt Wright + Version 2.2: Calls htonl in the right places 20000620 + Version 2.3: Gets typed messages right. + */ + +/* + pd + ------------- + + raf@interaccess.com: + rev. for Win32 build (verified under Win-2ooo) 11-April-2002 + +*/ + +/* Here are the possible values of the state field: */ + +#define EMPTY 0 /* Nothing written to packet yet */ +#define ONE_MSG_ARGS 1 /* Packet has a single message; gathering arguments */ +#define NEED_COUNT 2 /* Just opened a bundle; must write message name or + open another bundle */ +#define GET_ARGS 3 /* Getting arguments to a message. If we see a message + name or a bundle open/close then the current message + will end. */ +#define DONE 4 /* All open bundles have been closed, so can't write + anything else */ + +#ifdef WIN32 + #include + #include + #include + #include + #include + #include + #include +#endif + + +#include "OSC-client.h" + +char *OSC_errorMessage; + +#ifndef WIN32 + static int strlen(char *s); +#endif +static int OSC_padString(char *dest, char *str); +static int OSC_padStringWithAnExtraStupidComma(char *dest, char *str); +static int OSC_WritePadding(char *dest, int i); +static int CheckTypeTag(OSCbuf *buf, char expectedType); + +void OSC_initBuffer(OSCbuf *buf, int size, char *byteArray) { + buf->buffer = byteArray; + buf->size = size; + OSC_resetBuffer(buf); +} + +void OSC_resetBuffer(OSCbuf *buf) { + buf->bufptr = buf->buffer; + buf->state = EMPTY; + buf->bundleDepth = 0; + buf->prevCounts[0] = 0; + buf->gettingFirstUntypedArg = 0; + buf->typeStringPtr = 0; +} + +int OSC_isBufferEmpty(OSCbuf *buf) { + return buf->bufptr == buf->buffer; +} + +int OSC_freeSpaceInBuffer(OSCbuf *buf) { + return buf->size - (buf->bufptr - buf->buffer); +} + +int OSC_isBufferDone(OSCbuf *buf) { + return (buf->state == DONE || buf->state == ONE_MSG_ARGS); +} + +char *OSC_getPacket(OSCbuf *buf) { +#ifdef ERROR_CHECK_GETPACKET + if (buf->state == DONE || buf->state == ONE_MSG_ARGS) { + return buf->buffer; + } else { + OSC_errorMessage = "Packet has unterminated bundles"; + return 0; + } +#else + return buf->buffer; +#endif +} + +int OSC_packetSize(OSCbuf *buf) { +#ifdef ERROR_CHECK_PACKETSIZE + if (buf->state == DONE || buf->state == ONE_MSG_ARGS) { + return (buf->bufptr - buf->buffer); + } else { + OSC_errorMessage = "Packet has unterminated bundles"; + return 0; + } +#else + return (buf->bufptr - buf->buffer); +#endif +} + +#define CheckOverflow(buf, bytesNeeded) { \ + if ((bytesNeeded) > OSC_freeSpaceInBuffer(buf)) { \ + OSC_errorMessage = "buffer overflow"; \ + return 1; \ + } \ +} + +static void PatchMessageSize(OSCbuf *buf) { + int4byte size; + size = buf->bufptr - ((char *) buf->thisMsgSize) - 4; + *(buf->thisMsgSize) = htonl(size); +} + +int OSC_openBundle(OSCbuf *buf, OSCTimeTag tt) { + if (buf->state == ONE_MSG_ARGS) { + OSC_errorMessage = "Can't open a bundle in a one-message packet"; + return 3; + } + + if (buf->state == DONE) { + OSC_errorMessage = "This packet is finished; can't open a new bundle"; + return 4; + } + + if (++(buf->bundleDepth) >= MAX_BUNDLE_NESTING) { + OSC_errorMessage = "Bundles nested too deeply; change MAX_BUNDLE_NESTING in OpenSoundControl.h"; + return 2; + } + + if (CheckTypeTag(buf, '\0')) return 9; + + if (buf->state == GET_ARGS) { + PatchMessageSize(buf); + } + + if (buf->state == EMPTY) { + /* Need 16 bytes for "#bundle" and time tag */ + CheckOverflow(buf, 16); + } else { + /* This bundle is inside another bundle, so we need to leave + a blank size count for the size of this current bundle. */ + CheckOverflow(buf, 20); + *((int4byte *)buf->bufptr) = 0xaaaaaaaa; + buf->prevCounts[buf->bundleDepth] = (int4byte *)buf->bufptr; + + buf->bufptr += 4; + } + + buf->bufptr += OSC_padString(buf->bufptr, "#bundle"); + + + *((OSCTimeTag *) buf->bufptr) = tt; + + if (htonl(1) != 1) { + /* Byte swap the 8-byte integer time tag */ + int4byte *intp = (int4byte *)buf->bufptr; + intp[0] = htonl(intp[0]); + intp[1] = htonl(intp[1]); + +#ifdef HAS8BYTEINT + { /* tt is a 64-bit int so we have to swap the two 32-bit words. + (Otherwise tt is a struct of two 32-bit words, and even though + each word was wrong-endian, they were in the right order + in the struct.) */ + int4byte temp = intp[0]; + intp[0] = intp[1]; + intp[1] = temp; + } +#endif + } + + buf->bufptr += sizeof(OSCTimeTag); + + buf->state = NEED_COUNT; + + buf->gettingFirstUntypedArg = 0; + buf->typeStringPtr = 0; + return 0; +} + + +int OSC_closeBundle(OSCbuf *buf) { + if (buf->bundleDepth == 0) { + /* This handles EMPTY, ONE_MSG, ARGS, and DONE */ + OSC_errorMessage = "Can't close bundle; no bundle is open!"; + return 5; + } + + if (CheckTypeTag(buf, '\0')) return 9; + + if (buf->state == GET_ARGS) { + PatchMessageSize(buf); + } + + if (buf->bundleDepth == 1) { + /* Closing the last bundle: No bundle size to patch */ + buf->state = DONE; + } else { + /* Closing a sub-bundle: patch bundle size */ + int size = buf->bufptr - ((char *) buf->prevCounts[buf->bundleDepth]) - 4; + *(buf->prevCounts[buf->bundleDepth]) = htonl(size); + buf->state = NEED_COUNT; + } + + --buf->bundleDepth; + buf->gettingFirstUntypedArg = 0; + buf->typeStringPtr = 0; + return 0; +} + + +int OSC_closeAllBundles(OSCbuf *buf) { + if (buf->bundleDepth == 0) { + /* This handles EMPTY, ONE_MSG, ARGS, and DONE */ + OSC_errorMessage = "Can't close all bundles; no bundle is open!"; + return 6; + } + + if (CheckTypeTag(buf, '\0')) return 9; + + while (buf->bundleDepth > 0) { + OSC_closeBundle(buf); + } + buf->typeStringPtr = 0; + return 0; +} + +int OSC_writeAddress(OSCbuf *buf, char *name) { + int4byte paddedLength; + + if (buf->state == ONE_MSG_ARGS) { + OSC_errorMessage = "This packet is not a bundle, so you can't write another address"; + return 7; + } + + if (buf->state == DONE) { + OSC_errorMessage = "This packet is finished; can't write another address"; + return 8; + } + + if (CheckTypeTag(buf, '\0')) return 9; + + paddedLength = OSC_effectiveStringLength(name); + + if (buf->state == EMPTY) { + /* This will be a one-message packet, so no sizes to worry about */ + CheckOverflow(buf, paddedLength); + buf->state = ONE_MSG_ARGS; + } else { + /* GET_ARGS or NEED_COUNT */ + CheckOverflow(buf, 4+paddedLength); + if (buf->state == GET_ARGS) { + /* Close the old message */ + PatchMessageSize(buf); + } + buf->thisMsgSize = (int4byte *)buf->bufptr; + *(buf->thisMsgSize) = 0xbbbbbbbb; + buf->bufptr += 4; + buf->state = GET_ARGS; + } + + /* Now write the name */ + buf->bufptr += OSC_padString(buf->bufptr, name); + buf->typeStringPtr = 0; + buf->gettingFirstUntypedArg = 1; + + return 0; +} + +int OSC_writeAddressAndTypes(OSCbuf *buf, char *name, char *types) { + int result; + int4byte paddedLength; + + if (CheckTypeTag(buf, '\0')) return 9; + + result = OSC_writeAddress(buf, name); + + if (result) return result; + + paddedLength = OSC_effectiveStringLength(types); + + CheckOverflow(buf, paddedLength); + + buf->typeStringPtr = buf->bufptr + 1; /* skip comma */ + buf->bufptr += OSC_padString(buf->bufptr, types); + + buf->gettingFirstUntypedArg = 0; + return 0; +} + +static int CheckTypeTag(OSCbuf *buf, char expectedType) { + if (buf->typeStringPtr) { + if (*(buf->typeStringPtr) != expectedType) { + if (expectedType == '\0') { + OSC_errorMessage = + "According to the type tag I expected more arguments."; + } else if (*(buf->typeStringPtr) == '\0') { + OSC_errorMessage = + "According to the type tag I didn't expect any more arguments."; + } else { + OSC_errorMessage = + "According to the type tag I expected an argument of a different type."; + printf("* Expected %c, string now %s\n", expectedType, buf->typeStringPtr); + } + return 9; + } + ++(buf->typeStringPtr); + } + return 0; +} + + +int OSC_writeFloatArg(OSCbuf *buf, float arg) { + int4byte *intp; + //int result; + + CheckOverflow(buf, 4); + + if (CheckTypeTag(buf, 'f')) return 9; + + /* Pretend arg is a long int so we can use htonl() */ + intp = ((int4byte *) &arg); + *((int4byte *) buf->bufptr) = htonl(*intp); + + buf->bufptr += 4; + + buf->gettingFirstUntypedArg = 0; + return 0; +} + + + +int OSC_writeFloatArgs(OSCbuf *buf, int numFloats, float *args) { + int i; + int4byte *intp; + + CheckOverflow(buf, 4 * numFloats); + + /* Pretend args are long ints so we can use htonl() */ + intp = ((int4byte *) args); + + for (i = 0; i < numFloats; i++) { + if (CheckTypeTag(buf, 'f')) return 9; + *((int4byte *) buf->bufptr) = htonl(intp[i]); + buf->bufptr += 4; + } + + buf->gettingFirstUntypedArg = 0; + return 0; +} + +int OSC_writeIntArg(OSCbuf *buf, int4byte arg) { + CheckOverflow(buf, 4); + if (CheckTypeTag(buf, 'i')) return 9; + + *((int4byte *) buf->bufptr) = htonl(arg); + buf->bufptr += 4; + + buf->gettingFirstUntypedArg = 0; + return 0; +} + +int OSC_writeStringArg(OSCbuf *buf, char *arg) { + int len; + + if (CheckTypeTag(buf, 's')) return 9; + + len = OSC_effectiveStringLength(arg); + + if (buf->gettingFirstUntypedArg && arg[0] == ',') { + /* This un-type-tagged message starts with a string + that starts with a comma, so we have to escape it + (with a double comma) so it won't look like a type + tag string. */ + + CheckOverflow(buf, len+4); /* Too conservative */ + buf->bufptr += + OSC_padStringWithAnExtraStupidComma(buf->bufptr, arg); + + } else { + CheckOverflow(buf, len); + buf->bufptr += OSC_padString(buf->bufptr, arg); + } + + buf->gettingFirstUntypedArg = 0; + return 0; + +} + +/* String utilities */ + +#ifndef WIN32 +static int strlen(char *s) { + int i; + for (i=0; s[i] != '\0'; i++) /* Do nothing */ ; + return i; +} +#endif + +#define STRING_ALIGN_PAD 4 +int OSC_effectiveStringLength(char *string) { + int len = strlen(string) + 1; /* We need space for the null char. */ + + /* Round up len to next multiple of STRING_ALIGN_PAD to account for alignment padding */ + if ((len % STRING_ALIGN_PAD) != 0) { + len += STRING_ALIGN_PAD - (len % STRING_ALIGN_PAD); + } + return len; +} + +static int OSC_padString(char *dest, char *str) { + int i; + + for (i = 0; str[i] != '\0'; i++) { + dest[i] = str[i]; + } + + return OSC_WritePadding(dest, i); +} + +static int OSC_padStringWithAnExtraStupidComma(char *dest, char *str) { + int i; + + dest[0] = ','; + for (i = 0; str[i] != '\0'; i++) { + dest[i+1] = str[i]; + } + + return OSC_WritePadding(dest, i+1); +} + +static int OSC_WritePadding(char *dest, int i) { + dest[i] = '\0'; + i++; + + for (; (i % STRING_ALIGN_PAD) != 0; i++) { + dest[i] = '\0'; + } + + return i; +} diff --git a/libOSC/OSC-client.c.pre-htonl b/libOSC/OSC-client.c.pre-htonl new file mode 100644 index 0000000..6aebfe2 --- /dev/null +++ b/libOSC/OSC-client.c.pre-htonl @@ -0,0 +1,303 @@ +/* +Copyright (c) 1996. The Regents of the University of California (Regents). +All Rights Reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation for educational, research, and not-for-profit purposes, 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. Contact The Office of +Technology Licensing, UC Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, +CA 94720-1620, (510) 643-7201, for commercial licensing opportunities. + +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. + + 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. +*/ + + +/* + Author: Matt Wright + Version 2.1 + */ + + +/* Here are the possible values of the state field: */ + +#define EMPTY 0 /* Nothing written to packet yet */ +#define ONE_MSG_ARGS 1 /* Packet has a single message; gathering arguments */ +#define NEED_COUNT 2 /* Just opened a bundle; must write message name or + open another bundle */ +#define GET_ARGS 3 /* Getting arguments to a message. If we see a message + name or a bundle open/close then the current message + will end. */ +#define DONE 4 /* All open bundles have been closed, so can't write + anything else */ + +#include "OSC-client.h" + +char *OSC_errorMessage; + + +static int strlen(char *s); +static int OSC_padString(char *dest, char *str); + +void OSC_initBuffer(OSCbuf *buf, int size, char *byteArray) { + buf->buffer = byteArray; + buf->size = size; + OSC_resetBuffer(buf); +} + +void OSC_resetBuffer(OSCbuf *buf) { + buf->bufptr = buf->buffer; + buf->state = EMPTY; + buf->bundleDepth = 0; + buf->prevCounts[0] = 0; +} + +int OSC_isBufferEmpty(OSCbuf *buf) { + return buf->bufptr == buf->buffer; +} + +int OSC_freeSpaceInBuffer(OSCbuf *buf) { + return buf->size - (buf->bufptr - buf->buffer); +} + +int OSC_isBufferDone(OSCbuf *buf) { + return (buf->state == DONE || buf->state == ONE_MSG_ARGS); +} + +char *OSC_getPacket(OSCbuf *buf) { +#ifdef ERROR_CHECK_GETPACKET + if (buf->state == DONE || buf->state == ONE_MSG_ARGS) { + return buf->buffer; + } else { + OSC_errorMessage = "Packet has unterminated bundles"; + return 0; + } +#else + return buf->buffer; +#endif +} + +int OSC_packetSize(OSCbuf *buf) { +#ifdef ERROR_CHECK_PACKETSIZE + if (buf->state == DONE || buf->state == ONE_MSG_ARGS) { + return (buf->bufptr - buf->buffer); + } else { + OSC_errorMessage = "Packet has unterminated bundles"; + return 0; + } +#else + return (buf->bufptr - buf->buffer); +#endif +} + +#define CheckOverflow(buf, bytesNeeded) { \ + if ((bytesNeeded) > OSC_freeSpaceInBuffer(buf)) { \ + OSC_errorMessage = "buffer overflow"; \ + return 1; \ + } \ +} + +static void PatchMessageSize(OSCbuf *buf) { + int4byte size; + size = buf->bufptr - ((char *) buf->thisMsgSize) - 4; + *(buf->thisMsgSize) = size; +} + +int OSC_openBundle(OSCbuf *buf, OSCTimeTag tt) { + if (buf->state == ONE_MSG_ARGS) { + OSC_errorMessage = "Can't open a bundle in a one-message packet"; + return 3; + } + + if (buf->state == DONE) { + OSC_errorMessage = "This packet is finished; can't open a new bundle"; + return 4; + } + + if (++(buf->bundleDepth) >= MAX_BUNDLE_NESTING) { + OSC_errorMessage = "Bundles nested too deeply; change MAX_BUNDLE_NESTING in OpenSoundControl.h"; + return 2; + } + + if (buf->state == GET_ARGS) { + PatchMessageSize(buf); + } + + if (buf->state == EMPTY) { + /* Need 16 bytes for "#bundle" and time tag */ + CheckOverflow(buf, 16); + } else { + /* This bundle is inside another bundle, so we need to leave + a blank size count for the size of this current bundle. */ + CheckOverflow(buf, 20); + *((int4byte *)buf->bufptr) = 0xaaaaaaaa; + buf->prevCounts[buf->bundleDepth] = (int4byte *)buf->bufptr; + + buf->bufptr += 4; + } + + buf->bufptr += OSC_padString(buf->bufptr, "#bundle"); + *((OSCTimeTag *) buf->bufptr) = tt; + buf->bufptr += sizeof(OSCTimeTag); + + buf->state = NEED_COUNT; + return 0; +} + + +int OSC_closeBundle(OSCbuf *buf) { + if (buf->bundleDepth == 0) { + /* This handles EMPTY, ONE_MSG, ARGS, and DONE */ + OSC_errorMessage = "Can't close bundle; no bundle is open!"; + return 5; + } + + if (buf->state == GET_ARGS) { + PatchMessageSize(buf); + } + + if (buf->bundleDepth == 1) { + /* Closing the last bundle: No bundle size to patch */ + buf->state = DONE; + } else { + /* Closing a sub-bundle: patch bundle size */ + int size = buf->bufptr - ((char *) buf->prevCounts[buf->bundleDepth]) - 4; + *(buf->prevCounts[buf->bundleDepth]) = size; + buf->state = NEED_COUNT; + } + + --buf->bundleDepth; + return 0; +} + + +int OSC_closeAllBundles(OSCbuf *buf) { + if (buf->bundleDepth == 0) { + /* This handles EMPTY, ONE_MSG, ARGS, and DONE */ + OSC_errorMessage = "Can't close all bundles; no bundle is open!"; + return 6; + } + + while (buf->bundleDepth > 0) { + OSC_closeBundle(buf); + } + return 0; +} + +int OSC_writeAddress(OSCbuf *buf, char *name) { + int4byte paddedLength; + + if (buf->state == ONE_MSG_ARGS) { + OSC_errorMessage = "This packet is not a bundle, so you can't write another address"; + return 7; + } + + if (buf->state == DONE) { + OSC_errorMessage = "This packet is finished; can't write another address"; + return 8; + } + + paddedLength = OSC_effectiveStringLength(name); + + if (buf->state == EMPTY) { + /* This will be a one-message packet, so no sizes to worry about */ + CheckOverflow(buf, paddedLength); + buf->state = ONE_MSG_ARGS; + } else { + /* GET_ARGS or NEED_COUNT */ + CheckOverflow(buf, 4+paddedLength); + if (buf->state == GET_ARGS) { + /* Close the old message */ + PatchMessageSize(buf); + } + buf->thisMsgSize = (int4byte *)buf->bufptr; + *(buf->thisMsgSize) = 0xbbbbbbbb; + buf->bufptr += 4; + buf->state = GET_ARGS; + } + + /* Now write the name */ + buf->bufptr += OSC_padString(buf->bufptr, name); + return 0; +} + +int OSC_writeFloatArg(OSCbuf *buf, float arg) { + CheckOverflow(buf, 4); + *((float *) buf->bufptr) = arg; + buf->bufptr += 4; + return 0; +} + +int OSC_writeFloatArgs(OSCbuf *buf, int numFloats, float *args) { + int i; + CheckOverflow(buf, 4 * numFloats); + for (i = 0; i < numFloats; i++) { + *((float *) buf->bufptr) = args[i]; + buf->bufptr += 4; + } + return 0; +} + +int OSC_writeIntArg(OSCbuf *buf, int4byte arg) { + CheckOverflow(buf, 4); + *((int4byte *) buf->bufptr) = arg; + buf->bufptr += 4; + return 0; +} + +int OSC_writeStringArg(OSCbuf *buf, char *arg) { + CheckOverflow(buf, OSC_effectiveStringLength(arg)); + buf->bufptr += OSC_padString(buf->bufptr, arg); + return 0; +} + +/* String utilities */ + +static int strlen(char *s) { + int i; + for (i=0; s[i] != '\0'; i++) /* Do nothing */ ; + return i; +} + +#define STRING_ALIGN_PAD 4 +int OSC_effectiveStringLength(char *string) { + int len = strlen(string) + 1; /* We need space for the null char. */ + + /* Round up len to next multiple of STRING_ALIGN_PAD to account for alignment padding */ + if ((len % STRING_ALIGN_PAD) != 0) { + len += STRING_ALIGN_PAD - (len % STRING_ALIGN_PAD); + } + return len; +} + +static int OSC_padString(char *dest, char *str) { + int i; + + for (i = 0; str[i] != '\0'; i++) { + dest[i] = str[i]; + } + + dest[i] = '\0'; + i++; + + for (; (i % STRING_ALIGN_PAD) != 0; i++) { + dest[i] = '\0'; + } + + return i; +} + diff --git a/libOSC/OSC-client.h b/libOSC/OSC-client.h new file mode 100644 index 0000000..b1fd833 --- /dev/null +++ b/libOSC/OSC-client.h @@ -0,0 +1,181 @@ +/* +Copyright (c) 1996,1997. The Regents of the University of California (Regents). +All Rights Reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation for educational, research, and not-for-profit purposes, 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. Contact The Office of +Technology Licensing, UC Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, +CA 94720-1620, (510) 643-7201, for commercial licensing opportunities. + +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. + + 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. +*/ + +/* + + OSC-client.h: library for constructing OpenSoundControl messages. + Derived from SynthControl.h + Author: Matt Wright + Version 0.1: 6/13/97 + Version 0.2: 7/21/2000: Support for type-tagged messages + + + General notes: + + This library abstracts away the data format for the OpenSoundControl + protocol. Users of this library can construct OpenSoundControl packets + with a function call interface instead of knowing how to lay out the bits. + + All issues of memory allocation are deferred to the user of this library. + There are two data structures that the user must allocate. The first + is the actual buffer that the message will be written into. This buffer + can be any size, but if it's too small there's a possibility that it + will become overfull. The other data structure is called an OSCbuf, + and it holds all the state used by the library as it's constructing + a buffer. + + All procedures that have the possibility of an error condition return int, + with 0 indicating no error and nonzero indicating an error. The variable + OSC_errorMessage will be set to point to a string containing an error + message explaining what the problem is. + +*/ + + +#include "OSC-timetag.h" + +/* The int4byte type has to be a 4-byte integer. You may have to + change this to long or something else on your system. */ +#ifdef __MWERKS__ + /* In Metrowerks you can set ints to be 2 or 4 bytes on 68K, but long is + always 4 bytes */ + typedef long int4byte; +#else + typedef int int4byte; +#endif + +/* The maximum depth of bundles within bundles within bundles within... + This is the size of a static array. If you exceed this limit you'll + get an error message. */ +#define MAX_BUNDLE_NESTING 32 + + +/* Don't ever manipulate the data in the OSCbuf struct directly. (It's + declared here in the header file only so your program will be able to + declare variables of type OSCbuf and have the right amount of memory + be allocated.) */ + +typedef struct OSCbuf_struct { + char *buffer; /* The buffer to hold the OSC packet */ + int size; /* Size of the buffer */ + char *bufptr; /* Current position as we fill the buffer */ + int state; /* State of partially-constructed message */ + int4byte *thisMsgSize; /* Pointer to count field before + currently-being-written message */ + int4byte *prevCounts[MAX_BUNDLE_NESTING]; + /* Pointers to count field before each currently + open bundle */ + int bundleDepth; /* How many sub-sub-bundles are we in now? */ + char *typeStringPtr; /* This pointer advances through the type + tag string as you add arguments. */ + int gettingFirstUntypedArg; /* nonzero if this message doesn't have + a type tag and we're waiting for the 1st arg */ +} OSCbuf; + + + +/* Initialize the given OSCbuf. The user of this module must pass in the + block of memory that this OSCbuf will use for a buffer, and the number of + bytes in that block. (It's the user's job to allocate the memory because + you do it differently in different systems.) */ +void OSC_initBuffer(OSCbuf *buf, int size, char *byteArray); + + +/* Reset the given OSCbuf. Do this after you send out the contents of + the buffer and want to start writing new data into it. */ +void OSC_resetBuffer(OSCbuf *buf); + + +/* Is the buffer empty? (I.e., would it be stupid to send the buffer + contents to the synth?) */ +int OSC_isBufferEmpty(OSCbuf *buf); + + +/* How much space is left in the buffer? */ +int OSC_freeSpaceInBuffer(OSCbuf *buf); + +/* Does the buffer contain a valid OSC packet? (Returns nonzero if yes.) */ +int OSC_isBufferDone(OSCbuf *buf); + +/* When you're ready to send out the buffer (i.e., when OSC_isBufferDone() + returns true), call these two procedures to get the OSC packet that's been + assembled and its size in bytes. (And then call OSC_resetBuffer() if you + want to re-use this OSCbuf for the next packet.) */ +char *OSC_getPacket(OSCbuf *buf); +int OSC_packetSize(OSCbuf *buf); + + + +/* Here's the basic model for building up OSC messages in an OSCbuf: + + - Make sure the OSCbuf has been initialized with OSC_initBuffer(). + + - To open a bundle, call OSC_openBundle(). You can then write + messages or open new bundles within the bundle you opened. + Call OSC_closeBundle() to close the bundle. Note that a packet + does not have to have a bundle; it can instead consist of just a + single message. + + + - For each message you want to send: + + - Call OSC_writeAddress() with the name of your message. (In + addition to writing your message name into the buffer, this + procedure will also leave space for the size count of this message.) + + - Alternately, call OSC_writeAddressAndTypes() with the name of + your message and with a type string listing the types of all the + arguments you will be putting in this message. + + - Now write each of the arguments into the buffer, by calling one of: + OSC_writeFloatArg() + OSC_writeFloatArgs() + OSC_writeIntArg() + OSC_writeStringArg() + + - Now your message is complete; you can send out the buffer or you can + add another message to it. +*/ + +int OSC_openBundle(OSCbuf *buf, OSCTimeTag tt); +int OSC_closeBundle(OSCbuf *buf); +int OSC_closeAllBundles(OSCbuf *buf); + +int OSC_writeAddress(OSCbuf *buf, char *name); +int OSC_writeAddressAndTypes(OSCbuf *buf, char *name, char *types); +int OSC_writeFloatArg(OSCbuf *buf, float arg); +int OSC_writeFloatArgs(OSCbuf *buf, int numFloats, float *args); +int OSC_writeIntArg(OSCbuf *buf, int4byte arg); +int OSC_writeStringArg(OSCbuf *buf, char *arg); + +extern char *OSC_errorMessage; + +/* How many bytes will be needed in the OSC format to hold the given + string? The length of the string, plus the null char, plus any padding + needed for 4-byte alignment. */ +int OSC_effectiveStringLength(char *string); diff --git a/libOSC/OSC-timetag.c b/libOSC/OSC-timetag.c new file mode 100644 index 0000000..639eae9 --- /dev/null +++ b/libOSC/OSC-timetag.c @@ -0,0 +1,175 @@ +/* +Copyright (c) 1998. The Regents of the University of California (Regents). +All Rights Reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation for educational, research, and not-for-profit purposes, 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. Contact The Office of +Technology Licensing, UC Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, +CA 94720-1620, (510) 643-7201, for commercial licensing opportunities. + +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. + + 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 "OSC-timetag.h" + + +#ifdef HAS8BYTEINT +#define TWO_TO_THE_32_FLOAT 4294967296.0f + +OSCTimeTag OSCTT_Immediately(void) { + return (OSCTimeTag) 1; +} + +OSCTimeTag OSCTT_BiggestPossibleTimeTag(void) { + return (OSCTimeTag) 0xffffffffffffffff; +} + +OSCTimeTag OSCTT_PlusSeconds(OSCTimeTag original, float secondsOffset) { + int64 offset = (int64) (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 + +#define SECONDS_FROM_1900_to_1970 2208988800 /* 17 leap years */ +#define TWO_TO_THE_32_OVER_ONE_MILLION 4295 + + +OSCTimeTag OSCTT_CurrentTime(void) { + uint64 result; + uint32 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 */ + diff --git a/libOSC/OSC-timetag.h b/libOSC/OSC-timetag.h new file mode 100644 index 0000000..3ce693a --- /dev/null +++ b/libOSC/OSC-timetag.h @@ -0,0 +1,93 @@ +/* +Copyright (c) 1998. The Regents of the University of California (Regents). +All Rights Reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation for educational, research, and not-for-profit purposes, 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. Contact The Office of +Technology Licensing, UC Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, +CA 94720-1620, (510) 643-7201, for commercial licensing opportunities. + +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. + + 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 a 64-bit + unsigned long if possible, or else a struct. + + NB: On many architectures with 64-bit ints, it's illegal (like maybe a bus error) + to dereference a pointer to a 64-bit int that's not 64-bit 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 64 bit ints on your system */ + typedef long long int64; + typedef unsigned long long uint64; + typedef unsigned long uint32; +#else + /* You may have to redefine this typedef if ints on your system + aren't 32 bits. */ + typedef unsigned int uint32; +#endif + + +#ifdef HAS8BYTEINT + typedef uint64 OSCTimeTag; +#else + typedef struct { + uint32 seconds; + uint32 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 */ diff --git a/libOSC/test_OSC.c b/libOSC/test_OSC.c new file mode 100644 index 0000000..4593ec6 --- /dev/null +++ b/libOSC/test_OSC.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 1997 Regents of the University of California. + * All rights reserved. + * + * The name of the University may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE + * IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE. + */ + +/* + test_OSC.c + Trivial program to test OpenSoundControl.[ch] + + Matt Wright 6/2/97 +*/ + +#include +#include +#include "OpenSoundControl.h" + +#define SIZE 10000 + +void PrintBuf(OSCbuf *b) { + printf("Buffer is %sempty.\n", OSC_isBufferEmpty(b) ? "" : "not "); + printf("%d bytes free in buffer\n", OSC_freeSpaceInBuffer(b)); + printf("Buffer is %sready to send\n", OSC_isBufferDone(b) ?"":"not "); + + printf("Buffer: bufptr %p, state %d, thisMsgSize %p, bundleDepth %d\n" + "prevCounts[%d] %p\n", b->bufptr, b->state, b->thisMsgSize, + b->bundleDepth, b->bundleDepth, b->prevCounts[b->bundleDepth]); +} + +void PrintPacket(OSCbuf *b) { + char *p = OSC_getPacket(b); + int size = OSC_packetSize(b); + unsigned int *intp; + int i; + + printf("PrintPacket: packet at %p, size %d\n", p, size); + if (p == 0 || size == 0) return; + + printf("Hex version:"); + for (i = 0, intp = (unsigned int *)p; i < size; i += 4, intp++) { + if (i % 40 == 0) printf("\n"); + printf("%x ", *intp); + } + + printf("\n\nString version:"); + for (i = 0; i < size; i++) { + if (i % 40 == 0) printf("\n"); + if (isprint(p[i])) { + printf("%c", p[i]); + } else { + printf("\\%x", p[i] & 0x000000ff); + } + } + printf("\n"); +} + + +main() { + OSCbuf myBuf; + OSCbuf *b = &myBuf; + char bytes[SIZE]; + OSCTimeTag tt; + + printf("OSC_initBuffer\n"); + OSC_initBuffer(b, SIZE, bytes); + + PrintBuf(b); + + printf("Testing one-message packet\n"); + if (OSC_writeAddress(b, "/blah/bleh/singlemessage")) { + printf("** ERROR: %s\n", OSC_errorMessage); + } + + if (OSC_writeFloatArg(b, 1.23456f)) { + printf("** ERROR: %s\n", OSC_errorMessage); + } + + { + float floatarray[10]; + int i; + for (i = 0; i < 10; ++i) { + floatarray[i] = i * 10.0f; + } + if (OSC_writeFloatArgs(b, 10, floatarray)) { + printf("** ERROR: %s\n", OSC_errorMessage); + } + } + + if (OSC_writeIntArg(b, 123456)) { + printf("** ERROR: %s\n", OSC_errorMessage); + } + + if (OSC_writeStringArg(b, "This is a cool string, dude.")) { + printf("** ERROR: %s\n", OSC_errorMessage); + } + + PrintBuf(b); + PrintPacket(b); + + printf("Resetting\n"); + OSC_resetBuffer(b); + + printf("Testing time tags\n"); + tt = OSCTT_CurrentTime(); + printf("Time now is %llx\n", tt); + + printf("Testing bundles\n"); + if (OSC_openBundle(b, tt)) { + printf("** ERROR: %s\n", OSC_errorMessage); + } + + if (OSC_writeAddress(b, "/a/hello")) { + printf("** ERROR: %s\n", OSC_errorMessage); + } + + if (OSC_writeIntArg(b, 16)) { + printf("** ERROR: %s\n", OSC_errorMessage); + } + + if (OSC_writeIntArg(b, 32)) { + printf("** ERROR: %s\n", OSC_errorMessage); + } + + if (OSC_openBundle(b, OSCTT_PlusSeconds(tt, 1.0f))) { + printf("** ERROR: %s\n", OSC_errorMessage); + } + + if (OSC_writeAddress(b, "/b/hello")) { + printf("** ERROR: %s\n", OSC_errorMessage); + } + + if (OSC_writeAddress(b, "/c/hello")) { + printf("** ERROR: %s\n", OSC_errorMessage); + } + + OSC_closeAllBundles(b); + + PrintBuf(b); + PrintPacket(b); +} + + + diff --git a/libOSC/test_OSC_timeTag.c b/libOSC/test_OSC_timeTag.c new file mode 100644 index 0000000..8a1cabf --- /dev/null +++ b/libOSC/test_OSC_timeTag.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 1997 Regents of the University of California. + * All rights reserved. + * + * The name of the University may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE + * IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE. + */ + +/* + test_OSC_timeTag.c + Matt Wright, 5/30/97 +*/ + +#include +#include "OSC_timeTag.h" + +main() { + OSCTimeTag now, later; + + now = OSCTT_CurrentTime(); + printf("Now it's %llu (0x%llx)\n", now, now); + + printf("Immediately would be %llu (0x%llx)\n", OSCTT_Immediately(), + OSCTT_Immediately()); + + later = OSCTT_PlusSeconds(now, 1.0f); + printf("One second from now would be %llu (0x%llx)\n", later, later); + + now = OSCTT_CurrentTime(); + printf("And *now* it's %llu (0x%llx)\n", now, now); +} + -- cgit v1.2.1