├── .github └── workflows │ └── maven-deploy-snapshot.yml ├── .gitignore ├── .java-version ├── .java-version.license ├── .mdl_style.rb ├── .mdlrc ├── LICENSE.md ├── LICENSES ├── BSD-3-Clause.txt ├── CC0-1.0.txt └── Unlicense.txt ├── README.markdown ├── modules ├── cmds │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── illposed │ │ └── osc │ │ └── cmds │ │ ├── ConsoleEchoServer.java │ │ └── package-info.java ├── core │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── illposed │ │ │ └── osc │ │ │ ├── BufferBytesReceiver.java │ │ │ ├── ByteArrayListBytesReceiver.java │ │ │ ├── BytesReceiver.java │ │ │ ├── EchoOSCMessageListener.java │ │ │ ├── LibraryInfo.java │ │ │ ├── MessageSelector.java │ │ │ ├── OSCBadDataEvent.java │ │ │ ├── OSCBadDataListener.java │ │ │ ├── OSCBundle.java │ │ │ ├── OSCMessage.java │ │ │ ├── OSCMessageEvent.java │ │ │ ├── OSCMessageInfo.java │ │ │ ├── OSCMessageListener.java │ │ │ ├── OSCPacket.java │ │ │ ├── OSCPacketDispatcher.java │ │ │ ├── OSCPacketEvent.java │ │ │ ├── OSCPacketListener.java │ │ │ ├── OSCParseException.java │ │ │ ├── OSCParser.java │ │ │ ├── OSCSerializeException.java │ │ │ ├── OSCSerializer.java │ │ │ ├── OSCSerializerAndParserBuilder.java │ │ │ ├── SerializableByteBuffer.java │ │ │ ├── argument │ │ │ ├── ArgumentHandler.java │ │ │ ├── OSCColor.java │ │ │ ├── OSCImpulse.java │ │ │ ├── OSCMidiMessage.java │ │ │ ├── OSCSymbol.java │ │ │ ├── OSCTimeTag64.java │ │ │ ├── OSCUnsigned.java │ │ │ ├── handler │ │ │ │ ├── Activator.java │ │ │ │ ├── BlobArgumentHandler.java │ │ │ │ ├── BooleanFalseArgumentHandler.java │ │ │ │ ├── BooleanTrueArgumentHandler.java │ │ │ │ ├── ByteArrayBlobArgumentHandler.java │ │ │ │ ├── CharArgumentHandler.java │ │ │ │ ├── ColorArgumentHandler.java │ │ │ │ ├── DateTimeStampArgumentHandler.java │ │ │ │ ├── DoubleArgumentHandler.java │ │ │ │ ├── FloatArgumentHandler.java │ │ │ │ ├── ImpulseArgumentHandler.java │ │ │ │ ├── IntegerArgumentHandler.java │ │ │ │ ├── LongArgumentHandler.java │ │ │ │ ├── MidiMessageArgumentHandler.java │ │ │ │ ├── NullArgumentHandler.java │ │ │ │ ├── StringArgumentHandler.java │ │ │ │ ├── SymbolArgumentHandler.java │ │ │ │ ├── TimeTag64ArgumentHandler.java │ │ │ │ ├── UnsignedIntegerArgumentHandler.java │ │ │ │ └── package-info.java │ │ │ └── package-info.java │ │ │ ├── messageselector │ │ │ ├── CombinedMessageSelector.java │ │ │ ├── JavaRegexAddressMessageSelector.java │ │ │ ├── JavaRegexTypeTagsMessageSelector.java │ │ │ ├── OSCPatternAddressMessageSelector.java │ │ │ ├── OSCPatternTypeTagsMessageSelector.java │ │ │ └── package-info.java │ │ │ ├── package-info.java │ │ │ └── transport │ │ │ ├── NetworkProtocol.java │ │ │ ├── OSCPort.java │ │ │ ├── OSCPortIn.java │ │ │ ├── OSCPortInBuilder.java │ │ │ ├── OSCPortOut.java │ │ │ ├── OSCPortOutBuilder.java │ │ │ ├── Transport.java │ │ │ ├── channel │ │ │ ├── OSCDatagramChannel.java │ │ │ └── package-info.java │ │ │ ├── package-info.java │ │ │ ├── tcp │ │ │ ├── TCPTransport.java │ │ │ └── package-info.java │ │ │ └── udp │ │ │ ├── UDPTransport.java │ │ │ └── package-info.java │ │ └── test │ │ └── java │ │ └── com │ │ └── illposed │ │ └── osc │ │ ├── BenchmarkHashMapVsElseIf.java │ │ ├── Debug.java │ │ ├── DebugClient.java │ │ ├── DebugServer.java │ │ ├── OSCBundleTest.java │ │ ├── OSCMessageTest.java │ │ ├── OSCPacketDispatcherTest.java │ │ ├── OSCParserTest.java │ │ ├── OSCReparserTest.java │ │ ├── OSCSerializerTest.java │ │ ├── SimpleOSCMessageListener.java │ │ ├── SimpleOSCPacketListener.java │ │ ├── argument │ │ └── handler │ │ │ ├── ColorArgumentHandlerTest.java │ │ │ ├── MidiMessageArgumentHandlerTest.java │ │ │ └── SymbolArgumentHandlerTest.java │ │ ├── messageselector │ │ ├── CombinedMessageSelectorTest.java │ │ ├── OSCPatternAddressMessageSelectorTest.java │ │ └── OSCPatternTypeTagsMessageSelectorTest.java │ │ └── transport │ │ ├── OSCPortTest.java │ │ └── udp │ │ ├── DatagramChannelTest.java │ │ └── UDPTransportTest.java ├── java-se-addons │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── illposed │ │ │ └── osc │ │ │ └── argument │ │ │ └── handler │ │ │ └── javase │ │ │ ├── Activator.java │ │ │ ├── AwtColorArgumentHandler.java │ │ │ └── package-info.java │ │ └── test │ │ └── java │ │ └── com │ │ └── illposed │ │ └── osc │ │ └── argument │ │ └── handler │ │ └── javase │ │ └── AwtColorArgumentHandlerTest.java ├── parent │ ├── pom.xml │ └── src │ │ └── main │ │ └── resources │ │ ├── checkstyle.xml │ │ ├── java_header_regex_template.txt │ │ ├── java_header_regex_template.txt.license │ │ ├── pmd.xml │ │ ├── puredata │ │ ├── javaosc.pd │ │ └── javaosc.pd.license │ │ └── supercollider │ │ ├── javaosc-example.sc │ │ ├── synthdefs │ │ ├── default.scsyndef │ │ ├── default.scsyndef.license │ │ ├── javaosc-example.scsyndef │ │ └── javaosc-example.scsyndef.license │ │ └── test1.sc └── ui │ ├── pom.xml │ └── src │ └── main │ ├── java │ └── com │ │ └── illposed │ │ └── osc │ │ └── ui │ │ ├── Main.java │ │ ├── OscUI.java │ │ └── package-info.java │ └── resources │ └── log4j-dev.properties └── pom.xml /.github/workflows/maven-deploy-snapshot.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Robin Vobruba 2 | # 3 | # SPDX-License-Identifier: CC0-1.0 4 | 5 | name: Build sample Java Maven project 6 | 7 | on: [push, pull_request] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | strategy: 13 | matrix: 14 | # java: [ 8, 11, 14, 17, 23 ] 15 | java: [ 17 ] 16 | name: Java ${{ matrix.java }} compile 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Setup JDK 20 | uses: actions/setup-java@v1 21 | with: 22 | java-version: ${{ matrix.java }} 23 | - run: mvn --batch-mode clean package 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 - 2024 Robin Vobruba 2 | # 3 | # SPDX-License-Identifier: Unlicense 4 | 5 | target 6 | dependency-reduced-pom.xml 7 | release.properties 8 | pom.xml.next 9 | pom.xml.releaseBackup 10 | pom.xml.tag 11 | /README.html 12 | # EMMA maven plugin report file 13 | coverage.ec 14 | .classpath 15 | .project 16 | .settings/ 17 | .idea 18 | -------------------------------------------------------------------------------- /.java-version: -------------------------------------------------------------------------------- 1 | 1.8 2 | -------------------------------------------------------------------------------- /.java-version.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2019 Dave Yarwood 2 | 3 | SPDX-License-Identifier: CC0-1.0 4 | -------------------------------------------------------------------------------- /.mdl_style.rb: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 - 2024 Robin Vobruba 2 | # 3 | # SPDX-License-Identifier: Unlicense 4 | 5 | # Enforce the style guide at https://cirosantilli.com/markdown-style-guide 6 | all 7 | 8 | rule 'MD003', :style => :atx 9 | #rule 'MD004', :style => :dash 10 | #rule 'MD004', :style => :asterisk 11 | #rule 'MD004', :style => :consistent 12 | #rule 'MD007', :indent => 4 13 | rule 'MD013', :tables => false 14 | rule 'MD029', :style => 'ordered' 15 | #rule 'MD030', :ul_multi => 3, :ol_multi => 2 16 | rule 'MD035', :style => '---' 17 | 18 | # First header should be a top level header 19 | # - We have the title in the YAML meta-data, 20 | # so we can use headers however we want 21 | exclude_rule 'MD002' 22 | # No hard tabs 23 | # - We use tabs in the sources, 24 | # and thus also in the excerpts from the sources 25 | exclude_rule 'MD010' 26 | # Multiple top level headers in the same document 27 | # - We have the title in the YAML meta-data, 28 | # so we can legitimately use level 1 headers for sections 29 | exclude_rule 'MD025' 30 | # Trailing punctuation in header 31 | exclude_rule 'MD026' 32 | # First line in file should be a top level header 33 | # - The README has the title as a big ASCII-art 34 | exclude_rule 'MD041' 35 | -------------------------------------------------------------------------------- /.mdlrc: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2018 Robin Vobruba 2 | # 3 | # SPDX-License-Identifier: Unlicense 4 | 5 | style "#{File.dirname(__FILE__)}/.mdl_style.rb" 6 | git_recurse true 7 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2002-2014, Chandrasekhar Ramakrishnan / Illposed Software 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the {organization} nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /LICENSES/BSD-3-Clause.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) . All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 4 | 5 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 6 | 7 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | 9 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 10 | 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 | -------------------------------------------------------------------------------- /LICENSES/Unlicense.txt: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. 4 | 5 | In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and 6 | successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | 10 | For more information, please refer to 11 | -------------------------------------------------------------------------------- /modules/cmds/pom.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 4.0.0 9 | 10 | 11 | com.illposed.osc.cmds 12 | 1.0 13 | ${project.packageName}.ConsoleEchoServer 14 | 15 | 16 | 17 | com.illposed.osc 18 | javaosc-parent 19 | 0.10-SNAPSHOT 20 | ../parent 21 | 22 | 23 | javaosc-cmds 24 | 0.10-SNAPSHOT 25 | 26 | jar 27 | 28 | JavaOSC-Commands 29 | An Open Sound Control library implementation in Java - Commands 30 | 31 | 32 | package 33 | 34 | 35 | 36 | org.apache.maven.plugins 37 | maven-jar-plugin 38 | 39 | 40 | 41 | true 42 | dependency 43 | ${project.packageName} 44 | ${project.mainClass} 45 | 46 | 47 | 48 | 49 | 50 | 53 | 54 | org.apache.maven.plugins 55 | maven-assembly-plugin 56 | 57 | 58 | jar-with-dependencies 59 | 60 | 61 | 62 | ${project.mainClass} 63 | 64 | 65 | 66 | 67 | 68 | 69 | org.codehaus.mojo 70 | exec-maven-plugin 71 | 72 | ${project.mainClass} 73 | 74 | 75 | 76 | 77 | org.apache.maven.plugins 78 | maven-checkstyle-plugin 79 | 80 | 81 | 82 | 83 | check 84 | 85 | 86 | 87 | 88 | 89 | 95 | 96 | 97 | 108 | 109 | 110 | com.github.spotbugs 111 | spotbugs-maven-plugin 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | com.illposed.osc 127 | javaosc-core 128 | 0.10-SNAPSHOT 129 | 130 | 131 | org.slf4j 132 | slf4j-simple 133 | runtime 134 | 135 | 136 | 137 | 138 | 139 | -------------------------------------------------------------------------------- /modules/cmds/src/main/java/com/illposed/osc/cmds/ConsoleEchoServer.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021-2024 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.cmds; 7 | 8 | import com.illposed.osc.EchoOSCMessageListener; 9 | import com.illposed.osc.OSCBadDataEvent; 10 | import com.illposed.osc.OSCBadDataListener; 11 | import com.illposed.osc.OSCMessageListener; 12 | import com.illposed.osc.messageselector.JavaRegexAddressMessageSelector; 13 | import com.illposed.osc.transport.OSCPortIn; 14 | import org.slf4j.Logger; 15 | import org.slf4j.LoggerFactory; 16 | import java.io.IOException; 17 | import java.net.InetAddress; 18 | import java.net.InetSocketAddress; 19 | import java.net.SocketAddress; 20 | import java.net.UnknownHostException; 21 | import java.nio.charset.StandardCharsets; 22 | 23 | /** 24 | * Runs a basic OSC server, printing all received OSC content 25 | * to stdout. 26 | * Errors and warnings are printed to stderr. 27 | * @see EchoOSCMessageListener 28 | */ 29 | public class ConsoleEchoServer extends OSCPortIn { 30 | 31 | // Public API 32 | @SuppressWarnings("WeakerAccess") 33 | public static final int DEFAULT_PORT = 7770; 34 | private static final int ARG_INDEX_ADDRESS = 0; 35 | private static final int ARG_INDEX_PORT = 1; 36 | 37 | private final Logger log; 38 | 39 | private final class PrintBadDataListener implements OSCBadDataListener { 40 | 41 | PrintBadDataListener() { 42 | // declared only for setting the access level 43 | } 44 | 45 | @Override 46 | public void badDataReceived(final OSCBadDataEvent evt) { 47 | 48 | if (log.isWarnEnabled()) { 49 | log.warn("Bad packet received while listening on " + ConsoleEchoServer.this.toString() + " ...", 50 | evt.getException()); 51 | log.warn( 52 | "### Received data (bad): ###\n{}\n###\n\n", 53 | new String(evt.getData().array(), StandardCharsets.UTF_8)); 54 | } 55 | } 56 | } 57 | 58 | // Public API 59 | @SuppressWarnings("WeakerAccess") 60 | public ConsoleEchoServer(final SocketAddress serverAddress, final Logger log) throws IOException { 61 | super(serverAddress); 62 | this.log = log; 63 | } 64 | 65 | // Public API 66 | @SuppressWarnings("WeakerAccess") 67 | public void start() { 68 | 69 | final OSCMessageListener listener = new EchoOSCMessageListener(log); 70 | // select all messages 71 | getDispatcher().addListener( 72 | new JavaRegexAddressMessageSelector(".*"), 73 | listener); 74 | // log errors to console 75 | getDispatcher().addBadDataListener(new PrintBadDataListener()); 76 | // never stop listening 77 | setResilient(true); 78 | setDaemonListener(false); 79 | startListening(); 80 | log.info("# Listening for OSC Packets via {} ...", getTransport()); 81 | } 82 | 83 | // Public API 84 | @SuppressWarnings("WeakerAccess") 85 | public static SocketAddress parseServerAddress(final Logger log, final String[] args) 86 | throws UnknownHostException 87 | { 88 | final InetAddress host; 89 | int port = DEFAULT_PORT; 90 | if (args.length > ARG_INDEX_ADDRESS) { 91 | host = InetAddress.getByName(args[ARG_INDEX_ADDRESS]); 92 | if (args.length > ARG_INDEX_PORT) { 93 | // try if we just got a port 94 | try { 95 | port = Integer.parseInt(args[ARG_INDEX_PORT]); 96 | } catch (final NumberFormatException ex) { 97 | log.error("# ERROR: Invalid port: {}", args[ARG_INDEX_PORT]); 98 | throw ex; 99 | } 100 | } 101 | } else { 102 | // this will use the wildcard address "0.0.0.0": all local addresses 103 | host = null; 104 | } 105 | return new InetSocketAddress(host, port); 106 | } 107 | 108 | public static void main(final String[] args) throws IOException { 109 | final Logger log = LoggerFactory.getLogger(ConsoleEchoServer.class); 110 | new ConsoleEchoServer(parseServerAddress(log, args), log).start(); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /modules/cmds/src/main/java/com/illposed/osc/cmds/package-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2024 Robin Vobruba 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | /** 6 | * Provides directly runnable sofwtare, using the core package. 7 | */ 8 | package com.illposed.osc.cmds; 9 | -------------------------------------------------------------------------------- /modules/core/pom.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 4.0.0 9 | 10 | 11 | com.illposed.osc 12 | 1.0 13 | ${project.packageName}.LibraryInfo 14 | 15 | 16 | 17 | com.illposed.osc 18 | javaosc-parent 19 | 0.10-SNAPSHOT 20 | ../parent 21 | 22 | 23 | javaosc-core 24 | 0.10-SNAPSHOT 25 | 26 | bundle 27 | 28 | JavaOSC 29 | An Open Sound Control library implementation in Java 30 | 31 | 32 | package 33 | 34 | 35 | 36 | org.apache.maven.plugins 37 | maven-jar-plugin 38 | 39 | 40 | 41 | ${project.packageName} 42 | ${project.mainClass} 43 | 44 | 45 | 46 | 47 | 48 | 49 | org.apache.felix 50 | maven-bundle-plugin 51 | true 52 | 53 | 54 | 55 | ${project.packageName}, 56 | ${project.packageName}.argument, 57 | ${project.packageName}.messageselector, 58 | ${project.packageName}.transport, 59 | ${project.packageName}.transport.udp 60 | ${project.packageName}.transport.tcp 61 | 62 | ${supported.osc.version} 63 | 64 | 65 | 66 | 67 | 68 | org.apache.maven.plugins 69 | maven-checkstyle-plugin 70 | 71 | 72 | 73 | 74 | check 75 | 76 | 77 | 78 | 79 | 80 | 86 | 87 | 88 | 99 | 100 | 101 | com.github.spotbugs 102 | spotbugs-maven-plugin 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | org.junit.jupiter 118 | junit-jupiter 119 | test 120 | 121 | 122 | 123 | org.slf4j 124 | slf4j-api 125 | 126 | 127 | org.slf4j 128 | slf4j-ext 129 | 130 | 131 | org.slf4j 132 | slf4j-simple 133 | test 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/BufferBytesReceiver.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc; 7 | 8 | import java.nio.ByteBuffer; 9 | 10 | /** 11 | * Implementation of a {@link BytesReceiver} using a {@code ByteBuffer} 12 | * as the internal buffer. 13 | * This is useful if we know an upper limit for the size 14 | * of the expected data in total. 15 | * It is thus an ideal candidate for synchronous data receiving, 16 | * as is the case in TCP. 17 | */ 18 | public class BufferBytesReceiver implements BytesReceiver { 19 | 20 | private final ByteBuffer buffer; 21 | 22 | public BufferBytesReceiver(final ByteBuffer buffer) { 23 | this.buffer = buffer; 24 | } 25 | 26 | @Override 27 | public BytesReceiver put(final byte data) { 28 | 29 | buffer.put(data); 30 | return this; 31 | } 32 | 33 | @Override 34 | public BytesReceiver put(final byte[] src) { 35 | 36 | buffer.put(src); 37 | return this; 38 | } 39 | 40 | @Override 41 | public BytesReceiver put(final ByteBuffer src) { 42 | 43 | buffer.put(src); 44 | return this; 45 | } 46 | 47 | @Override 48 | public BytesReceiver clear() { 49 | 50 | buffer.clear(); 51 | return this; 52 | } 53 | 54 | @Override 55 | public int position() { 56 | return buffer.position(); 57 | } 58 | 59 | // HACK try to get rid of this method 60 | public ByteBuffer getBuffer() { 61 | return buffer; 62 | } 63 | 64 | private class PlaceHolderImpl implements PlaceHolder { 65 | 66 | private final int position; 67 | private final int size; 68 | 69 | PlaceHolderImpl(final int position, final int size) { 70 | 71 | this.position = position; 72 | this.size = size; 73 | } 74 | 75 | @Override 76 | public void replace(final byte[] src) throws OSCSerializeException { 77 | 78 | if (src.length != size) { 79 | throw new OSCSerializeException(String.format( 80 | "Trying to replace placeholder of size %d with data of size %d", 81 | size, src.length)); 82 | } 83 | final int curPosition = buffer.position(); 84 | buffer.position(position); 85 | put(src); 86 | buffer.position(curPosition); 87 | } 88 | } 89 | 90 | @Override 91 | public PlaceHolder putPlaceHolder(final byte[] src) { 92 | 93 | final PlaceHolderImpl placeHolder = new PlaceHolderImpl(position(), src.length); 94 | put(src); 95 | return placeHolder; 96 | } 97 | 98 | @Override 99 | public byte[] toByteArray() { 100 | 101 | // TODO check if this flip is always required 102 | buffer.flip(); 103 | final byte[] bytes = new byte[buffer.remaining()]; 104 | buffer.get(bytes); 105 | return bytes; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/ByteArrayListBytesReceiver.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc; 7 | 8 | import java.io.IOException; 9 | import java.io.OutputStream; 10 | import java.nio.ByteBuffer; 11 | import java.util.LinkedList; 12 | import java.util.List; 13 | 14 | /** 15 | * Implementation of a {@link BytesReceiver} using a {@code List} 16 | * as the internal buffer. 17 | * This is useful if we do not now initially know the size 18 | * of the expected data in total, and at the same time want to prevent 19 | * re-allocating {@code ByteBuffer} or {@code byte[]} 20 | * whenever the buffer gets too small. 21 | * It is thus an ideal candidate for asynchronous data receiving, 22 | * as is the case in UDP. 23 | */ 24 | public class ByteArrayListBytesReceiver implements BytesReceiver { 25 | 26 | private final List buffer; 27 | private int pos; 28 | 29 | public ByteArrayListBytesReceiver() { 30 | 31 | this.buffer = new LinkedList<>(); 32 | this.pos = 0; 33 | } 34 | 35 | @Override 36 | public BytesReceiver put(final byte data) { 37 | 38 | buffer.add(new byte[] {data}); 39 | pos += 1; 40 | return this; 41 | } 42 | 43 | @Override 44 | public BytesReceiver put(final byte[] src) { 45 | 46 | buffer.add(src); 47 | pos += src.length; 48 | return this; 49 | } 50 | 51 | @Override 52 | public BytesReceiver put(final ByteBuffer src) { 53 | // HACK better get rid of this method altogether! 54 | return put(src.array()); 55 | } 56 | 57 | @Override 58 | public BytesReceiver clear() { 59 | 60 | buffer.clear(); 61 | return this; 62 | } 63 | 64 | @Override 65 | public int position() { 66 | return pos; 67 | } 68 | 69 | private static class PlaceHolderImpl implements PlaceHolder { 70 | 71 | private final byte[] part; 72 | 73 | PlaceHolderImpl(final byte[] part) { 74 | 75 | this.part = part; 76 | } 77 | 78 | @Override 79 | public void replace(final byte[] src) throws OSCSerializeException { 80 | 81 | if (src.length != part.length) { 82 | throw new OSCSerializeException(String.format( 83 | "Trying to replace placeholder of size %d with data of size %d", 84 | part.length, src.length)); 85 | } 86 | System.arraycopy(src, 0, part, 0, src.length); 87 | } 88 | } 89 | 90 | @Override 91 | public PlaceHolder putPlaceHolder(final byte[] src) { 92 | 93 | final PlaceHolderImpl placeHolder = new PlaceHolderImpl(src); 94 | put(src); 95 | return placeHolder; 96 | } 97 | 98 | @Override 99 | public byte[] toByteArray() { 100 | 101 | final byte[] bytes = new byte[pos]; 102 | int curPos = 0; 103 | for (final byte[] curPart : buffer) { 104 | System.arraycopy(curPart, 0, bytes, curPos, curPart.length); 105 | curPos += curPart.length; 106 | } 107 | return bytes; 108 | } 109 | 110 | public void writeTo(final OutputStream dest) throws IOException { 111 | 112 | for (final byte[] dataPiece : buffer) { 113 | dest.write(dataPiece); 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/EchoOSCMessageListener.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc; 7 | 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | /** 12 | * Prints out received messages to a {@link Logger}. 13 | * Messages are printed in this format: 14 | *
{@code
15 |  * address
16 |  *   type-tags
17 |  *     argument-0
18 |  *     argument-1
19 |  *     ...
20 |  *     argument-(n-1)
21 |  * new-line
22 |  * }
23 | * so for example: 24 | *
{@code
25 |  * /my/messages/address
26 |  *   iffc
27 |  *     100
28 |  *     0.3
29 |  *     99.2
30 |  *     x
31 |  *
32 |  * /my/other/messages/address
33 |  *   fsi
34 |  *     9234.63
35 |  *     hello world
36 |  *     8325
37 |  *
38 |  * }
39 | * @see ConsoleEchoServer 40 | */ 41 | public class EchoOSCMessageListener implements OSCMessageListener { 42 | 43 | private final Logger log; 44 | 45 | // Public API 46 | @SuppressWarnings("WeakerAccess") 47 | public EchoOSCMessageListener(final Logger log) { 48 | 49 | this.log = log; 50 | } 51 | 52 | // Public API 53 | @SuppressWarnings("unused") 54 | public EchoOSCMessageListener() { 55 | this(LoggerFactory.getLogger(EchoOSCMessageListener.class)); 56 | } 57 | 58 | @Override 59 | public void acceptMessage(final OSCMessageEvent event) { 60 | 61 | final OSCMessage message = event.getMessage(); 62 | log.info(message.getAddress()); 63 | log.info(" {}", message.getInfo().getArgumentTypeTags()); 64 | for (final Object arg : message.getArguments()) { 65 | log.info(" {}", arg); 66 | } 67 | log.info(""); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/MessageSelector.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2014-2017 C. Ramakrishnan / Auracle 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc; 7 | 8 | /** 9 | * Checks whether an OSC Message fulfills certain criteria. 10 | */ 11 | public interface MessageSelector { 12 | 13 | /** 14 | * Returns whether this selector requires meta-info to be present for messages 15 | * that are checked for matching. 16 | * @return {@code true} if this matcher requires meta-info 17 | */ 18 | boolean isInfoRequired(); 19 | 20 | /** 21 | * Checks whether the OSC Message in question matches this selector. 22 | * @param messageEvent the message and meta-data to be checked if it matches 23 | * @return {@code true} if this matcher selects the message in question 24 | */ 25 | boolean matches(OSCMessageEvent messageEvent); 26 | } 27 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/OSCBadDataEvent.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc; 7 | 8 | import java.nio.ByteBuffer; 9 | import java.util.EventObject; 10 | 11 | /** 12 | * Event state of reception of unrecognized/bad (supposed to be) OSC data. 13 | */ 14 | public class OSCBadDataEvent extends EventObject { 15 | 16 | private static final long serialVersionUID = 1L; 17 | 18 | private final SerializableByteBuffer data; 19 | private final OSCParseException exception; 20 | 21 | public OSCBadDataEvent(final Object source, final ByteBuffer data, final OSCParseException exception) { 22 | super(source); 23 | 24 | this.data = new SerializableByteBuffer(data.asReadOnlyBuffer()); 25 | this.exception = exception; 26 | } 27 | 28 | /** 29 | * Returns the bad/unrecognized bunch of data, 30 | * which we expected to be OSC protocol formatted. 31 | * @return the unrecognized, raw data, as received from 32 | * {@link com.illposed.osc.transport.OSCPortIn}, for example 33 | */ 34 | public ByteBuffer getData() { 35 | return data.getBuffer(); 36 | } 37 | 38 | /** 39 | * Returns the exception that was triggered this event, 40 | * indicating that the received data is not proper OSC data. 41 | * @return details about what went wrong when parsing the data 42 | */ 43 | public OSCParseException getException() { 44 | return exception; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/OSCBadDataListener.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc; 7 | 8 | /** 9 | * Receives data that could not be properly parsed as OSC packet, 10 | * be it due to the data being invalid OSC, or a bug in this library. 11 | * This is most useful for error logging or debugging. 12 | */ 13 | public interface OSCBadDataListener { 14 | 15 | /** 16 | * Process a bad/unrecognized bunch of data, 17 | * which we expected to be OSC protocol formatted. 18 | * @param evt bad OSC data event state 19 | */ 20 | void badDataReceived(OSCBadDataEvent evt); 21 | } 22 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/OSCBundle.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2003-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc; 7 | 8 | import com.illposed.osc.argument.OSCTimeTag64; 9 | import java.util.ArrayList; 10 | import java.util.Collections; 11 | import java.util.LinkedList; 12 | import java.util.List; 13 | 14 | /** 15 | * A bundle represents a collection of OSC packets 16 | * (either messages or other bundles) 17 | * and has a time-tag which can be used by a scheduler to execute 18 | * a bundle in the future, instead of immediately. 19 | * {@link OSCMessage}s are executed immediately. 20 | * 21 | * Bundles should be used if you want to send multiple messages to be executed 22 | * as soon as possible and in immediate succession to each other, 23 | * or you want to schedule one or more messages to be executed in the future. 24 | */ 25 | public class OSCBundle implements OSCPacket { 26 | 27 | private static final long serialVersionUID = 1L; 28 | 29 | private OSCTimeTag64 timestamp; 30 | private List packets; 31 | 32 | /** 33 | * Create a new empty OSCBundle with a timestamp of immediately. 34 | * You can add packets to the bundle with addPacket() 35 | */ 36 | public OSCBundle() { 37 | this(OSCTimeTag64.IMMEDIATE); 38 | } 39 | 40 | /** 41 | * Create an OSCBundle with the specified timestamp. 42 | * @param timestamp the time to execute the bundle 43 | */ 44 | public OSCBundle(final OSCTimeTag64 timestamp) { 45 | this(null, timestamp); 46 | } 47 | 48 | /** 49 | * Creates an OSCBundle made up of the given packets 50 | * with a timestamp of now. 51 | * @param packets array of OSCPackets to initialize this object with 52 | */ 53 | public OSCBundle(final List packets) { 54 | this(packets, OSCTimeTag64.IMMEDIATE); 55 | } 56 | 57 | /** 58 | * Create an OSCBundle, specifying the packets and timestamp. 59 | * @param packets the packets that make up the bundle 60 | * @param timestamp the time to execute the bundle 61 | */ 62 | public OSCBundle(final List packets, final OSCTimeTag64 timestamp) { 63 | 64 | if (null == packets) { 65 | this.packets = new LinkedList<>(); 66 | } else { 67 | this.packets = new ArrayList<>(packets); 68 | } 69 | checkNonNullTimestamp(timestamp); 70 | this.timestamp = timestamp; 71 | } 72 | 73 | private static void checkNonNullTimestamp(final OSCTimeTag64 timestamp) { 74 | 75 | if (timestamp == null) { 76 | throw new IllegalArgumentException("Bundle time-stamp may not be null; you may want to " 77 | + "use OSCTimeStamp.IMMEDIATE."); 78 | } 79 | } 80 | 81 | /** 82 | * Returns the time the bundle will execute. 83 | * @return will never be {@code null} 84 | */ 85 | public OSCTimeTag64 getTimestamp() { 86 | return timestamp; 87 | } 88 | 89 | // Public API 90 | /** 91 | * Sets the time the bundle will execute. 92 | * @param timestamp when the bundle should execute, can not be {@code null}, 93 | * but {@code OSCTimeTag64.IMMEDIATE} 94 | */ 95 | @SuppressWarnings("WeakerAccess") 96 | public void setTimestamp(final OSCTimeTag64 timestamp) { 97 | 98 | checkNonNullTimestamp(timestamp); 99 | this.timestamp = timestamp; 100 | } 101 | 102 | /** 103 | * Add a packet to the list of packets in this bundle. 104 | * @param packet OSCMessage or OSCBundle 105 | */ 106 | public void addPacket(final OSCPacket packet) { 107 | packets.add(packet); 108 | } 109 | 110 | /** 111 | * Get the packets contained in this bundle. 112 | * @return the packets contained in this bundle. 113 | */ 114 | public List getPackets() { 115 | return Collections.unmodifiableList(packets); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/OSCMessage.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2003-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc; 7 | 8 | import java.util.Collections; 9 | import java.util.List; 10 | import java.util.regex.Pattern; 11 | 12 | /** 13 | * An simple (non-bundle) OSC message. 14 | * 15 | * An OSC Message is made up of 16 | * an Address Pattern (the receiver of the message) 17 | * and Arguments (the content of the message). 18 | */ 19 | public class OSCMessage implements OSCPacket { 20 | 21 | private static final long serialVersionUID = 1L; 22 | 23 | /** 24 | * Java regular expression pattern matching a single invalid character. 25 | * The invalid characters are: 26 | * ' ', '#', '*', ',', '?', '[', ']', '{', '}' 27 | */ 28 | private static final Pattern ILLEGAL_ADDRESS_CHAR 29 | = Pattern.compile("[ #*,?\\[\\]{}]"); 30 | 31 | private final String address; 32 | private final List arguments; 33 | private OSCMessageInfo info; 34 | 35 | /** 36 | * Creates an OSCMessage with an address already initialized. 37 | * @param address the recipient of this OSC message 38 | */ 39 | public OSCMessage(final String address) { 40 | this(address, Collections.emptyList()); 41 | } 42 | 43 | /** 44 | * Creates an OSCMessage with an address 45 | * and arguments already initialized. 46 | * @param address the recipient of this OSC message 47 | * @param arguments the data sent to the receiver 48 | */ 49 | public OSCMessage(final String address, final List arguments) { 50 | this(address, arguments, null); 51 | } 52 | 53 | /** 54 | * Creates an OSCMessage with an address 55 | * and arguments already initialized. 56 | * @param address the recipient of this OSC message 57 | * @param arguments the data sent to the receiver 58 | * @param info meta-info about the message, or {@code null}, if not yet available 59 | */ 60 | public OSCMessage(final String address, final List arguments, final OSCMessageInfo info) { 61 | this(address, arguments, info, true); 62 | } 63 | 64 | /** 65 | * Creates an OSCMessage with an address 66 | * and arguments already initialized, 67 | * optionally skipping address verification. 68 | * NOTE This only makes sense for testing purposes! 69 | * Under normal circumstances one should never disable address checking. 70 | * @param address the recipient of this OSC message 71 | * @param arguments the data sent to the receiver 72 | * @param info meta-info about the message, or {@code null}, if not yet available 73 | * @param checkAddress whether to check the address for validity; CAUTION! 74 | */ 75 | OSCMessage(final String address, final List arguments, final OSCMessageInfo info, final boolean checkAddress) { 76 | 77 | if (checkAddress) { 78 | checkAddress(address); 79 | } 80 | this.address = address; 81 | this.arguments = Collections.unmodifiableList(arguments); 82 | this.info = info; 83 | } 84 | 85 | /** 86 | * The receiver of this message. 87 | * @return the receiver of this OSC Message 88 | */ 89 | public String getAddress() { 90 | return address; 91 | } 92 | 93 | /** 94 | * The arguments of this message. 95 | * @return the arguments to this message 96 | */ 97 | public List getArguments() { 98 | return arguments; 99 | } 100 | 101 | /** 102 | * Returns meta-info about this message. 103 | * @return the meta-info, or {@code null}, if none are set yet. 104 | */ 105 | public OSCMessageInfo getInfo() { 106 | return info; 107 | } 108 | 109 | // Public API 110 | @SuppressWarnings("WeakerAccess") 111 | public boolean isInfoSet() { 112 | return (info != null); 113 | } 114 | 115 | // Public API 116 | /** 117 | * Sets meta-info about this message. 118 | * This method may only be called if the meta-info has not yet been set. 119 | * @param info the meta-info for this message, may not be {@code null} 120 | */ 121 | @SuppressWarnings("WeakerAccess") 122 | public void setInfo(final OSCMessageInfo info) { 123 | 124 | if (this.info != null) { 125 | throw new IllegalStateException("The meta-info of a message may only be set once"); 126 | } 127 | this.info = info; 128 | } 129 | 130 | /** 131 | * Throws an exception if the given address is invalid. 132 | * @param address to be checked for validity 133 | */ 134 | private static void checkAddress(final String address) { 135 | if (!isValidAddress(address)) { 136 | throw new IllegalArgumentException("Not a valid OSC address: " + address); 137 | } 138 | } 139 | 140 | // Public API 141 | /** 142 | * Checks whether a given string is a valid OSC Address Pattern. 143 | * @param address to be checked for validity 144 | * @return true if the supplied string constitutes a valid OSC address 145 | */ 146 | @SuppressWarnings("WeakerAccess") 147 | public static boolean isValidAddress(final String address) { 148 | return (address != null) 149 | && !address.isEmpty() 150 | && ( 151 | address.equals("#reply") 152 | || ( 153 | (address.charAt(0) == '/') 154 | && !address.contains("//") 155 | && !ILLEGAL_ADDRESS_CHAR.matcher(address).find() 156 | )); 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/OSCMessageEvent.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc; 7 | 8 | import com.illposed.osc.argument.OSCTimeTag64; 9 | 10 | import java.util.EventObject; 11 | 12 | /** 13 | * Event state of reception of an OSC Message. 14 | */ 15 | public class OSCMessageEvent extends EventObject { 16 | 17 | private static final long serialVersionUID = 1L; 18 | 19 | private final OSCTimeTag64 time; 20 | private final OSCMessage message; 21 | 22 | /** 23 | * Creates a new message received event. 24 | * @param source The object on which the Event initially occurred. 25 | * @param time when the message is to be processed. 26 | * This should be the time the event is delivered, or {@code OSCTimeTag64.IMMEDIATE}. 27 | * It may never be {@code null}. 28 | * @param message the message that was received/is to be processed 29 | */ 30 | public OSCMessageEvent(final Object source, final OSCTimeTag64 time, final OSCMessage message) { 31 | super(source); 32 | 33 | this.time = time; 34 | this.message = message; 35 | } 36 | 37 | /** 38 | * Returns the time for message processing. 39 | * @return the time the message is to be processed. 40 | * This should be the time the event is delivered, or {@code OSCTimeTag64.IMMEDIATE}. 41 | * It may never be {@code null}. 42 | */ 43 | public OSCTimeTag64 getTime() { 44 | return time; 45 | } 46 | 47 | /** 48 | * Returns the main content of this event. 49 | * @return the received message 50 | */ 51 | public OSCMessage getMessage() { 52 | return message; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/OSCMessageInfo.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc; 7 | 8 | import java.io.Serializable; 9 | 10 | /** 11 | * Holds (meta-)info about a message. 12 | * This might be used by some implementations of {@link MessageSelector}, for example. 13 | */ 14 | public class OSCMessageInfo implements Serializable { 15 | 16 | private static final long serialVersionUID = 1L; 17 | 18 | private final CharSequence argumentTypeTags; 19 | 20 | // Public API 21 | /** 22 | * @param argumentTypeTags the Arguments Type Tags string, for example "iiscdi[fff]h" 23 | */ 24 | @SuppressWarnings({"WeakerAccess", "SpellCheckingInspection"}) 25 | public OSCMessageInfo(final CharSequence argumentTypeTags) { 26 | this.argumentTypeTags = argumentTypeTags; 27 | } 28 | 29 | /** 30 | * Returns the Arguments Type Tags string. 31 | * @return for example "iiscdi[fff]h" 32 | */ 33 | @SuppressWarnings("SpellCheckingInspection") 34 | public CharSequence getArgumentTypeTags() { 35 | return argumentTypeTags; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/OSCMessageListener.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2003-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc; 7 | 8 | /** 9 | * Allows to listen to incoming messages. 10 | * In OSC speak, this is a Method, and it listens to Messages. 11 | */ 12 | public interface OSCMessageListener { 13 | 14 | /** 15 | * Process a matching, incoming OSC Message. 16 | * @param event the message received event to be processed 17 | */ 18 | void acceptMessage(OSCMessageEvent event); 19 | } 20 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/OSCPacket.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2003-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc; 7 | 8 | import java.io.Serializable; 9 | 10 | /** 11 | * An abstract superclass for messages and bundles. 12 | * 13 | * The actual packets are: 14 | *
    15 | *
  • {@link OSCMessage}: simple OSC messages 16 | *
  • {@link OSCBundle}: OSC messages with timestamps 17 | * and/or made up of multiple messages 18 | *
19 | */ 20 | public interface OSCPacket extends Serializable { 21 | 22 | } 23 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/OSCPacketEvent.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2019 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc; 7 | 8 | import java.util.EventObject; 9 | 10 | /** 11 | * Event state of reception of an OSC packet. 12 | */ 13 | public class OSCPacketEvent extends EventObject { 14 | 15 | private static final long serialVersionUID = 1L; 16 | 17 | private final OSCPacket packet; 18 | 19 | /** 20 | * Creates a new packet received event. 21 | * @param source the source of the packet 22 | * @param packet the packet to process 23 | */ 24 | public OSCPacketEvent(final Object source, final OSCPacket packet) { 25 | super(source); 26 | this.packet = packet; 27 | } 28 | 29 | /** 30 | * Returns the main content of this event. 31 | * @return the received packet 32 | */ 33 | public OSCPacket getPacket() { 34 | return packet; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/OSCPacketListener.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2018-2019 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc; 7 | 8 | /** 9 | * A listener that handles packets. A packet can be either a bundle or a 10 | * message. 11 | * 12 | * This is useful if you need to handle the messages in bundles differently than 13 | * individual messages. 14 | * 15 | * If you don't have this constraint, you might prefer to use OSCMessageListener 16 | * instead. 17 | */ 18 | public interface OSCPacketListener { 19 | 20 | /** 21 | * Process an incoming packet. 22 | * @param event contains the packet content and meta-data 23 | */ 24 | void handlePacket(OSCPacketEvent event); 25 | 26 | /** 27 | * Process a bad data event. 28 | * @param event the bad data event to handle 29 | */ 30 | void handleBadData(OSCBadDataEvent event); 31 | } 32 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/OSCParseException.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc; 7 | 8 | import java.nio.ByteBuffer; 9 | 10 | public class OSCParseException extends Exception { 11 | private final ByteBuffer data; 12 | 13 | public ByteBuffer getData() { 14 | return data; 15 | } 16 | 17 | public OSCParseException(final String message, final ByteBuffer data) { 18 | super(message); 19 | this.data = data; 20 | } 21 | 22 | public OSCParseException(final Throwable cause, final ByteBuffer data) { 23 | super(cause); 24 | this.data = data; 25 | } 26 | 27 | public OSCParseException( 28 | final String message, 29 | final Throwable cause, 30 | final ByteBuffer data) 31 | { 32 | super(message, cause); 33 | this.data = data; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/OSCSerializeException.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc; 7 | 8 | public class OSCSerializeException extends Exception { 9 | 10 | public OSCSerializeException() { 11 | super(); 12 | } 13 | 14 | public OSCSerializeException(final String message) { 15 | super(message); 16 | } 17 | 18 | public OSCSerializeException(final String message, final Throwable cause) { 19 | super(message, cause); 20 | } 21 | 22 | public OSCSerializeException(final Throwable cause) { 23 | super(cause); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/SerializableByteBuffer.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc; 7 | 8 | import java.io.IOException; 9 | import java.io.ObjectInputStream; 10 | import java.io.ObjectOutputStream; 11 | import java.io.Serializable; 12 | import java.nio.Buffer; 13 | import java.nio.ByteBuffer; 14 | import java.nio.ByteOrder; 15 | 16 | // Public API 17 | /** 18 | * Allows to serialize and deserialize a {@link ByteBuffer}. 19 | */ 20 | @SuppressWarnings("WeakerAccess") 21 | public class SerializableByteBuffer implements Serializable { 22 | 23 | private static final long serialVersionUID = 1L; 24 | 25 | // mark as transient so this is not serialized by default 26 | private transient ByteBuffer buffer; 27 | 28 | // Public API 29 | @SuppressWarnings("WeakerAccess") 30 | public SerializableByteBuffer(final ByteBuffer buffer) { 31 | this.buffer = buffer; 32 | } 33 | 34 | // Public API 35 | @SuppressWarnings("WeakerAccess") 36 | public ByteBuffer getBuffer() { 37 | return buffer; 38 | } 39 | 40 | private void writeObject(final ObjectOutputStream serializer) throws IOException { 41 | 42 | // write default properties 43 | serializer.defaultWriteObject(); 44 | // write buffer meta info and data 45 | serializer.writeInt(buffer.capacity()); 46 | serializer.writeInt(buffer.position()); 47 | serializer.writeInt(buffer.limit()); 48 | // sets position to mark 49 | buffer.reset(); 50 | // store the mark 51 | serializer.writeInt(buffer.position()); 52 | serializer.writeObject(buffer.order().toString()); 53 | if (buffer.hasArray()) { 54 | serializer.write(buffer.array()); 55 | } else { 56 | final byte[] bufferArray = new byte[buffer.capacity()]; 57 | buffer.rewind(); 58 | ((Buffer)buffer).limit(buffer.capacity()); 59 | buffer.get(bufferArray); 60 | serializer.write(buffer.array()); 61 | } 62 | 63 | } 64 | 65 | private void readObject(final ObjectInputStream deserializer) 66 | throws IOException, ClassNotFoundException 67 | { 68 | //read default properties 69 | deserializer.defaultReadObject(); 70 | 71 | //read buffer data and wrap with ByteBuffer 72 | final int capacity = deserializer.readInt(); 73 | final int position = deserializer.readInt(); 74 | final int limit = deserializer.readInt(); 75 | final int mark = deserializer.readInt(); 76 | final String orderName = (String) deserializer.readObject(); 77 | final ByteOrder order 78 | = orderName.equals(ByteOrder.LITTLE_ENDIAN.toString()) 79 | ? ByteOrder.LITTLE_ENDIAN 80 | : ByteOrder.BIG_ENDIAN; 81 | final byte[] bufferArray = new byte[capacity]; 82 | final int bufferContentSize = deserializer.read(bufferArray); 83 | if (bufferContentSize != capacity) { 84 | throw new IllegalStateException( 85 | "Actual content size does not match the indicated buffer size"); 86 | } 87 | buffer = ByteBuffer.wrap(bufferArray, 0, capacity); 88 | buffer.order(order); 89 | ((Buffer)buffer).position(mark); 90 | buffer.mark(); 91 | ((Buffer)buffer).limit(limit); 92 | ((Buffer)buffer).position(position); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/argument/ArgumentHandler.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.argument; 7 | 8 | import com.illposed.osc.BytesReceiver; 9 | import com.illposed.osc.OSCParseException; 10 | import com.illposed.osc.OSCSerializeException; 11 | import java.nio.ByteBuffer; 12 | import java.util.Map; 13 | 14 | /** 15 | * Handles all aspects regarding a single OSC Argument type. 16 | * This is used to {@link #parse} (convert from OSC byte representation to Java objects), 17 | * and to {@link #serialize} (convert from Java objects to OSC byte representation). 18 | * @param Java type of the OSC argument this handler deals with 19 | */ 20 | public interface ArgumentHandler extends Cloneable { 21 | 22 | /** 23 | * Returns the default identifier character of this type of OSC Argument, 24 | * which is the character used in the types string of an OSC Message. 25 | * @return default type identifier, as specified in the OSC specification, 26 | * if this type is part of it 27 | */ 28 | char getDefaultIdentifier(); 29 | 30 | /** 31 | * Returns the Java class this OSC type converts to/from. 32 | * Objects of this class are serialized to this OSC Argument type, 33 | * and this type is parsed into Java Objects of this class. 34 | * @return the Java class this OSC type converts to/from. 35 | */ 36 | Class getJavaClass(); 37 | 38 | /** 39 | * Used to configure special properties that might further specify 40 | * parsing and/or serializing objects of this type. 41 | * Most default OSC Argument are "static" in this regard, 42 | * as they have a single, not configurable way of operating. 43 | * But the String type for example, allows to specify the character-set. 44 | * This method is usually called once for all types before the parsing/serialization starts. 45 | * Note that this set of properties is parser/serializer global, 46 | * meaning that there is a single set per parser/serializer 47 | * and all the associated handlers, 48 | * which means one has to make sure to not use a single property key 49 | * in multiple places (i.e. two different handlers) 50 | * with different meaning or syntax. 51 | * @param properties a set of properties that usually gets passed over to all types, 52 | * for example: properties.put(StringArgumentHandler.PROP_NAME_CHARSET, Charset.defaultCharset()); 53 | */ 54 | void setProperties(Map properties); 55 | 56 | /** 57 | * Indicates whether this type is only a marker type, 58 | * meaning all of its information is incorporated in the type identifier, 59 | * and that it comes with no additional data. 60 | * This means that the {@link #parse} and {@link #serialize} methods never throw exceptions, 61 | * and that {@link #parse} always returns the same value, even parse(null), 62 | * and that {@link #serialize} is basically a no-op. 63 | * @return true if this is only a marker type, 64 | * false if it comes with additional data 65 | */ 66 | boolean isMarkerOnly(); 67 | 68 | ArgumentHandler clone() throws CloneNotSupportedException; 69 | 70 | /** 71 | * Converts from the OSC byte representation to a Java object. 72 | * @param input contains the OSC byte representation of one instance of this type. 73 | * The data for this types object starts at the current position. 74 | * Where the end is, depends on the specific type. 75 | * After the invocation of this method, the current position should point at 76 | * the last byte of this types object + 1. 77 | * @return the parsed Java object 78 | * @throws OSCParseException if anything went wrong while parsing, 79 | * for example invalid or incomplete data in the input 80 | */ 81 | T parse(ByteBuffer input) throws OSCParseException; 82 | 83 | /** 84 | * Converts from a Java objects to the OSC byte representation. 85 | * @param output where the OSC byte representation of value has to be written to 86 | * @param value the Java value to be serialized into its OSC byte representation 87 | * @throws OSCSerializeException if anything went wrong while serializing, 88 | * for example an invalid value was given 89 | */ 90 | void serialize(BytesReceiver output, T value) throws OSCSerializeException; 91 | } 92 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/argument/OSCImpulse.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2014-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.argument; 7 | 8 | import java.io.Serializable; 9 | 10 | /** 11 | * An OSC 1.0 optional, and OSC 1.1 required argument type. 12 | * Impulse aka "bang", is used for event triggers. 13 | * No bytes are allocated in the argument data. 14 | * This type was named "Infinitum" in OSC 1.0. 15 | * Use like this: 16 | *
{@code
17 |  * OSCMessage msg = new OSCMessage("/my/address");
18 |  * msg.arguments.add(OSCImpulse.INSTANCE);
19 |  * }
20 | */ 21 | public final class OSCImpulse implements Serializable { 22 | 23 | public static final OSCImpulse INSTANCE = new OSCImpulse(); 24 | 25 | private static final long serialVersionUID = 1L; 26 | 27 | private OSCImpulse() {} 28 | 29 | @Override 30 | public String toString() { 31 | return "I"; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/argument/OSCMidiMessage.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.argument; 7 | 8 | import java.io.Serializable; 9 | 10 | /** 11 | * This represents an OSC compliant MIDI message. 12 | * From the 1.0 specification: Bytes from MSB to LSB are: port id, status byte, data1, data2 13 | */ 14 | public class OSCMidiMessage implements Cloneable, Serializable, Comparable { 15 | 16 | public static final int NUM_CONTENT_BYTES = 4; 17 | private static final long serialVersionUID = 1L; 18 | private final byte portId; 19 | private final byte status; 20 | private final byte data1; 21 | private final byte data2; 22 | 23 | // Public API 24 | @SuppressWarnings("WeakerAccess") 25 | public OSCMidiMessage(final byte portId, final byte status, final byte data1, final byte data2) { 26 | 27 | this.portId = portId; 28 | this.status = status; 29 | this.data1 = data1; 30 | this.data2 = data2; 31 | } 32 | 33 | public byte[] toContentArray() { 34 | return new byte[] {getPortId(), getStatus(), getData1(), getData2()}; 35 | } 36 | 37 | // Public API 38 | @SuppressWarnings("WeakerAccess") 39 | public byte getPortId() { 40 | return portId; 41 | } 42 | 43 | // Public API 44 | @SuppressWarnings("WeakerAccess") 45 | public byte getStatus() { 46 | return status; 47 | } 48 | 49 | // Public API 50 | @SuppressWarnings("WeakerAccess") 51 | public byte getData1() { 52 | return data1; 53 | } 54 | 55 | // Public API 56 | @SuppressWarnings("WeakerAccess") 57 | public byte getData2() { 58 | return data2; 59 | } 60 | 61 | @Override 62 | public boolean equals(final Object other) { 63 | 64 | boolean equal = false; 65 | if (other instanceof OSCMidiMessage) { 66 | final OSCMidiMessage otherMidiMsg = (OSCMidiMessage) other; 67 | if ( 68 | (this.portId == otherMidiMsg.portId) 69 | && (this.status == otherMidiMsg.status) 70 | && (this.data1 == otherMidiMsg.data1) 71 | && (this.data2 == otherMidiMsg.data2)) 72 | { 73 | equal = true; 74 | } 75 | } 76 | 77 | return equal; 78 | } 79 | 80 | @Override 81 | public int hashCode() { 82 | int hash = 7; 83 | hash = (97 * hash) + this.portId; 84 | hash = (97 * hash) + this.status; 85 | hash = (97 * hash) + this.data1; 86 | hash = (97 * hash) + this.data2; 87 | return hash; 88 | } 89 | 90 | @Override 91 | public int compareTo(final OSCMidiMessage other) { 92 | return Integer.compare(hashCode(), other.hashCode()); 93 | } 94 | 95 | @Override 96 | public OSCMidiMessage clone() throws CloneNotSupportedException { 97 | return (OSCMidiMessage) super.clone(); 98 | } 99 | 100 | public static OSCMidiMessage valueOf(final byte[] content) { 101 | 102 | if (content.length != NUM_CONTENT_BYTES) { 103 | throw new IllegalArgumentException("The content has to be exactly " + NUM_CONTENT_BYTES 104 | + " bytes"); 105 | } 106 | int contentByteIndex = 0; 107 | return new OSCMidiMessage( 108 | content[contentByteIndex++], 109 | content[contentByteIndex++], 110 | content[contentByteIndex++], 111 | content[contentByteIndex]); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/argument/OSCSymbol.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.argument; 7 | 8 | import java.io.Serializable; 9 | 10 | /** 11 | * Represents an OSC compliant symbol. 12 | * Technically, this is not different from a {@code String}, but some systems may differentiate 13 | * between "strings" and "symbols". 14 | */ 15 | public class OSCSymbol implements Cloneable, Serializable, Comparable { 16 | 17 | private static final long serialVersionUID = 1L; 18 | 19 | private final String value; 20 | 21 | // Public API 22 | @SuppressWarnings("WeakerAccess") 23 | public OSCSymbol(final String value) { 24 | this.value = value; 25 | } 26 | 27 | @Override 28 | public boolean equals(final Object other) { 29 | 30 | return (other instanceof OSCSymbol) 31 | && toString().equals(other.toString()); 32 | } 33 | 34 | @Override 35 | public int hashCode() { 36 | int hash = 7; 37 | hash = (37 * hash) + ((this.value == null) ? 0 : this.value.hashCode()); 38 | return hash; 39 | } 40 | 41 | @Override 42 | public int compareTo(final OSCSymbol other) { 43 | return toString().compareTo(other.toString()); 44 | } 45 | 46 | @Override 47 | public OSCSymbol clone() throws CloneNotSupportedException { 48 | return (OSCSymbol) super.clone(); 49 | } 50 | 51 | @Override 52 | public String toString() { 53 | return value; 54 | } 55 | 56 | public static OSCSymbol valueOf(final String str) { 57 | return new OSCSymbol(str); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/argument/OSCUnsigned.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.argument; 7 | 8 | import java.io.Serializable; 9 | 10 | /** 11 | * This class represents an OSC 32bit unsigned integer. 12 | * We use this class, because Java has no matching primitive data-type, 13 | * and long is already used for signed 64bit integers. 14 | */ 15 | public final class OSCUnsigned implements Cloneable, Serializable, Comparable { 16 | 17 | // Public API 18 | /** 19 | * The number of bytes used to represent an unsigned integer value in binary form. 20 | */ 21 | @SuppressWarnings("WeakerAccess") 22 | public static final int BYTES = 4; 23 | // Public API 24 | /** 25 | * A constant holding the minimum value a 32bit unsigned integer can have, 0. 26 | */ 27 | @SuppressWarnings("WeakerAccess") 28 | public static final OSCUnsigned MIN_VALUE = new OSCUnsigned(0x0L); 29 | // Public API 30 | /** 31 | * A constant holding the maximum value a 32bit unsigned integer can have, 2^{32}. 32 | */ 33 | @SuppressWarnings("WeakerAccess") 34 | public static final OSCUnsigned MAX_VALUE = new OSCUnsigned(0xFFFFFFFFL); 35 | 36 | private static final long serialVersionUID = 1L; 37 | 38 | private final long value; 39 | 40 | private OSCUnsigned(final long value) { 41 | this.value = value; 42 | } 43 | 44 | @Override 45 | public boolean equals(final Object other) { 46 | 47 | return (other instanceof OSCUnsigned) 48 | && (toLong() == ((OSCUnsigned) other).toLong()); 49 | } 50 | 51 | @Override 52 | public int hashCode() { 53 | int hash = 5; 54 | hash = (89 * hash) + (int) (this.value ^ (this.value >>> 32)); 55 | return hash; 56 | } 57 | 58 | @Override 59 | public int compareTo(final OSCUnsigned other) { 60 | return (int) (toLong() - other.toLong()); 61 | } 62 | 63 | @Override 64 | public OSCUnsigned clone() throws CloneNotSupportedException { 65 | return (OSCUnsigned) super.clone(); 66 | } 67 | 68 | /** 69 | * Returns the 32bit unsigned value in form of a long. 70 | * @return contains the value in the lower/least significant 32 bits; always positive 71 | */ 72 | public long toLong() { 73 | return value; 74 | } 75 | 76 | @Override 77 | public String toString() { 78 | return String.valueOf(value); 79 | } 80 | 81 | public static OSCUnsigned valueOf(final byte[] bytes) { 82 | 83 | if (bytes.length != BYTES) { 84 | throw new IllegalArgumentException("We need exactly 4 bytes"); 85 | } 86 | final long value 87 | = (((long) bytes[0] & 0xFF) << (3 * Byte.SIZE)) 88 | | (((long) bytes[1] & 0xFF) << (2 * Byte.SIZE)) 89 | | (((long) bytes[2] & 0xFF) << (Byte.SIZE)) 90 | | ((long) bytes[3] & 0xFF); 91 | return valueOf(value); 92 | } 93 | 94 | public static OSCUnsigned valueOf(final long value) { 95 | 96 | if ((value < MIN_VALUE.value) || (value > MAX_VALUE.value)) { 97 | throw new IllegalArgumentException( 98 | "Value " + value + " lies not within 32bit unsigned integer range (" 99 | + MIN_VALUE.value + " - " + MAX_VALUE.value + ")."); 100 | } 101 | return new OSCUnsigned(value); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/argument/handler/Activator.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.argument.handler; 7 | 8 | import com.illposed.osc.LibraryInfo; 9 | import com.illposed.osc.argument.ArgumentHandler; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | import java.lang.reflect.Field; 14 | import java.util.ArrayList; 15 | import java.util.Collections; 16 | import java.util.HashMap; 17 | import java.util.List; 18 | import java.util.Map; 19 | 20 | /** 21 | * Allows to easily register and unregister all types in this package. 22 | */ 23 | public final class Activator { 24 | 25 | private static final Logger LOG = LoggerFactory.getLogger(Activator.class); 26 | 27 | private static final List TYPES_STATIC_COMMON; 28 | static { 29 | final ArrayList types = new ArrayList<>(); 30 | types.add(BlobArgumentHandler.INSTANCE); 31 | types.add(BooleanFalseArgumentHandler.INSTANCE); 32 | types.add(BooleanTrueArgumentHandler.INSTANCE); 33 | types.add(CharArgumentHandler.INSTANCE); 34 | types.add(ColorArgumentHandler.INSTANCE); 35 | types.add(DoubleArgumentHandler.INSTANCE); 36 | types.add(FloatArgumentHandler.INSTANCE); 37 | types.add(ImpulseArgumentHandler.INSTANCE); 38 | types.add(IntegerArgumentHandler.INSTANCE); 39 | types.add(LongArgumentHandler.INSTANCE); 40 | types.add(MidiMessageArgumentHandler.INSTANCE); 41 | types.add(NullArgumentHandler.INSTANCE); 42 | types.add(TimeTag64ArgumentHandler.INSTANCE); 43 | types.add(UnsignedIntegerArgumentHandler.INSTANCE); 44 | types.trimToSize(); 45 | TYPES_STATIC_COMMON = Collections.unmodifiableList(types); 46 | } 47 | 48 | private Activator() {} 49 | 50 | public static Map createParserTypes() { 51 | 52 | final Map parserTypes 53 | = new HashMap<>(TYPES_STATIC_COMMON.size() + 1); 54 | for (final ArgumentHandler type : TYPES_STATIC_COMMON) { 55 | parserTypes.put(type.getDefaultIdentifier(), type); 56 | } 57 | 58 | final StringArgumentHandler stringArgumentHandler = new StringArgumentHandler(); 59 | parserTypes.put(stringArgumentHandler.getDefaultIdentifier(), stringArgumentHandler); 60 | 61 | final SymbolArgumentHandler symbolArgumentHandler = new SymbolArgumentHandler(); 62 | parserTypes.put(symbolArgumentHandler.getDefaultIdentifier(), symbolArgumentHandler); 63 | 64 | // NOTE We do not register ByteArrayBlobArgumentHandler (byte[]) here, 65 | // because type 'b' already converts to byteArray. 66 | 67 | // NOTE We do not register DateTimeStampArgumentHandler (Date) here, 68 | // because type 't' already converts to OSCTimeTag64. 69 | 70 | return parserTypes; 71 | } 72 | 73 | public static List createSerializerTypes() { 74 | 75 | final List serializerTypes 76 | = new ArrayList<>(TYPES_STATIC_COMMON.size() + 2); 77 | serializerTypes.addAll(TYPES_STATIC_COMMON); 78 | 79 | final StringArgumentHandler stringArgumentHandler = new StringArgumentHandler(); 80 | serializerTypes.add(stringArgumentHandler); 81 | 82 | final SymbolArgumentHandler symbolArgumentHandler = new SymbolArgumentHandler(); 83 | serializerTypes.add(symbolArgumentHandler); 84 | 85 | // NOTE As not all JRE's support AWT (for example headless ones and Android)), 86 | // we extracted `AwtColorArgumentHandler` into a separate maven-artifact 87 | // under the same groupId, with artifactId `java-se-addons`. 88 | // We try to load it through reflection here, 89 | // which will only succeed, if that class is in the class-path. 90 | if (LibraryInfo.isAwtColorAvailable()) { 91 | try { 92 | final String awtColorArgHClsName = ColorArgumentHandler.class.getPackage().getName() + ".javase.AwtColorArgumentHandler"; 93 | final Class awtColorArgumentHandler = Activator.class.getClassLoader().loadClass(awtColorArgHClsName); 94 | final Field instance = awtColorArgumentHandler.getDeclaredField("INSTANCE"); 95 | instance.setAccessible(true); 96 | serializerTypes.add((ArgumentHandler) instance.get(null)); 97 | } catch (final ClassNotFoundException ex) { 98 | LOG.debug("Not supporting AWT color serialization; You may want to add the com.illposed.osc:javaosc-java-se-addons artifact", ex); 99 | } catch (final NoSuchFieldException | SecurityException | IllegalAccessException ex) { 100 | LOG.error("Failed to add AWT Color serializer", ex); 101 | } 102 | } 103 | 104 | // NOTE We add this for legacy support, though it is recommended 105 | // to use ByteBuffer over byte[], as it may be handled more efficiently by some code. 106 | final ArgumentHandler byteArrayBlobArgumentHandler = ByteArrayBlobArgumentHandler.INSTANCE; 107 | serializerTypes.add(byteArrayBlobArgumentHandler); 108 | 109 | // NOTE We add this for legacy support, though it is recommended 110 | // to use OSCTimeTag64 over Date, to not loose precision and range during conversions. 111 | final ArgumentHandler dateArgumentHandler = DateTimeStampArgumentHandler.INSTANCE; 112 | serializerTypes.add(dateArgumentHandler); 113 | 114 | return serializerTypes; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/argument/handler/BlobArgumentHandler.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.argument.handler; 7 | 8 | import com.illposed.osc.BytesReceiver; 9 | import com.illposed.osc.OSCParseException; 10 | import com.illposed.osc.OSCSerializeException; 11 | import com.illposed.osc.OSCSerializer; 12 | import com.illposed.osc.argument.ArgumentHandler; 13 | import java.nio.Buffer; 14 | import java.nio.ByteBuffer; 15 | import java.util.Map; 16 | 17 | /** 18 | * Parses and serializes an OSC binary-blob type. 19 | */ 20 | public class BlobArgumentHandler implements ArgumentHandler, Cloneable { 21 | 22 | public static final ArgumentHandler INSTANCE = new BlobArgumentHandler(); 23 | 24 | /** Allow overriding, but somewhat enforce the ugly singleton. */ 25 | protected BlobArgumentHandler() { 26 | // declared only for setting the access level 27 | } 28 | 29 | @Override 30 | public char getDefaultIdentifier() { 31 | return 'b'; 32 | } 33 | 34 | @Override 35 | public Class getJavaClass() { 36 | return ByteBuffer.class; 37 | } 38 | 39 | @Override 40 | public void setProperties(final Map properties) { 41 | // we make no use of any properties 42 | } 43 | 44 | @Override 45 | public boolean isMarkerOnly() { 46 | return false; 47 | } 48 | 49 | @Override 50 | @SuppressWarnings("unchecked") 51 | public BlobArgumentHandler clone() throws CloneNotSupportedException { 52 | return (BlobArgumentHandler) super.clone(); 53 | } 54 | 55 | @Override 56 | public ByteBuffer parse(final ByteBuffer input) throws OSCParseException { 57 | final int blobLen = IntegerArgumentHandler.INSTANCE.parse(input); 58 | final int previousLimit = input.limit(); 59 | ((Buffer)input).limit(input.position() + blobLen); 60 | final ByteBuffer value = input.slice(); 61 | ((Buffer)input).limit(previousLimit); 62 | return value; 63 | } 64 | 65 | @Override 66 | public void serialize(final BytesReceiver output, final ByteBuffer value) 67 | throws OSCSerializeException 68 | { 69 | final int numBytes = value.remaining(); 70 | IntegerArgumentHandler.INSTANCE.serialize(output, numBytes); 71 | output.put(value); 72 | OSCSerializer.align(output); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/argument/handler/BooleanFalseArgumentHandler.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.argument.handler; 7 | 8 | import com.illposed.osc.BytesReceiver; 9 | import com.illposed.osc.argument.ArgumentHandler; 10 | import java.nio.ByteBuffer; 11 | import java.util.Map; 12 | 13 | /** 14 | * Parses and serializes an OSC boolean FALSE type. 15 | */ 16 | public class BooleanFalseArgumentHandler implements ArgumentHandler, Cloneable { 17 | 18 | public static final ArgumentHandler INSTANCE = new BooleanFalseArgumentHandler(); 19 | 20 | // Public API 21 | /** Allow overriding, but somewhat enforce the ugly singleton. */ 22 | @SuppressWarnings("WeakerAccess") 23 | protected BooleanFalseArgumentHandler() { 24 | // declared only for setting the access level 25 | } 26 | 27 | @Override 28 | public char getDefaultIdentifier() { 29 | return 'F'; 30 | } 31 | 32 | @Override 33 | public Class getJavaClass() { 34 | return Boolean.class; 35 | } 36 | 37 | @Override 38 | public void setProperties(final Map properties) { 39 | // we make no use of any properties 40 | } 41 | 42 | @Override 43 | public boolean isMarkerOnly() { 44 | return true; 45 | } 46 | 47 | @Override 48 | @SuppressWarnings("unchecked") 49 | public BooleanFalseArgumentHandler clone() throws CloneNotSupportedException { 50 | return (BooleanFalseArgumentHandler) super.clone(); 51 | } 52 | 53 | @Override 54 | public Boolean parse(final ByteBuffer input) { 55 | return Boolean.FALSE; 56 | } 57 | 58 | @Override 59 | public void serialize(final BytesReceiver output, final Boolean value) { 60 | 61 | // if (!value.equals(Boolean.FALSE)) { 62 | // throw new OSCSerializeException(); 63 | // } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/argument/handler/BooleanTrueArgumentHandler.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.argument.handler; 7 | 8 | import com.illposed.osc.BytesReceiver; 9 | import com.illposed.osc.argument.ArgumentHandler; 10 | import java.nio.ByteBuffer; 11 | import java.util.Map; 12 | 13 | /** 14 | * Parses and serializes an OSC boolean TRUE type. 15 | */ 16 | public class BooleanTrueArgumentHandler implements ArgumentHandler, Cloneable { 17 | 18 | public static final ArgumentHandler INSTANCE = new BooleanTrueArgumentHandler(); 19 | 20 | // Public API 21 | /** Allow overriding, but somewhat enforce the ugly singleton. */ 22 | @SuppressWarnings("WeakerAccess") 23 | protected BooleanTrueArgumentHandler() { 24 | // declared only for setting the access level 25 | } 26 | 27 | @Override 28 | public char getDefaultIdentifier() { 29 | return 'T'; 30 | } 31 | 32 | @Override 33 | public Class getJavaClass() { 34 | return Boolean.class; 35 | } 36 | 37 | @Override 38 | public void setProperties(final Map properties) { 39 | // we make no use of any properties 40 | } 41 | 42 | @Override 43 | public boolean isMarkerOnly() { 44 | return true; 45 | } 46 | 47 | @Override 48 | @SuppressWarnings("unchecked") 49 | public BooleanTrueArgumentHandler clone() throws CloneNotSupportedException { 50 | return (BooleanTrueArgumentHandler) super.clone(); 51 | } 52 | 53 | @Override 54 | public Boolean parse(final ByteBuffer input) { 55 | return Boolean.TRUE; 56 | } 57 | 58 | @Override 59 | public void serialize(final BytesReceiver output, final Boolean value) { 60 | 61 | // if (!value.equals(Boolean.TRUE)) { 62 | // throw new OSCSerializeException(); 63 | // } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/argument/handler/ByteArrayBlobArgumentHandler.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.argument.handler; 7 | 8 | import com.illposed.osc.BytesReceiver; 9 | import com.illposed.osc.OSCParseException; 10 | import com.illposed.osc.OSCSerializeException; 11 | import com.illposed.osc.argument.ArgumentHandler; 12 | import java.nio.ByteBuffer; 13 | import java.util.Map; 14 | 15 | /** 16 | * Parses and serializes an OSC binary-blob type. 17 | */ 18 | public class ByteArrayBlobArgumentHandler implements ArgumentHandler, Cloneable { 19 | 20 | public static final ArgumentHandler INSTANCE = new ByteArrayBlobArgumentHandler(); 21 | 22 | // Public API 23 | /** Allow overriding, but somewhat enforce the ugly singleton. */ 24 | @SuppressWarnings("WeakerAccess") 25 | protected ByteArrayBlobArgumentHandler() { 26 | // declared only for setting the access level 27 | } 28 | 29 | @Override 30 | public char getDefaultIdentifier() { 31 | return 'b'; 32 | } 33 | 34 | @Override 35 | public Class getJavaClass() { 36 | return byte[].class; 37 | } 38 | 39 | @Override 40 | public void setProperties(final Map properties) { 41 | // we make no use of any properties 42 | } 43 | 44 | @Override 45 | public boolean isMarkerOnly() { 46 | return false; 47 | } 48 | 49 | @Override 50 | @SuppressWarnings("unchecked") 51 | public ByteArrayBlobArgumentHandler clone() throws CloneNotSupportedException { 52 | return (ByteArrayBlobArgumentHandler) super.clone(); 53 | } 54 | 55 | @Override 56 | public byte[] parse(final ByteBuffer input) throws OSCParseException { 57 | 58 | final ByteBuffer bufferValue = BlobArgumentHandler.INSTANCE.parse(input); 59 | final byte[] value = new byte[bufferValue.remaining()]; 60 | bufferValue.get(value); 61 | return value; 62 | } 63 | 64 | @Override 65 | public void serialize(final BytesReceiver output, final byte[] value) throws OSCSerializeException { 66 | 67 | final ByteBuffer bufferValue = ByteBuffer.wrap(value).asReadOnlyBuffer(); 68 | BlobArgumentHandler.INSTANCE.serialize(output, bufferValue); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/argument/handler/CharArgumentHandler.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.argument.handler; 7 | 8 | import com.illposed.osc.BytesReceiver; 9 | import com.illposed.osc.argument.ArgumentHandler; 10 | import java.nio.ByteBuffer; 11 | import java.util.Map; 12 | 13 | /** 14 | * Parses and serializes an OSC character type. 15 | */ 16 | public class CharArgumentHandler implements ArgumentHandler, Cloneable { 17 | 18 | public static final ArgumentHandler INSTANCE = new CharArgumentHandler(); 19 | 20 | // Public API 21 | /** Allow overriding, but somewhat enforce the ugly singleton. */ 22 | @SuppressWarnings("WeakerAccess") 23 | protected CharArgumentHandler() { 24 | // declared only for setting the access level 25 | } 26 | 27 | @Override 28 | public char getDefaultIdentifier() { 29 | return 'c'; 30 | } 31 | 32 | @Override 33 | public Class getJavaClass() { 34 | return Character.class; 35 | } 36 | 37 | @Override 38 | public void setProperties(final Map properties) { 39 | // we make no use of any properties 40 | } 41 | 42 | @Override 43 | public boolean isMarkerOnly() { 44 | return false; 45 | } 46 | 47 | @Override 48 | @SuppressWarnings("unchecked") 49 | public CharArgumentHandler clone() throws CloneNotSupportedException { 50 | return (CharArgumentHandler) super.clone(); 51 | } 52 | 53 | @Override 54 | public Character parse(final ByteBuffer input) { 55 | 56 | // Read the char as 1 byte from the last 8 of 32bits 57 | // to be compatible with liblo. 58 | // This might later be expanded to support multi-byte encoded chars. 59 | input.get(); 60 | input.get(); 61 | input.get(); 62 | return (char) input.get(); 63 | } 64 | 65 | @Override 66 | public void serialize(final BytesReceiver output, final Character value) { 67 | 68 | // Put the char as 1 byte in the last 8 of 32bits 69 | // to be compatible with liblo. 70 | // This might later be expanded to support multi-byte encoded chars. 71 | output.put((byte) 0); 72 | output.put((byte) 0); 73 | output.put((byte) 0); 74 | output.put((byte) (char) value); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/argument/handler/ColorArgumentHandler.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.argument.handler; 7 | 8 | import com.illposed.osc.BytesReceiver; 9 | import com.illposed.osc.argument.ArgumentHandler; 10 | import com.illposed.osc.argument.OSCColor; 11 | 12 | import java.nio.ByteBuffer; 13 | import java.util.Map; 14 | 15 | /** 16 | * Parses and serializes an OSC 1.1 optional 32bit RGBA color type. 17 | */ 18 | public class ColorArgumentHandler implements ArgumentHandler, Cloneable { 19 | 20 | public static final ArgumentHandler INSTANCE = new ColorArgumentHandler(); 21 | 22 | // Public API 23 | /** Allow overriding, but somewhat enforce the ugly singleton. */ 24 | @SuppressWarnings("WeakerAccess") 25 | protected ColorArgumentHandler() { 26 | // declared only for setting the access level 27 | } 28 | 29 | @Override 30 | public char getDefaultIdentifier() { 31 | return 'r'; 32 | } 33 | 34 | @Override 35 | public Class getJavaClass() { 36 | return OSCColor.class; 37 | } 38 | 39 | @Override 40 | public void setProperties(final Map properties) { 41 | // we make no use of any properties 42 | } 43 | 44 | @Override 45 | public boolean isMarkerOnly() { 46 | return false; 47 | } 48 | 49 | @Override 50 | @SuppressWarnings("unchecked") 51 | public ColorArgumentHandler clone() throws CloneNotSupportedException { 52 | return (ColorArgumentHandler) super.clone(); 53 | } 54 | 55 | @Override 56 | public OSCColor parse(final ByteBuffer input) { 57 | return new OSCColor( 58 | input.get(), 59 | input.get(), 60 | input.get(), 61 | input.get()); 62 | } 63 | 64 | @Override 65 | public void serialize(final BytesReceiver output, final OSCColor value) { 66 | 67 | output.put(value.getRed()); 68 | output.put(value.getGreen()); 69 | output.put(value.getBlue()); 70 | output.put(value.getAlpha()); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/argument/handler/DateTimeStampArgumentHandler.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.argument.handler; 7 | 8 | import com.illposed.osc.BytesReceiver; 9 | import com.illposed.osc.argument.OSCTimeTag64; 10 | import com.illposed.osc.OSCParseException; 11 | import com.illposed.osc.OSCSerializeException; 12 | import com.illposed.osc.argument.ArgumentHandler; 13 | import java.nio.ByteBuffer; 14 | import java.util.Date; 15 | import java.util.Map; 16 | 17 | /** 18 | * Parses and serializes an OSC Time-tag, 19 | * using {@link Date} as a wrapper, 20 | * and thus loosing out on the resolution. 21 | * You should consider using {@link TimeTag64ArgumentHandler} instead; 22 | */ 23 | public class DateTimeStampArgumentHandler implements ArgumentHandler, Cloneable { 24 | 25 | public static final ArgumentHandler INSTANCE = new DateTimeStampArgumentHandler(); 26 | /** 27 | * This {@link Date} property indicates the epoch into which we parse 28 | * OSC Time-tags. 29 | * The Java dates parsed by this handler will be in the same OSC/NTP epoch 30 | * as this properties value. 31 | */ 32 | public static final String PROP_NAME_EPOCH_INDICATOR_TIME = "epoch-indicator"; 33 | 34 | private Long epochIndicatorTime; 35 | 36 | // Public API 37 | /** Allow overriding, but somewhat enforce the ugly singleton. */ 38 | @SuppressWarnings("WeakerAccess") 39 | protected DateTimeStampArgumentHandler() { 40 | 41 | // now 42 | this.epochIndicatorTime = new Date().getTime(); 43 | } 44 | 45 | @Override 46 | public char getDefaultIdentifier() { 47 | return 't'; 48 | } 49 | 50 | @Override 51 | public Class getJavaClass() { 52 | return Date.class; 53 | } 54 | 55 | // Public API 56 | @SuppressWarnings("WeakerAccess") 57 | public void setEpochIndicatorTime(final Long epochIndicatorTime) { 58 | this.epochIndicatorTime = epochIndicatorTime; 59 | } 60 | 61 | @Override 62 | public void setProperties(final Map properties) { 63 | 64 | final Long newEpochIndicatorTime 65 | = (Long) properties.get(PROP_NAME_EPOCH_INDICATOR_TIME); 66 | if (newEpochIndicatorTime != null) { 67 | setEpochIndicatorTime(newEpochIndicatorTime); 68 | } 69 | } 70 | 71 | @Override 72 | public boolean isMarkerOnly() { 73 | return false; 74 | } 75 | 76 | @Override 77 | @SuppressWarnings("unchecked") 78 | public DateTimeStampArgumentHandler clone() throws CloneNotSupportedException { 79 | return (DateTimeStampArgumentHandler) super.clone(); 80 | } 81 | 82 | @Override 83 | public Date parse(final ByteBuffer input) throws OSCParseException { 84 | return TimeTag64ArgumentHandler.INSTANCE.parse(input).toDate(epochIndicatorTime); 85 | } 86 | 87 | @Override 88 | public void serialize(final BytesReceiver output, final Date value) throws OSCSerializeException { 89 | TimeTag64ArgumentHandler.INSTANCE.serialize(output, OSCTimeTag64.valueOf(value)); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/argument/handler/DoubleArgumentHandler.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.argument.handler; 7 | 8 | import com.illposed.osc.BytesReceiver; 9 | import com.illposed.osc.OSCParseException; 10 | import com.illposed.osc.OSCSerializeException; 11 | import com.illposed.osc.argument.ArgumentHandler; 12 | import java.nio.ByteBuffer; 13 | import java.util.Map; 14 | 15 | /** 16 | * Parses and serializes an OSC double type (64bit floating point number). 17 | */ 18 | public class DoubleArgumentHandler implements ArgumentHandler, Cloneable { 19 | 20 | public static final ArgumentHandler INSTANCE = new DoubleArgumentHandler(); 21 | 22 | // Public API 23 | /** Allow overriding, but somewhat enforce the ugly singleton. */ 24 | @SuppressWarnings("WeakerAccess") 25 | protected DoubleArgumentHandler() { 26 | // declared only for setting the access level 27 | } 28 | 29 | @Override 30 | public char getDefaultIdentifier() { 31 | return 'd'; 32 | } 33 | 34 | @Override 35 | public Class getJavaClass() { 36 | return Double.class; 37 | } 38 | 39 | @Override 40 | public void setProperties(final Map properties) { 41 | // we make no use of any properties 42 | } 43 | 44 | @Override 45 | public boolean isMarkerOnly() { 46 | return false; 47 | } 48 | 49 | @Override 50 | @SuppressWarnings("unchecked") 51 | public DoubleArgumentHandler clone() throws CloneNotSupportedException { 52 | return (DoubleArgumentHandler) super.clone(); 53 | } 54 | 55 | @Override 56 | public Double parse(final ByteBuffer input) throws OSCParseException { 57 | return Double.longBitsToDouble(LongArgumentHandler.INSTANCE.parse(input)); 58 | } 59 | 60 | @Override 61 | public void serialize(final BytesReceiver output, final Double value) throws OSCSerializeException { 62 | LongArgumentHandler.INSTANCE.serialize(output, Double.doubleToRawLongBits(value)); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/argument/handler/FloatArgumentHandler.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.argument.handler; 7 | 8 | import com.illposed.osc.BytesReceiver; 9 | import com.illposed.osc.OSCParseException; 10 | import com.illposed.osc.OSCSerializeException; 11 | import com.illposed.osc.argument.ArgumentHandler; 12 | import java.nio.ByteBuffer; 13 | import java.util.Map; 14 | 15 | /** 16 | * Parses and serializes an OSC float type (32bit floating point number). 17 | */ 18 | public class FloatArgumentHandler implements ArgumentHandler, Cloneable { 19 | 20 | public static final ArgumentHandler INSTANCE = new FloatArgumentHandler(); 21 | 22 | // Public API 23 | /** Allow overriding, but somewhat enforce the ugly singleton. */ 24 | @SuppressWarnings("WeakerAccess") 25 | protected FloatArgumentHandler() { 26 | // declared only for setting the access level 27 | } 28 | 29 | @Override 30 | public char getDefaultIdentifier() { 31 | return 'f'; 32 | } 33 | 34 | @Override 35 | public Class getJavaClass() { 36 | return Float.class; 37 | } 38 | 39 | @Override 40 | public void setProperties(final Map properties) { 41 | // we make no use of any properties 42 | } 43 | 44 | @Override 45 | public boolean isMarkerOnly() { 46 | return false; 47 | } 48 | 49 | @Override 50 | @SuppressWarnings("unchecked") 51 | public FloatArgumentHandler clone() throws CloneNotSupportedException { 52 | return (FloatArgumentHandler) super.clone(); 53 | } 54 | 55 | @Override 56 | public Float parse(final ByteBuffer input) throws OSCParseException { 57 | return Float.intBitsToFloat(IntegerArgumentHandler.INSTANCE.parse(input)); 58 | } 59 | 60 | @Override 61 | public void serialize(final BytesReceiver output, final Float value) throws OSCSerializeException { 62 | IntegerArgumentHandler.INSTANCE.serialize(output, Float.floatToRawIntBits(value)); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/argument/handler/ImpulseArgumentHandler.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.argument.handler; 7 | 8 | import com.illposed.osc.BytesReceiver; 9 | import com.illposed.osc.argument.OSCImpulse; 10 | import com.illposed.osc.argument.ArgumentHandler; 11 | import java.nio.ByteBuffer; 12 | import java.util.Map; 13 | 14 | /** 15 | * Parses and serializes an OSC Impulse type. 16 | */ 17 | public class ImpulseArgumentHandler implements ArgumentHandler, Cloneable { 18 | 19 | public static final ArgumentHandler INSTANCE = new ImpulseArgumentHandler(); 20 | 21 | // Public API 22 | /** Allow overriding, but somewhat enforce the ugly singleton. */ 23 | @SuppressWarnings("WeakerAccess") 24 | protected ImpulseArgumentHandler() { 25 | // declared only for setting the access level 26 | } 27 | 28 | @Override 29 | public char getDefaultIdentifier() { 30 | return 'I'; 31 | } 32 | 33 | @Override 34 | public Class getJavaClass() { 35 | return OSCImpulse.class; 36 | } 37 | 38 | @Override 39 | public void setProperties(final Map properties) { 40 | // we make no use of any properties 41 | } 42 | 43 | @Override 44 | public boolean isMarkerOnly() { 45 | return true; 46 | } 47 | 48 | @Override 49 | @SuppressWarnings("unchecked") 50 | public ImpulseArgumentHandler clone() throws CloneNotSupportedException { 51 | return (ImpulseArgumentHandler) super.clone(); 52 | } 53 | 54 | @Override 55 | public OSCImpulse parse(final ByteBuffer input) { 56 | return OSCImpulse.INSTANCE; 57 | } 58 | 59 | @Override 60 | public void serialize(final BytesReceiver output, final OSCImpulse value) { 61 | 62 | // if (value != OSCImpulse.INSTANCE) { 63 | // throw new OSCSerializeException(); 64 | // } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/argument/handler/IntegerArgumentHandler.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.argument.handler; 7 | 8 | import com.illposed.osc.BytesReceiver; 9 | import com.illposed.osc.argument.ArgumentHandler; 10 | import java.nio.ByteBuffer; 11 | import java.util.Map; 12 | 13 | /** 14 | * Parses and serializes an OSC integer type (32bit signed integer). 15 | */ 16 | public class IntegerArgumentHandler implements ArgumentHandler, Cloneable { 17 | 18 | // Public API 19 | /** 20 | * The number of bytes used to represent this type in an OSC byte array (4). 21 | */ 22 | @SuppressWarnings("WeakerAccess") 23 | public static final int BYTES = Integer.SIZE / Byte.SIZE; 24 | public static final ArgumentHandler INSTANCE = new IntegerArgumentHandler(); 25 | 26 | // Public API 27 | /** Allow overriding, but somewhat enforce the ugly singleton. */ 28 | @SuppressWarnings("WeakerAccess") 29 | protected IntegerArgumentHandler() { 30 | // declared only for setting the access level 31 | } 32 | 33 | @Override 34 | public char getDefaultIdentifier() { 35 | return 'i'; 36 | } 37 | 38 | @Override 39 | public Class getJavaClass() { 40 | return Integer.class; 41 | } 42 | 43 | @Override 44 | public void setProperties(final Map properties) { 45 | // we make no use of any properties 46 | } 47 | 48 | @Override 49 | public boolean isMarkerOnly() { 50 | return false; 51 | } 52 | 53 | @Override 54 | @SuppressWarnings("unchecked") 55 | public IntegerArgumentHandler clone() throws CloneNotSupportedException { 56 | return (IntegerArgumentHandler) super.clone(); 57 | } 58 | 59 | @Override 60 | public Integer parse(final ByteBuffer input) { 61 | 62 | final Integer value = input.asIntBuffer().get(); 63 | input.position(input.position() + BYTES); 64 | return value; 65 | } 66 | 67 | @Override 68 | public void serialize(final BytesReceiver output, final Integer value) { 69 | 70 | int curValue = value; 71 | final byte[] intBytes = new byte[4]; 72 | intBytes[3] = (byte)curValue; curValue >>>= 8; 73 | intBytes[2] = (byte)curValue; curValue >>>= 8; 74 | intBytes[1] = (byte)curValue; curValue >>>= 8; 75 | intBytes[0] = (byte)curValue; 76 | 77 | output.put(intBytes); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/argument/handler/LongArgumentHandler.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.argument.handler; 7 | 8 | import com.illposed.osc.BytesReceiver; 9 | import com.illposed.osc.argument.ArgumentHandler; 10 | import java.nio.Buffer; 11 | import java.nio.ByteBuffer; 12 | import java.util.Map; 13 | 14 | /** 15 | * Parses and serializes an OSC long type (64bit signed integer). 16 | */ 17 | public class LongArgumentHandler implements ArgumentHandler, Cloneable { 18 | 19 | // Public API 20 | /** 21 | * The number of bytes used to represent this type in an OSC byte array (8). 22 | */ 23 | @SuppressWarnings("WeakerAccess") 24 | public static final int BYTES = Long.SIZE / Byte.SIZE; 25 | public static final ArgumentHandler INSTANCE = new LongArgumentHandler(); 26 | 27 | // Public API 28 | /** Allow overriding, but somewhat enforce the ugly singleton. */ 29 | @SuppressWarnings("WeakerAccess") 30 | protected LongArgumentHandler() { 31 | // declared only for setting the access level 32 | } 33 | 34 | @Override 35 | public char getDefaultIdentifier() { 36 | return 'h'; 37 | } 38 | 39 | @Override 40 | public Class getJavaClass() { 41 | return Long.class; 42 | } 43 | 44 | @Override 45 | public void setProperties(final Map properties) { 46 | // we make no use of any properties 47 | } 48 | 49 | @Override 50 | public boolean isMarkerOnly() { 51 | return false; 52 | } 53 | 54 | @Override 55 | @SuppressWarnings("unchecked") 56 | public LongArgumentHandler clone() throws CloneNotSupportedException { 57 | return (LongArgumentHandler) super.clone(); 58 | } 59 | 60 | @Override 61 | public Long parse(final ByteBuffer input) { 62 | 63 | final Long value = input.asLongBuffer().get(); 64 | ((Buffer)input).position(input.position() + BYTES); 65 | return value; 66 | } 67 | 68 | @Override 69 | public void serialize(final BytesReceiver output, final Long value) { 70 | 71 | long curValue = value; 72 | final byte[] longIntBytes = new byte[8]; 73 | longIntBytes[7] = (byte)curValue; curValue >>>= 8; 74 | longIntBytes[6] = (byte)curValue; curValue >>>= 8; 75 | longIntBytes[5] = (byte)curValue; curValue >>>= 8; 76 | longIntBytes[4] = (byte)curValue; curValue >>>= 8; 77 | longIntBytes[3] = (byte)curValue; curValue >>>= 8; 78 | longIntBytes[2] = (byte)curValue; curValue >>>= 8; 79 | longIntBytes[1] = (byte)curValue; curValue >>>= 8; 80 | longIntBytes[0] = (byte)curValue; 81 | 82 | output.put(longIntBytes); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/argument/handler/MidiMessageArgumentHandler.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.argument.handler; 7 | 8 | import com.illposed.osc.BytesReceiver; 9 | import com.illposed.osc.argument.OSCMidiMessage; 10 | import com.illposed.osc.argument.ArgumentHandler; 11 | import java.nio.ByteBuffer; 12 | import java.util.Map; 13 | 14 | /** 15 | * Parses and serializes an OSC MIDI message type (4 bytes). 16 | */ 17 | public class MidiMessageArgumentHandler implements ArgumentHandler, Cloneable { 18 | 19 | public static final ArgumentHandler INSTANCE = new MidiMessageArgumentHandler(); 20 | 21 | // Public API 22 | /** Allow overriding, but somewhat enforce the ugly singleton. */ 23 | @SuppressWarnings("WeakerAccess") 24 | protected MidiMessageArgumentHandler() { 25 | // declared only for setting the access level 26 | } 27 | 28 | @Override 29 | public char getDefaultIdentifier() { 30 | return 'm'; 31 | } 32 | 33 | @Override 34 | public Class getJavaClass() { 35 | return OSCMidiMessage.class; 36 | } 37 | 38 | @Override 39 | public void setProperties(final Map properties) { 40 | // we make no use of any properties 41 | } 42 | 43 | @Override 44 | public boolean isMarkerOnly() { 45 | return false; 46 | } 47 | 48 | @Override 49 | @SuppressWarnings("unchecked") 50 | public MidiMessageArgumentHandler clone() throws CloneNotSupportedException { 51 | return (MidiMessageArgumentHandler) super.clone(); 52 | } 53 | 54 | @Override 55 | public OSCMidiMessage parse(final ByteBuffer input) { 56 | return OSCMidiMessage.valueOf(new byte[] { 57 | input.get(), 58 | input.get(), 59 | input.get(), 60 | input.get()}); 61 | } 62 | 63 | @Override 64 | public void serialize(final BytesReceiver output, final OSCMidiMessage value) { 65 | output.put(value.toContentArray()); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/argument/handler/NullArgumentHandler.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.argument.handler; 7 | 8 | import com.illposed.osc.BytesReceiver; 9 | import com.illposed.osc.argument.ArgumentHandler; 10 | import java.nio.ByteBuffer; 11 | import java.util.Map; 12 | 13 | /** 14 | * Parses and serializes an OSC null type. 15 | */ 16 | public class NullArgumentHandler implements ArgumentHandler, Cloneable { 17 | 18 | public static final ArgumentHandler INSTANCE = new NullArgumentHandler(); 19 | 20 | // Public API 21 | /** Allow overriding, but somewhat enforce the ugly singleton. */ 22 | @SuppressWarnings("WeakerAccess") 23 | protected NullArgumentHandler() { 24 | // declared only for setting the access level 25 | } 26 | 27 | @Override 28 | public char getDefaultIdentifier() { 29 | return 'N'; 30 | } 31 | 32 | @Override 33 | public Class getJavaClass() { 34 | return Object.class; 35 | } 36 | 37 | @Override 38 | public void setProperties(final Map properties) { 39 | // we make no use of any properties 40 | } 41 | 42 | @Override 43 | public boolean isMarkerOnly() { 44 | return true; 45 | } 46 | 47 | @Override 48 | @SuppressWarnings("unchecked") 49 | public NullArgumentHandler clone() throws CloneNotSupportedException { 50 | return (NullArgumentHandler) super.clone(); 51 | } 52 | 53 | @Override 54 | public Object parse(final ByteBuffer input) { 55 | return null; 56 | } 57 | 58 | @Override 59 | public void serialize(final BytesReceiver output, final Object value) { 60 | 61 | // if (value != null) { 62 | // throw new OSCSerializeException(); 63 | // } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/argument/handler/StringArgumentHandler.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.argument.handler; 7 | 8 | import com.illposed.osc.BytesReceiver; 9 | import com.illposed.osc.OSCParseException; 10 | import com.illposed.osc.OSCParser; 11 | import com.illposed.osc.OSCSerializer; 12 | import com.illposed.osc.argument.ArgumentHandler; 13 | import java.nio.Buffer; 14 | import java.nio.ByteBuffer; 15 | import java.nio.charset.CharacterCodingException; 16 | import java.nio.charset.Charset; 17 | import java.util.Map; 18 | 19 | /** 20 | * Parses and serializes an OSC string type. 21 | */ 22 | public class StringArgumentHandler implements ArgumentHandler, Cloneable { 23 | 24 | // Public API 25 | @SuppressWarnings("WeakerAccess") 26 | public static final char DEFAULT_IDENTIFIER = 's'; 27 | public static final String PROP_NAME_CHARSET = "charset"; 28 | 29 | private Charset charset; 30 | 31 | // Public API 32 | @SuppressWarnings("WeakerAccess") 33 | public StringArgumentHandler(final Charset charset) { 34 | this.charset = charset; 35 | } 36 | // Public API 37 | @SuppressWarnings("WeakerAccess") 38 | public StringArgumentHandler() { 39 | this(Charset.defaultCharset()); 40 | } 41 | 42 | // Public API 43 | /** 44 | * Returns the character-set used to encode and decode string arguments. 45 | * @return the currently used character-encoding-set 46 | */ 47 | @SuppressWarnings("unused") 48 | public Charset getCharset() { 49 | return charset; 50 | } 51 | 52 | // Public API 53 | /** 54 | * Sets the character-set used to encode and decode string arguments. 55 | * @param charset the new character-encoding-set 56 | */ 57 | @SuppressWarnings("WeakerAccess") 58 | public void setCharset(final Charset charset) { 59 | this.charset = charset; 60 | } 61 | 62 | @Override 63 | public char getDefaultIdentifier() { 64 | return DEFAULT_IDENTIFIER; 65 | } 66 | 67 | @Override 68 | public Class getJavaClass() { 69 | return String.class; 70 | } 71 | 72 | @Override 73 | public void setProperties(final Map properties) { 74 | 75 | final Charset newCharset = (Charset) properties.get(PROP_NAME_CHARSET); 76 | if (newCharset != null) { 77 | setCharset(newCharset); 78 | } 79 | } 80 | 81 | @Override 82 | public boolean isMarkerOnly() { 83 | return false; 84 | } 85 | 86 | @Override 87 | @SuppressWarnings("unchecked") 88 | public StringArgumentHandler clone() throws CloneNotSupportedException { 89 | return (StringArgumentHandler) super.clone(); 90 | } 91 | 92 | /** 93 | * Get the length of the string currently in the byte stream. 94 | */ 95 | private int lengthOfCurrentString(final ByteBuffer rawInput) { 96 | int len = 0; 97 | while (rawInput.get(rawInput.position() + len) != 0) { 98 | len++; 99 | } 100 | return len; 101 | } 102 | 103 | @Override 104 | public String parse(final ByteBuffer input) throws OSCParseException { 105 | 106 | final int strLen = lengthOfCurrentString(input); 107 | final ByteBuffer strBuffer = input.slice(); 108 | ((Buffer)strBuffer).limit(strLen); 109 | final String res; 110 | try { 111 | res = charset.newDecoder().decode(strBuffer).toString(); 112 | } catch (final CharacterCodingException ex) { 113 | throw new OSCParseException( 114 | "Failed decoding a string argument", ex, input 115 | ); 116 | } 117 | ((Buffer)input).position(input.position() + strLen); 118 | // because strings are always padded with at least one zero, 119 | // as their length is not given in advance, as is the case with blobs, 120 | // we skip over the terminating zero byte (position++) 121 | input.get(); 122 | OSCParser.align(input); 123 | return res; 124 | } 125 | 126 | @Override 127 | public void serialize(final BytesReceiver output, final String value) { 128 | 129 | final byte[] stringBytes = value.getBytes(charset); 130 | output.put(stringBytes); 131 | OSCSerializer.terminateAndAlign(output); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/argument/handler/SymbolArgumentHandler.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.argument.handler; 7 | 8 | import com.illposed.osc.BytesReceiver; 9 | import com.illposed.osc.argument.ArgumentHandler; 10 | import com.illposed.osc.argument.OSCSymbol; 11 | import com.illposed.osc.OSCParseException; 12 | import java.nio.ByteBuffer; 13 | import java.util.Map; 14 | 15 | /** 16 | * Parses and serializes an OSC symbol type. 17 | */ 18 | public class SymbolArgumentHandler implements ArgumentHandler, Cloneable { 19 | 20 | // Public API 21 | @SuppressWarnings("WeakerAccess") 22 | public static final char DEFAULT_IDENTIFIER = 'S'; 23 | 24 | private final StringArgumentHandler stringArgumentHandler; 25 | 26 | // Public API 27 | @SuppressWarnings("WeakerAccess") 28 | public SymbolArgumentHandler() { 29 | this.stringArgumentHandler = new StringArgumentHandler(); 30 | } 31 | 32 | // Public API 33 | @SuppressWarnings("unused") 34 | public StringArgumentHandler getInternalStringArgumentHandler() { 35 | return stringArgumentHandler; 36 | } 37 | 38 | @Override 39 | public char getDefaultIdentifier() { 40 | return DEFAULT_IDENTIFIER; 41 | } 42 | 43 | @Override 44 | public Class getJavaClass() { 45 | return OSCSymbol.class; 46 | } 47 | 48 | @Override 49 | public void setProperties(final Map properties) { 50 | stringArgumentHandler.setProperties(properties); 51 | } 52 | 53 | @Override 54 | public boolean isMarkerOnly() { 55 | return false; 56 | } 57 | 58 | @Override 59 | @SuppressWarnings("unchecked") 60 | public SymbolArgumentHandler clone() throws CloneNotSupportedException { 61 | return (SymbolArgumentHandler) super.clone(); 62 | } 63 | 64 | @Override 65 | public OSCSymbol parse(final ByteBuffer input) throws OSCParseException { 66 | return OSCSymbol.valueOf(stringArgumentHandler.parse(input)); 67 | } 68 | 69 | @Override 70 | public void serialize(final BytesReceiver output, final OSCSymbol value) { 71 | stringArgumentHandler.serialize(output, value.toString()); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/argument/handler/TimeTag64ArgumentHandler.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.argument.handler; 7 | 8 | import com.illposed.osc.BytesReceiver; 9 | import com.illposed.osc.argument.OSCTimeTag64; 10 | import com.illposed.osc.OSCParseException; 11 | import com.illposed.osc.OSCSerializeException; 12 | import com.illposed.osc.argument.ArgumentHandler; 13 | import java.nio.ByteBuffer; 14 | import java.util.Map; 15 | 16 | /** 17 | * Parses and serializes an OSC Time-tag. 18 | */ 19 | public class TimeTag64ArgumentHandler implements ArgumentHandler, Cloneable { 20 | 21 | public static final ArgumentHandler INSTANCE = new TimeTag64ArgumentHandler(); 22 | 23 | // Public API 24 | /** Allow overriding, but somewhat enforce the ugly singleton. */ 25 | @SuppressWarnings("WeakerAccess") 26 | protected TimeTag64ArgumentHandler() { 27 | // declared only for setting the access level 28 | } 29 | 30 | @Override 31 | public char getDefaultIdentifier() { 32 | return 't'; 33 | } 34 | 35 | @Override 36 | public Class getJavaClass() { 37 | return OSCTimeTag64.class; 38 | } 39 | 40 | @Override 41 | public void setProperties(final Map properties) { 42 | // we make no use of any properties 43 | } 44 | 45 | @Override 46 | public boolean isMarkerOnly() { 47 | return false; 48 | } 49 | 50 | @Override 51 | @SuppressWarnings("unchecked") 52 | public TimeTag64ArgumentHandler clone() throws CloneNotSupportedException { 53 | return (TimeTag64ArgumentHandler) super.clone(); 54 | } 55 | 56 | @Override 57 | public OSCTimeTag64 parse(final ByteBuffer input) throws OSCParseException { 58 | 59 | final long ntpTime = LongArgumentHandler.INSTANCE.parse(input); 60 | return OSCTimeTag64.valueOf(ntpTime); 61 | } 62 | 63 | @Override 64 | public void serialize(final BytesReceiver output, final OSCTimeTag64 value) 65 | throws OSCSerializeException 66 | { 67 | LongArgumentHandler.INSTANCE.serialize(output, value.getNtpTime()); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/argument/handler/UnsignedIntegerArgumentHandler.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.argument.handler; 7 | 8 | import com.illposed.osc.BytesReceiver; 9 | import com.illposed.osc.argument.OSCUnsigned; 10 | import com.illposed.osc.argument.ArgumentHandler; 11 | import java.nio.ByteBuffer; 12 | import java.util.Map; 13 | 14 | /** 15 | * Parses and serializes an OSC unsigned type (32bit unsigned integer). 16 | */ 17 | public class UnsignedIntegerArgumentHandler implements ArgumentHandler, Cloneable { 18 | 19 | public static final ArgumentHandler INSTANCE = new UnsignedIntegerArgumentHandler(); 20 | 21 | // Public API 22 | /** Allow overriding, but somewhat enforce the ugly singleton. */ 23 | @SuppressWarnings("WeakerAccess") 24 | protected UnsignedIntegerArgumentHandler() { 25 | // declared only for setting the access level 26 | } 27 | 28 | @Override 29 | public char getDefaultIdentifier() { 30 | return 'u'; 31 | } 32 | 33 | @Override 34 | public Class getJavaClass() { 35 | return OSCUnsigned.class; 36 | } 37 | 38 | @Override 39 | public void setProperties(final Map properties) { 40 | // we make no use of any properties 41 | } 42 | 43 | @Override 44 | public boolean isMarkerOnly() { 45 | return false; 46 | } 47 | 48 | @Override 49 | @SuppressWarnings("unchecked") 50 | public UnsignedIntegerArgumentHandler clone() throws CloneNotSupportedException { 51 | return (UnsignedIntegerArgumentHandler) super.clone(); 52 | } 53 | 54 | /** 55 | * Reads an unsigned integer (32 bit) from the byte stream. 56 | * This code is copied from 57 | * here, and it is licensed under the Public Domain. 58 | * @return single precision, unsigned integer (32 bit) wrapped in a 64 bit integer (long) 59 | */ 60 | @Override 61 | public OSCUnsigned parse(final ByteBuffer input) { 62 | return OSCUnsigned.valueOf(new byte[] { 63 | input.get(), 64 | input.get(), 65 | input.get(), 66 | input.get()}); 67 | } 68 | 69 | @Override 70 | public void serialize(final BytesReceiver output, final OSCUnsigned value) { 71 | 72 | final long asLong = value.toLong(); 73 | output.put((byte) (asLong >> 24 & 0xFFL)); 74 | output.put((byte) (asLong >> 16 & 0xFFL)); 75 | output.put((byte) (asLong >> 8 & 0xFFL)); 76 | output.put((byte) (asLong & 0xFFL)); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/argument/handler/package-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | /** 7 | * Provides {@link com.illposed.osc.argument.ArgumentHandler} implementations. 8 | * Most, if not all of them can be found in the OSC specification (1.0 and 1.1). 9 | */ 10 | package com.illposed.osc.argument.handler; 11 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/argument/package-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | /** 7 | * Provides OSC Argument type value classes. 8 | * Most of the Java classes used as argument values are chosen from within standard Java, 9 | * like {@code Integer}, {@code Double} and {@code String}. 10 | * For the OSC argument types that do not have a suitable representative in standard Java, 11 | * we added new classes here. 12 | * In addition, it also contains the API class {@link com.illposed.osc.argument.ArgumentHandler}. 13 | */ 14 | package com.illposed.osc.argument; 15 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/messageselector/CombinedMessageSelector.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2014-2017 C. Ramakrishnan / Auracle 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.messageselector; 7 | 8 | import com.illposed.osc.MessageSelector; 9 | import com.illposed.osc.OSCMessageEvent; 10 | 11 | /** 12 | * Checks whether a certain logical combination of two message selectors matches. 13 | * 14 | * An example:
15 | *
{@code
16 |  * // matches only if both the address and the argument tags match
17 |  * MessageSelector matcher = new CombinedMessageSelector(
18 |  *         new OSCPatternAddressMessageSelector("/hello/*"),
19 |  *         new OSCPatternTypeTagsMessageSelector("tiff"),
20 |  *         CombinedMessageSelector.LogicOperator.AND);
21 |  * }
22 | */ 23 | public class CombinedMessageSelector implements MessageSelector { 24 | 25 | public enum LogicOperator { 26 | AND { 27 | @Override 28 | public boolean matches(final boolean matches1, final boolean matches2) { 29 | return (matches1 && matches2); 30 | } 31 | }, 32 | // Public API 33 | @SuppressWarnings("unused") 34 | OR 35 | { 36 | @Override 37 | public boolean matches(final boolean matches1, final boolean matches2) { 38 | return (matches1 || matches2); 39 | } 40 | }, 41 | // Public API 42 | @SuppressWarnings("unused") 43 | XOR 44 | { 45 | @Override 46 | public boolean matches(final boolean matches1, final boolean matches2) { 47 | return ((matches1 && !matches2) || (!matches1 && matches2)); 48 | } 49 | }; 50 | 51 | public abstract boolean matches(boolean matches1, boolean matches2); 52 | } 53 | 54 | private final MessageSelector selector1; 55 | private final MessageSelector selector2; 56 | private final LogicOperator logicOperator; 57 | 58 | // Public API 59 | @SuppressWarnings("WeakerAccess") 60 | public CombinedMessageSelector( 61 | final MessageSelector selector1, 62 | final MessageSelector selector2, 63 | final LogicOperator logicOperator) 64 | { 65 | this.selector1 = selector1; 66 | this.selector2 = selector2; 67 | this.logicOperator = logicOperator; 68 | } 69 | 70 | // Public API 71 | @SuppressWarnings("WeakerAccess") 72 | public CombinedMessageSelector( 73 | final MessageSelector selector1, 74 | final MessageSelector selector2) 75 | { 76 | this(selector1, selector2, LogicOperator.AND); 77 | } 78 | 79 | @Override 80 | public boolean isInfoRequired() { 81 | return (selector1.isInfoRequired() || selector2.isInfoRequired()); 82 | } 83 | 84 | @Override 85 | public boolean matches(final OSCMessageEvent messageEvent) { 86 | return logicOperator.matches(selector1.matches(messageEvent), selector2.matches(messageEvent)); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/messageselector/JavaRegexAddressMessageSelector.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2014-2017 C. Ramakrishnan / Auracle 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.messageselector; 7 | 8 | import com.illposed.osc.MessageSelector; 9 | import com.illposed.osc.OSCMessageEvent; 10 | 11 | import java.util.regex.Pattern; 12 | 13 | /** 14 | * Checks whether an OSC Address Pattern matches a given Java regular expression. 15 | */ 16 | public class JavaRegexAddressMessageSelector implements MessageSelector { 17 | 18 | private final Pattern selector; 19 | 20 | // Public API 21 | @SuppressWarnings("WeakerAccess") 22 | public JavaRegexAddressMessageSelector(final Pattern selector) { 23 | this.selector = selector; 24 | } 25 | 26 | public JavaRegexAddressMessageSelector(final String selectorRegex) { 27 | this(Pattern.compile(selectorRegex)); 28 | } 29 | 30 | @Override 31 | public boolean equals(final Object other) { 32 | 33 | boolean equal = false; 34 | if (other instanceof JavaRegexAddressMessageSelector) { 35 | final JavaRegexAddressMessageSelector otherSelector 36 | = (JavaRegexAddressMessageSelector) other; 37 | equal = this.selector.equals(otherSelector.selector); 38 | } 39 | 40 | return equal; 41 | } 42 | 43 | @Override 44 | public int hashCode() { 45 | return this.selector.hashCode(); 46 | } 47 | 48 | @Override 49 | public boolean isInfoRequired() { 50 | return false; 51 | } 52 | 53 | @Override 54 | public boolean matches(final OSCMessageEvent messageEvent) { 55 | return selector.matcher(messageEvent.getMessage().getAddress()).matches(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/messageselector/JavaRegexTypeTagsMessageSelector.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2014-2017 C. Ramakrishnan / Auracle 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.messageselector; 7 | 8 | import com.illposed.osc.MessageSelector; 9 | import com.illposed.osc.OSCMessageEvent; 10 | 11 | import java.util.regex.Pattern; 12 | 13 | /** 14 | * Checks whether an OSC Argument Type Tags string matches a given Java regular expression. 15 | */ 16 | public class JavaRegexTypeTagsMessageSelector implements MessageSelector { 17 | 18 | private final Pattern selector; 19 | 20 | // Public API 21 | @SuppressWarnings("WeakerAccess") 22 | public JavaRegexTypeTagsMessageSelector(final Pattern selector) { 23 | this.selector = selector; 24 | } 25 | 26 | // Public API 27 | @SuppressWarnings("unused") 28 | public JavaRegexTypeTagsMessageSelector(final String selectorRegex) { 29 | this(Pattern.compile(selectorRegex)); 30 | } 31 | 32 | // Public API 33 | @SuppressWarnings("unused") 34 | public static MessageSelector createAddressAndTypeTagsSelector( 35 | final Pattern addressSelector, 36 | final Pattern typeTagsSelector) 37 | { 38 | return new CombinedMessageSelector( 39 | new JavaRegexAddressMessageSelector(addressSelector), 40 | new JavaRegexTypeTagsMessageSelector(typeTagsSelector)); 41 | } 42 | 43 | @Override 44 | public boolean equals(final Object other) { 45 | 46 | boolean equal = false; 47 | if (other instanceof JavaRegexTypeTagsMessageSelector) { 48 | final JavaRegexTypeTagsMessageSelector otherSelector 49 | = (JavaRegexTypeTagsMessageSelector) other; 50 | equal = this.selector.equals(otherSelector.selector); 51 | } 52 | 53 | return equal; 54 | } 55 | 56 | @Override 57 | public int hashCode() { 58 | return this.selector.hashCode(); 59 | } 60 | 61 | @Override 62 | public boolean isInfoRequired() { 63 | return true; 64 | } 65 | 66 | @Override 67 | public boolean matches(final OSCMessageEvent messageEvent) { 68 | return selector.matcher(messageEvent.getMessage().getInfo().getArgumentTypeTags()).matches(); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/messageselector/OSCPatternTypeTagsMessageSelector.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2014-2017 C. Ramakrishnan / Auracle 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.messageselector; 7 | 8 | import com.illposed.osc.MessageSelector; 9 | import com.illposed.osc.OSCMessageEvent; 10 | 11 | /** 12 | * Checks whether an OSC Argument Type Tags string matches a given wildcard expression, 13 | * as described in the OSC protocol specification for address matching. 14 | * See {@link OSCPatternAddressMessageSelector the corresponding address selector} for more details. 15 | */ 16 | public class OSCPatternTypeTagsMessageSelector implements MessageSelector { 17 | 18 | private final String selector; 19 | 20 | // Public API 21 | @SuppressWarnings("WeakerAccess") 22 | public OSCPatternTypeTagsMessageSelector(final String selector) { 23 | this.selector = selector; 24 | } 25 | 26 | // Public API 27 | @SuppressWarnings("unused") 28 | public static MessageSelector createAddressAndTypeTagsSelector( 29 | final String addressSelector, 30 | final String typeTagsSelector) 31 | { 32 | return new CombinedMessageSelector( 33 | new OSCPatternAddressMessageSelector(addressSelector), 34 | new OSCPatternTypeTagsMessageSelector(typeTagsSelector)); 35 | } 36 | 37 | @Override 38 | public boolean equals(final Object other) { 39 | 40 | boolean equal = false; 41 | if (other instanceof OSCPatternTypeTagsMessageSelector) { 42 | final OSCPatternTypeTagsMessageSelector otherSelector 43 | = (OSCPatternTypeTagsMessageSelector) other; 44 | equal = this.selector.equals(otherSelector.selector); 45 | } 46 | 47 | return equal; 48 | } 49 | 50 | @Override 51 | public int hashCode() { 52 | return this.selector.hashCode(); 53 | } 54 | 55 | @Override 56 | public boolean isInfoRequired() { 57 | return true; 58 | } 59 | 60 | @Override 61 | public boolean matches(final OSCMessageEvent messageEvent) { 62 | return OSCPatternAddressMessageSelector.matches( 63 | messageEvent.getMessage().getInfo().getArgumentTypeTags().toString(), 64 | selector); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/messageselector/package-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | /** 7 | * Provides {@link com.illposed.osc.MessageSelector} implementations. 8 | */ 9 | package com.illposed.osc.messageselector; 10 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/package-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2014-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | /** 7 | * Provides the main part of the Java OSC API. 8 | * The main part of which is serialization 9 | * (conversion from Java objects to OSC byte-stream) 10 | * and parsing 11 | * (conversion from OSC byte-stream to Java objects). 12 | */ 13 | package com.illposed.osc; 14 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/transport/NetworkProtocol.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2019 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.transport; 7 | 8 | /** 9 | * An enumeration of network protocols by which OSC packets can be sent. 10 | */ 11 | public enum NetworkProtocol { 12 | UDP, TCP; 13 | } 14 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/transport/OSCPort.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2003-2014 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.transport; 7 | 8 | import com.illposed.osc.transport.udp.UDPTransport; 9 | import com.illposed.osc.transport.tcp.TCPTransport; 10 | import com.illposed.osc.OSCSerializerAndParserBuilder; 11 | import java.io.IOException; 12 | import java.net.Inet4Address; 13 | import java.net.Inet6Address; 14 | import java.net.InetAddress; 15 | import java.net.InetSocketAddress; 16 | import java.net.SocketAddress; 17 | import java.net.UnknownHostException; 18 | 19 | /** 20 | * An abstract superclass. 21 | * To send OSC messages, use {@link OSCPortOut}. 22 | * To listen for OSC messages, use {@link OSCPortIn}. 23 | */ 24 | public class OSCPort { 25 | 26 | public static final int DEFAULT_SC_OSC_PORT = 57110; 27 | public static final int DEFAULT_SC_LANG_OSC_PORT = 57120; 28 | 29 | private final Transport transport; 30 | 31 | protected OSCPort( 32 | final SocketAddress local, 33 | final SocketAddress remote, 34 | final OSCSerializerAndParserBuilder serializerAndParserBuilder, 35 | final NetworkProtocol protocol) 36 | throws IOException 37 | { 38 | switch (protocol) { 39 | case UDP: 40 | this.transport = new UDPTransport(local, remote, serializerAndParserBuilder); 41 | break; 42 | case TCP: 43 | if (!((local instanceof InetSocketAddress) 44 | && (remote instanceof InetSocketAddress))) 45 | { 46 | throw new IllegalArgumentException( 47 | "Only InetSocketAddress is supported for TCP transport." 48 | ); 49 | } 50 | 51 | this.transport = new TCPTransport( 52 | (InetSocketAddress)local, 53 | (InetSocketAddress)remote, 54 | serializerAndParserBuilder 55 | ); 56 | break; 57 | default: 58 | throw new IllegalArgumentException( 59 | "Unexpected NetworkProtocol: " + protocol 60 | ); 61 | } 62 | } 63 | 64 | protected OSCPort( 65 | final SocketAddress local, 66 | final SocketAddress remote, 67 | final OSCSerializerAndParserBuilder serializerAndParserBuilder) 68 | throws IOException 69 | { 70 | this(local, remote, serializerAndParserBuilder, NetworkProtocol.UDP); 71 | } 72 | 73 | public Transport getTransport() { 74 | return transport; 75 | } 76 | 77 | /** 78 | * The port that the SuperCollider synth engine 79 | * usually listens to. 80 | * @return default SuperCollider synth UDP port 81 | * @see #DEFAULT_SC_OSC_PORT 82 | */ 83 | public static int defaultSCOSCPort() { 84 | return DEFAULT_SC_OSC_PORT; 85 | } 86 | 87 | /** 88 | * The port that the SuperCollider language engine 89 | * usually listens to. 90 | * @return default SuperCollider language UDP port 91 | * @see #DEFAULT_SC_LANG_OSC_PORT 92 | */ 93 | public static int defaultSCLangOSCPort() { 94 | return DEFAULT_SC_LANG_OSC_PORT; 95 | } 96 | 97 | /** 98 | * Generates a wildcard IP address (matches all IPs) of the same 99 | * family as the given address. 100 | * @param address from this we figure out the IP address family (IP v4 or v6) 101 | * @return 102 | * 0.0.0.0 if IP v4, 103 | * :: if IP v6, 104 | * undefined behavior otherwise 105 | * @throws UnknownHostException this should never occur 106 | */ 107 | public static InetAddress generateWildcard(final SocketAddress address) throws UnknownHostException { 108 | return InetAddress.getByName((extractFamily(address) == 4) ? "0.0.0.0" : "::"); 109 | } 110 | 111 | /** 112 | * Extracts the (IP) family of a given address. 113 | * @param address the address of which to return the (IP) family of 114 | * @return 115 | * 4 if IP v4, 116 | * 6 if IP v6, 117 | * 0 otherwise 118 | */ 119 | public static int extractFamily(final SocketAddress address) { 120 | final int family; 121 | if (address instanceof InetSocketAddress) { 122 | final InetSocketAddress iNetAddress = (InetSocketAddress) address; 123 | if (iNetAddress.getAddress() instanceof Inet4Address) { 124 | family = 4; 125 | } else if (iNetAddress.getAddress() instanceof Inet6Address) { 126 | family = 6; 127 | } else { 128 | family = 0; 129 | } 130 | } else { 131 | family = 0; 132 | } 133 | 134 | return family; 135 | } 136 | 137 | public void connect() throws IOException { 138 | transport.connect(); 139 | } 140 | 141 | public void disconnect() throws IOException { 142 | transport.disconnect(); 143 | } 144 | 145 | public boolean isConnected() { 146 | return transport.isConnected(); 147 | } 148 | 149 | /** 150 | * Close the socket and free-up resources. 151 | * It is recommended that clients call this when they are done with the 152 | * port. 153 | * @throws IOException If an I/O error occurs on the channel 154 | */ 155 | public void close() throws IOException { 156 | transport.close(); 157 | } 158 | 159 | @Override 160 | public String toString() { 161 | return String.format("[%s (%s)]", getClass().getSimpleName(), transport); 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/transport/OSCPortInBuilder.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2019 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.transport; 7 | 8 | import com.illposed.osc.MessageSelector; 9 | import com.illposed.osc.OSCMessageListener; 10 | import com.illposed.osc.OSCPacketDispatcher; 11 | import com.illposed.osc.OSCPacketListener; 12 | import com.illposed.osc.OSCSerializerAndParserBuilder; 13 | 14 | import java.io.IOException; 15 | import java.net.InetSocketAddress; 16 | import java.net.SocketAddress; 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | 20 | public class OSCPortInBuilder { 21 | 22 | private OSCSerializerAndParserBuilder parserBuilder; 23 | private List packetListeners; 24 | private SocketAddress local; 25 | private SocketAddress remote; 26 | private NetworkProtocol networkProtocol = NetworkProtocol.UDP; 27 | 28 | private OSCPacketListener addDefaultPacketListener() { 29 | if (packetListeners == null) { 30 | packetListeners = new ArrayList<>(); 31 | } 32 | 33 | final OSCPacketListener listener = OSCPortIn.defaultPacketListener(); 34 | packetListeners.add(listener); 35 | 36 | return listener; 37 | } 38 | 39 | public OSCPortIn build() throws IOException { 40 | if (local == null) { 41 | throw new IllegalArgumentException( 42 | "Missing local socket address / port."); 43 | } 44 | 45 | if (remote == null) { 46 | remote = new InetSocketAddress(OSCPort.generateWildcard(local), 0); 47 | } 48 | 49 | if (parserBuilder == null) { 50 | parserBuilder = new OSCSerializerAndParserBuilder(); 51 | } 52 | 53 | if (packetListeners == null) { 54 | addDefaultPacketListener(); 55 | } 56 | 57 | return new OSCPortIn( 58 | parserBuilder, packetListeners, local, remote, networkProtocol 59 | ); 60 | } 61 | 62 | public OSCPortInBuilder setPort(final int port) { 63 | final SocketAddress address = new InetSocketAddress(port); 64 | local = address; 65 | remote = address; 66 | return this; 67 | } 68 | 69 | public OSCPortInBuilder setLocalPort(final int port) { 70 | local = new InetSocketAddress(port); 71 | return this; 72 | } 73 | 74 | public OSCPortInBuilder setRemotePort(final int port) { 75 | remote = new InetSocketAddress(port); 76 | return this; 77 | } 78 | 79 | public OSCPortInBuilder setSocketAddress(final SocketAddress address) { 80 | local = address; 81 | remote = address; 82 | return this; 83 | } 84 | 85 | public OSCPortInBuilder setLocalSocketAddress(final SocketAddress address) { 86 | local = address; 87 | return this; 88 | } 89 | 90 | public OSCPortInBuilder setRemoteSocketAddress(final SocketAddress address) { 91 | remote = address; 92 | return this; 93 | } 94 | 95 | public OSCPortInBuilder setNetworkProtocol(final NetworkProtocol protocol) { 96 | networkProtocol = protocol; 97 | return this; 98 | } 99 | 100 | public OSCPortInBuilder setPacketListeners( 101 | final List listeners) 102 | { 103 | packetListeners = listeners; 104 | return this; 105 | } 106 | 107 | public OSCPortInBuilder setPacketListener(final OSCPacketListener listener) { 108 | packetListeners = new ArrayList<>(); 109 | packetListeners.add(listener); 110 | return this; 111 | } 112 | 113 | public OSCPortInBuilder addPacketListener(final OSCPacketListener listener) { 114 | if (packetListeners == null) { 115 | packetListeners = new ArrayList<>(); 116 | } 117 | 118 | packetListeners.add(listener); 119 | return this; 120 | } 121 | 122 | public OSCPortInBuilder addMessageListener( 123 | final MessageSelector selector, final OSCMessageListener listener) 124 | { 125 | OSCPacketDispatcher dispatcher = OSCPortIn.getDispatcher(packetListeners); 126 | 127 | if (dispatcher == null) { 128 | dispatcher = (OSCPacketDispatcher)addDefaultPacketListener(); 129 | } 130 | 131 | dispatcher.addListener(selector, listener); 132 | 133 | return this; 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/transport/OSCPortOut.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2004-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.transport; 7 | 8 | import com.illposed.osc.OSCPacket; 9 | import com.illposed.osc.OSCSerializeException; 10 | import com.illposed.osc.OSCSerializerAndParserBuilder; 11 | import java.io.IOException; 12 | import java.net.InetAddress; 13 | import java.net.InetSocketAddress; 14 | import java.net.SocketAddress; 15 | 16 | /** 17 | * Sends OSC packets to a specific address and port. 18 | * 19 | * To send an OSC message, call {@link #send(OSCPacket)}. 20 | * 21 | * An example:
22 | *
{@code
 23 |  * // sends from "localhost"
 24 |  * OSCPortOut sender = new OSCPortOut();
 25 |  * List args = new ArrayList(2);
 26 |  * args.add(3);
 27 |  * args.add("hello");
 28 |  * OSCMessage msg = new OSCMessage("/sayHello", args);
 29 |  * try {
 30 |  * 	sender.send(msg);
 31 |  * } catch (Exception ex) {
 32 |  * 	System.err.println("Couldn't send");
 33 |  * }
 34 |  * }
 35 |  */
 36 | public class OSCPortOut extends OSCPort {
 37 | 
 38 | 	/**
 39 | 	 * Creates an OSC-Port that sends to {@code remote} from the specified local socket,
 40 | 	 * using an {@link com.illposed.osc.OSCSerializer}
 41 | 	 * created from the given factory for converting the packets.
 42 | 	 * @param serializerBuilder used to create a single
 43 | 	 *   {@link com.illposed.osc.OSCSerializer} that is used to convert
 44 | 	 *   all packets to be sent from this port,
 45 | 	 *   from Java objects to their OSC byte array representations
 46 | 	 * @param remote where we will send the OSC byte array data to
 47 | 	 * @param local the local address we use to connect to the remote
 48 | 	 * @param protocol the network protocol by which to send OSC packets
 49 | 	 * @throws IOException if we fail to bind a channel to the local address
 50 | 	 */
 51 | 	public OSCPortOut(
 52 | 			final OSCSerializerAndParserBuilder serializerBuilder,
 53 | 			final SocketAddress remote,
 54 | 			final SocketAddress local,
 55 | 			final NetworkProtocol protocol)
 56 | 			throws IOException
 57 | 	{
 58 | 		super(local, remote, serializerBuilder, protocol);
 59 | 	}
 60 | 
 61 | 	public OSCPortOut(
 62 | 			final OSCSerializerAndParserBuilder serializerBuilder,
 63 | 			final SocketAddress remote,
 64 | 			final SocketAddress local)
 65 | 			throws IOException
 66 | 	{
 67 | 		this(serializerBuilder, remote, local, NetworkProtocol.UDP);
 68 | 	}
 69 | 
 70 | 	public OSCPortOut(
 71 | 			final OSCSerializerAndParserBuilder serializerFactory,
 72 | 			final SocketAddress remote)
 73 | 			throws IOException
 74 | 	{
 75 | 		this(serializerFactory, remote, new InetSocketAddress(
 76 | 				OSCPort.generateWildcard(remote), 0));
 77 | 	}
 78 | 
 79 | 	public OSCPortOut(final SocketAddress remote) throws IOException {
 80 | 		this(new OSCSerializerAndParserBuilder(), remote);
 81 | 	}
 82 | 
 83 | 	/**
 84 | 	 * Creates an OSC-Port that sends to {@code remote}:{@code port}.
 85 | 	 * @param remote the address to send to
 86 | 	 * @param port the port number to send to
 87 | 	 * @throws IOException if we fail to bind a channel to the local address
 88 | 	 */
 89 | 	public OSCPortOut(final InetAddress remote, final int port) throws IOException {
 90 | 		this(new InetSocketAddress(remote, port));
 91 | 	}
 92 | 
 93 | 	/**
 94 | 	 * Creates an OSC-Port that sends to {@code remote}:{@link #DEFAULT_SC_OSC_PORT}.
 95 | 	 * @param remote the address to send to
 96 | 	 * @throws IOException if we fail to bind a channel to the local address
 97 | 	 */
 98 | 	public OSCPortOut(final InetAddress remote) throws IOException {
 99 | 		this(remote, DEFAULT_SC_OSC_PORT);
100 | 	}
101 | 
102 | 	/**
103 | 	 * Creates an OSC-Port that sends to "localhost":{@link #DEFAULT_SC_OSC_PORT}.
104 | 	 * @throws IOException if we fail to bind a channel to the local address,
105 | 	 *   or if the local host name could not be resolved into an address
106 | 	 */
107 | 	public OSCPortOut() throws IOException {
108 | 		this(new InetSocketAddress(InetAddress.getLocalHost(), DEFAULT_SC_OSC_PORT));
109 | 	}
110 | 
111 | 	/**
112 | 	 * Converts and sends an OSC packet (message or bundle) to the remote address.
113 | 	 * @param packet the bundle or message to be converted and sent
114 | 	 * @throws IOException if a socket I/O error occurs while sending
115 | 	 * @throws OSCSerializeException if the packet fails to serialize,
116 | 	 *   including when the buffer overruns
117 | 	 */
118 | 	public void send(final OSCPacket packet) throws IOException, OSCSerializeException {
119 | 		getTransport().send(packet);
120 | 	}
121 | }
122 | 


--------------------------------------------------------------------------------
/modules/core/src/main/java/com/illposed/osc/transport/OSCPortOutBuilder.java:
--------------------------------------------------------------------------------
 1 | // SPDX-FileCopyrightText: 2019 C. Ramakrishnan / Illposed Software
 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 
 3 | //
 4 | // SPDX-License-Identifier: BSD-3-Clause
 5 | 
 6 | package com.illposed.osc.transport;
 7 | 
 8 | import com.illposed.osc.OSCSerializerAndParserBuilder;
 9 | 
10 | import java.io.IOException;
11 | import java.net.InetSocketAddress;
12 | import java.net.SocketAddress;
13 | 
14 | public class OSCPortOutBuilder {
15 | 
16 | 	private OSCSerializerAndParserBuilder serializerBuilder;
17 | 	private SocketAddress remote;
18 | 	private SocketAddress local;
19 | 	private NetworkProtocol networkProtocol = NetworkProtocol.UDP;
20 | 
21 | 	public OSCPortOut build() throws IOException {
22 | 		if (remote == null) {
23 | 			throw new IllegalArgumentException(
24 | 				"Missing remote socket address / port.");
25 | 		}
26 | 
27 | 		if (local == null) {
28 | 			local = new InetSocketAddress(OSCPort.generateWildcard(remote), 0);
29 | 		}
30 | 
31 | 		if (serializerBuilder == null) {
32 | 			serializerBuilder = new OSCSerializerAndParserBuilder();
33 | 		}
34 | 
35 | 		return new OSCPortOut(
36 | 			serializerBuilder, remote, local, networkProtocol
37 | 		);
38 | 	}
39 | 
40 | 	public OSCPortOutBuilder setPort(final int port) {
41 | 		final SocketAddress address = new InetSocketAddress(port);
42 | 		local = address;
43 | 		remote = address;
44 | 		return this;
45 | 	}
46 | 
47 | 	public OSCPortOutBuilder setRemotePort(final int port) {
48 | 		remote = new InetSocketAddress(port);
49 | 		return this;
50 | 	}
51 | 
52 | 	public OSCPortOutBuilder setLocalPort(final int port) {
53 | 		local = new InetSocketAddress(port);
54 | 		return this;
55 | 	}
56 | 
57 | 	public OSCPortOutBuilder setSocketAddress(final SocketAddress address) {
58 | 		local = address;
59 | 		remote = address;
60 | 		return this;
61 | 	}
62 | 
63 | 	public OSCPortOutBuilder setLocalSocketAddress(final SocketAddress address) {
64 | 		local = address;
65 | 		return this;
66 | 	}
67 | 
68 | 	public OSCPortOutBuilder setRemoteSocketAddress(final SocketAddress address) {
69 | 		remote = address;
70 | 		return this;
71 | 	}
72 | 
73 | 	public OSCPortOutBuilder setNetworkProtocol(final NetworkProtocol protocol) {
74 | 		networkProtocol = protocol;
75 | 		return this;
76 | 	}
77 | }
78 | 


--------------------------------------------------------------------------------
/modules/core/src/main/java/com/illposed/osc/transport/Transport.java:
--------------------------------------------------------------------------------
 1 | // SPDX-FileCopyrightText: 2004-2019 C. Ramakrishnan / Illposed Software
 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 
 3 | //
 4 | // SPDX-License-Identifier: BSD-3-Clause
 5 | 
 6 | package com.illposed.osc.transport;
 7 | 
 8 | import com.illposed.osc.OSCPacket;
 9 | import com.illposed.osc.OSCSerializeException;
10 | import com.illposed.osc.OSCParseException;
11 | import java.io.IOException;
12 | 
13 | /**
14 |  * An interface about sending and receiving OSC packets over a network.
15 |  *
16 |  * Implementations:
17 |  * 
    18 | *
  • {@link com.illposed.osc.transport.udp.UDPTransport}
  • 19 | *
  • {@link com.illposed.osc.transport.tcp.TCPTransport}
  • 20 | *
21 | */ 22 | public interface Transport { 23 | 24 | /** 25 | * Converts and sends an OSC packet (message or bundle) to the remote address. 26 | * @param packet the bundle or message to be converted and sent 27 | * @throws IOException if we run out of memory while converting, 28 | * or a socket I/O error occurs while sending 29 | * @throws OSCSerializeException if the packet fails to serialize 30 | */ 31 | void send(OSCPacket packet) throws IOException, OSCSerializeException; 32 | 33 | /** 34 | * Receive an OSC packet. 35 | * @return the packet received 36 | * @throws IOException if an I/O error occurs while trying to read from the 37 | * @throws OSCParseException if the packet fails to parse 38 | * channel 39 | */ 40 | OSCPacket receive() throws IOException, OSCParseException; 41 | 42 | boolean isBlocking(); 43 | 44 | void connect() throws IOException; 45 | 46 | void disconnect() throws IOException; 47 | 48 | boolean isConnected(); 49 | 50 | /** 51 | * Close the socket and free-up resources. 52 | * It is recommended that clients call this when they are done with the 53 | * port. 54 | * @throws IOException If an I/O error occurs 55 | */ 56 | void close() throws IOException; 57 | } 58 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/transport/channel/package-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | /** 7 | * Provides means to send and receive OSC content over the UDP(/IP) protocol. 8 | */ 9 | package com.illposed.osc.transport.channel; 10 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/transport/package-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | /** 7 | * Provides means to send and receive OSC content over a network. 8 | */ 9 | package com.illposed.osc.transport; 10 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/transport/tcp/package-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2004-2019 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | /** 7 | * Provides means to send and receive OSC content via TCP. 8 | */ 9 | package com.illposed.osc.transport.tcp; 10 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/transport/udp/UDPTransport.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2004-2019 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.transport.udp; 7 | 8 | import com.illposed.osc.LibraryInfo; 9 | import com.illposed.osc.OSCPacket; 10 | import com.illposed.osc.OSCParseException; 11 | import com.illposed.osc.OSCSerializerAndParserBuilder; 12 | import com.illposed.osc.OSCSerializeException; 13 | import com.illposed.osc.transport.Transport; 14 | import com.illposed.osc.transport.channel.OSCDatagramChannel; 15 | import java.io.IOException; 16 | import java.net.Inet4Address; 17 | import java.net.Inet6Address; 18 | import java.net.InetSocketAddress; 19 | import java.net.SocketAddress; 20 | import java.net.StandardProtocolFamily; 21 | import java.net.StandardSocketOptions; 22 | import java.nio.ByteBuffer; 23 | import java.nio.channels.DatagramChannel; 24 | 25 | /** 26 | * A {@link Transport} implementation for sending and receiving OSC packets over 27 | * a network via UDP. 28 | */ 29 | public class UDPTransport implements Transport { 30 | 31 | /** 32 | * Buffers were 1500 bytes in size, but were increased to 1536, as this 33 | * is a common MTU, and then increased to 65507, as this is the maximum 34 | * incoming datagram data size. 35 | */ 36 | public static final int BUFFER_SIZE = 65507; 37 | private final ByteBuffer recvBuffer = ByteBuffer.allocate(BUFFER_SIZE); 38 | private final ByteBuffer sendBuffer = ByteBuffer.allocate(BUFFER_SIZE); 39 | 40 | private final SocketAddress local; 41 | private final SocketAddress remote; 42 | private final DatagramChannel channel; 43 | private final OSCDatagramChannel oscChannel; 44 | 45 | public UDPTransport( 46 | final SocketAddress local, 47 | final SocketAddress remote) 48 | throws IOException 49 | { 50 | this(local, remote, new OSCSerializerAndParserBuilder()); 51 | } 52 | 53 | public UDPTransport( 54 | final SocketAddress local, 55 | final SocketAddress remote, 56 | final OSCSerializerAndParserBuilder serializerAndParserBuilder) 57 | throws IOException 58 | { 59 | this.local = local; 60 | this.remote = remote; 61 | final DatagramChannel tmpChannel; 62 | if ((local instanceof InetSocketAddress) && LibraryInfo.hasStandardProtocolFamily()) { 63 | final InetSocketAddress localIsa = (InetSocketAddress) local; 64 | final InetSocketAddress remoteIsa = (InetSocketAddress) remote; 65 | final Class localClass = localIsa.getAddress().getClass(); 66 | final Class remoteClass = remoteIsa.getAddress().getClass(); 67 | 68 | if (!localClass.equals(remoteClass)) { 69 | throw new IllegalArgumentException( 70 | "local and remote addresses are not of the same family" 71 | + " (IP v4 vs v6)"); 72 | } 73 | if (localIsa.getAddress() instanceof Inet4Address) { 74 | tmpChannel = DatagramChannel.open(StandardProtocolFamily.INET); 75 | } else if (localIsa.getAddress() instanceof Inet6Address) { 76 | tmpChannel = DatagramChannel.open(StandardProtocolFamily.INET6); 77 | } else { 78 | throw new IllegalArgumentException( 79 | "Unknown address type: " 80 | + localIsa.getAddress().getClass().getCanonicalName()); 81 | } 82 | } else { 83 | tmpChannel = DatagramChannel.open(); 84 | } 85 | this.channel = tmpChannel; 86 | if (LibraryInfo.hasStandardProtocolFamily()) { 87 | this.channel.setOption(StandardSocketOptions.SO_SNDBUF, BUFFER_SIZE); 88 | // NOTE So far, we never saw an issue with the receive-buffer size, 89 | // thus we leave it at its default. 90 | this.channel.setOption(StandardSocketOptions.SO_REUSEADDR, true); 91 | this.channel.setOption(StandardSocketOptions.SO_BROADCAST, true); 92 | } else { 93 | this.channel.socket().setSendBufferSize(BUFFER_SIZE); 94 | // NOTE So far, we never saw an issue with the receive-buffer size, 95 | // thus we leave it at its default. 96 | this.channel.socket().setReuseAddress(true); 97 | this.channel.socket().setBroadcast(true); 98 | } 99 | this.channel.socket().bind(local); 100 | this.oscChannel = new OSCDatagramChannel(channel, serializerAndParserBuilder); 101 | } 102 | 103 | @Override 104 | public void connect() throws IOException { 105 | if (remote == null) { 106 | throw new IllegalStateException( 107 | "Can not connect a socket without a remote address specified" 108 | ); 109 | } 110 | channel.connect(remote); 111 | } 112 | 113 | @Override 114 | public void disconnect() throws IOException { 115 | channel.disconnect(); 116 | } 117 | 118 | @Override 119 | public boolean isConnected() { 120 | return channel.isConnected(); 121 | } 122 | 123 | /** 124 | * Close the socket and free-up resources. 125 | * It is recommended that clients call this when they are done with the port. 126 | * @throws IOException If an I/O error occurs on the channel 127 | */ 128 | @Override 129 | public void close() throws IOException { 130 | channel.close(); 131 | } 132 | 133 | @Override 134 | public void send(final OSCPacket packet) throws IOException, OSCSerializeException { 135 | oscChannel.send(sendBuffer, packet, remote); 136 | } 137 | 138 | @Override 139 | public OSCPacket receive() throws IOException, OSCParseException { 140 | return oscChannel.read(recvBuffer); 141 | } 142 | 143 | @Override 144 | public boolean isBlocking() { 145 | return channel.isBlocking(); 146 | } 147 | 148 | @Override 149 | public String toString() { 150 | return String.format( 151 | "%s: local=%s, remote=%s", getClass().getSimpleName(), local, remote 152 | ); 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /modules/core/src/main/java/com/illposed/osc/transport/udp/package-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2004-2019 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | /** 7 | * Provides means to send and receive OSC content via UDP. 8 | */ 9 | package com.illposed.osc.transport.udp; 10 | -------------------------------------------------------------------------------- /modules/core/src/test/java/com/illposed/osc/BenchmarkHashMapVsElseIf.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2014 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc; 7 | 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | import java.util.ArrayList; 11 | import java.util.Collections; 12 | import java.util.HashMap; 13 | import java.util.List; 14 | import java.util.Map; 15 | import java.util.Random; 16 | 17 | /** 18 | * Runs a very basic benchmark test to check whether using an else-if-chain or 19 | * a HashMap based approach is faster, when trying to convert a java class to 20 | * an OSC Type indicator char. 21 | */ 22 | public class BenchmarkHashMapVsElseIf { 23 | 24 | private static final Logger LOG = LoggerFactory.getLogger(BenchmarkHashMapVsElseIf.class); 25 | 26 | private static final Map JAVA_CLASS_TO_OSC_TYPE; 27 | static { 28 | Map classToType = new HashMap<>(6); 29 | 30 | classToType.put(Integer.class, 'i'); 31 | classToType.put(Long.class, 'h'); 32 | classToType.put(Float.class, 'f'); 33 | classToType.put(Double.class, 'd'); 34 | classToType.put(String.class, 's'); 35 | classToType.put(Character.class, 'c'); 36 | 37 | JAVA_CLASS_TO_OSC_TYPE = Collections.unmodifiableMap(classToType); 38 | } 39 | private static final List JAVA_CLASSES 40 | = new ArrayList<>(JAVA_CLASS_TO_OSC_TYPE.keySet()); 41 | private static final Random TYPE_GENERATOR_RND = new Random(); 42 | 43 | public static void main(String[] args) { 44 | 45 | final int numDataPoints = 1000000; 46 | final int numTestRuns = 100; 47 | 48 | runBenchmark(numDataPoints, numTestRuns); 49 | } 50 | 51 | @SuppressWarnings("WeakerAccess") 52 | public static void runBenchmark(final int numDataPoints, final int numTestRuns) { 53 | 54 | LOG.info("Generating {} data-points", numDataPoints); 55 | long start = System.currentTimeMillis(); 56 | final List generateRandomTypes = generateRandomTypes(numDataPoints); 57 | final long timeGenerateData = System.currentTimeMillis() - start; 58 | LOG.info("Time data generation: {} ms", timeGenerateData); 59 | 60 | LOG.info("Running '... else if ...' benchmark {} times ...", numTestRuns); 61 | start = System.currentTimeMillis(); 62 | for (int tri = 0; tri < numTestRuns; tri++) { 63 | for (Class type : generateRandomTypes) { 64 | convertToTypeElseIf(type); 65 | } 66 | } 67 | final long timeElseIf = (System.currentTimeMillis() - start) / numTestRuns; 68 | LOG.info("Average time '... else if ...': {} ms", timeElseIf); 69 | 70 | LOG.info("Running 'HashMap' benchmark {} times ...", numTestRuns); 71 | start = System.currentTimeMillis(); 72 | for (int tri = 0; tri < numTestRuns; tri++) { 73 | for (Class type : generateRandomTypes) { 74 | convertToTypeHashMap(type); 75 | } 76 | } 77 | final long timeHashMap = (System.currentTimeMillis() - start) / numTestRuns; 78 | LOG.info("Average time 'HashMap': {} ms", timeHashMap); 79 | } 80 | 81 | private static Class generateRandomType() { 82 | return JAVA_CLASSES.get(TYPE_GENERATOR_RND.nextInt(JAVA_CLASSES.size())); 83 | } 84 | 85 | private static List generateRandomTypes(int numEntries) { 86 | 87 | List types = new ArrayList<>(numEntries); 88 | for (int ti = 0; ti < numEntries; ti++) { 89 | types.add(generateRandomType()); 90 | } 91 | 92 | return types; 93 | } 94 | 95 | @SuppressWarnings({"WeakerAccess", "UnusedReturnValue"}) 96 | public static Character convertToTypeHashMap(Class cls) { 97 | return JAVA_CLASS_TO_OSC_TYPE.get(cls); 98 | } 99 | 100 | @SuppressWarnings({"WeakerAccess", "UnusedReturnValue"}) 101 | public static Character convertToTypeElseIf(Class cls) { 102 | 103 | final char type; 104 | 105 | // A big ol' else-if chain -- what's polymorphism mean, again? 106 | // I really wish I could extend the base classes! 107 | if (Integer.class.equals(cls)) { 108 | type = 'i'; 109 | } else if (Long.class.equals(cls)) { 110 | type = 'h'; 111 | } else if (Float.class.equals(cls)) { 112 | type = 'f'; 113 | } else if (Double.class.equals(cls)) { 114 | type = 'd'; 115 | } else if (String.class.equals(cls)) { 116 | type = 's'; 117 | } else if (Character.class.equals(cls)) { 118 | type = 'c'; 119 | } else { 120 | throw new RuntimeException(); 121 | } 122 | 123 | return type; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /modules/core/src/test/java/com/illposed/osc/Debug.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | package com.illposed.osc; 6 | 7 | import com.illposed.osc.OSCBundle; 8 | import com.illposed.osc.OSCMessage; 9 | import com.illposed.osc.OSCPacket; 10 | import java.util.Arrays; 11 | import java.util.Collections; 12 | import java.util.stream.Collectors; 13 | 14 | public class Debug 15 | { 16 | private static String indent(String str, int indentLevel) { 17 | String indentation = String.join("", Collections.nCopies(indentLevel, " ")); 18 | 19 | return Arrays.asList(str.split("\\R")) 20 | .stream() 21 | .map(line -> indentation + line) 22 | .collect(Collectors.joining("\n")); 23 | } 24 | 25 | private static String debug(OSCPacket packet, int indentLevel) { 26 | if (packet instanceof OSCBundle) { 27 | OSCBundle bundle = (OSCBundle)packet; 28 | 29 | StringBuilder sb = new StringBuilder(); 30 | sb.append(String.format("bundle (%s)", bundle.getTimestamp())); 31 | 32 | for (OSCPacket entry : bundle.getPackets()) { 33 | sb.append("\n" + indent(debug(entry), indentLevel + 1)); 34 | } 35 | 36 | return sb.toString(); 37 | } 38 | 39 | OSCMessage message = (OSCMessage)packet; 40 | 41 | StringBuilder sb = new StringBuilder(); 42 | sb.append(String.format("message (%s)", message.getAddress())); 43 | 44 | for (Object argument : message.getArguments()) { 45 | sb.append( 46 | "\n" + 47 | indent( 48 | argument == null 49 | ? "[null]" 50 | : String.format( 51 | "[%s] %s", argument.getClass(), argument.toString() 52 | ), 53 | indentLevel + 1 54 | ) 55 | ); 56 | } 57 | 58 | return sb.toString(); 59 | } 60 | 61 | public static String debug(OSCPacket packet) { 62 | return debug(packet, 0); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /modules/core/src/test/java/com/illposed/osc/DebugClient.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | package com.illposed.osc; 6 | 7 | // To run from the command line: 8 | // 9 | // cd modules/core 10 | // 11 | // mvn test-compile exec:java \ 12 | // -Dexec.mainClass=com.illposed.osc.DebugClient \ 13 | // -Dexec.classpathScope=test \ 14 | // -Dexec.args="udp 12345" # protocol and port number 15 | 16 | import com.illposed.osc.OSCBundle; 17 | import com.illposed.osc.OSCMessage; 18 | import com.illposed.osc.OSCPacket; 19 | import com.illposed.osc.argument.OSCTimeTag64; 20 | import com.illposed.osc.transport.NetworkProtocol; 21 | import com.illposed.osc.transport.OSCPortOut; 22 | import com.illposed.osc.transport.OSCPortOutBuilder; 23 | import java.net.InetAddress; 24 | import java.net.InetSocketAddress; 25 | import java.util.ArrayList; 26 | import java.util.Arrays; 27 | import java.util.Date; 28 | import java.util.List; 29 | import java.util.Scanner; 30 | import java.util.function.Supplier; 31 | 32 | public class DebugClient 33 | { 34 | private static int randInt(int bound) { 35 | return (int)(Math.floor(Math.random() * bound)); 36 | } 37 | 38 | private static List> argFunctions = Arrays.asList( 39 | () -> randInt(100000), 40 | () -> Math.random() * 100000, 41 | () -> "test string " + randInt(1000), 42 | () -> ("test string " + randInt(1000)).getBytes(), 43 | () -> OSCTimeTag64.valueOf(new Date()), 44 | () -> true, 45 | () -> false, 46 | () -> null 47 | ); 48 | 49 | private static OSCMessage randomMessage(String address) { 50 | List args = new ArrayList(); 51 | 52 | for (int i = 0; i < 1 + randInt(5); i++) { 53 | args.add(argFunctions.get(randInt(argFunctions.size())).get()); 54 | } 55 | 56 | return new OSCMessage(address, args); 57 | } 58 | 59 | private static OSCBundle randomBundle() { 60 | List packets = new ArrayList(); 61 | 62 | for (int i = 0; i < 1 + randInt(5); i++) { 63 | if (Math.random() < 0.00000001) { 64 | packets.add(randomBundle()); 65 | } else { 66 | packets.add(randomMessage("/bundle/message/" + (i + 1))); 67 | } 68 | } 69 | 70 | return new OSCBundle(packets); 71 | } 72 | 73 | public static void main(String[] args) throws Exception 74 | { 75 | if (args.length != 2) { 76 | System.err.println("Usage: DebugClient PROTOCOL PORT"); 77 | System.exit(1); 78 | } 79 | 80 | String protocolStr = args[0].toLowerCase(); 81 | 82 | NetworkProtocol protocol; 83 | switch (protocolStr) { 84 | case "udp": 85 | protocol = NetworkProtocol.UDP; 86 | break; 87 | case "tcp": 88 | protocol = NetworkProtocol.TCP; 89 | break; 90 | default: 91 | throw new IllegalArgumentException("Invalid protocol: " + protocolStr); 92 | } 93 | 94 | int port = Integer.parseInt(args[1]); 95 | 96 | OSCPortOut client = 97 | new OSCPortOutBuilder() 98 | .setNetworkProtocol(protocol) 99 | .setRemoteSocketAddress( 100 | new InetSocketAddress(InetAddress.getLoopbackAddress(), port) 101 | ) 102 | .build(); 103 | 104 | System.out.printf("Protocol: %s, port: %d\n", protocol, port); 105 | System.out.println("Enter m to send a message, b to send a bundle."); 106 | 107 | try (Scanner scanner = new Scanner(System.in)) { 108 | while (true) { 109 | System.out.print("> "); 110 | String input = scanner.nextLine(); 111 | 112 | try { 113 | switch (input) { 114 | case "m": 115 | OSCMessage message = randomMessage("/message/address"); 116 | System.out.println(Debug.debug(message)); 117 | client.send(message); 118 | break; 119 | case "b": 120 | OSCBundle bundle = randomBundle(); 121 | System.out.println(Debug.debug(bundle)); 122 | client.send(bundle); 123 | break; 124 | } 125 | } catch (Throwable t) { 126 | t.printStackTrace(); 127 | } 128 | } 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /modules/core/src/test/java/com/illposed/osc/DebugServer.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | package com.illposed.osc; 6 | 7 | // To run from the command line: 8 | // 9 | // cd modules/core 10 | // 11 | // mvn test-compile exec:java \ 12 | // -Dexec.mainClass=com.illposed.osc.DebugServer \ 13 | // -Dexec.classpathScope=test \ 14 | // -Dexec.args="udp 12345" # protocol and port number 15 | 16 | import com.illposed.osc.OSCBadDataEvent; 17 | import com.illposed.osc.OSCPacketEvent; 18 | import com.illposed.osc.OSCPacketListener; 19 | import com.illposed.osc.transport.NetworkProtocol; 20 | import com.illposed.osc.transport.OSCPortIn; 21 | import com.illposed.osc.transport.OSCPortInBuilder; 22 | 23 | public class DebugServer 24 | { 25 | public static void main(String[] args) throws Exception 26 | { 27 | if (args.length != 2) { 28 | System.err.println("Usage: DebugServer PROTOCOL PORT"); 29 | System.exit(1); 30 | } 31 | 32 | String protocolStr = args[0].toLowerCase(); 33 | 34 | NetworkProtocol protocol; 35 | switch (protocolStr) { 36 | case "udp": 37 | protocol = NetworkProtocol.UDP; 38 | break; 39 | case "tcp": 40 | protocol = NetworkProtocol.TCP; 41 | break; 42 | default: 43 | throw new IllegalArgumentException("Invalid protocol: " + protocolStr); 44 | } 45 | 46 | int port = Integer.parseInt(args[1]); 47 | 48 | OSCPacketListener debugger = new OSCPacketListener() { 49 | public void handlePacket(OSCPacketEvent event) { 50 | System.out.println(Debug.debug(event.getPacket()) + "\n"); 51 | } 52 | 53 | public void handleBadData(OSCBadDataEvent event) { 54 | System.out.println("bad data event: " + event); 55 | } 56 | }; 57 | 58 | OSCPortIn server = 59 | new OSCPortInBuilder() 60 | .setNetworkProtocol(protocol) 61 | .setLocalPort(port) 62 | .setPacketListener(debugger) 63 | .build(); 64 | 65 | System.out.printf("Listening via %s on port %d...\n", protocol, port); 66 | 67 | server.startListening(); 68 | 69 | while (true) { 70 | Thread.sleep(100); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /modules/core/src/test/java/com/illposed/osc/OSCBundleTest.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2003 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc; 7 | 8 | import com.illposed.osc.argument.OSCTimeTag64; 9 | import java.util.ArrayList; 10 | import java.util.Date; 11 | import java.util.GregorianCalendar; 12 | import java.util.List; 13 | import org.junit.jupiter.api.Assertions; 14 | import org.junit.jupiter.api.Test; 15 | 16 | /** 17 | * @see OSCBundle 18 | */ 19 | public class OSCBundleTest { 20 | 21 | private void sendBundleTimestampTestHelper( 22 | final OSCBundle bundle, 23 | final OSCTimeTag64 expectedTimestamp) 24 | throws OSCSerializeException, OSCParseException 25 | { 26 | final OSCBundle reparsedBundle = OSCReparserTest.reparse(bundle); 27 | if (!reparsedBundle.getTimestamp().equals(expectedTimestamp)) { 28 | Assertions.fail("Send Bundle did not receive the correct timestamp " 29 | + reparsedBundle.getTimestamp().getNtpTime() 30 | + " (should be " + expectedTimestamp.getNtpTime() + ')'); 31 | } 32 | List packets = reparsedBundle.getPackets(); 33 | OSCMessage msg = (OSCMessage) packets.get(0); 34 | if (!msg.getAddress().equals("/dummy")) { 35 | Assertions.fail("Send Bundle's message did not receive the correct address"); 36 | } 37 | } 38 | 39 | @Test 40 | public void testSendBundle() throws Exception { 41 | final Date timeNow = GregorianCalendar.getInstance().getTime(); 42 | final OSCTimeTag64 timestampNow = OSCTimeTag64.valueOf(timeNow); 43 | List packetsSent = new ArrayList<>(1); 44 | packetsSent.add(new OSCMessage("/dummy")); 45 | OSCBundle bundle = new OSCBundle(packetsSent, timestampNow); 46 | sendBundleTimestampTestHelper(bundle, timestampNow); 47 | } 48 | 49 | @Test 50 | public void testSendBundleImmediate() throws Exception { 51 | List packetsSent = new ArrayList<>(1); 52 | packetsSent.add(new OSCMessage("/dummy")); 53 | OSCBundle bundle = new OSCBundle(packetsSent); 54 | sendBundleTimestampTestHelper(bundle, OSCTimeTag64.IMMEDIATE); 55 | } 56 | 57 | @Test 58 | public void testSendBundleImmediateExplicit() throws Exception { 59 | final Date timeNow = GregorianCalendar.getInstance().getTime(); 60 | final OSCTimeTag64 timestampNow = OSCTimeTag64.valueOf(timeNow); 61 | List packetsSent = new ArrayList<>(1); 62 | packetsSent.add(new OSCMessage("/dummy")); 63 | OSCBundle bundle = new OSCBundle(packetsSent, timestampNow); 64 | bundle.setTimestamp(OSCTimeTag64.IMMEDIATE); 65 | sendBundleTimestampTestHelper(bundle, OSCTimeTag64.IMMEDIATE); 66 | } 67 | 68 | @Test 69 | public void testSendBundleImmediateExplicitNull() throws Exception { 70 | final Date timeNow = GregorianCalendar.getInstance().getTime(); 71 | final OSCTimeTag64 timestampNow = OSCTimeTag64.valueOf(timeNow); 72 | List packetsSent = new ArrayList<>(1); 73 | packetsSent.add(new OSCMessage("/dummy")); 74 | OSCBundle bundle = new OSCBundle(packetsSent, timestampNow); 75 | Assertions.assertThrows( 76 | IllegalArgumentException.class, 77 | () -> bundle.setTimestamp(null) 78 | ); 79 | // sendBundleTimestampTestHelper(bundle, OSCTimeTag64.IMMEDIATE); 80 | } 81 | 82 | @Test 83 | public void testSendMultiLevelBundle() throws Exception { 84 | 85 | // create this structure: 86 | // bundle-0 87 | // > message-0 88 | // > bundle-1 89 | // > message-1 90 | // > bundle-2 91 | // > message-2 92 | // > message-3 93 | 94 | final List packetsBundle2 = new ArrayList<>(2); 95 | packetsBundle2.add(new OSCMessage("/leaf/2")); 96 | packetsBundle2.add(new OSCMessage("/leaf/3")); 97 | final OSCBundle bundle2 = new OSCBundle(packetsBundle2); 98 | 99 | final List packetsBundle1 = new ArrayList<>(2); 100 | packetsBundle1.add(new OSCMessage("/leaf/1")); 101 | packetsBundle1.add(bundle2); 102 | final OSCBundle bundle1 = new OSCBundle(packetsBundle1); 103 | 104 | final List packetsBundle0 = new ArrayList<>(2); 105 | packetsBundle0.add(new OSCMessage("/leaf/0")); 106 | packetsBundle0.add(bundle1); 107 | final OSCBundle bundle0 = new OSCBundle(packetsBundle0); 108 | 109 | OSCReparserTest.reparse(bundle0); 110 | // TODO make a smarter test, where we serialize, re-parse and then check the whole thing 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /modules/core/src/test/java/com/illposed/osc/OSCPacketDispatcherTest.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2003 C. Ramakrishnan / Auracle 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc; 7 | 8 | import com.illposed.osc.messageselector.OSCPatternAddressMessageSelector; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | import org.junit.jupiter.api.BeforeEach; 12 | import org.junit.jupiter.api.Assertions; 13 | import org.junit.jupiter.api.Test; 14 | 15 | /** 16 | * @see OSCPacketDispatcher 17 | */ 18 | public class OSCPacketDispatcherTest { 19 | 20 | private OSCPacketDispatcher dispatcher; 21 | private SimpleOSCMessageListener listener1; 22 | private SimpleOSCMessageListener listener2; 23 | 24 | @BeforeEach 25 | public void setUp() { 26 | dispatcher = new OSCPacketDispatcher(new OSCSerializerAndParserBuilder()); 27 | listener1 = new SimpleOSCMessageListener(); 28 | dispatcher.addListener(new OSCPatternAddressMessageSelector("/listener1"), listener1); 29 | listener2 = new SimpleOSCMessageListener(); 30 | dispatcher.addListener(new OSCPatternAddressMessageSelector("/listener2"), listener2); 31 | } 32 | 33 | @Test 34 | public void testDispatchToListener1() { 35 | OSCMessage message = new OSCMessage("/listener1"); 36 | dispatcher.handlePacket(new OSCPacketEvent(this, message)); 37 | if (!listener1.isMessageReceived()) { 38 | Assertions.fail("Message to listener1 didn't get sent to listener1"); 39 | } 40 | if (listener2.isMessageReceived()) { 41 | Assertions.fail("Message to listener1 got sent to listener2"); 42 | } 43 | } 44 | 45 | @Test 46 | public void testDispatchToListener2() { 47 | OSCMessage message = new OSCMessage("/listener2"); 48 | dispatcher.handlePacket(new OSCPacketEvent(this, message)); 49 | if (listener1.isMessageReceived()) { 50 | Assertions.fail("Message to listener2 got sent to listener1"); 51 | } 52 | if (!listener2.isMessageReceived()) { 53 | Assertions.fail("Message to listener2 didn't get sent to listener2"); 54 | } 55 | } 56 | 57 | @Test 58 | public void testDispatchToNobody() { 59 | OSCMessage message = new OSCMessage("/nobody"); 60 | dispatcher.handlePacket(new OSCPacketEvent(this, message)); 61 | if (listener1.isMessageReceived() || listener2.isMessageReceived()) { 62 | Assertions.fail("Message to nobody got dispatched incorrectly"); 63 | } 64 | } 65 | 66 | @Test 67 | public void testDispatchBundle() { 68 | OSCBundle bundle = new OSCBundle(); 69 | bundle.addPacket(new OSCMessage("/listener1")); 70 | bundle.addPacket(new OSCMessage("/listener2")); 71 | dispatcher.handlePacket(new OSCPacketEvent(this, bundle)); 72 | if (!listener1.isMessageReceived()) { 73 | Assertions.fail("Bundle didn't dispatch message to listener 1"); 74 | } 75 | if (!listener2.isMessageReceived()) { 76 | Assertions.fail("Bundle didn't dispatch message to listener 2"); 77 | } 78 | } 79 | 80 | @Test 81 | public void testDispatchManyArguments() { 82 | 83 | final int numArguments = OSCPacketDispatcher.MAX_ARGUMENTS + 1; 84 | final List arguments = new ArrayList<>(numArguments); 85 | for (int ai = 0; ai < numArguments; ai++) { 86 | arguments.add(ai); 87 | } 88 | OSCMessage message = new OSCMessage("/listener1", arguments); 89 | dispatcher.handlePacket(new OSCPacketEvent(this, message)); 90 | Assertions.assertEquals(numArguments, listener1.getReceivedEvent().getMessage().getArguments().size()); 91 | } 92 | 93 | @Test 94 | public void testListenerRemoval() { 95 | // change the setup 96 | dispatcher.removeListener(new OSCPatternAddressMessageSelector("/listener1"), listener1); 97 | 98 | OSCMessage message = new OSCMessage("/listener1"); 99 | dispatcher.handlePacket(new OSCPacketEvent(this, message)); 100 | if (listener1.isMessageReceived()) { 101 | Assertions.fail("Message listener did not get removed"); 102 | } 103 | } 104 | 105 | @Test 106 | public void testDispatchMultipleListenersSameSelector() { 107 | // change the setup 108 | dispatcher.removeListener(new OSCPatternAddressMessageSelector("/listener2"), listener2); 109 | dispatcher.addListener(new OSCPatternAddressMessageSelector("/listener1"), listener2); 110 | 111 | OSCMessage message = new OSCMessage("/listener1"); 112 | dispatcher.handlePacket(new OSCPacketEvent(this, message)); 113 | if (!listener1.isMessageReceived()) { 114 | Assertions.fail("Message did not get sent to listener 1"); 115 | } 116 | if (!listener2.isMessageReceived()) { 117 | Assertions.fail("Message did not get sent to listener 2"); 118 | } 119 | } 120 | 121 | @Test 122 | public void testDispatchMultipleTimesSingleListenersSameSelector() { 123 | // change the setup 124 | dispatcher.removeListener(new OSCPatternAddressMessageSelector("/listener2"), listener2); 125 | dispatcher.addListener(new OSCPatternAddressMessageSelector("/listener1"), listener1); 126 | 127 | OSCMessage message = new OSCMessage("/listener1"); 128 | dispatcher.handlePacket(new OSCPacketEvent(this, message)); 129 | if (listener1.getMessageReceivedCount() != 2) { 130 | Assertions.fail("Message did not get sent two times to listener 1, but " 131 | + listener1.getMessageReceivedCount() + " times"); 132 | } 133 | } 134 | 135 | @Test 136 | public void testDispatchMultipleTimesSingleListenersDifferentSelectors() { 137 | // change the setup 138 | dispatcher.removeListener(new OSCPatternAddressMessageSelector("/listener2"), listener2); 139 | dispatcher.addListener(new OSCPatternAddressMessageSelector("/*"), listener1); 140 | 141 | OSCMessage message = new OSCMessage("/listener1"); 142 | dispatcher.handlePacket(new OSCPacketEvent(this, message)); 143 | if (listener1.getMessageReceivedCount() != 2) { 144 | Assertions.fail("Message did not get sent two times to listener 1, but " 145 | + listener1.getMessageReceivedCount() + " times"); 146 | } 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /modules/core/src/test/java/com/illposed/osc/OSCSerializerTest.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2001 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc; 7 | 8 | import com.illposed.osc.argument.handler.StringArgumentHandler; 9 | import java.nio.ByteBuffer; 10 | import java.nio.charset.Charset; 11 | import java.nio.charset.StandardCharsets; 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | import java.util.Arrays; 15 | import org.junit.jupiter.api.Test; 16 | 17 | /** 18 | * This implementation is based on Markus Gaelli and Iannis Zannos's 19 | * OSC implementation in Squeak 20 | * @see OSCSerializer 21 | */ 22 | public class OSCSerializerTest { 23 | 24 | private void checkResultEqualsAnswer(byte[] result, byte[] answer) { 25 | OSCMessageTest.checkResultEqualsAnswer(result, answer); 26 | } 27 | 28 | private static int calcTypeIdentifiersStrLength(final int numArguments) { 29 | 30 | if (numArguments == 0) { 31 | return 0; 32 | } 33 | return ((numArguments + 5) / 4) * 4; 34 | } 35 | 36 | private void checkSerializedArguments( 37 | final Charset charset, 38 | final byte[] expected, 39 | final Object... arguments) 40 | throws OSCSerializeException 41 | { 42 | final ByteBuffer buffer = ByteBuffer.allocate(1024); 43 | final BufferBytesReceiver bytesReceiver = new BufferBytesReceiver(buffer); 44 | final OSCSerializerAndParserBuilder serializerBuilder = new OSCSerializerAndParserBuilder(); 45 | if (charset != null) { 46 | final Map properties = new HashMap<>(); 47 | properties.put(StringArgumentHandler.PROP_NAME_CHARSET, charset); 48 | serializerBuilder.addProperties(properties); 49 | } 50 | final OSCSerializer stream = serializerBuilder.buildSerializer(bytesReceiver); 51 | final OSCMessage oscMessage = new OSCMessage("/ab", Arrays.asList(arguments)); 52 | stream.write(oscMessage); 53 | byte[] result = bytesReceiver.toByteArray(); 54 | final int toBeStrippedOffPrefixBytes = 4 + calcTypeIdentifiersStrLength(arguments.length); 55 | result = Arrays.copyOfRange(result, toBeStrippedOffPrefixBytes, result.length); 56 | checkResultEqualsAnswer(result, expected); 57 | } 58 | 59 | private void checkSerializedArguments( 60 | final byte[] expected, 61 | final Object... arguments) 62 | throws OSCSerializeException 63 | { 64 | checkSerializedArguments(null, expected, arguments); 65 | } 66 | 67 | /** 68 | * This is different from the SmallTalk implementation. 69 | * In Squeak, this produces: 70 | * byte[] answer = {62, 76, (byte) 204, (byte) 204}; 71 | * (i.e. answer= {62, 76, -52, -52}) 72 | * 73 | * The source of this discrepancy is Squeak conversion 74 | * routine Float>>asIEEE32BitWord vs. the Java 75 | * {@link Float#floatToIntBits(float)}. 76 | * 77 | * 0.2 asIEEE32BitWord yields: 1045220556 78 | * {@link Float#floatToIntBits(float)} with parameter 0.2f 79 | * yields: (int) 1045220557 (VA Java 3.5) 80 | * 81 | * Looks like there is an OBO bug somewhere -- either Java or Squeak. 82 | * @throws Exception because {@link OSCSerializer#write(Object)} may throw something 83 | */ 84 | @Test 85 | public void testSerializeFloat2() throws Exception { 86 | checkSerializedArguments( 87 | new byte[] {62, 76, -52, -51}, 88 | 0.2f); 89 | } 90 | 91 | @Test 92 | public void testSerializeFloat() throws Exception { 93 | checkSerializedArguments( 94 | new byte[] {65, 44, 27, 113}, 95 | 10.7567f); 96 | } 97 | 98 | @Test 99 | public void testSerializeInteger() throws Exception { 100 | checkSerializedArguments( 101 | new byte[] {0, 0, 4, 100}, 102 | 1124); 103 | } 104 | 105 | @Test 106 | public void testSerializeStringAndInt() throws Exception { 107 | checkSerializedArguments( 108 | new byte[] {47, 101, 120, 97, 109, 112, 108, 101, 49, 0, 0, 0, 0, 0, 0, 100}, 109 | "/example1", 110 | 100); 111 | } 112 | 113 | @Test 114 | public void testSerializeString2() throws Exception { 115 | //noinspection SpellCheckingInspection 116 | checkSerializedArguments( 117 | new byte[] {97, 98, 99, 100, 0, 0, 0, 0}, 118 | "abcd"); 119 | } 120 | 121 | @Test 122 | public void testSerializeString3() throws Exception { 123 | checkSerializedArguments( 124 | StandardCharsets.UTF_8, 125 | new byte[] {(byte) 0xc3, (byte) 0xa1, 0, 0}, 126 | "\u00e1"); // latin 'a' with an acute accent 127 | } 128 | 129 | @Test 130 | public void testSerializeString() throws Exception { 131 | checkSerializedArguments( 132 | new byte[] {97, 98, 99, 0}, 133 | "abc"); 134 | } 135 | 136 | @Test 137 | public void testSerializeLong() throws Exception { 138 | checkSerializedArguments( 139 | new byte[] {0, 0, 0, 0, 0, 0, 4, 100}, 140 | 1124L); 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /modules/core/src/test/java/com/illposed/osc/SimpleOSCMessageListener.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2001 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 - 2024 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc; 7 | 8 | public class SimpleOSCMessageListener implements OSCMessageListener { 9 | 10 | private int messageReceivedCount; 11 | private OSCMessageEvent event; 12 | 13 | public SimpleOSCMessageListener() { 14 | 15 | this.messageReceivedCount = 0; 16 | this.event = null; 17 | } 18 | public boolean isMessageReceived() { 19 | return (messageReceivedCount > 0); 20 | } 21 | 22 | @SuppressWarnings("WeakerAccess") 23 | public int getMessageReceivedCount() { 24 | return messageReceivedCount; 25 | } 26 | 27 | public OSCMessageEvent getReceivedEvent() { 28 | return event; 29 | } 30 | 31 | @Override 32 | public void acceptMessage(final OSCMessageEvent event) { 33 | messageReceivedCount++; 34 | this.event = event; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /modules/core/src/test/java/com/illposed/osc/SimpleOSCPacketListener.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | package com.illposed.osc; 6 | 7 | public class SimpleOSCPacketListener implements OSCPacketListener { 8 | 9 | private int packetReceivedCount; 10 | private OSCPacket packet; 11 | 12 | public SimpleOSCPacketListener() { 13 | 14 | this.packetReceivedCount = 0; 15 | this.packet = null; 16 | } 17 | public boolean isMessageReceived() { 18 | return (packetReceivedCount > 0); 19 | } 20 | 21 | @SuppressWarnings("WeakerAccess") 22 | public int getMessageReceivedCount() { 23 | return packetReceivedCount; 24 | } 25 | 26 | public OSCPacket getReceivedPacket() { 27 | return packet; 28 | } 29 | 30 | @Override 31 | public void handlePacket(final OSCPacketEvent event) { 32 | packetReceivedCount++; 33 | this.packet = event.getPacket(); 34 | } 35 | 36 | @Override 37 | public void handleBadData(final OSCBadDataEvent event) {} 38 | } 39 | -------------------------------------------------------------------------------- /modules/core/src/test/java/com/illposed/osc/argument/handler/ColorArgumentHandlerTest.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.argument.handler; 7 | 8 | import com.illposed.osc.BufferBytesReceiver; 9 | import com.illposed.osc.OSCParseException; 10 | import com.illposed.osc.OSCSerializeException; 11 | import com.illposed.osc.argument.ArgumentHandler; 12 | import com.illposed.osc.argument.OSCColor; 13 | import org.junit.jupiter.api.Assertions; 14 | import org.junit.jupiter.api.Test; 15 | import org.slf4j.Logger; 16 | import org.slf4j.LoggerFactory; 17 | 18 | import java.nio.ByteBuffer; 19 | import java.util.Random; 20 | 21 | public class ColorArgumentHandlerTest { 22 | 23 | private final Logger log = LoggerFactory.getLogger(ColorArgumentHandlerTest.class); 24 | private static final OSCColor[] DEFAULT_COLORS = { 25 | OSCColor.BLACK, 26 | OSCColor.BLUE, 27 | OSCColor.CYAN, 28 | OSCColor.DARK_GRAY, 29 | OSCColor.GRAY, 30 | OSCColor.GREEN, 31 | OSCColor.LIGHT_GRAY, 32 | OSCColor.MAGENTA, 33 | OSCColor.ORANGE, 34 | OSCColor.PINK, 35 | OSCColor.RED, 36 | OSCColor.WHITE, 37 | OSCColor.YELLOW, 38 | }; 39 | 40 | static T reparse(final ArgumentHandler type, final int bufferSize, final T orig) 41 | throws OSCSerializeException, OSCParseException 42 | { 43 | // serialize 44 | final ByteBuffer buffer = ByteBuffer.allocate(bufferSize); 45 | final BufferBytesReceiver bytesReceiver = new BufferBytesReceiver(buffer); 46 | type.serialize(bytesReceiver, orig); 47 | final ByteBuffer reparsableBuffer = (ByteBuffer) buffer.flip(); 48 | 49 | // re-parse 50 | return type.parse(reparsableBuffer); 51 | } 52 | 53 | private static OSCColor reparse(final OSCColor orig) 54 | throws OSCSerializeException, OSCParseException 55 | { 56 | return reparse(ColorArgumentHandler.INSTANCE, OSCColor.NUM_CONTENT_BYTES, orig); 57 | } 58 | 59 | @Test 60 | public void testReconvertBytes() { 61 | 62 | final byte[] testBytes = new byte[] { 63 | -128, 64 | -1, 65 | 0, 66 | 1, 67 | 127 68 | }; 69 | final int[] testInts = new int[] { 70 | 128, 71 | 255, 72 | 0, 73 | 1, 74 | 127 75 | }; 76 | 77 | for (int tni = 0; tni < testBytes.length; tni++) { 78 | final byte origByte = testBytes[tni]; 79 | final int origInt = testInts[tni]; 80 | 81 | final int createdInt = OSCColor.toUnsignedInt(origByte); 82 | Assertions.assertEquals(origInt, createdInt); 83 | 84 | final byte createdByte = OSCColor.toSignedByte(createdInt); 85 | Assertions.assertEquals(origByte, createdByte); 86 | } 87 | } 88 | 89 | @Test 90 | public void testReparseDefaultColors() throws Exception { 91 | 92 | for (final OSCColor origColor: DEFAULT_COLORS) { 93 | Assertions.assertEquals(origColor, reparse(origColor)); 94 | } 95 | } 96 | 97 | /** 98 | * Adds random alpha values between 0 and 255 to the default colors, 99 | * and then tries to re-parse them. 100 | * @throws Exception on re-parse failure 101 | */ 102 | @Test 103 | @SuppressWarnings("SpellCheckingInspection") 104 | public void testReparseDefaultColorsAlphaed() throws Exception { 105 | 106 | final long alphaRandomSeed = new Random().nextLong(); 107 | log.debug("{}#testReparseDefaultColorsAlphaed:alphaRandomSeed: {}", 108 | ColorArgumentHandlerTest.class.getSimpleName(), alphaRandomSeed); 109 | final Random alphaRandom = new Random(alphaRandomSeed); 110 | for (final OSCColor orig: DEFAULT_COLORS) { 111 | final int alpha = alphaRandom.nextInt(256); 112 | final OSCColor alphaed = new OSCColor(orig.getRed(), orig.getGreen(), orig.getBlue(), alpha); 113 | Assertions.assertEquals(alphaed, reparse(alphaed)); 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /modules/core/src/test/java/com/illposed/osc/argument/handler/MidiMessageArgumentHandlerTest.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.argument.handler; 7 | 8 | import com.illposed.osc.argument.OSCMidiMessage; 9 | import com.illposed.osc.OSCParseException; 10 | import com.illposed.osc.OSCSerializeException; 11 | import java.util.Random; 12 | import org.junit.jupiter.api.Assertions; 13 | import org.junit.jupiter.api.Test; 14 | import org.slf4j.Logger; 15 | import org.slf4j.LoggerFactory; 16 | 17 | public class MidiMessageArgumentHandlerTest { 18 | 19 | private final Logger log = LoggerFactory.getLogger(MidiMessageArgumentHandlerTest.class); 20 | 21 | private static OSCMidiMessage reparse(final OSCMidiMessage orig) 22 | throws OSCSerializeException, OSCParseException 23 | { 24 | return ColorArgumentHandlerTest.reparse( 25 | MidiMessageArgumentHandler.INSTANCE, 26 | OSCMidiMessage.NUM_CONTENT_BYTES, 27 | orig); 28 | } 29 | 30 | private static void testReparse(final OSCMidiMessage orig) 31 | throws OSCSerializeException, OSCParseException 32 | { 33 | Assertions.assertEquals(orig, reparse(orig)); 34 | } 35 | 36 | @Test 37 | public void testReparseNull() throws OSCSerializeException, OSCParseException { 38 | 39 | final OSCMidiMessage orig = null; 40 | Assertions.assertThrows( 41 | NullPointerException.class, 42 | () -> Assertions.assertEquals(orig, reparse(orig)) 43 | ); 44 | } 45 | 46 | private static void testContent(final byte[] content) { 47 | OSCMidiMessage.valueOf(content); 48 | } 49 | 50 | @Test 51 | public void testContentBytesZero() { 52 | Assertions.assertThrows( 53 | IllegalArgumentException.class, 54 | () -> testContent(new byte[0]) 55 | ); 56 | } 57 | 58 | @Test 59 | public void testContentBytesOne() { 60 | Assertions.assertThrows( 61 | IllegalArgumentException.class, 62 | () -> testContent(new byte[1]) 63 | ); 64 | } 65 | 66 | @Test 67 | public void testContentBytesTwo() { 68 | Assertions.assertThrows( 69 | IllegalArgumentException.class, 70 | () -> testContent(new byte[2]) 71 | ); 72 | } 73 | 74 | @Test 75 | public void testContentBytesThree() { 76 | Assertions.assertThrows( 77 | IllegalArgumentException.class, 78 | () -> testContent(new byte[3]) 79 | ); 80 | } 81 | 82 | @Test 83 | public void testContentBytesFour() { 84 | testContent(new byte[4]); 85 | } 86 | 87 | @Test 88 | public void testContentBytesFive() { 89 | Assertions.assertThrows( 90 | IllegalArgumentException.class, 91 | () -> testContent(new byte[5]) 92 | ); 93 | } 94 | 95 | @Test 96 | public void testReparseZeros() throws Exception { 97 | testReparse(OSCMidiMessage.valueOf(new byte[] {0, 0, 0, 0})); 98 | } 99 | 100 | @Test 101 | public void testReparsePositive() throws Exception { 102 | testReparse(OSCMidiMessage.valueOf(new byte[] {127, 127, 127, 127})); 103 | } 104 | 105 | @Test 106 | public void testReparseNegative() throws Exception { 107 | testReparse(OSCMidiMessage.valueOf(new byte[] {-128, -128, -128, -128})); 108 | } 109 | 110 | @Test 111 | public void testReparseRandom() throws Exception { 112 | 113 | final long contentRandomSeed = new Random().nextLong(); 114 | log.debug("{}#testReparseRandom:contentRandomSeed: {}", 115 | MidiMessageArgumentHandlerTest.class.getSimpleName(), contentRandomSeed); 116 | final Random contentRandom = new Random(contentRandomSeed); 117 | final byte[] content = new byte[4]; 118 | contentRandom.nextBytes(content); 119 | testReparse(OSCMidiMessage.valueOf(content)); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /modules/core/src/test/java/com/illposed/osc/argument/handler/SymbolArgumentHandlerTest.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.argument.handler; 7 | 8 | import com.illposed.osc.argument.OSCSymbol; 9 | import com.illposed.osc.OSCParseException; 10 | import com.illposed.osc.OSCSerializeException; 11 | import org.junit.jupiter.api.Assertions; 12 | import org.junit.jupiter.api.Test; 13 | 14 | public class SymbolArgumentHandlerTest { 15 | 16 | private static OSCSymbol reparse(final OSCSymbol orig) 17 | throws OSCSerializeException, OSCParseException 18 | { 19 | final int strLength = (orig.toString() == null) ? 0 : orig.toString().length(); 20 | return ColorArgumentHandlerTest.reparse(new SymbolArgumentHandler(), strLength + 4, orig); 21 | } 22 | 23 | @Test 24 | public void testReparseNull() throws Exception { 25 | 26 | final OSCSymbol orig = OSCSymbol.valueOf(null); 27 | Assertions.assertThrows( 28 | NullPointerException.class, 29 | () -> Assertions.assertEquals(orig, reparse(orig)) 30 | ); 31 | } 32 | 33 | @Test 34 | public void testReparseValid() throws Exception { 35 | 36 | @SuppressWarnings("SpellCheckingInspection") final OSCSymbol[] symbols = new OSCSymbol[] { 37 | OSCSymbol.valueOf(""), 38 | OSCSymbol.valueOf("a"), 39 | OSCSymbol.valueOf("ab"), 40 | OSCSymbol.valueOf("abc"), 41 | OSCSymbol.valueOf("abcd") 42 | }; 43 | 44 | for (final OSCSymbol orig : symbols) { 45 | Assertions.assertEquals(orig, reparse(orig)); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /modules/core/src/test/java/com/illposed/osc/messageselector/CombinedMessageSelectorTest.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2019 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.messageselector; 7 | 8 | import com.illposed.osc.MessageSelector; 9 | import com.illposed.osc.OSCMessage; 10 | import com.illposed.osc.OSCMessageEvent; 11 | import com.illposed.osc.OSCMessageInfo; 12 | import org.junit.jupiter.api.Assertions; 13 | import org.junit.jupiter.api.Test; 14 | 15 | public class CombinedMessageSelectorTest { 16 | 17 | private boolean matches(final MessageSelector selector, final String address, final String typeTags) { 18 | 19 | final OSCMessage message = new OSCMessage(address); 20 | message.setInfo(new OSCMessageInfo(typeTags)); 21 | return selector.matches(new OSCMessageEvent(this, null, message)); 22 | } 23 | 24 | @Test 25 | public void testNoAddressNorArgs() { 26 | 27 | final MessageSelector matcher = new CombinedMessageSelector( 28 | new OSCPatternAddressMessageSelector("/"), 29 | new OSCPatternTypeTagsMessageSelector(""), 30 | CombinedMessageSelector.LogicOperator.AND); 31 | 32 | Assertions.assertTrue( matches(matcher, "/", "")); 33 | Assertions.assertFalse(matches(matcher, "/hello", "")); 34 | Assertions.assertFalse(matches(matcher, "/", "i")); 35 | Assertions.assertFalse(matches(matcher, "/hello", "i")); 36 | } 37 | 38 | @Test 39 | public void testNoArgs() { 40 | 41 | final MessageSelector matcher = new CombinedMessageSelector( 42 | new OSCPatternAddressMessageSelector("/hello"), 43 | new OSCPatternTypeTagsMessageSelector(""), 44 | CombinedMessageSelector.LogicOperator.AND); 45 | 46 | Assertions.assertFalse( matches(matcher, "/", "")); 47 | Assertions.assertTrue(matches(matcher, "/hello", "")); 48 | Assertions.assertFalse(matches(matcher, "/", "i")); 49 | Assertions.assertFalse(matches(matcher, "/hello", "i")); 50 | } 51 | 52 | @Test 53 | public void testAddressAndArgs() { 54 | 55 | final MessageSelector matcher = new CombinedMessageSelector( 56 | new OSCPatternAddressMessageSelector("/hello"), 57 | new OSCPatternTypeTagsMessageSelector("i"), 58 | CombinedMessageSelector.LogicOperator.AND); 59 | 60 | Assertions.assertFalse(matches(matcher, "/", "")); 61 | Assertions.assertFalse(matches(matcher, "/hello", "")); 62 | Assertions.assertFalse(matches(matcher, "/", "i")); 63 | Assertions.assertTrue( matches(matcher, "/hello", "i")); 64 | } 65 | 66 | @Test 67 | public void testPartPostfix() { 68 | 69 | final MessageSelector matcher = new CombinedMessageSelector( 70 | new OSCPatternAddressMessageSelector("/hello"), 71 | new OSCPatternTypeTagsMessageSelector("i"), 72 | CombinedMessageSelector.LogicOperator.OR); 73 | 74 | Assertions.assertFalse(matches(matcher, "/", "")); 75 | Assertions.assertTrue( matches(matcher, "/hello", "")); 76 | Assertions.assertTrue( matches(matcher, "/", "i")); 77 | Assertions.assertTrue( matches(matcher, "/hello", "i")); 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /modules/core/src/test/java/com/illposed/osc/transport/udp/UDPTransportTest.java: -------------------------------------------------------------------------------- 1 | package com.illposed.osc.transport.udp; 2 | 3 | import java.io.IOException; 4 | import java.net.InetSocketAddress; 5 | import java.net.SocketAddress; 6 | import java.nio.BufferOverflowException; 7 | 8 | import com.illposed.osc.OSCMessage; 9 | import com.illposed.osc.OSCParseException; 10 | import com.illposed.osc.OSCSerializeException; 11 | import org.junit.jupiter.api.Test; 12 | import org.opentest4j.AssertionFailedError; 13 | 14 | public class UDPTransportTest 15 | { 16 | @Test 17 | void testSimultaneusReadWrite() throws IOException, OSCSerializeException, InterruptedException { 18 | final SocketAddress local = new InetSocketAddress(11111); 19 | final SocketAddress remote = new InetSocketAddress(22222); 20 | final UDPTransport transport = new UDPTransport(local, remote); 21 | final UDPTransport reverseTransport = new UDPTransport(remote, local); 22 | 23 | final Object lock = new Object(); 24 | final Exception[] result = new Exception[1]; 25 | 26 | final Thread readThread = new Thread(() -> { 27 | while (true) 28 | { 29 | try 30 | { 31 | transport.receive(); 32 | } 33 | catch (IOException | OSCParseException | BufferOverflowException e) 34 | { 35 | result[0] = e; 36 | } 37 | finally 38 | { 39 | synchronized (lock) 40 | { 41 | lock.notifyAll(); 42 | } 43 | } 44 | } 45 | }); 46 | readThread.setDaemon(true); 47 | readThread.start(); 48 | 49 | // Put the transport in the "I lastly send a message" state 50 | transport.send(new OSCMessage("/xremote")); 51 | 52 | // Trigger the bug 53 | synchronized (lock) 54 | { 55 | reverseTransport.send(new OSCMessage("/xremote")); 56 | lock.wait(1000); 57 | } 58 | 59 | // Assert the result 60 | if (result[0] != null) 61 | { 62 | throw new AssertionFailedError("Can not read in one thread and write in another", result[0]); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /modules/java-se-addons/pom.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 4.0.0 9 | 10 | 11 | com.illposed.osc.argument.handler.javase 12 | 1.0 13 | 14 | 15 | 16 | com.illposed.osc 17 | javaosc-parent 18 | 0.10-SNAPSHOT 19 | ../parent 20 | 21 | 22 | javaosc-java-se-addons 23 | 0.10-SNAPSHOT 24 | 25 | bundle 26 | 27 | JavaOSC-Java-SE-addons 28 | An Open Sound Control library implementation in Java - Java SE/non-Android addons 29 | 30 | 31 | package 32 | 33 | 34 | 35 | org.apache.felix 36 | maven-bundle-plugin 37 | true 38 | 39 | 40 | 41 | ${project.packageName}, 42 | 43 | ${supported.osc.version} 44 | 45 | 46 | 47 | 48 | 49 | org.apache.maven.plugins 50 | maven-checkstyle-plugin 51 | 52 | 53 | 54 | 55 | check 56 | 57 | 58 | 59 | 60 | 61 | 67 | 68 | 69 | 73 | 74 | 75 | com.github.spotbugs 76 | spotbugs-maven-plugin 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | com.illposed.osc 92 | javaosc-core 93 | 0.10-SNAPSHOT 94 | 95 | 96 | 97 | org.junit.jupiter 98 | junit-jupiter 99 | test 100 | 101 | 102 | 103 | org.slf4j 104 | slf4j-api 105 | 106 | 107 | org.slf4j 108 | slf4j-ext 109 | 110 | 111 | org.slf4j 112 | slf4j-simple 113 | test 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /modules/java-se-addons/src/main/java/com/illposed/osc/argument/handler/javase/Activator.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | package com.illposed.osc.argument.handler.javase; 6 | 7 | import com.illposed.osc.argument.ArgumentHandler; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | import java.util.ArrayList; 12 | import java.util.Collections; 13 | import java.util.HashMap; 14 | import java.util.List; 15 | import java.util.Map; 16 | 17 | /** 18 | * Allows to easily register and unregister all types in this package. 19 | */ 20 | public final class Activator { 21 | 22 | private static final Logger LOG = LoggerFactory.getLogger(Activator.class); 23 | 24 | private static final List TYPES_STATIC_COMMON; 25 | static { 26 | final ArrayList types = new ArrayList<>(); 27 | types.add(AwtColorArgumentHandler.INSTANCE); 28 | types.trimToSize(); 29 | TYPES_STATIC_COMMON = Collections.unmodifiableList(types); 30 | } 31 | 32 | private Activator() {} 33 | 34 | public static Map createParserTypes() { 35 | 36 | final Map parserTypes 37 | = new HashMap<>(TYPES_STATIC_COMMON.size() + 1); 38 | for (final ArgumentHandler type : TYPES_STATIC_COMMON) { 39 | parserTypes.put(type.getDefaultIdentifier(), type); 40 | } 41 | 42 | return parserTypes; 43 | } 44 | 45 | public static List createSerializerTypes() { 46 | 47 | final List serializerTypes 48 | = new ArrayList<>(TYPES_STATIC_COMMON.size() + 2); 49 | serializerTypes.addAll(TYPES_STATIC_COMMON); 50 | 51 | return serializerTypes; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /modules/java-se-addons/src/main/java/com/illposed/osc/argument/handler/javase/AwtColorArgumentHandler.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015-2017 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021-2024 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.argument.handler.javase; 7 | 8 | import com.illposed.osc.BytesReceiver; 9 | import com.illposed.osc.OSCParseException; 10 | import com.illposed.osc.OSCSerializeException; 11 | import com.illposed.osc.argument.ArgumentHandler; 12 | import com.illposed.osc.argument.OSCColor; 13 | import com.illposed.osc.argument.handler.ColorArgumentHandler; 14 | 15 | import java.awt.Color; 16 | import java.nio.ByteBuffer; 17 | import java.util.Map; 18 | 19 | /** 20 | * Parses and serializes an OSC 1.1 optional 32bit RGBA color type. 21 | * 22 | * Note That this class is not in javaosc-core, 23 | * because it uses java.awt.Color, 24 | * which is part of Java SE, 25 | * but not part of the Java implementation on Android (Dalvik), 26 | * and thus would make JavaOSC unusable on Android, 27 | * if it were not separated. 28 | * It was part of javaosc-core until version 0.8. 29 | * 30 | * As an alternative on Android, 31 | * see com.illposed.osc.argument.handler.ColorArgumentHandler 32 | * in javaosc-core. 33 | */ 34 | public class AwtColorArgumentHandler implements ArgumentHandler, Cloneable { 35 | 36 | public static final ArgumentHandler INSTANCE = new AwtColorArgumentHandler(); 37 | 38 | // Public API 39 | /** Allow overriding, but somewhat enforce the ugly singleton. */ 40 | @SuppressWarnings("WeakerAccess") 41 | protected AwtColorArgumentHandler() { 42 | // declared only for setting the access level 43 | } 44 | 45 | @Override 46 | public char getDefaultIdentifier() { 47 | return 'r'; 48 | } 49 | 50 | @Override 51 | public Class getJavaClass() { 52 | return Color.class; 53 | } 54 | 55 | @Override 56 | public void setProperties(final Map properties) { 57 | // we make no use of any properties 58 | } 59 | 60 | @Override 61 | public boolean isMarkerOnly() { 62 | return false; 63 | } 64 | 65 | @Override 66 | @SuppressWarnings("unchecked") 67 | public AwtColorArgumentHandler clone() throws CloneNotSupportedException { 68 | return (AwtColorArgumentHandler) super.clone(); 69 | } 70 | 71 | public static Color toAwt(final OSCColor color) { 72 | return new Color( 73 | color.getRedInt(), 74 | color.getGreenInt(), 75 | color.getBlueInt(), 76 | color.getAlphaInt()); 77 | } 78 | 79 | public static OSCColor toOsc(final Color color) { 80 | return new OSCColor( 81 | color.getRed(), 82 | color.getGreen(), 83 | color.getBlue(), 84 | color.getAlpha()); 85 | } 86 | 87 | @Override 88 | public Color parse(final ByteBuffer input) throws OSCParseException { 89 | return toAwt(ColorArgumentHandler.INSTANCE.parse(input)); 90 | } 91 | 92 | @Override 93 | public void serialize(final BytesReceiver output, final Color value) throws OSCSerializeException { 94 | ColorArgumentHandler.INSTANCE.serialize(output, toOsc(value)); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /modules/java-se-addons/src/main/java/com/illposed/osc/argument/handler/javase/package-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | /** 6 | * Provides {@link com.illposed.osc.argument.ArgumentHandler} implementations. 7 | * The ones in this package are Java SE specific, 8 | * meaning they work on Oracle JDK and OpenJDK, 9 | * but specifically not on Android. 10 | */ 11 | package com.illposed.osc.argument.handler.javase; 12 | -------------------------------------------------------------------------------- /modules/java-se-addons/src/test/java/com/illposed/osc/argument/handler/javase/AwtColorArgumentHandlerTest.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2015 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021-2024 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.argument.handler.javase; 7 | 8 | import com.illposed.osc.BufferBytesReceiver; 9 | import com.illposed.osc.argument.ArgumentHandler; 10 | import com.illposed.osc.OSCParseException; 11 | import com.illposed.osc.OSCSerializeException; 12 | import java.awt.Color; 13 | import java.nio.ByteBuffer; 14 | import java.util.Arrays; 15 | import java.util.Random; 16 | 17 | import com.illposed.osc.argument.OSCColor; 18 | import org.junit.jupiter.api.Assertions; 19 | import org.junit.jupiter.api.Test; 20 | import org.slf4j.Logger; 21 | import org.slf4j.LoggerFactory; 22 | 23 | public class AwtColorArgumentHandlerTest { 24 | 25 | private final Logger log = LoggerFactory.getLogger(AwtColorArgumentHandlerTest.class); 26 | 27 | public static final Color[] DEFAULT_COLORS = new Color[] { 28 | Color.BLACK, 29 | Color.BLUE, 30 | Color.CYAN, 31 | Color.DARK_GRAY, 32 | Color.GRAY, 33 | Color.GREEN, 34 | Color.LIGHT_GRAY, 35 | Color.MAGENTA, 36 | Color.ORANGE, 37 | Color.PINK, 38 | Color.RED, 39 | Color.WHITE, 40 | Color.YELLOW}; 41 | 42 | 43 | private static T reparse(final ArgumentHandler type, final int bufferSize, final T orig) 44 | throws OSCSerializeException, OSCParseException 45 | { 46 | // serialize 47 | final ByteBuffer buffer = ByteBuffer.allocate(bufferSize); 48 | final BufferBytesReceiver bytesReceiver = new BufferBytesReceiver(buffer); 49 | type.serialize(bytesReceiver, orig); 50 | final ByteBuffer reparsableBuffer = (ByteBuffer) buffer.flip(); 51 | 52 | // re-parse 53 | return type.parse(reparsableBuffer); 54 | } 55 | 56 | private static Color reparse(final Color orig) 57 | throws OSCSerializeException, OSCParseException 58 | { 59 | return reparse(AwtColorArgumentHandler.INSTANCE, OSCColor.NUM_CONTENT_BYTES, orig); 60 | } 61 | 62 | @Test 63 | public void testReparseDefaultColors() throws Exception { 64 | 65 | for (final Color orig : DEFAULT_COLORS) { 66 | Assertions.assertEquals(orig, reparse(orig)); 67 | } 68 | } 69 | 70 | /** 71 | * Adds random alpha values between 0 and 255 to the default colors, 72 | * and then tries to re-parse them. 73 | * @throws Exception on re-parse failure 74 | */ 75 | @Test 76 | @SuppressWarnings("SpellCheckingInspection") 77 | public void testReparseDefaultColorsAlphaed() throws Exception { 78 | 79 | final long alphaRandomSeed = new Random().nextLong(); 80 | log.debug("{}#testReparseDefaultColorsAlphaed:alphaRandomSeed: {}", 81 | AwtColorArgumentHandlerTest.class.getSimpleName(), alphaRandomSeed); 82 | final Random alphaRandom = new Random(alphaRandomSeed); 83 | final Color[] alphaedDefaultColors = Arrays.copyOf(DEFAULT_COLORS, DEFAULT_COLORS.length); 84 | for (int tci = 0; tci < alphaedDefaultColors.length; tci++) { 85 | final Color orig = alphaedDefaultColors[tci]; 86 | final int alpha = alphaRandom.nextInt(256); 87 | final Color alphaed = new Color(orig.getRed(), orig.getGreen(), orig.getBlue(), alpha); 88 | alphaedDefaultColors[tci] = alphaed; 89 | } 90 | 91 | for (final Color origColor : alphaedDefaultColors) { 92 | Assertions.assertEquals(origColor, reparse(origColor)); 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /modules/parent/src/main/resources/java_header_regex_template.txt: -------------------------------------------------------------------------------- 1 | ^// SPDX-FileCopyrightText: \d\d\d\d(-\d\d\d\d)? .+$ 2 | ^// SPDX-FileCopyrightText: \d\d\d\d(-\d\d\d\d)? .+$ 3 | ^//$ 4 | ^// SPDX-License-Identifier: BSD-3-Clause$ 5 | ^$ 6 | -------------------------------------------------------------------------------- /modules/parent/src/main/resources/java_header_regex_template.txt.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2021 Robin Vobruba 2 | 3 | SPDX-License-Identifier: CC0-1.0 4 | -------------------------------------------------------------------------------- /modules/parent/src/main/resources/pmd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 14 | 15 | PMD rules selection suitable for JavaOSC 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /modules/parent/src/main/resources/puredata/javaosc.pd: -------------------------------------------------------------------------------- 1 | #N canvas 50 296 623 461 10; 2 | #X obj 56 56 dumpOSC 57110; 3 | #X obj 146 105 OSCroute /n_set /n_free /s_new; 4 | #X obj 26 154 route 1000 1001 1002; 5 | #X obj 26 193 unpack s f; 6 | #X obj 91 229 osc~; 7 | #X obj 110 193 unpack s f; 8 | #X obj 175 229 osc~; 9 | #X obj 192 194 unpack s f; 10 | #X obj 257 230 osc~; 11 | #X obj 119 392 +~; 12 | #X obj 166 366 /~ 2; 13 | #X obj 208 396 +~; 14 | #X obj 153 421 dac~; 15 | #X obj 302 197 route 1000 1001 1002; 16 | #X obj 254 349 *~; 17 | #X obj 453 198 route 1000 1001 1002; 18 | #X msg 453 235 1; 19 | #X msg 491 233 1; 20 | #X msg 529 236 1; 21 | #X msg 305 230 0; 22 | #X msg 340 231 0; 23 | #X msg 374 232 0; 24 | #X obj 97 343 *~; 25 | #X obj 173 338 *~; 26 | #X obj 37 101 print OSC; 27 | #X obj 346 146 route javaosc-example; 28 | #X connect 0 0 1 0; 29 | #X connect 0 0 24 0; 30 | #X connect 1 0 2 0; 31 | #X connect 1 1 13 0; 32 | #X connect 1 2 25 0; 33 | #X connect 2 0 3 0; 34 | #X connect 2 1 5 0; 35 | #X connect 2 2 7 0; 36 | #X connect 3 1 4 0; 37 | #X connect 4 0 22 0; 38 | #X connect 5 1 6 0; 39 | #X connect 6 0 23 0; 40 | #X connect 7 1 8 0; 41 | #X connect 8 0 14 0; 42 | #X connect 9 0 12 0; 43 | #X connect 10 0 9 1; 44 | #X connect 10 0 11 0; 45 | #X connect 11 0 12 1; 46 | #X connect 13 0 19 0; 47 | #X connect 13 1 20 0; 48 | #X connect 13 2 21 0; 49 | #X connect 14 0 11 1; 50 | #X connect 15 0 16 0; 51 | #X connect 15 1 17 0; 52 | #X connect 15 2 18 0; 53 | #X connect 16 0 22 1; 54 | #X connect 17 0 23 1; 55 | #X connect 18 0 14 1; 56 | #X connect 19 0 22 1; 57 | #X connect 20 0 23 1; 58 | #X connect 21 0 14 1; 59 | #X connect 22 0 9 0; 60 | #X connect 23 0 10 0; 61 | #X connect 25 0 15 0; 62 | 63 | -------------------------------------------------------------------------------- /modules/parent/src/main/resources/puredata/javaosc.pd.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2012 C. Ramakrishnan / Auracle 2 | 3 | SPDX-License-Identifier: BSD-3-Clause 4 | -------------------------------------------------------------------------------- /modules/parent/src/main/resources/supercollider/javaosc-example.sc: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2012 C. Ramakrishnan / Auracle 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | ( 6 | SynthDef("javaosc-example",{ arg freq = 440; 7 | Out.ar(0, SinOsc.ar(freq, 0, 0.2) 8 | ) 9 | }).writeDefFile; 10 | s.sendMsg("/d_load", "synthdefs/javaosc-example.scsyndef"); 11 | ) 12 | 13 | -------------------------------------------------------------------------------- /modules/parent/src/main/resources/supercollider/synthdefs/default.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hoijui/JavaOSC/3fc203e8cd521b2c3a53122d74961661d19547c9/modules/parent/src/main/resources/supercollider/synthdefs/default.scsyndef -------------------------------------------------------------------------------- /modules/parent/src/main/resources/supercollider/synthdefs/default.scsyndef.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2012 C. Ramakrishnan / Auracle 2 | 3 | SPDX-License-Identifier: BSD-3-Clause -------------------------------------------------------------------------------- /modules/parent/src/main/resources/supercollider/synthdefs/javaosc-example.scsyndef: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hoijui/JavaOSC/3fc203e8cd521b2c3a53122d74961661d19547c9/modules/parent/src/main/resources/supercollider/synthdefs/javaosc-example.scsyndef -------------------------------------------------------------------------------- /modules/parent/src/main/resources/supercollider/synthdefs/javaosc-example.scsyndef.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2012 C. Ramakrishnan / Auracle 2 | 3 | SPDX-License-Identifier: BSD-3-Clause -------------------------------------------------------------------------------- /modules/parent/src/main/resources/supercollider/test1.sc: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2012 C. Ramakrishnan / Auracle 2 | // 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | s.boot; 6 | b = "hola"; 7 | b.postln; 8 | 9 | a = { 10 | Out.ar(0, SinOsc.ar(800, 0, 0.1)) 11 | }; 12 | 13 | 14 | a.play; 15 | -------------------------------------------------------------------------------- /modules/ui/pom.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 4.0.0 9 | 10 | 11 | ${project.packageName}.ui.Main 12 | 13 | 14 | 15 | com.illposed.osc 16 | javaosc-parent 17 | 0.10-SNAPSHOT 18 | ../parent 19 | 20 | 21 | javaosc-ui 22 | 0.10-SNAPSHOT 23 | 24 | jar 25 | 26 | JavaOSC-UI 27 | An Open Sound Control library implementation in Java - UI 28 | 29 | 30 | package 31 | 32 | 33 | 37 | 38 | org.apache.maven.plugins 39 | maven-jar-plugin 40 | 41 | 42 | 43 | true 44 | dependency 45 | ${project.packageName} 46 | ${project.mainClass} 47 | 48 | 49 | 50 | 51 | 52 | 55 | 56 | org.apache.maven.plugins 57 | maven-assembly-plugin 58 | 59 | 60 | jar-with-dependencies 61 | 62 | 63 | 64 | ${project.mainClass} 65 | 66 | 67 | 68 | 69 | 70 | 71 | org.codehaus.mojo 72 | exec-maven-plugin 73 | 74 | ${project.mainClass} 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | com.illposed.osc 83 | javaosc-core 84 | 0.10-SNAPSHOT 85 | 86 | 87 | org.slf4j 88 | slf4j-simple 89 | runtime 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /modules/ui/src/main/java/com/illposed/osc/ui/Main.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2003-2014 C. Ramakrishnan / Auracle 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | package com.illposed.osc.ui; 7 | 8 | import java.awt.event.WindowAdapter; 9 | import java.awt.event.WindowEvent; 10 | import javax.swing.JFrame; 11 | 12 | public class Main extends JFrame { 13 | 14 | public Main() { 15 | super("OSC"); 16 | 17 | final OscUI myUi = new OscUI(this); 18 | setBounds(10, 10, 500, 350); 19 | setContentPane(myUi); 20 | 21 | addWindowListener(new WindowAdapter() { 22 | @Override 23 | public void windowClosing(final WindowEvent evt) { 24 | myUi.doSendGlobalOff(1000, 1001, 1002); 25 | System.exit(0); 26 | } 27 | }); 28 | 29 | setVisible(true); 30 | } 31 | 32 | 33 | public static void main(final String[] args) { 34 | new Main(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /modules/ui/src/main/java/com/illposed/osc/ui/package-info.java: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2019 C. Ramakrishnan / Illposed Software 2 | // SPDX-FileCopyrightText: 2021 Robin Vobruba 3 | // 4 | // SPDX-License-Identifier: BSD-3-Clause 5 | 6 | /** 7 | * Provides a simple test GUI to send SuperCollider OSC messages over the UDP(/IP) protocol. 8 | */ 9 | package com.illposed.osc.ui; 10 | -------------------------------------------------------------------------------- /modules/ui/src/main/resources/log4j-dev.properties: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2019 Robin Vobruba 2 | # 3 | # SPDX-License-Identifier: CC0-1.0 4 | 5 | log4j.rootLogger=debug, stdout 6 | 7 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender 8 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 9 | 10 | # Pattern to output the caller's file name and line number. 11 | log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n 12 | 13 | # This log message happens all the time and isn't important unless you need to 14 | # serialize colors. Suppressing it significantly decreases log noise. 15 | log4j.appender.stdout.filter.1=org.apache.log4j.varia.StringMatchFilter 16 | log4j.appender.stdout.filter.1.StringToMatch=Failed to add AWT Color serializer 17 | log4j.appender.stdout.filter.1.AcceptOnMatch=false 18 | 19 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 4.0.0 9 | 10 | 11 | 12 | ${project.basedir}/modules/parent 13 | 14 | 15 | 16 | com.illposed.osc 17 | javaosc-parent 18 | 0.10-SNAPSHOT 19 | modules/parent 20 | 21 | 22 | javaosc 23 | 0.10-SNAPSHOT 24 | 25 | pom 26 | 27 | JavaOSC-Aggregation 28 | An Open Sound Control library implementation in Java - Aggregation 29 | 30 | 31 | scm:git:git://github.com/hoijui/JavaOSC 32 | scm:git:git@github.com:hoijui/JavaOSC.git 33 | http://github.com/hoijui/JavaOSC 34 | HEAD 35 | 36 | 37 | 38 | 39 | modules/parent 40 | modules/core 41 | modules/cmds 42 | modules/ui 43 | modules/java-se-addons 44 | 45 | 46 | 47 | 48 | 49 | org.apache.maven.plugins 50 | maven-deploy-plugin 51 | 52 | 53 | true 54 | 55 | 56 | 57 | 58 | org.apache.maven.plugins 59 | maven-release-plugin 60 | 61 | true 62 | false 63 | 64 | 65 | 66 | 67 | 68 | 69 | --------------------------------------------------------------------------------