diff options
Diffstat (limited to 'libraries/oscP5/src/oscP5/OscMessage.java')
-rw-r--r-- | libraries/oscP5/src/oscP5/OscMessage.java | 764 |
1 files changed, 764 insertions, 0 deletions
diff --git a/libraries/oscP5/src/oscP5/OscMessage.java b/libraries/oscP5/src/oscP5/OscMessage.java new file mode 100644 index 0000000..153cfba --- /dev/null +++ b/libraries/oscP5/src/oscP5/OscMessage.java @@ -0,0 +1,764 @@ +/** + * An OSC (Open Sound Control) library for processing. + * + * (c) 2004-2012 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + * @author Andreas Schlegel http://www.sojamo.de + * @modified 12/23/2012 + * @version 0.9.9 + */ + +package oscP5; + + +import java.net.DatagramPacket; + +import java.net.InetAddress; +import netP5.Bytes; +import netP5.Logger; +import netP5.TcpClient; +import netP5.TcpPacket; + + +/** + * An OSC message consists of an OSC Address Pattern, an OSC Type Tag String + * and the OSC arguments. + * + * @related OscBundle + * @example oscP5sendReceive + */ +public class OscMessage extends OscPacket { + + protected final OscArgument _myOscArgument = new OscArgument(); + + protected boolean isPlugged = false; + + protected OscMessage(final DatagramPacket theDatagramPacket) { + inetAddress = theDatagramPacket.getAddress(); + port = theDatagramPacket.getPort(); + hostAddress = inetAddress.toString(); + parseMessage(theDatagramPacket.getData()); + _myType = MESSAGE; + } + + + protected OscMessage(final TcpPacket thePacket) { + _myTcpClient = thePacket.getTcpConnection(); + inetAddress = _myTcpClient.netAddress().inetaddress(); + port = _myTcpClient.netAddress().port(); + hostAddress = inetAddress.toString(); + parseMessage(thePacket.getData()); + _myType = MESSAGE; + } + + + /** + * + * @param theOscMessage OscMessage + * @invisible + */ + + public OscMessage(final OscMessage theOscMessage) { + inetAddress = theOscMessage.inetAddress; + port = theOscMessage.port; + hostAddress = theOscMessage.hostAddress; + _myTcpClient = theOscMessage.tcpConnection(); + _myAddrPattern = theOscMessage._myAddrPattern; + _myTypetag = theOscMessage._myTypetag; + _myData = theOscMessage._myData; + _myArguments = theOscMessage._myArguments; + isValid = true; + } + + + /** + * + * @param theAddrPattern + * String + */ + public OscMessage(final String theAddrPattern) { + this(theAddrPattern, new Object[0]); + } + + + /** + * + * @param theAddrInt + * int + */ + public OscMessage(final int theAddrInt) { + this(theAddrInt, new Object[0]); + } + + + /** + * + * @param theAddrPattern String + * @param theArguments + * Object[] + */ + public OscMessage(final String theAddrPattern, + final Object[] theArguments) { + init(); + setAddrPattern(theAddrPattern); + setArguments(theArguments); + } + + + /** + * + * @param theAddrPattern int + * @param theArguments Object[] + */ + public OscMessage(final int theAddrPattern, + final Object[] theArguments) { + init(); + setAddrPattern(theAddrPattern); + setArguments(theArguments); + } + + + protected OscMessage(final byte[] theBytes, + final InetAddress theInetAddress, + final int thePort, + final TcpClient theClient + ) { + _myTcpClient = theClient; + inetAddress = theInetAddress; + port = thePort; + hostAddress = inetAddress.toString(); + parseMessage(theBytes); + } + + protected OscMessage(final byte[] theBytes, + final InetAddress theInetAddress, + final int thePort, + final long theTimetag, + final TcpClient theClient + ) { + this(theBytes,theInetAddress,thePort,theClient); + timetag = theTimetag; + } + + + + protected void init() { + _myTypetag = new byte[0]; + _myData = new byte[0]; + } + + + /** + * clear and reset an OscMessage for reuse. + */ + public void clear() { + init(); + setAddrPattern(""); + setArguments(new Object[0]); + } + + /** + * clears the arguments in a message, + * but keeps the address the address pattern. + * + */ + public void clearArguments() { + _myTypetag = new byte[0]; + _myData = new byte[0]; + _myArguments = new Object[0]; + } + + + /** + * TODO + * set should enable the programmer to set values + * of an existing osc message. + */ + public void set(final int theIndex, final Object theObject) { +// byte[] myPreTypetag = new byte[theIndex]; +// byte[] myPostTypetag = new byte[_myTypetag.length - theIndex]; + System.out.println("Typetag:\t" + _myTypetag.length); + System.out.println("Arguments:\t"); + Bytes.printBytes(_myData); + System.out.println(_myArguments.length); + for(int i=0;i<_myArguments.length;i++) { + System.out.println(_myArguments[i]); + } + } + + + /** + * + * @param theTypeTag + * String + * @return boolean + * @example oscP5parsing + */ + public boolean checkTypetag(final String theTypeTag) { + return theTypeTag.equals(typetag()); + } + + + /** + * check if an address pattern equals a specific address pattern + * you are looking for. this is usually used when parsing an osc message. + * e.g. if(theOscMessage.checkAddrPattern("/test")==true) {...} + * @param theAddrPattern + * String + * @return boolean + * @example oscP5parsing + */ + public boolean checkAddrPattern(final String theAddrPattern) { + return theAddrPattern.equals(addrPattern()); + } + + + /** + * set the address pattern of an osc message. you can set + * a string or an int as address pattern.tnt might be useful for + * supercollider users. oscP5 does support ints and strings as + * address patterns when sending and receiving messages. + * @param theAddrPattern + * String + */ + public void setAddrPattern(final String theAddrPattern) { + _myAddrPattern = theAddrPattern.getBytes(); + } + + + /** + * + * @param theAddrPattern + * int + */ + public void setAddrPattern(final int theAddrPattern) { + _myAddrPattern = Bytes.toBytes(theAddrPattern); + } + + + /** + * set the arguments of the osc message using an object array. + * with version 0.9.4 the existing arguments are overwritten, + * to add the arguments to the argument list, use addArguments(Object[]) + * @param theArguments + * Object[] + */ + public void setArguments(final Object[] theArguments) { + clearArguments(); + addArguments(theArguments); + } + + /** + * add a list of arguments to an exisiting set of arguments. + * to overwrite the existing argument list, use setArguments(Object[]) + * + * @param theArguments + */ + public OscMessage addArguments(final Object[] theArguments) { + return add(theArguments); + } + + + public String addrPattern() { + return Bytes.getAsString(_myAddrPattern); + } + + + /** + * returns the address pattern of the osc message as int. + * @return int + */ + public int addrInt() { + return _myAddrInt; + } + + + /** + * returns the typetag of the osc message. e.g. the message contains + * 3 floats then the typetag would be "fff" + * @return String + */ + public String typetag() { + return Bytes.getAsString(_myTypetag); + } + + /** + * get the timetag of an osc message. timetags are only sent by + * osc bundles. + * @return long + */ + public long timetag() { + return timetag; + } + + /** + * + * @return Object[] + */ + public Object[] arguments() { + return _myArguments; + } + + + /** + * supported arrays see OscPlug.getArgs + * @return Object[] + */ + protected Object[] argsAsArray() { + switch (_myTypetag[0]) { + case (0X66): // float f + final float[] myFloatArray = new float[_myArguments.length]; + for (int i = 0; i < myFloatArray.length; i++) { + myFloatArray[i] = ((Float) _myArguments[i]).floatValue(); + } + return new Object[] {myFloatArray}; + case (0x69): // int i + final int[] myIntArray = new int[_myArguments.length]; + for (int i = 0; i < myIntArray.length; i++) { + myIntArray[i] = ((Integer) _myArguments[i]).intValue(); + } + return new Object[] {myIntArray}; + case (0x53): // Symbol S + case (0x73): // String s + final String[] myStringArray = new String[_myArguments.length]; + for (int i = 0; i < myStringArray.length; i++) { + myStringArray[i] = ((String) _myArguments[i]); + } + return new Object[] {myStringArray}; + default: + break; + } + return new Object[] {}; + } + + /** + * + * @return byte[] + * @invisible + */ + public byte[] getAddrPatternAsBytes() { + return Bytes.append(_myAddrPattern, + new byte[align(_myAddrPattern.length)]); + } + + + /** + * + * @return byte[] + * @invisible + */ + public byte[] getTypetagAsBytes() { + return _myTypetag; + } + + + /** + * + * @return byte[] + * @invisible + */ + public byte[] getBytes() { + byte[] myBytes = new byte[0]; + byte[] myTypeTag = Bytes.copy(_myTypetag, 0); + myBytes = Bytes.append(myBytes, _myAddrPattern, + new byte[align(_myAddrPattern.length)]); + if (myTypeTag.length == 0) { + myTypeTag = new byte[] {KOMMA}; + } else if (myTypeTag[0] != KOMMA) { + myTypeTag = Bytes.append(new byte[] {KOMMA}, myTypeTag); + } + myBytes = Bytes.append(myBytes, myTypeTag, + new byte[align(myTypeTag.length)]); + myBytes = Bytes.append(myBytes, _myData, + new byte[align(_myData.length) % 4]); + return myBytes; + } + + + protected Object[] increase(int theAmount) { + if(_myArguments.length<1 || _myArguments == null) { + return new Object[1]; + } + Object[] myArguments = new Object[_myArguments.length + theAmount]; + System.arraycopy(_myArguments, 0, myArguments, 0, _myArguments.length); + return myArguments; + } + /** + * add values to an osc message. please check the + * add documentation for specific information. + * @example oscP5message + */ + public OscMessage add() { + _myTypetag = Bytes.append(_myTypetag, new byte[] {0x4e}); + return this; + } + + + /** + * @param theValue int + */ + public OscMessage add(final int theValue) { + _myTypetag = Bytes.append(_myTypetag, new byte[] {0x69}); + _myData = Bytes.append(_myData, Bytes.toBytes(theValue)); + _myArguments = increase(1); + _myArguments[_myArguments.length-1] = new Integer(theValue); + return this; + } + + + /** + * + * @param theValue String + */ + public OscMessage add(final String theValue) { + _myTypetag = Bytes.append(_myTypetag, new byte[] {0x73}); + final byte[] myString = theValue.getBytes(); + _myData = Bytes.append(_myData, myString, + new byte[align(myString.length)]); + _myArguments = increase(1); + _myArguments[_myArguments.length-1] = theValue; + return this; + } + + + /** + * + * @param theValue float + */ + public OscMessage add(final float theValue) { + _myTypetag = Bytes.append(_myTypetag, new byte[] {0x66}); + _myData = Bytes.append(_myData, Bytes.toBytes(Float + .floatToIntBits(theValue))); + _myArguments = increase(1); + _myArguments[_myArguments.length-1] = new Float(theValue); + return this; + } + + + /** + * + * @param theValue double + */ + public OscMessage add(final double theValue) { + _myTypetag = Bytes.append(_myTypetag, new byte[] {0x64}); + _myData = Bytes.append(_myData, Bytes.toBytes(Double + .doubleToLongBits(theValue))); + _myArguments = increase(1); + _myArguments[_myArguments.length-1] = new Double(theValue); + return this; + } + + + /** + * + * @param theValue boolean + */ + public OscMessage add(final boolean theValue) { + if (theValue) { + _myTypetag = Bytes.append(_myTypetag, new byte[] {0x54}); + } else { + _myTypetag = Bytes.append(_myTypetag, new byte[] {0x46}); + } + return this; + } + + + /** + * + * @param theValue Boolean + */ + public OscMessage add(final Boolean theValue) { + add((theValue).booleanValue()); + return this; + } + + + /** + * + * @param theValue Integer + */ + public OscMessage add(final Integer theValue) { + add(theValue.intValue()); + return this; + } + + + /** + * + * @param theValue + * Float + */ + public OscMessage add(final Float theValue) { + add(theValue.floatValue()); + return this; + } + + + /** + * + * @param theValue + * Double + */ + public OscMessage add(final Double theValue) { + add(theValue.doubleValue()); + return this; + } + + + /** + * + * @param theValue + * Character + */ + public OscMessage add(final Character theValue) { + add(theValue.charValue()); + return this; + } + + + /** + * + * @param theValue + * char + */ + public OscMessage add(final char theValue) { + _myTypetag = Bytes.append(_myTypetag, new byte[] {0x63}); + _myData = Bytes.append(_myData, Bytes.toBytes(theValue)); + _myArguments = increase(1); + _myArguments[_myArguments.length-1] = new Character(theValue); + return this; + } + + + /** + * + * @param channel int + * @param status int + * @param value1 int + * @param value2 int + */ + + public OscMessage add(final int channel, + final int status, + final int value1, + final int value2) { + _myTypetag = Bytes.append(_myTypetag, new byte[] {0x6d}); // m + final byte[] theBytes = new byte[4]; + theBytes[0] = (byte) channel; + theBytes[1] = (byte) status; + theBytes[2] = (byte) value1; + theBytes[3] = (byte) value2; + _myData = Bytes.append(_myData, theBytes); + _myArguments = increase(1); + _myArguments[_myArguments.length-1] = theBytes; + return this; + } + + + /** + * + * @param theArray + * int[] + */ + public OscMessage add(final int[] theArray) { + for (int i = 0; i < theArray.length; i++) { + add(theArray[i]); + } + return this; + } + + + /** + * + * @param theArray + * char[] + */ + public OscMessage add(final char[] theArray) { + for (int i = 0; i < theArray.length; i++) { + add(theArray[i]); + } + return this; + } + + + /** + * + * @param theArray + * float[] + */ + public OscMessage add(final float[] theArray) { + for (int i = 0; i < theArray.length; i++) { + add(theArray[i]); + } + return this; + } + + + /** + * + * @param theArray + * String[] + */ + public OscMessage add(final String[] theArray) { + for (int i = 0; i < theArray.length; i++) { + add(theArray[i]); + } + return this; + } + + + /** + * + * @param theArray + * byte[] + */ + public OscMessage add(final byte[] theArray) { + _myTypetag = Bytes.append(_myTypetag, new byte[] {0x62}); + _myData = Bytes.append(_myData, makeBlob(theArray)); + _myArguments = increase(1); + _myArguments[_myArguments.length-1] = theArray; + return this; + } + + + /** + * + * @param theArray + * Object[] + */ + public OscMessage add(final Object[] theArray) { + for (int i = 0; i < theArray.length; i++) { + if (!add(theArray[i])) { + System.out.println("type of Argument not defined in osc specs."); + } + } + return this; + } + + + private boolean add(final Object theObject) { + if (theObject instanceof Number) { + if (theObject instanceof Integer) { + add((Integer) theObject); + } else if (theObject instanceof Float) { + add((Float) theObject); + } else if (theObject instanceof Double) { + add((Double) theObject); + } else if (theObject instanceof Long) { + add((Long) theObject); + } + } else if (theObject instanceof String) { + add((String) theObject); + } else if (theObject instanceof Boolean) { + add((Boolean) theObject); + } else if (theObject instanceof Character) { + add((Character) theObject); + } + + else { + if (theObject instanceof int[]) { + add((int[]) theObject); + return true; + } else if (theObject instanceof float[]) { + add((float[]) theObject); + return true; + } else if (theObject instanceof byte[]) { + add((byte[]) theObject); + return true; + } + + else if (theObject instanceof String[]) { + add((String[]) theObject); + return true; + } else if (theObject instanceof char[]) { + add((char[]) theObject); + return true; + } else if (theObject instanceof double[]) { + add((float[]) theObject); + return true; + } + return false; + } + return true; + } + + + /** + * + * @param b byte[] + * @return byte[] + * @invisible + */ + public static byte[] makeBlob(final byte[] b) { + final int tLength = b.length; + byte[] b1 = Bytes.toBytes(tLength); + b1 = Bytes.append(b1, b); + final int t = tLength % 4; + if (t != 0) { + b1 = Bytes.append(b1, new byte[4 - t]); + } + return b1; + } + + + /** + * get a value at a specific position in the osc message. the get method + * returns an OscArgument from which the value can be parsed into the right + * format. e.g. to parse an int from the first argument in the osc message, + * use theOscMessage.get(0).intValue(); + * @param theIndex int + * @return OscArgument + */ + public OscArgument get(final int theIndex) { + if (theIndex < arguments().length) { + _myOscArgument.value = arguments()[theIndex]; + return _myOscArgument; + } + return null; + } + + + /** + * + * @return String + * @invisible + */ + public final String toString() { + return hostAddress + ":" + port + " | " + + addrPattern() + " " + typetag(); + } + + + public boolean isPlugged() { + return isPlugged; + } + + + public void print() { + Logger.println("-OscMessage----------"); + Logger.println("received from\t" + hostAddress + ":" + port); + Logger.println("addrpattern\t" + Bytes.getAsString(_myAddrPattern)); + Logger.println("typetag\t" + Bytes.getAsString(_myTypetag)); + Logger.println(Bytes.getAsString(_myArguments)); + Logger.println("---------------------"); + } + + public void printData() { + Bytes.printBytes(_myData); + } +} |