├── .github
└── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── .gitignore
├── .gitlab-ci.yml
├── .travis.yml
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE.md
├── PULL_REQUEST_TEMPLATE.md
├── README.md
├── artnet.gif
├── build.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── javadoc.args
├── lib
├── build.gradle
└── src
│ ├── main
│ ├── java
│ │ └── de
│ │ │ └── deltaeight
│ │ │ └── libartnet
│ │ │ ├── builders
│ │ │ ├── ArtDmxBuilder.java
│ │ │ ├── ArtNetPacketBuilder.java
│ │ │ ├── ArtPollBuilder.java
│ │ │ ├── ArtPollReplyBuilder.java
│ │ │ └── ArtTimeCodeBuilder.java
│ │ │ ├── descriptors
│ │ │ ├── ArtNet.java
│ │ │ ├── EquipmentStyle.java
│ │ │ ├── IndicatorState.java
│ │ │ ├── InputStatus.java
│ │ │ ├── OemCode.java
│ │ │ ├── OpCode.java
│ │ │ ├── OutputStatus.java
│ │ │ ├── PortAddressingAuthority.java
│ │ │ ├── PortStatus.java
│ │ │ ├── PortType.java
│ │ │ ├── Priority.java
│ │ │ ├── Product.java
│ │ │ └── TimeCodeType.java
│ │ │ ├── network
│ │ │ ├── ArtNetReceiver.java
│ │ │ ├── ArtNetSender.java
│ │ │ ├── ExceptionHandler.java
│ │ │ ├── NetworkHandler.java
│ │ │ ├── PacketReceiveDispatcher.java
│ │ │ └── PacketReceiveHandler.java
│ │ │ └── packets
│ │ │ ├── ArtDmx.java
│ │ │ ├── ArtNetPacket.java
│ │ │ ├── ArtPoll.java
│ │ │ ├── ArtPollReply.java
│ │ │ └── ArtTimeCode.java
│ └── resources
│ │ └── de
│ │ └── deltaeight
│ │ └── libartnet
│ │ └── descriptors
│ │ └── OemCodes.json
│ └── test
│ └── java
│ └── de
│ └── deltaeight
│ └── libartnet
│ ├── builders
│ ├── AbstractPacketBuilderTest.java
│ ├── ArtDmxBuilderTest.java
│ ├── ArtPollBuilderTest.java
│ ├── ArtPollReplyBuilderTest.java
│ └── ArtTimeCodeBuilderTest.java
│ ├── doc
│ ├── Receiver.java
│ └── Sender.java
│ └── network
│ ├── AbstractNetworkHandlerTest.java
│ ├── ArtNetReceiverTest.java
│ ├── ArtNetSenderTest.java
│ ├── DatagramSocketMockup.java
│ └── NetworkPacketIntegrityTest.java
├── maven-key.gpg.enc
├── settings.gradle
└── util
├── build.gradle
└── src
└── main
└── java
└── de
└── deltaeight
└── libartnet
└── util
└── OemJsonGenerator.java
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 |
5 | ---
6 |
7 | **Describe the bug**
8 | A clear and concise description of what the bug is.
9 |
10 | **To Reproduce**
11 | Steps to reproduce the behavior:
12 | 1. Go to '...'
13 | 2. Click on '....'
14 | 3. Scroll down to '....'
15 | 4. See error
16 |
17 | **Expected behavior**
18 | A clear and concise description of what you expected to happen.
19 |
20 | **Code examples**
21 | Add code examples to help us understand your problem.
22 |
23 | **System:**
24 | - OS: [e.g. Windows 10 Pro]
25 | - JDK/JRE Version
26 | - Library version / last tested commit
27 |
28 | **Additional context**
29 | Add any other context about the problem here.
30 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 |
5 | ---
6 |
7 | **Is your feature request related to a problem? Please describe.**
8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
9 |
10 | **Describe the solution you'd like**
11 | A clear and concise description of what you want to happen.
12 |
13 | **Describe alternatives you've considered**
14 | A clear and concise description of any alternative solutions or features you've considered.
15 |
16 | **Additional context**
17 | Add any other context or screenshots about the feature request here.
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Gradle
2 | .gradle
3 | build
4 |
5 | # IntelliJ project files
6 | .idea
7 | *.iml
8 | out
9 | gen
10 |
11 | # VSCode project files
12 | bin/
13 | .settings
14 | .classpath
15 | .project
16 |
17 |
18 | # Misc
19 | /util/src/main/resources/de/deltaeight/libartnet/util/Art-NetOemCodes.h
20 |
--------------------------------------------------------------------------------
/.gitlab-ci.yml:
--------------------------------------------------------------------------------
1 | image: gradle:jdk8
2 |
3 | variables:
4 | GRADLE_USER_HOME: $CI_PROJECT_DIR/.gradle
5 |
6 | cache:
7 | key: $CI_PROJECT_NAME
8 | paths:
9 | - .gradle/caches/
10 | - .gradle/wrapper/
11 |
12 | test:
13 | stage: test
14 | script: ./gradlew check
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 | install: true
3 |
4 | jdk:
5 | - openjdk8
6 |
7 | stages:
8 | - test
9 | - name: deploy
10 | if: type = push AND tag IS present
11 |
12 | jobs:
13 | include:
14 | - stage: test
15 | script: "./gradlew check"
16 | - stage: deploy
17 | script:
18 | - "openssl aes-256-cbc -K $encrypted_0d982abece1d_key -iv $encrypted_0d982abece1d_iv -in maven-key.gpg.enc -out maven-key.gpg -d"
19 | - "./gradlew publish"
20 | on:
21 | branch: master
22 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6 |
7 | ## Our Standards
8 |
9 | Examples of behavior that contributes to creating a positive environment include:
10 |
11 | * Using welcoming and inclusive language
12 | * Being respectful of differing viewpoints and experiences
13 | * Gracefully accepting constructive criticism
14 | * Focusing on what is best for the community
15 | * Showing empathy towards other community members
16 |
17 | Examples of unacceptable behavior by participants include:
18 |
19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances
20 | * Trolling, insulting/derogatory comments, and personal or political attacks
21 | * Public or private harassment
22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission
23 | * Other conduct which could reasonably be considered inappropriate in a professional setting
24 |
25 | ## Our Responsibilities
26 |
27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28 |
29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30 |
31 | ## Scope
32 |
33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34 |
35 | ## Enforcement
36 |
37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at julian@deltaeight.de. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38 |
39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40 |
41 | ## Attribution
42 |
43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
44 |
45 | [homepage]: http://contributor-covenant.org
46 | [version]: http://contributor-covenant.org/version/1/4/
47 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to contribute
2 |
3 | Great that you are here and want to help!
4 |
5 | ## Documentation
6 |
7 | LibArtNet uses Javadoc comment blocks for documentation of the API. This should include a brief explanation of what
8 | classes/methods do and how to use them. You can also include the `@author`-tag if you wish.
9 |
10 | Please don't forget to describe what values are expected by methods and what they throw (and why).
11 |
12 | ## Testing
13 |
14 | LibArtNet uses [JUnit 5](https://junit.org/junit5/) as its Java test framework. Please make sure to write useful test
15 | cases for code you create. This ensures reliability and integrity of the library.
16 |
17 | ## Submitting changes
18 |
19 | When you want to submit code changes, please create a pull request including a clear list of what you changed. It would
20 | also be great if you could test as much as possible, the more coverage the better.
21 |
22 | Please follow the coding conventions below and try to add clear log messages to your commits.
23 |
24 | ## Coding conventions
25 |
26 | Nothing fancy here and you should get your head around it real quickly.
27 |
28 | * Intend using four spaces, **not tabs**!
29 | * Use `camelCase` rather than `snake_case`.
30 | * Classes start with a capital letter, variables don't. Constants are in `UPPER_CASE`.
31 | * Use lambda code whereever possible.
32 | * Opening braces belong in the same line.
33 |
34 | Thanks for reading!
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Julian Rabe
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ### General:
4 |
5 | * [ ] I followed the guidelines in the Contributing document
6 | * [ ] I have checked to ensure there aren't other open [Pull Requests](../../pulls) for the same update/change
7 | * [ ] I have written new tests for my core changes, as applicable
8 | * [ ] My submission passes new and existing tests
9 | * [ ] I have updated the documentation accordingly
10 |
11 | ### Type of changes ?
12 | * [ ] Bugfix
13 | * [ ] New feature, doesn't change API
14 | * [ ] New feature, adds to API but doesn't change old API
15 | * [ ] New feature, changes old API
16 |
17 | ### Changes by this PR
18 |
19 | ### Current behaviour
20 |
21 |
22 |
23 | ### New behaviour
24 |
25 | ### Other information
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # LibArtNet [](https://search.maven.org/search?q=g:%22de.deltaeight%22%20AND%20a:%22LibArtNet%22) [](http://www.javadoc.io/doc/de.deltaeight/LibArtNet) [](https://travis-ci.com/deltaeight/LibArtNet)
2 |
3 | LibArtNet is a Java implementation of the [Art-Net 4](https://art-net.org.uk) protocol as maintained by
4 | [Artistic License Ltd.](https://artisticlicence.com)
5 |
6 |
7 | **Please have in mind that LibArtNet is still in beta.**
8 |
9 | However, see the [feature list](#features), the [roadmap](#roadmap) and how to [contribute](#contribute) for further
10 | information. If you feel there is something missing that is not listed there, feel free to open an issue.
11 |
12 | ## Features
13 |
14 | * Basic Art-Net receiver
15 | * Basic Art-Net sender
16 |
17 | ### Supported Art-Net packets
18 |
19 | * ArtDmx
20 | * Sequence number
21 | * 15bit universe addressing
22 | * ArtPoll
23 | * unicast
24 | * sending `ArtPollReply` on state changes
25 | * priorities for diagnostic data
26 | * ArtPollReply
27 | * macros
28 | * remotes
29 | * OEM codes (all OEM codes built in)
30 | * short/long names
31 | * equipment styles
32 | * much more
33 | * ArtTimeCode
34 | * 24/25/29.97/30 fps
35 |
36 | ## Roadmap
37 |
38 | Planned features are
39 |
40 | * Art-Net controller, an abstraction layer using the existing receiver and sender to act as a console
41 | * Art-Net node, an abstraction layer using the existing receiver and sender to act as a node
42 | * RDM support
43 |
44 | ## Usage
45 |
46 | All classes are documented using [Javadoc](https://javadoc.io/doc/de.deltaeight/LibArtNet). However, if there is
47 | something missing or unclear, feel free to open an issue.
48 |
49 | ### Requirements
50 |
51 | * Java 1.8 or higher
52 | * Gradle if you want to compile from source
53 |
54 | ### Installation
55 |
56 | LibArtNet is available on [Maven Central](https://search.maven.org/search?q=g:%22de.deltaeight%22%20AND%20a:%22LibArtNet%22)
57 | and on the [release page](../../releases).
58 |
59 | #### Maven
60 |
61 | Add this dependency to `pom.xml`:
62 |
63 | ```xml
64 |
65 | de.deltaeight
66 | LibArtNet
67 | 1.1.2-beta
68 |
69 | ```
70 |
71 | #### Gradle
72 |
73 | Add this to `build.gradle`:
74 |
75 | ```groovy
76 | dependencies {
77 | implementation 'de.deltaeight:LibArtNet:1.1.2-beta'
78 | }
79 | ```
80 |
81 | ### Compiling from source
82 |
83 | To build a `.jar` file to use in your IDE, run
84 |
85 | ```bash
86 | ./gradlew :lib:jar
87 | ```
88 |
89 | ### Usage examples
90 |
91 | #### Using the receiver
92 |
93 | The receiver needs receive handlers which are called when the appropriate packet is received:
94 |
95 | ```java
96 | ArtNetReceiver receiver = new ArtNetReceiver()
97 | .withArtDmxReceiveHandler(packet -> System.out.println("Channel 63 value: " + packet.getData()[62]));
98 |
99 | receiver.start();
100 |
101 | // Do other stuff
102 |
103 | receiver.stop();
104 | ```
105 |
106 | #### Using the sender
107 |
108 | The sender needs Art-Net packets to send, therefore we need a builder instance for the desired packets first:
109 |
110 | ```java
111 | ArtPollReplyBuilder builder = new ArtPollReplyBuilder()
112 | // report as Robert Juliat Dalis Reference : 860
113 | .withProduct(OemCode.getProductByOemCode("OemRobertJulDalis1"))
114 | .withBindIp(new byte[]{127, 0, 0, 1});
115 |
116 | ArtNetSender sender = new ArtNetSender();
117 | sender.start();
118 |
119 | sender.send(InetAddress.getByName("127.0.0.1"), builder.build());
120 |
121 | // Do other stuff
122 |
123 | sender.stop();
124 | ```
125 |
126 | ## Contribute
127 |
128 | Your contribution is more than welcome!
129 |
130 | If you'd like to contribute, every help is much appreciated. Feel free to fork, create pull requests and open issues for
131 | bugs or feature requests.
132 |
133 | For bug reports, feature requests and pull requests there are templates that you can just fill out to provide us with
134 | the required information.
135 |
136 | Please have a look at the [contribution guide](CONTRIBUTING.md) and the [code of conduct](CODE_OF_CONDUCT.md) before
137 | you contribute.
138 |
139 | ## License
140 |
141 | LibArtNet is licensed under the MIT License. See [LICENSE.md](LICENSE.md) for details.
142 |
--------------------------------------------------------------------------------
/artnet.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deltaeight/LibArtNet/90e4b834b44de6740cec11e2021bb61c05c447f4/artnet.gif
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | allprojects {
2 | repositories {
3 | mavenCentral()
4 | }
5 | }
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deltaeight/LibArtNet/90e4b834b44de6740cec11e2021bb61c05c447f4/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu Jul 02 18:14:44 CEST 2020
2 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-all.zip
3 | distributionBase=GRADLE_USER_HOME
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto init
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto init
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :init
68 | @rem Get command-line arguments, handling Windows variants
69 |
70 | if not "%OS%" == "Windows_NT" goto win9xME_args
71 |
72 | :win9xME_args
73 | @rem Slurp the command line arguments.
74 | set CMD_LINE_ARGS=
75 | set _SKIP=2
76 |
77 | :win9xME_args_slurp
78 | if "x%~1" == "x" goto execute
79 |
80 | set CMD_LINE_ARGS=%*
81 |
82 | :execute
83 | @rem Setup the command line
84 |
85 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
86 |
87 |
88 | @rem Execute Gradle
89 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
90 |
91 | :end
92 | @rem End local scope for the variables with windows NT shell
93 | if "%ERRORLEVEL%"=="0" goto mainEnd
94 |
95 | :fail
96 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
97 | rem the _cmd.exe /c_ return code!
98 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
99 | exit /b 1
100 |
101 | :mainEnd
102 | if "%OS%"=="Windows_NT" endlocal
103 |
104 | :omega
105 |
--------------------------------------------------------------------------------
/javadoc.args:
--------------------------------------------------------------------------------
1 | -protected
2 | -splitindex
3 | -author
4 | -version
5 | -sourcepath lib/src/main/java
6 | -subpackages de.deltaeight.libartnet
--------------------------------------------------------------------------------
/lib/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'java'
3 | id 'maven-publish'
4 | id 'signing'
5 | }
6 |
7 | group 'de.deltaeight'
8 | version '1.1.2-beta'
9 |
10 | sourceCompatibility = 1.8
11 | targetCompatibility = 1.8
12 |
13 | dependencies {
14 |
15 | implementation 'com.google.code.gson:gson:2.8.6'
16 |
17 | // Test framework
18 | testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.2'
19 | testImplementation 'org.hamcrest:hamcrest:2.2'
20 |
21 | testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.6.2'
22 | }
23 |
24 | test {
25 | useJUnitPlatform()
26 | testLogging {
27 | events 'passed', 'skipped', 'failed'
28 | exceptionFormat 'full'
29 | }
30 | }
31 |
32 | java {
33 | withJavadocJar()
34 | withSourcesJar()
35 | }
36 |
37 | publishing {
38 | publications {
39 | mavenJava(MavenPublication) {
40 |
41 | from components.java
42 |
43 | pom {
44 | name = project.getName()
45 | description = 'Art-Net 4 protocol implementation in Java'
46 | url = 'https://github.com/deltaeight/LibArtNet'
47 |
48 | licenses {
49 | license {
50 | name = 'The MIT License'
51 | url = 'https://opensource.org/licenses/mit-license.php'
52 | }
53 | }
54 |
55 | developers {
56 | developer {
57 | id = 'schw4rzlicht'
58 | name = 'Julian Rabe'
59 | email = 'julian@deltaeight.de'
60 | }
61 | }
62 |
63 | scm {
64 | connection = 'scm:https://github.com/deltaeight/LibArtNet.git'
65 | developerConnection = 'scm:https://github.com/deltaeight/LibArtNet.git'
66 | url = 'https://github.com/deltaeight/LibArtNet'
67 | }
68 | }
69 | }
70 | }
71 |
72 | repositories {
73 | maven {
74 | def releasesRepoUrl = 'https://oss.sonatype.org/service/local/staging/deploy/maven2/'
75 | def snapshotsRepoUrl = 'https://oss.sonatype.org/content/repositories/snapshots/'
76 | url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
77 | credentials {
78 | username = System.getenv('MAVEN_REPO_USER')
79 | password = System.getenv('MAVEN_REPO_PASSWORD')
80 | }
81 | }
82 | }
83 | }
84 |
85 | gradle.taskGraph.whenReady { taskGraph ->
86 | if (taskGraph.allTasks.any { it instanceof Sign }) {
87 | allprojects { ext."signing.keyId" = System.getenv('MAVEN_SIGNING_KEY_ID') }
88 | allprojects { ext."signing.secretKeyRingFile" = '../maven-key.gpg' }
89 | allprojects { ext."signing.password" = System.getenv('MAVEN_SIGNING_KEY_PASSWORD') }
90 | }
91 | if (taskGraph.allTasks.any { it.name == 'build' || it.name == 'assemble' }) {
92 | tasks.findAll { it.name == 'signArchives' || it.name == 'signDocsJar' || it.name == 'signTestJar' }.each { task ->
93 | task.enabled = false
94 | }
95 | }
96 | }
97 |
98 | signing {
99 | sign publishing.publications.mavenJava
100 | }
--------------------------------------------------------------------------------
/lib/src/main/java/de/deltaeight/libartnet/builders/ArtDmxBuilder.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2020 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.builders;
23 |
24 | import java.util.Arrays;
25 |
26 | import de.deltaeight.libartnet.descriptors.ArtNet;
27 | import de.deltaeight.libartnet.descriptors.OpCode;
28 | import de.deltaeight.libartnet.packets.ArtDmx;
29 |
30 | /**
31 | * Builds instances of {@link ArtDmx}.
32 | *
33 | * See the Art-Net Specification for details.
34 | *
35 | * @author Julian Rabe
36 | * @see ArtDmx
37 | * @see Art-Net Specification
38 | */
39 | public class ArtDmxBuilder extends ArtNetPacketBuilder {
40 |
41 | private static final byte[] OP_CODE_BYTES = OpCode.OpDmx.getBytesLittleEndian();
42 | private final byte[] data;
43 | private int sequence;
44 | private int physical;
45 | private int subnetAddress;
46 | private int universeAddress;
47 | private int netAddress;
48 | private int dataSize;
49 |
50 | private boolean changed;
51 | private ArtDmx artDmx;
52 |
53 | public ArtDmxBuilder() {
54 | data = new byte[512];
55 | changed = true;
56 | }
57 |
58 | /**
59 | * {@inheritDoc}
60 | *
61 | * @return {@link ArtDmx} instance.
62 | * @see ArtNetPacketBuilder#build()
63 | */
64 | @Override
65 | public ArtDmx build() {
66 |
67 | if (changed) {
68 |
69 | if (dataSize % 2 > 0) {
70 | data[dataSize++] = 0x00;
71 | }
72 |
73 | byte[] bytes = new byte[18 + dataSize];
74 |
75 | System.arraycopy(ArtNet.HEADER.getBytes(), 0, bytes, 0, 8);
76 | System.arraycopy(OP_CODE_BYTES, 0, bytes, 8, 2);
77 | System.arraycopy(ArtNet.PROTOCOL_REVISION.getBytes(), 0, bytes, 10, 2);
78 |
79 | bytes[12] = (byte) sequence;
80 | bytes[13] = (byte) physical;
81 | bytes[14] = (byte) (subnetAddress << 4 | universeAddress);
82 | bytes[15] = (byte) netAddress;
83 | bytes[16] = (byte) (dataSize >> 8);
84 | bytes[17] = (byte) dataSize;
85 |
86 | System.arraycopy(data, 0, bytes, 18, dataSize);
87 |
88 | artDmx = new ArtDmx(sequence, physical, netAddress, subnetAddress, universeAddress,
89 | Arrays.copyOfRange(data, 0, dataSize), bytes);
90 |
91 | changed = false;
92 | }
93 |
94 | return artDmx;
95 | }
96 |
97 | /**
98 | * {@inheritDoc}
99 | *
100 | * @return {@link ArtDmx} instance.
101 | * @see ArtNetPacketBuilder#build()
102 | */
103 | @Override
104 | public ArtDmx buildFromBytes(byte[] packetData) {
105 | if (packetData[8] == OP_CODE_BYTES[0] && packetData[9] == OP_CODE_BYTES[1]) {
106 |
107 | byte[] data = new byte[packetData[16] << 8 | packetData[17]];
108 | System.arraycopy(packetData, 18, data, 0, data.length);
109 |
110 | int subUni = packetData[14];
111 |
112 | return new ArtDmx(packetData[12] & 0xFF, packetData[13] & 0xFF, packetData[15], (subUni & 0xFF) >>> 4,
113 | subUni & 0xF, data.clone(), packetData.clone());
114 | }
115 | return null;
116 | }
117 |
118 | public int getSequence() {
119 | return sequence;
120 | }
121 |
122 | public void setSequence(int sequence) {
123 | if (this.sequence != sequence) {
124 | if (0 > sequence || sequence > 255) {
125 | throw new IllegalArgumentException("Illegal sequence number!");
126 | }
127 | this.sequence = sequence;
128 | changed = true;
129 | }
130 | }
131 |
132 | public ArtDmxBuilder withSequence(int sequence) {
133 | setSequence(sequence);
134 | return this;
135 | }
136 |
137 | public int getPhysical() {
138 | return physical;
139 | }
140 |
141 | public void setPhysical(int physical) {
142 | if (this.physical != physical) {
143 | if (0 > physical || physical > 255) {
144 | throw new IllegalArgumentException("Illegal physical port number!");
145 | }
146 | this.physical = physical;
147 | changed = true;
148 | }
149 | }
150 |
151 | public ArtDmxBuilder withPhysical(int physical) {
152 | setPhysical(physical);
153 | return this;
154 | }
155 |
156 | public int getSubnetAddress() {
157 | return subnetAddress;
158 | }
159 |
160 | public void setSubnetAddress(int subnetAddress) {
161 | if (this.subnetAddress != subnetAddress) {
162 | if (0 > subnetAddress || subnetAddress > 15) {
163 | throw new IllegalArgumentException("Illegal subnet address!");
164 | }
165 | this.subnetAddress = subnetAddress;
166 | changed = true;
167 | }
168 | }
169 |
170 | public ArtDmxBuilder withSubnetAddress(int subnetAddress) {
171 | setSubnetAddress(subnetAddress);
172 | return this;
173 | }
174 |
175 | public int getUniverseAddress() {
176 | return universeAddress;
177 | }
178 |
179 | public void setUniverseAddress(int universeAddress) {
180 | if (this.universeAddress != universeAddress) {
181 | if (0 > universeAddress || universeAddress > 15) {
182 | throw new IllegalArgumentException("Illegal universe address!");
183 | }
184 | this.universeAddress = universeAddress;
185 | changed = true;
186 | }
187 | }
188 |
189 | public ArtDmxBuilder withUniverseAddress(int universeAddress) {
190 | setUniverseAddress(universeAddress);
191 | return this;
192 | }
193 |
194 | public int getNetAddress() {
195 | return netAddress;
196 | }
197 |
198 | public void setNetAddress(int netAddress) {
199 | if (this.netAddress != netAddress) {
200 | if (0 > netAddress || netAddress > 127) {
201 | throw new IllegalArgumentException("Illegal net address!");
202 | }
203 | this.netAddress = netAddress;
204 | changed = true;
205 | }
206 | }
207 |
208 | public ArtDmxBuilder withNetAddress(int netAddress) {
209 | setNetAddress(netAddress);
210 | return this;
211 | }
212 |
213 | public int getDataSize() {
214 | return dataSize;
215 | }
216 |
217 | public byte[] getData() {
218 | return Arrays.copyOfRange(data, 0, dataSize);
219 | }
220 |
221 | public void setData(byte[] data) {
222 | if (data != null) {
223 | if (data.length > 512) {
224 | throw new IllegalArgumentException("Payload too large!");
225 | }
226 |
227 | System.arraycopy(data, 0, this.data, 0, data.length);
228 |
229 | dataSize = data.length;
230 | changed = true;
231 | }
232 | }
233 |
234 | public byte getData(int index) {
235 | if (0 > index || index > 511) {
236 | throw new IllegalArgumentException("Illegal data index!");
237 | }
238 | if (index > dataSize - 1) {
239 | return 0x00;
240 | }
241 | return data[index];
242 | }
243 |
244 | public void setData(int index, byte data) {
245 | if (0 > index || index > 511) {
246 | throw new IllegalArgumentException("Illegal data index!");
247 | }
248 |
249 | for (int i = dataSize; i < index; i++) {
250 | this.data[i] = 0x00;
251 | }
252 |
253 | this.data[index] = data;
254 | dataSize = index + 1;
255 | changed = true;
256 | }
257 |
258 | public ArtDmxBuilder withData(byte[] data) {
259 | setData(data);
260 | return this;
261 | }
262 |
263 | public ArtDmxBuilder withData(int index, byte data) {
264 | setData(index, data);
265 | return this;
266 | }
267 | }
268 |
--------------------------------------------------------------------------------
/lib/src/main/java/de/deltaeight/libartnet/builders/ArtNetPacketBuilder.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2018 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.builders;
23 |
24 | import de.deltaeight.libartnet.packets.ArtNetPacket;
25 |
26 | /**
27 | * Builder class for {@link ArtNetPacket}s. Can be used to build packets from received payloads.
28 | *
29 | * @param The {@link ArtNetPacket} implementation the implementing builder class is used for.
30 | * @author Julian Rabe
31 | */
32 | public abstract class ArtNetPacketBuilder {
33 |
34 | /**
35 | * Builds and returns an instance of {@link ArtNetPacket}.
36 | *
37 | * @return {@link ArtNetPacket} instance.
38 | */
39 | public abstract T build();
40 |
41 | /**
42 | * Builds and returns an instance of {@link ArtNetPacket}.
43 | *
44 | * @param packetData The payload received via {@code UDP}.
45 | * @return {@link ArtNetPacket} instance.
46 | */
47 | public abstract T buildFromBytes(byte[] packetData);
48 | }
49 |
--------------------------------------------------------------------------------
/lib/src/main/java/de/deltaeight/libartnet/builders/ArtPollBuilder.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2018 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.builders;
23 |
24 | import de.deltaeight.libartnet.descriptors.ArtNet;
25 | import de.deltaeight.libartnet.descriptors.OpCode;
26 | import de.deltaeight.libartnet.descriptors.Priority;
27 | import de.deltaeight.libartnet.packets.ArtPoll;
28 |
29 | /**
30 | * Builds instances of {@link ArtPoll}.
31 | *
32 | * Default diagnose data priority is {@link Priority#Low}.
33 | *
34 | * See the Art-Net Specification for details.
35 | *
36 | * @author Julian Rabe
37 | * @see ArtPoll
38 | * @see Art-Net Specification
39 | */
40 | public class ArtPollBuilder extends ArtNetPacketBuilder {
41 |
42 | private static final byte[] OP_CODE_BYTES = OpCode.OpPoll.getBytesLittleEndian();
43 |
44 | private boolean disableVlcTransmission;
45 | private boolean unicastDiagnosticMessages;
46 | private boolean sendDiagnosticMessages;
47 | private boolean sendArtPollReplyOnChanges;
48 | private Priority priority;
49 |
50 | private boolean changed;
51 | private ArtPoll artPoll;
52 |
53 | public ArtPollBuilder() {
54 | priority = Priority.Low;
55 | changed = true;
56 | }
57 |
58 | /**
59 | * {@inheritDoc}
60 | *
61 | * @return {@link ArtPoll} instance.
62 | * @see ArtNetPacketBuilder#build()
63 | */
64 | @Override
65 | public ArtPoll build() {
66 | if (changed) {
67 |
68 | byte[] bytes = new byte[14];
69 | System.arraycopy(ArtNet.HEADER.getBytes(), 0, bytes, 0, 8);
70 | System.arraycopy(OP_CODE_BYTES, 0, bytes, 8, 2);
71 | System.arraycopy(ArtNet.PROTOCOL_REVISION.getBytes(), 0, bytes, 10, 2);
72 |
73 | if (disableVlcTransmission) {
74 | bytes[12] |= 0b00010000;
75 | }
76 | if (unicastDiagnosticMessages) {
77 | bytes[12] |= 0b00001000;
78 | }
79 | if (sendDiagnosticMessages) {
80 | bytes[12] |= 0b00000100;
81 | }
82 | if (sendArtPollReplyOnChanges) {
83 | bytes[12] |= 0b00000010;
84 | }
85 |
86 | bytes[13] = priority.getValue();
87 |
88 | artPoll = new ArtPoll(vlcTransmissionDisabled(), unicastDiagnosticMessages(), sendDiagnosticMessages(),
89 | sendArtPollReplyOnChanges(), getPriority(), bytes.clone());
90 |
91 | changed = false;
92 | }
93 |
94 | return artPoll;
95 | }
96 |
97 | /**
98 | * {@inheritDoc}
99 | *
100 | * @return {@link ArtPoll} instance.
101 | * @see ArtNetPacketBuilder#build()
102 | */
103 | @Override
104 | public ArtPoll buildFromBytes(byte[] packetData) {
105 | if (packetData[8] == OP_CODE_BYTES[0] && packetData[9] == OP_CODE_BYTES[1]) {
106 |
107 | return new ArtPoll((packetData[12] & 0b00010000) > 0, (packetData[12] & 0b00001000) > 0,
108 | (packetData[12] & 0b00000100) > 0, (packetData[12] & 0b00000010) > 0, Priority.getPriority(packetData[13]),
109 | packetData.clone());
110 | }
111 | return null;
112 | }
113 |
114 | public boolean vlcTransmissionDisabled() {
115 | return disableVlcTransmission;
116 | }
117 |
118 | public void setDisableVlcTransmission(boolean disableVlcTransmission) {
119 | if (this.disableVlcTransmission != disableVlcTransmission) {
120 | this.disableVlcTransmission = disableVlcTransmission;
121 | changed = true;
122 | }
123 | }
124 |
125 | public ArtPollBuilder withDisableVlcTransmission(boolean disableVlcTransmission) {
126 | setDisableVlcTransmission(disableVlcTransmission);
127 | return this;
128 | }
129 |
130 | public boolean unicastDiagnosticMessages() {
131 | return unicastDiagnosticMessages;
132 | }
133 |
134 | public void setUnicastDiagnosticMessages(boolean unicastDiagnosticMessages) {
135 | if (this.unicastDiagnosticMessages != unicastDiagnosticMessages) {
136 | this.unicastDiagnosticMessages = unicastDiagnosticMessages;
137 | changed = true;
138 | }
139 | }
140 |
141 | public ArtPollBuilder withUnicastDiagnosticMessages(boolean unicastDiagnosticMessages) {
142 | setUnicastDiagnosticMessages(unicastDiagnosticMessages);
143 | return this;
144 | }
145 |
146 | public boolean sendDiagnosticMessages() {
147 | return sendDiagnosticMessages;
148 | }
149 |
150 | public void setSendDiagnosticMessages(boolean sendDiagnosticMessages) {
151 | if (this.sendDiagnosticMessages != sendDiagnosticMessages) {
152 | this.sendDiagnosticMessages = sendDiagnosticMessages;
153 | changed = true;
154 | }
155 | }
156 |
157 | public ArtPollBuilder withSendDiagnosticMessages(boolean sendDiagnosticMessages) {
158 | setSendDiagnosticMessages(sendDiagnosticMessages);
159 | return this;
160 | }
161 |
162 | public boolean sendArtPollReplyOnChanges() {
163 | return sendArtPollReplyOnChanges;
164 | }
165 |
166 | public void setSendArtPollReplyOnChanges(boolean sendArtPollReplyOnChanges) {
167 | if (this.sendArtPollReplyOnChanges != sendArtPollReplyOnChanges) {
168 | this.sendArtPollReplyOnChanges = sendArtPollReplyOnChanges;
169 | changed = true;
170 | }
171 | }
172 |
173 | public ArtPollBuilder withSendArtPollReplyOnChanges(boolean sendArtPollReplyOnChanges) {
174 | setSendArtPollReplyOnChanges(sendArtPollReplyOnChanges);
175 | return this;
176 | }
177 |
178 | public Priority getPriority() {
179 | return priority;
180 | }
181 |
182 | public void setPriority(Priority priority) {
183 |
184 | if (priority == null) {
185 | priority = Priority.Low;
186 | }
187 |
188 | if (this.priority != priority) {
189 | this.priority = priority;
190 | changed = true;
191 | }
192 | }
193 |
194 | public ArtPollBuilder withPriority(Priority priority) {
195 | setPriority(priority);
196 | return this;
197 | }
198 | }
199 |
--------------------------------------------------------------------------------
/lib/src/main/java/de/deltaeight/libartnet/builders/ArtTimeCodeBuilder.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2018 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.builders;
23 |
24 | import de.deltaeight.libartnet.descriptors.ArtNet;
25 | import de.deltaeight.libartnet.descriptors.OpCode;
26 | import de.deltaeight.libartnet.descriptors.TimeCodeType;
27 | import de.deltaeight.libartnet.packets.ArtPoll;
28 | import de.deltaeight.libartnet.packets.ArtTimeCode;
29 |
30 | /**
31 | * Builds instances of {@link ArtTimeCode}.
32 | *
33 | * Default {@link TimeCodeType} is {@link TimeCodeType#Film}.
34 | *
35 | * See the Art-Net Specification for details.
36 | *
37 | * @author Julian Rabe
38 | * @see ArtTimeCode
39 | * @see Art-Net Specification
40 | */
41 | public class ArtTimeCodeBuilder extends ArtNetPacketBuilder {
42 |
43 | private static final byte[] OP_CODE_BYTES = OpCode.OpTimeCode.getBytesLittleEndian();
44 |
45 | private TimeCodeType type;
46 | private int hours;
47 | private int minutes;
48 | private int seconds;
49 | private int frames;
50 |
51 | private boolean changed;
52 | private ArtTimeCode artTimeCode;
53 |
54 | public ArtTimeCodeBuilder() {
55 | type = TimeCodeType.Film;
56 | changed = true;
57 | }
58 |
59 | /**
60 | * {@inheritDoc}
61 | *
62 | * @return {@link ArtTimeCode} instance.
63 | * @see ArtNetPacketBuilder#build()
64 | */
65 | @Override
66 | public ArtTimeCode build() {
67 | if (changed) {
68 |
69 | byte[] bytes = new byte[19];
70 | System.arraycopy(ArtNet.HEADER.getBytes(), 0, bytes, 0, 8);
71 | System.arraycopy(OP_CODE_BYTES, 0, bytes, 8, 2);
72 | System.arraycopy(ArtNet.PROTOCOL_REVISION.getBytes(), 0, bytes, 10, 2);
73 |
74 | bytes[14] = (byte) frames;
75 | bytes[15] = (byte) seconds;
76 | bytes[16] = (byte) minutes;
77 | bytes[17] = (byte) hours;
78 | bytes[18] = type.getByte();
79 |
80 | artTimeCode = new ArtTimeCode(type, hours, minutes, seconds, frames, bytes.clone());
81 |
82 | changed = false;
83 | }
84 |
85 | return artTimeCode;
86 | }
87 |
88 | /**
89 | * {@inheritDoc}
90 | *
91 | * @return {@link ArtPoll} instance.
92 | * @see ArtNetPacketBuilder#build()
93 | */
94 | @Override
95 | public ArtTimeCode buildFromBytes(byte[] packetData) {
96 | if (packetData[8] == OP_CODE_BYTES[0] && packetData[9] == OP_CODE_BYTES[1]) {
97 |
98 | return new ArtTimeCode(TimeCodeType.getTimeCodeType(packetData[18]), packetData[17], packetData[16],
99 | packetData[15], packetData[14], packetData.clone());
100 | }
101 | return null;
102 | }
103 |
104 | public TimeCodeType getType() {
105 | return type;
106 | }
107 |
108 | public void setType(TimeCodeType type) {
109 | if (this.type != type) {
110 |
111 | if (type == null) {
112 | type = TimeCodeType.Film;
113 | }
114 |
115 | if (frames > Math.ceil(type.getFramerate())) {
116 | frames = (int) (Math.ceil(type.getFramerate()) - 1);
117 | }
118 |
119 | this.type = type;
120 | changed = true;
121 | }
122 | }
123 |
124 | public ArtTimeCodeBuilder withType(TimeCodeType type) {
125 | setType(type);
126 | return this;
127 | }
128 |
129 | public int getHours() {
130 | return hours;
131 | }
132 |
133 | public void setHours(int hours) {
134 | if (this.hours != hours) {
135 |
136 | if (0 > hours || hours > 23) {
137 | throw new IllegalArgumentException("Illegal hours value!");
138 | }
139 |
140 | this.hours = hours;
141 | changed = true;
142 | }
143 | }
144 |
145 | public ArtTimeCodeBuilder withHours(int hours) {
146 | setHours(hours);
147 | return this;
148 | }
149 |
150 | public int getMinutes() {
151 | return minutes;
152 | }
153 |
154 | public void setMinutes(int minutes) {
155 | if (this.minutes != minutes) {
156 |
157 | if (0 > minutes || minutes > 59) {
158 | throw new IllegalArgumentException("Illegal minutes value!");
159 | }
160 |
161 | this.minutes = minutes;
162 | changed = true;
163 | }
164 | }
165 |
166 | public ArtTimeCodeBuilder withMinutes(int minutes) {
167 | setMinutes(minutes);
168 | return this;
169 | }
170 |
171 | public int getSeconds() {
172 | return seconds;
173 | }
174 |
175 | public void setSeconds(int seconds) {
176 | if (this.seconds != seconds) {
177 |
178 | if (0 > seconds || seconds > 59) {
179 | throw new IllegalArgumentException("Illegal seconds value!");
180 | }
181 |
182 | this.seconds = seconds;
183 | changed = true;
184 | }
185 | }
186 |
187 | public ArtTimeCodeBuilder withSeconds(int seconds) {
188 | setSeconds(seconds);
189 | return this;
190 | }
191 |
192 | public int getFrames() {
193 | return frames;
194 | }
195 |
196 | public void setFrames(int frames) {
197 | if (this.frames != frames) {
198 |
199 | if (0 > frames || frames > Math.ceil(type.getFramerate()) - 1) {
200 | throw new IllegalArgumentException("Illegal frames value!");
201 | }
202 |
203 | this.frames = frames;
204 | changed = true;
205 | }
206 | }
207 |
208 | public ArtTimeCodeBuilder withFrames(int frames) {
209 | setFrames(frames);
210 | return this;
211 | }
212 | }
213 |
--------------------------------------------------------------------------------
/lib/src/main/java/de/deltaeight/libartnet/descriptors/ArtNet.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2018 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.descriptors;
23 |
24 | /**
25 | * @author Julian Rabe
26 | * @see Art-Net Specification
27 | */
28 | public enum ArtNet {
29 |
30 | /**
31 | * The protocol revision this library works with (14).
32 | */
33 | PROTOCOL_REVISION(14),
34 |
35 | /**
36 | * The Art-Net Header to send with in every {@link de.deltaeight.libartnet.packets.ArtNetPacket} ("Art-Net\0").
37 | */
38 | HEADER(new byte[]{0x41, 0x72, 0x74, 0x2D, 0x4E, 0x65, 0x74, 0x00}),
39 |
40 | /**
41 | * The UDP port on which network traffic is handled ({@code 0x1936}).
42 | */
43 | PORT(0x1936);
44 |
45 | private final byte[] bytes;
46 |
47 | ArtNet(byte[] bytes) {
48 | this.bytes = bytes;
49 | }
50 |
51 | ArtNet(int value) {
52 | byte[] bytes = new byte[2];
53 | bytes[0] = (byte) (value >> 8);
54 | bytes[1] = (byte) value;
55 | this.bytes = bytes;
56 | }
57 |
58 | /**
59 | * @return Bytes in big endian byte order.
60 | */
61 | public byte[] getBytes() {
62 | return bytes;
63 | }
64 |
65 | /**
66 | * @return Bytes in little endian byte order.
67 | */
68 | public byte[] getBytesLittleEndian() {
69 | byte[] result = new byte[bytes.length];
70 | for (int i = 0; i < bytes.length; i++) {
71 | result[i] = bytes[bytes.length - i - 1];
72 | }
73 | return result;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/lib/src/main/java/de/deltaeight/libartnet/descriptors/EquipmentStyle.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2018 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.descriptors;
23 |
24 | /**
25 | * Supported equipment styles and their bytes
26 | *
27 | * @author Julian Rabe
28 | * @see de.deltaeight.libartnet.packets.ArtPollReply
29 | * @see Art-Net Specification
30 | */
31 | public enum EquipmentStyle {
32 |
33 | Node(0x00),
34 | Controller(0x01),
35 | MediaServer(0x02),
36 | Routing(0x03),
37 | Backup(0x04),
38 | Config(0x05),
39 | Visualiser(0x06);
40 |
41 | private final byte value;
42 |
43 | EquipmentStyle(int value) {
44 | this.value = (byte) value;
45 | }
46 |
47 | public static EquipmentStyle getEquipmentStyle(int value) {
48 | if (value > values().length - 1) {
49 | return Config;
50 | }
51 | return values()[value];
52 | }
53 |
54 | public byte getValue() {
55 | return value;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/lib/src/main/java/de/deltaeight/libartnet/descriptors/IndicatorState.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2018 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.descriptors;
23 |
24 | /**
25 | * Represents an indicator state.
26 | *
27 | * @author Julian Rabe
28 | * @see de.deltaeight.libartnet.packets.ArtPollReply
29 | * @see Art-Net Specification
30 | */
31 | public enum IndicatorState {
32 |
33 | Unknown(0b00000000),
34 | LocateIdentify(0b00000001),
35 | Mute(0b00000010),
36 | Normal(0b00000011);
37 |
38 | private final byte value;
39 |
40 | IndicatorState(int value) {
41 | this.value = (byte) value;
42 | }
43 |
44 | public byte getValue() {
45 | return value;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/lib/src/main/java/de/deltaeight/libartnet/descriptors/InputStatus.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2018 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.descriptors;
23 |
24 | import java.util.Objects;
25 |
26 | /**
27 | * Represents the status of an input port.
28 | *
29 | * @author Julian Rabe
30 | * @see de.deltaeight.libartnet.packets.ArtPollReply
31 | * @see Art-Net Specification
32 | */
33 | public class InputStatus extends PortStatus {
34 |
35 | public static final InputStatus DEFAULT = new InputStatus(false, false, false, false, false, false);
36 |
37 | private final boolean dataReceived;
38 | private final boolean inputDisabled;
39 | private final boolean errorsDetected;
40 |
41 | public InputStatus(boolean dataReceived,
42 | boolean includesTestPackets,
43 | boolean includesSIPs,
44 | boolean includesTextPackets,
45 | boolean inputDisabled,
46 | boolean errorsDetected) {
47 |
48 | super(includesTestPackets, includesSIPs, includesTextPackets);
49 |
50 | this.dataReceived = dataReceived;
51 | this.inputDisabled = inputDisabled;
52 | this.errorsDetected = errorsDetected;
53 | }
54 |
55 | public static InputStatus buildFromByte(byte b) {
56 | return new InputStatus((b & 0b10000000) > 0, (b & 0b01000000) > 0, (b & 0b00100000) > 0,
57 | (b & 0b00010000) > 0, (b & 0b00001000) > 0, (b & 0b00000100) > 0);
58 | }
59 |
60 | public byte getByte() {
61 | byte result = 0x00;
62 | if (dataReceived) {
63 | result |= 0b10000000;
64 | }
65 | if (includesTestPackets()) {
66 | result |= 0b01000000;
67 | }
68 | if (includesSIPs()) {
69 | result |= 0b00100000;
70 | }
71 | if (includesTextPackets()) {
72 | result |= 0b00010000;
73 | }
74 | if (inputDisabled) {
75 | result |= 0b00001000;
76 | }
77 | if (errorsDetected) {
78 | result |= 0b00000100;
79 | }
80 | return result;
81 | }
82 |
83 | @Override
84 | public boolean equals(Object o) {
85 | if (this == o) return true;
86 | if (o == null || getClass() != o.getClass()) return false;
87 | if (!super.equals(o)) return false;
88 | InputStatus that = (InputStatus) o;
89 | return dataReceived == that.dataReceived &&
90 | inputDisabled == that.inputDisabled &&
91 | errorsDetected == that.errorsDetected;
92 | }
93 |
94 | @Override
95 | public int hashCode() {
96 | return Objects.hash(dataReceived, inputDisabled, errorsDetected);
97 | }
98 |
99 | public boolean isDataReceived() {
100 | return dataReceived;
101 | }
102 |
103 | public boolean isInputDisabled() {
104 | return inputDisabled;
105 | }
106 |
107 | public boolean isErrorsDetected() {
108 | return errorsDetected;
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/lib/src/main/java/de/deltaeight/libartnet/descriptors/OemCode.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2020 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.descriptors;
23 |
24 | import com.google.gson.Gson;
25 |
26 | import java.io.BufferedReader;
27 | import java.io.InputStreamReader;
28 | import java.util.HashMap;
29 |
30 | /**
31 | * Imports products with OEM codes as assigned by Artistic License Ltd. and makes them searchable.
32 | *
33 | * @author Julian Rabe
34 | * @see de.deltaeight.libartnet.packets.ArtPollReply
35 | * @see Art-NetOemCodes.h
36 | */
37 | public class OemCode {
38 |
39 | private static final HashMap productsByProductCode;
40 | private static final HashMap productsByOemCode;
41 | private static final Product unknownProduct;
42 |
43 | static {
44 |
45 | productsByProductCode = new HashMap<>();
46 | productsByOemCode = new HashMap<>();
47 | unknownProduct = new Product("Unknown", 32767, "N/A",
48 | "N/A", 0, 0, false, false,
49 | "N/A", "N/A");
50 |
51 | addProduct(unknownProduct);
52 |
53 | Product[] products = new Gson().fromJson(new BufferedReader(new InputStreamReader(
54 | OemCode.class.getResourceAsStream("OemCodes.json"))), Product[].class);
55 |
56 | if (products != null) {
57 | for (Product product : products) {
58 | addProduct(product);
59 | }
60 | }
61 | }
62 |
63 | private static void addProduct(Product product) {
64 | productsByProductCode.put(product.getProductCode(), product);
65 | productsByOemCode.put(product.getOemCode(), product);
66 | }
67 |
68 | /**
69 | * @param productCode The code to search for.
70 | * @return The {@link Product} matching {@code productCode} or the unknown product if none exists.
71 | */
72 | public static Product getProductByProductCode(int productCode) {
73 | return productsByProductCode.getOrDefault(productCode, unknownProduct);
74 | }
75 |
76 | /**
77 | * @param oemCode The code to search for.
78 | * @return The {@link Product} matching {@code oemCode} or the unknown product if none exists.
79 | */
80 | public static Product getProductByOemCode(String oemCode) {
81 | return productsByOemCode.getOrDefault(oemCode, unknownProduct);
82 | }
83 |
84 | /**
85 | * @return The unknown product.
86 | */
87 | public static Product getUnknownProduct() {
88 | return unknownProduct;
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/lib/src/main/java/de/deltaeight/libartnet/descriptors/OpCode.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2018 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.descriptors;
23 |
24 | /**
25 | * Available OpCodes and their bytes
26 | *
27 | * @author Julian Rabe
28 | * @see Art-Net Specification
29 | */
30 | public enum OpCode {
31 |
32 | OpPoll(0x2000),
33 | OpPollReply(0x2100),
34 | OpDiagData(0x2300),
35 | OpCommand(0x2400),
36 | OpOutput(0x5000),
37 | OpDmx(OpOutput),
38 | OpNzs(0x5100),
39 | OpSync(0x5200),
40 | OpAddress(0x6000),
41 | OpInput(0x7000),
42 | OpTodRequest(0x8000),
43 | OpTodData(0x8100),
44 | OpTodControl(0x8200),
45 | OpRdm(0x8300),
46 | OpRdmSub(0x8400),
47 | OpVideoSetup(0xA010),
48 | OpVideoPalette(0xA020),
49 | OpVideoData(0xA040),
50 | OpFirmwareMaster(0xF200),
51 | OpFirmwareReply(0xF300),
52 | OpFileTnMaster(0xF400),
53 | OpFileFnMaster(0xF500),
54 | OpFileFnReply(0xF600),
55 | OpIpProg(0xF800),
56 | OpIpProgReply(0xF900),
57 | OpMedia(0x9000),
58 | OpMediaPatch(0x9100),
59 | OpMediaControl(0x9200),
60 | OpMediaControlReply(0x9300),
61 | OpTimeCode(0x9700),
62 | OpTimeSync(0x9800),
63 | OpTrigger(0x9900),
64 | OpDirectory(0x9A00),
65 | OpDirectoryReply(0x9B00);
66 |
67 | private final byte[] bytes;
68 |
69 | OpCode(int value) {
70 | this.bytes = new byte[]{(byte) (value >> 8), (byte) value};
71 | }
72 |
73 | OpCode(OpCode opCode) {
74 | this.bytes = opCode.bytes;
75 | }
76 |
77 | /**
78 | * @return Bytes in big endian byte order.
79 | */
80 | public byte[] getBytes() {
81 | return bytes;
82 | }
83 |
84 | /**
85 | * @return Bytes in little endian byte order.
86 | */
87 | public byte[] getBytesLittleEndian() {
88 | byte[] result = new byte[2];
89 | result[0] = bytes[1];
90 | result[1] = bytes[0];
91 | return result;
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/lib/src/main/java/de/deltaeight/libartnet/descriptors/OutputStatus.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2018 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.descriptors;
23 |
24 | import java.util.Objects;
25 |
26 | /**
27 | * Represents the status of an output port.
28 | *
29 | * @author Julian Rabe
30 | * @see de.deltaeight.libartnet.packets.ArtPollReply
31 | * @see Art-Net Specification
32 | */
33 | public class OutputStatus extends PortStatus {
34 |
35 | public static final OutputStatus DEFAULT = new OutputStatus(false, false, false, false, false, false, false, false);
36 |
37 | private final boolean dataTransmitted;
38 | private final boolean merging;
39 | private final boolean outputShort;
40 | private final boolean mergeModeLTP;
41 | private final boolean transmittingSACN;
42 |
43 | public OutputStatus(boolean dataTransmitted,
44 | boolean includesTestPackets,
45 | boolean includesSIPs,
46 | boolean includesTextPackets,
47 | boolean merging,
48 | boolean outputShort,
49 | boolean mergeModeLTP,
50 | boolean transmittingSACN) {
51 |
52 | super(includesTestPackets, includesSIPs, includesTextPackets);
53 |
54 | this.dataTransmitted = dataTransmitted;
55 | this.merging = merging;
56 | this.outputShort = outputShort;
57 | this.mergeModeLTP = mergeModeLTP;
58 | this.transmittingSACN = transmittingSACN;
59 | }
60 |
61 | public static OutputStatus buildFromByte(byte b) {
62 | return new OutputStatus((b & 0b10000000) > 0, (b & 0b01000000) > 0, (b & 0b00100000) > 0,
63 | (b & 0b000100000) > 0, (b & 0b00001000) > 0, (b & 0b00000100) > 0,
64 | (b & 0b00000010) > 0, (b & 0b00000001) > 0);
65 | }
66 |
67 | public byte getByte() {
68 | byte result = 0x00;
69 | if (dataTransmitted) {
70 | result |= 0b10000000;
71 | }
72 | if (includesTestPackets()) {
73 | result |= 0b01000000;
74 | }
75 | if (includesSIPs()) {
76 | result |= 0b00100000;
77 | }
78 | if (includesTextPackets()) {
79 | result |= 0b00010000;
80 | }
81 | if (merging) {
82 | result |= 0b00001000;
83 | }
84 | if (outputShort) {
85 | result |= 0b00000100;
86 | }
87 | if (mergeModeLTP) {
88 | result |= 0b00000010;
89 | }
90 | if (transmittingSACN) {
91 | result |= 0b00000001;
92 | }
93 | return result;
94 | }
95 |
96 | @Override
97 | public int hashCode() {
98 | return Objects.hash(dataTransmitted, merging, outputShort, mergeModeLTP, transmittingSACN);
99 | }
100 |
101 | @Override
102 | public boolean equals(Object o) {
103 | if (this == o) return true;
104 | if (o == null || getClass() != o.getClass()) return false;
105 | if (!super.equals(o)) return false;
106 | OutputStatus that = (OutputStatus) o;
107 | return dataTransmitted == that.dataTransmitted &&
108 | merging == that.merging &&
109 | outputShort == that.outputShort &&
110 | mergeModeLTP == that.mergeModeLTP &&
111 | transmittingSACN == that.transmittingSACN;
112 | }
113 |
114 | public boolean isDataTransmitted() {
115 | return dataTransmitted;
116 | }
117 |
118 | public boolean isMerging() {
119 | return merging;
120 | }
121 |
122 | public boolean isOutputShort() {
123 | return outputShort;
124 | }
125 |
126 | public boolean isMergeModeLTP() {
127 | return mergeModeLTP;
128 | }
129 |
130 | public boolean isTransmittingSACN() {
131 | return transmittingSACN;
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/lib/src/main/java/de/deltaeight/libartnet/descriptors/PortAddressingAuthority.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2018 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.descriptors;
23 |
24 | /**
25 | * Represents the port addressing authority.
26 | *
27 | * @author Julian Rabe
28 | * @see de.deltaeight.libartnet.packets.ArtPollReply
29 | * @see Art-Net Specification
30 | */
31 | public enum PortAddressingAuthority {
32 |
33 | Unknown(0b00000000),
34 | FrontPanel(0b00000001),
35 | Network(0b00000010),
36 | NotUsed(0b00000011);
37 |
38 | private final byte value;
39 |
40 | PortAddressingAuthority(int value) {
41 | this.value = (byte) value;
42 | }
43 |
44 | public byte getValue() {
45 | return value;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/lib/src/main/java/de/deltaeight/libartnet/descriptors/PortStatus.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2018 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.descriptors;
23 |
24 | import java.util.Objects;
25 |
26 | /**
27 | * Describes the status of a data port.
28 | *
29 | * @author Julian Rabe
30 | */
31 | public abstract class PortStatus {
32 |
33 | private final boolean includesTestPackets;
34 | private final boolean includesSIPs;
35 | private final boolean includesTextPackets;
36 |
37 | PortStatus(boolean includesTestPackets,
38 | boolean includesSIPs,
39 | boolean includesTextPackets) {
40 |
41 | this.includesTestPackets = includesTestPackets;
42 | this.includesSIPs = includesSIPs;
43 | this.includesTextPackets = includesTextPackets;
44 | }
45 |
46 | @Override
47 | public int hashCode() {
48 | return Objects.hash(includesTestPackets, includesSIPs, includesTextPackets);
49 | }
50 |
51 | @Override
52 | public boolean equals(Object o) {
53 | if (this == o) return true;
54 | if (o == null || getClass() != o.getClass()) return false;
55 | PortStatus that = (PortStatus) o;
56 | return includesTestPackets == that.includesTestPackets &&
57 | includesSIPs == that.includesSIPs &&
58 | includesTextPackets == that.includesTextPackets;
59 | }
60 |
61 | public boolean includesTestPackets() {
62 | return includesTestPackets;
63 | }
64 |
65 | public boolean includesSIPs() {
66 | return includesSIPs;
67 | }
68 |
69 | public boolean includesTextPackets() {
70 | return includesTextPackets;
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/lib/src/main/java/de/deltaeight/libartnet/descriptors/PortType.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2018 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.descriptors;
23 |
24 | import java.util.Objects;
25 |
26 | /**
27 | * Represents a port type.
28 | *
29 | * @author Julian Rabe
30 | * @see de.deltaeight.libartnet.packets.ArtPollReply
31 | * @see Art-Net Specification
32 | */
33 | public class PortType {
34 |
35 | public static final PortType DEFAULT = new PortType(false, false, Protocol.DMX512);
36 |
37 | private final boolean outputSupported;
38 | private final boolean inputSupported;
39 | private final Protocol protocol;
40 |
41 | public PortType(boolean outputSupported, boolean inputSupported, Protocol protocol) {
42 | this.outputSupported = outputSupported;
43 | this.inputSupported = inputSupported;
44 | this.protocol = protocol;
45 | }
46 |
47 | public static PortType buildFromByte(byte b) {
48 | return new PortType((b & 0b10000000) > 0, (b & 0b01000000) > 0, Protocol.getProtocol(b & 0b00000111));
49 | }
50 |
51 | public byte getByte() {
52 | byte result = 0x00;
53 | if (outputSupported) {
54 | result |= 0b10000000;
55 | }
56 | if (inputSupported) {
57 | result |= 0b01000000;
58 | }
59 | result |= protocol.getValue();
60 | return result;
61 | }
62 |
63 | @Override
64 | public int hashCode() {
65 | return Objects.hash(outputSupported, inputSupported, protocol);
66 | }
67 |
68 | @Override
69 | public boolean equals(Object o) {
70 | if (this == o) return true;
71 | if (o == null || getClass() != o.getClass()) return false;
72 | PortType portType = (PortType) o;
73 | return outputSupported == portType.outputSupported &&
74 | inputSupported == portType.inputSupported &&
75 | protocol == portType.protocol;
76 | }
77 |
78 | public boolean isOutputSupported() {
79 | return outputSupported;
80 | }
81 |
82 | public boolean isInputSupported() {
83 | return inputSupported;
84 | }
85 |
86 | public Protocol getProtocol() {
87 | return protocol;
88 | }
89 |
90 | /**
91 | * Represents a Protocol for input/output ports.
92 | *
93 | * @author Julian Rabe
94 | * @see Art-Net Specification
95 | */
96 | public enum Protocol {
97 |
98 | DMX512(0b00000000),
99 | MIDI(0b00000001),
100 | AVAB(0b00000010),
101 | COLORTRAN_CMX(0b00000011),
102 | ADB625(0b00000100),
103 | ARTNET(0b00000101);
104 |
105 | private final byte value;
106 |
107 | Protocol(int value) {
108 | this.value = (byte) value;
109 | }
110 |
111 | public static Protocol getProtocol(int value) {
112 | if (value > values().length - 1) {
113 | return DMX512;
114 | }
115 | return values()[value];
116 | }
117 |
118 | public byte getValue() {
119 | return value;
120 | }
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/lib/src/main/java/de/deltaeight/libartnet/descriptors/Priority.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2018 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.descriptors;
23 |
24 | import java.util.HashMap;
25 |
26 | /**
27 | * Priorities for diag data and their bytes
28 | *
29 | * @author Julian Rabe
30 | * @see de.deltaeight.libartnet.packets.ArtPoll
31 | * @see Art-Net Specification
32 | */
33 | public enum Priority {
34 |
35 | Low(0x10),
36 | Medium(0x40),
37 | High(0x80),
38 | Critical(0xE0),
39 | Volatile(0xF0);
40 |
41 | private static final HashMap priorities;
42 |
43 | static {
44 | priorities = new HashMap<>(5);
45 | for (Priority value : values()) {
46 | priorities.put(value.getValue(), value);
47 | }
48 | }
49 |
50 | private final byte value;
51 |
52 | Priority(int value) {
53 | this.value = (byte) value;
54 | }
55 |
56 | public static Priority getPriority(byte value) {
57 | return priorities.getOrDefault(value, Low);
58 | }
59 |
60 | public byte getValue() {
61 | return value;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/lib/src/main/java/de/deltaeight/libartnet/descriptors/Product.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2020 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.descriptors;
23 |
24 | /**
25 | * Represents a product defined by Artistic License Ltd.
26 | *
27 | * @author Julian Rabe
28 | * @see de.deltaeight.libartnet.descriptors.OemCode
29 | */
30 | public class Product {
31 |
32 | private final String oemCode;
33 | private final int productCode;
34 | private final String manufacturer;
35 | private final String name;
36 | private final int dmxOutputs;
37 | private final int dmxInputs;
38 | private final boolean dmxPortsPhysical;
39 | private final boolean supportsRdm;
40 | private final String supportEmail;
41 | private final String supportName;
42 |
43 | /**
44 | * @param oemCode The OEM code assigned by Artistic License Ltd.
45 | * @param productCode The product code assigned by Artistic License Ltd.
46 | * @param manufacturer The manufacturer of the product
47 | * @param name The name of the product
48 | * @param dmxOutputs The amount of DMX outputs
49 | * @param dmxInputs The amount of DMX inputs
50 | * @param dmxPortsPhysical Whether the product has physical DMX ports or not.
51 | * @param supportsRdm Whether the product supports RDM or not.
52 | * @param supportEmail The Email address of the customer support.
53 | * @param supportName The name of the customer support.
54 | */
55 | Product(String oemCode,
56 | int productCode,
57 | String manufacturer,
58 | String name,
59 | int dmxOutputs,
60 | int dmxInputs,
61 | boolean dmxPortsPhysical,
62 | boolean supportsRdm,
63 | String supportEmail,
64 | String supportName) {
65 |
66 | this.oemCode = oemCode;
67 | this.productCode = productCode;
68 | this.manufacturer = manufacturer;
69 | this.name = name;
70 | this.dmxOutputs = dmxOutputs;
71 | this.dmxInputs = dmxInputs;
72 | this.dmxPortsPhysical = dmxPortsPhysical;
73 | this.supportsRdm = supportsRdm;
74 | this.supportEmail = supportEmail;
75 | this.supportName = supportName;
76 | }
77 |
78 | public String getOemCode() {
79 | return oemCode;
80 | }
81 |
82 | public int getProductCode() {
83 | return productCode;
84 | }
85 |
86 | public String getManufacturer() {
87 | return manufacturer;
88 | }
89 |
90 | public String getName() {
91 | return name;
92 | }
93 |
94 | public int getDmxOutputs() {
95 | return dmxOutputs;
96 | }
97 |
98 | public int getDmxInputs() {
99 | return dmxInputs;
100 | }
101 |
102 | public boolean isDmxPortsPhysical() {
103 | return dmxPortsPhysical;
104 | }
105 |
106 | public boolean supportsRdm() {
107 | return supportsRdm;
108 | }
109 |
110 | public String getSupportEmail() {
111 | return supportEmail;
112 | }
113 |
114 | public String getSupportName() {
115 | return supportName;
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/lib/src/main/java/de/deltaeight/libartnet/descriptors/TimeCodeType.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2018 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.descriptors;
23 |
24 | /**
25 | * Available timecode types and their framerates.
26 | *
27 | * @author Julian Rabe
28 | * @see de.deltaeight.libartnet.packets.ArtTimeCode
29 | */
30 | public enum TimeCodeType {
31 |
32 | Film(24, 0x00),
33 | EBU(25, 0x01),
34 | DF(29.97f, 0x02),
35 | SMPTE(30, 0x03);
36 |
37 | private final float framerate;
38 | private final int value;
39 |
40 | TimeCodeType(float framerate, int value) {
41 | this.framerate = framerate;
42 | this.value = value;
43 | }
44 |
45 | public static TimeCodeType getTimeCodeType(int value) {
46 | if (value > values().length - 1) {
47 | return Film;
48 | }
49 | return values()[value];
50 | }
51 |
52 | public float getFramerate() {
53 | return framerate;
54 | }
55 |
56 | public byte getByte() {
57 | return (byte) value;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/lib/src/main/java/de/deltaeight/libartnet/network/ArtNetReceiver.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2020 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.network;
23 |
24 | import java.net.DatagramPacket;
25 | import java.net.DatagramSocket;
26 | import java.net.SocketException;
27 | import java.util.Arrays;
28 | import java.util.HashSet;
29 | import java.util.concurrent.ConcurrentHashMap;
30 | import java.util.concurrent.ExecutorService;
31 | import java.util.concurrent.ForkJoinPool;
32 |
33 | import de.deltaeight.libartnet.builders.ArtDmxBuilder;
34 | import de.deltaeight.libartnet.builders.ArtPollBuilder;
35 | import de.deltaeight.libartnet.builders.ArtPollReplyBuilder;
36 | import de.deltaeight.libartnet.builders.ArtTimeCodeBuilder;
37 | import de.deltaeight.libartnet.descriptors.ArtNet;
38 | import de.deltaeight.libartnet.packets.ArtDmx;
39 | import de.deltaeight.libartnet.packets.ArtNetPacket;
40 | import de.deltaeight.libartnet.packets.ArtPoll;
41 | import de.deltaeight.libartnet.packets.ArtPollReply;
42 | import de.deltaeight.libartnet.packets.ArtTimeCode;
43 |
44 | /**
45 | * Provides a multi-threaded receiver which listens to UDP network traffic and uses {@link PacketReceiveHandler}
46 | * instances to react to known packets.
47 | *
48 | * @author Julian Rabe
49 | * @see ArtNetSender
50 | */
51 | public class ArtNetReceiver extends NetworkHandler {
52 |
53 | private final ExecutorService workingPool;
54 | private final byte[] buffer;
55 | private final ConcurrentHashMap, PacketReceiveDispatcher extends ArtNetPacket>> packetReceiveDispatcher;
56 | private final HashSet> artDmxReceiveHandlers;
57 | private final HashSet> artPollReceiveHandlers;
58 | private final HashSet> artPollReplyReceiveHandlers;
59 | private final HashSet> artTimeCodeReceiveHandlers;
60 |
61 | /**
62 | * Initializes an instance for use.
63 | *
64 | * @param workingPool The {@link ExecutorService} to use.
65 | * @param socket The {@link DatagramSocket} to use.
66 | */
67 | public ArtNetReceiver(ExecutorService workingPool, DatagramSocket socket) {
68 | super(socket);
69 |
70 | if (socket.getLocalPort() != 0x1936) {
71 | throw new IllegalArgumentException("Illegal socket port " + socket.getLocalPort() + "!");
72 | }
73 |
74 | this.workingPool = workingPool;
75 |
76 | buffer = new byte[530];
77 | packetReceiveDispatcher = new ConcurrentHashMap<>();
78 |
79 | artDmxReceiveHandlers = new HashSet<>();
80 | artPollReceiveHandlers = new HashSet<>();
81 | artPollReplyReceiveHandlers = new HashSet<>();
82 | artTimeCodeReceiveHandlers = new HashSet<>();
83 | }
84 |
85 | /**
86 | * Initializes an instance for use but creates a default {@link DatagramSocket} bound to Port {@code 0x1936}.
87 | *
88 | * @param workingPool The {@link ExecutorService} to use.
89 | * @throws SocketException When it was not possible to bind to Port {@code 0x1936}, the socket is not able to switch
90 | * to broadcast or is not able to bind multiple addresses.
91 | */
92 | public ArtNetReceiver(ExecutorService workingPool) throws SocketException {
93 | this(workingPool, new DatagramSocket(0x1936));
94 | socket.setBroadcast(true);
95 | socket.setReuseAddress(true);
96 | }
97 |
98 | /**
99 | * Initializes an instance for use but uses the common {@link ForkJoinPool} shared across the JVM.
100 | *
101 | * @param socket The {@link DatagramSocket} to use.
102 | * @see ForkJoinPool#commonPool()
103 | */
104 | public ArtNetReceiver(DatagramSocket socket) {
105 | this(ForkJoinPool.commonPool(), socket);
106 | }
107 |
108 | /**
109 | * Initializes an instance for use but creates a default {@link DatagramSocket} bound to Port {@code 0x1936} and
110 | * uses the common {@link ForkJoinPool} shared across the JVM.
111 | *
112 | * @throws SocketException When it was not possible to bind to Port {@code 0x1936}, the socket is not able to switch
113 | * to broadcast or is not able to bind multiple addresses.
114 | * @see ForkJoinPool#commonPool()
115 | */
116 | public ArtNetReceiver() throws SocketException {
117 | this(ForkJoinPool.commonPool(), new DatagramSocket(0x1936));
118 | socket.setBroadcast(true);
119 | socket.setReuseAddress(true);
120 | }
121 |
122 | @Override
123 | void run() throws Exception {
124 | DatagramPacket datagramPacket = new DatagramPacket(buffer, buffer.length);
125 | socket.receive(datagramPacket);
126 |
127 | if (datagramPacket.getLength() > 10
128 | && Arrays.equals(ArtNet.HEADER.getBytes(), Arrays.copyOfRange(datagramPacket.getData(), 0, 8))) {
129 |
130 | for (PacketReceiveDispatcher extends ArtNetPacket> dispatcher : packetReceiveDispatcher.values()) {
131 |
132 | if (dispatcher.handleReceive(datagramPacket.getData().clone())) {
133 | break;
134 | }
135 | }
136 | }
137 | }
138 |
139 | /**
140 | * {@inheritDoc}
141 | */
142 | @Override
143 | public void stop() {
144 | super.stop();
145 | if (getState() == State.Running) {
146 | workingPool.shutdown();
147 | }
148 | }
149 |
150 | /**
151 | * Adds a {@link PacketReceiveHandler} which is called when {@link ArtDmx} packets are received.
152 | *
153 | * @param handler The {@link PacketReceiveHandler} to use.
154 | */
155 | public void addArtDmxReceiveHandler(PacketReceiveHandler handler) {
156 | if (!packetReceiveDispatcher.containsKey(ArtDmx.class)) {
157 | packetReceiveDispatcher.put(ArtDmx.class, new PacketReceiveDispatcher<>(workingPool,
158 | new ArtDmxBuilder(), artDmxReceiveHandlers));
159 | }
160 | artDmxReceiveHandlers.add(handler);
161 |
162 | }
163 |
164 | public void removeArtDmxReceiveHandler(PacketReceiveHandler handler) {
165 | artDmxReceiveHandlers.remove(handler);
166 | if (artDmxReceiveHandlers.isEmpty()) {
167 | packetReceiveDispatcher.remove(ArtDmx.class);
168 | }
169 | }
170 |
171 | /**
172 | * @param handler The {@link PacketReceiveHandler} to use.
173 | * @return Current {@link ArtNetReceiver} instance for fluent code style.
174 | * @see #addArtDmxReceiveHandler(PacketReceiveHandler)
175 | */
176 | public ArtNetReceiver withArtDmxReceiveHandler(PacketReceiveHandler handler) {
177 | addArtDmxReceiveHandler(handler);
178 | return this;
179 | }
180 |
181 | public ArtNetReceiver withoutArtDmxReceiveHandler(PacketReceiveHandler handler) {
182 | removeArtDmxReceiveHandler(handler);
183 | return this;
184 | }
185 |
186 | /**
187 | * Adds a {@link PacketReceiveHandler} which is called when {@link ArtPoll} packets are received.
188 | *
189 | * @param handler The {@link PacketReceiveHandler} to use.
190 | */
191 | public void addArtPollReceiveHandler(PacketReceiveHandler handler) {
192 | if (!packetReceiveDispatcher.containsKey(ArtPoll.class)) {
193 | packetReceiveDispatcher.put(ArtPoll.class, new PacketReceiveDispatcher<>(workingPool,
194 | new ArtPollBuilder(), artPollReceiveHandlers));
195 | }
196 | artPollReceiveHandlers.add(handler);
197 |
198 | }
199 |
200 | public void removeArtPollReceiveHandler(PacketReceiveHandler handler) {
201 | artPollReceiveHandlers.remove(handler);
202 | if (artPollReceiveHandlers.isEmpty()) {
203 | packetReceiveDispatcher.remove(ArtPoll.class);
204 | }
205 | }
206 |
207 | /**
208 | * @param handler The {@link PacketReceiveHandler} to use.
209 | * @return Current {@link ArtNetReceiver} instance for fluent code style.
210 | * @see #addArtPollReceiveHandler(PacketReceiveHandler)
211 | */
212 | public ArtNetReceiver withArtPollReceiveHandler(PacketReceiveHandler handler) {
213 | addArtPollReceiveHandler(handler);
214 | return this;
215 | }
216 |
217 | public ArtNetReceiver withoutArtPollReceiveHandler(PacketReceiveHandler handler) {
218 | removeArtPollReceiveHandler(handler);
219 | return this;
220 | }
221 |
222 | /**
223 | * Adds a {@link PacketReceiveHandler} which is called when {@link ArtPollReply} packets are received.
224 | *
225 | * @param handler The {@link PacketReceiveHandler} to use.
226 | */
227 | public void addArtPollReplyReceiveHandler(PacketReceiveHandler handler) {
228 | if (!packetReceiveDispatcher.containsKey(ArtPollReply.class)) {
229 | packetReceiveDispatcher.put(ArtPollReply.class, new PacketReceiveDispatcher<>(workingPool,
230 | new ArtPollReplyBuilder(), artPollReplyReceiveHandlers));
231 | }
232 | artPollReplyReceiveHandlers.add(handler);
233 |
234 | }
235 |
236 | public void removeArtPollReplyReceiveHandler(PacketReceiveHandler handler) {
237 | artPollReplyReceiveHandlers.remove(handler);
238 | if (artPollReplyReceiveHandlers.isEmpty()) {
239 | packetReceiveDispatcher.remove(ArtPollReply.class);
240 | }
241 | }
242 |
243 | /**
244 | * @param handler The {@link PacketReceiveHandler} to use.
245 | * @return Current {@link ArtNetReceiver} instance for fluent code style.
246 | * @see #addArtPollReplyReceiveHandler(PacketReceiveHandler)
247 | */
248 | public ArtNetReceiver withArtPollReplyReceiveHandler(PacketReceiveHandler handler) {
249 | addArtPollReplyReceiveHandler(handler);
250 | return this;
251 | }
252 |
253 | public ArtNetReceiver withoutArtPollReplyReceiveHandler(PacketReceiveHandler handler) {
254 | removeArtPollReplyReceiveHandler(handler);
255 | return this;
256 | }
257 |
258 | /**
259 | * Adds a {@link PacketReceiveHandler} which is called when {@link ArtTimeCode} packets are received.
260 | *
261 | * @param handler The {@link PacketReceiveHandler} to use.
262 | */
263 | public void addArtTimeCodeReceiveHandler(PacketReceiveHandler handler) {
264 | if (!packetReceiveDispatcher.containsKey(ArtTimeCode.class)) {
265 | packetReceiveDispatcher.put(ArtTimeCode.class, new PacketReceiveDispatcher<>(workingPool,
266 | new ArtTimeCodeBuilder(), artTimeCodeReceiveHandlers));
267 | }
268 | artTimeCodeReceiveHandlers.add(handler);
269 |
270 | }
271 |
272 | public void removeArtTimeCodeReceiveHandler(PacketReceiveHandler handler) {
273 | artTimeCodeReceiveHandlers.remove(handler);
274 | if (artTimeCodeReceiveHandlers.isEmpty()) {
275 | packetReceiveDispatcher.remove(ArtTimeCode.class);
276 | }
277 | }
278 |
279 | /**
280 | * @param handler The {@link PacketReceiveHandler} to use.
281 | * @return Current {@link ArtNetReceiver} instance for fluent code style.
282 | * @see #addArtTimeCodeReceiveHandler(PacketReceiveHandler)
283 | */
284 | public ArtNetReceiver withArtTimeCodeReceiveHandler(PacketReceiveHandler handler) {
285 | addArtTimeCodeReceiveHandler(handler);
286 | return this;
287 | }
288 |
289 | public ArtNetReceiver withoutArtTimeCodeReceiveHandler(PacketReceiveHandler handler) {
290 | removeArtTimeCodeReceiveHandler(handler);
291 | return this;
292 | }
293 | }
294 |
--------------------------------------------------------------------------------
/lib/src/main/java/de/deltaeight/libartnet/network/ArtNetSender.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2020 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.network;
23 |
24 | import java.net.DatagramPacket;
25 | import java.net.DatagramSocket;
26 | import java.net.InetAddress;
27 | import java.net.SocketException;
28 | import java.util.concurrent.LinkedBlockingQueue;
29 |
30 | import de.deltaeight.libartnet.packets.ArtNetPacket;
31 |
32 | /**
33 | * Provides a sender which queues packets to send.
34 | *
35 | * @author Julian Rabe
36 | * @see ArtNetReceiver
37 | */
38 | public class ArtNetSender extends NetworkHandler {
39 |
40 | private final LinkedBlockingQueue packetQueue;
41 |
42 | /**
43 | * Initializes an instance for use.
44 | *
45 | * @param socket The {@link DatagramSocket} to use.
46 | */
47 | public ArtNetSender(DatagramSocket socket) {
48 | super(socket);
49 | packetQueue = new LinkedBlockingQueue<>();
50 | }
51 |
52 | /**
53 | * Initializes an instance for use but creates a default {@link DatagramSocket} bound to Port {@code 0x1936}.
54 | *
55 | * @throws SocketException When socket is not usable.
56 | */
57 | public ArtNetSender() throws SocketException {
58 | this(new DatagramSocket());
59 | }
60 |
61 | @Override
62 | void run() throws Exception {
63 | socket.send(packetQueue.take());
64 | }
65 |
66 | /**
67 | * Queues the desired {@link ArtNetPacket} for sending.
68 | *
69 | * @param address The {@link InetAddress} to send to.
70 | * @param packet The {@link ArtNetPacket} to send.
71 | * @return {@code true} if queueing was successful, {@code false} if not.
72 | */
73 | public boolean send(InetAddress address, ArtNetPacket packet) {
74 | return packetQueue.offer(new DatagramPacket(packet.getBytes(), packet.getBytes().length, address, 0x1936));
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/lib/src/main/java/de/deltaeight/libartnet/network/ExceptionHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2018 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.network;
23 |
24 | /**
25 | * Used to handle exceptions thrown by network handlers.
26 | *
27 | * @author Julian Rabe
28 | * @see ArtNetReceiver
29 | */
30 | @FunctionalInterface
31 | public interface ExceptionHandler {
32 |
33 | /**
34 | * Is called when an exception is thrown.
35 | *
36 | * @param exception The exception that was thrown.
37 | */
38 | void handleException(Exception exception);
39 | }
40 |
--------------------------------------------------------------------------------
/lib/src/main/java/de/deltaeight/libartnet/network/NetworkHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2020 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.network;
23 |
24 | import java.net.DatagramSocket;
25 |
26 | /**
27 | * Provides a basic template for network handlers with a worker thread and states.
28 | *
29 | * @author Julian Rabe
30 | */
31 | abstract class NetworkHandler {
32 |
33 | final DatagramSocket socket;
34 | private final Thread workerThread;
35 | private State state;
36 | private ExceptionHandler exceptionHandler;
37 |
38 | /**
39 | * @param socket The {@link DatagramSocket} to use.
40 | * @throws IllegalArgumentException if {@code socket} is on a different port than {@code 0x1936}.
41 | */
42 | NetworkHandler(DatagramSocket socket) {
43 |
44 | this.socket = socket;
45 |
46 | workerThread = new Thread() {
47 |
48 | @Override
49 | public void run() {
50 | while (!isInterrupted()) {
51 | try {
52 | NetworkHandler.this.run();
53 | } catch (Exception e) {
54 | if (!isInterrupted()) {
55 | if (exceptionHandler != null) {
56 | exceptionHandler.handleException(e);
57 | } else {
58 | interrupt();
59 | }
60 | }
61 | }
62 | }
63 | }
64 | };
65 |
66 | workerThread.setName("ArtNet Network Worker");
67 | workerThread.setDaemon(true);
68 |
69 | state = State.Initialized;
70 | }
71 |
72 | /**
73 | * Is run in {@link #workerThread}.
74 | *
75 | * @throws Exception Can be anything and is forwarded to {@link #exceptionHandler} if set.
76 | */
77 | abstract void run() throws Exception;
78 |
79 | /**
80 | * Starts working. Only possible if not already running or stopped.
81 | *
82 | * It is recommended, to check the state using {@link #getState()} before calling.
83 | *
84 | * @throws IllegalStateException When {@link #getState()} {@code != } {@link State#Initialized}.
85 | * @see #stop()
86 | * @see State
87 | */
88 | public void start() {
89 | if (state == State.Initialized) {
90 | workerThread.start();
91 | state = State.Running;
92 | } else if (state == State.Running) {
93 | throw new IllegalStateException("Already running!");
94 | } else {
95 | throw new IllegalStateException("Not initialized!");
96 | }
97 | }
98 |
99 | /**
100 | * Stops working and closes the underlying socket. Only possible if running.
101 | *
102 | * It is recommended, to check the state using {@link #getState()} before calling.
103 | *
104 | * @throws IllegalStateException When {@link #getState()} {@code != } {@link State#Running}.
105 | * @see #start()
106 | * @see State
107 | */
108 | public void stop() {
109 | if (state == State.Running) {
110 | workerThread.interrupt();
111 | socket.close();
112 | state = State.Stopped;
113 | } else {
114 | throw new IllegalStateException("Not Running!");
115 | }
116 | }
117 |
118 | public State getState() {
119 | return state;
120 | }
121 |
122 | public ExceptionHandler getExceptionHandler() {
123 | return exceptionHandler;
124 | }
125 |
126 | /**
127 | * Sets the {@link ExceptionHandler} which is called when exceptions are thrown while listening to the UDP port.
128 | *
129 | * @param exceptionHandler The {@link ExceptionHandler} to use.
130 | */
131 | public void setExceptionHandler(ExceptionHandler exceptionHandler) {
132 | this.exceptionHandler = exceptionHandler;
133 | }
134 |
135 | /**
136 | * @param exceptionHandler The {@link ExceptionHandler} to use.
137 | * @return Current {@link NetworkHandler} instance for fluent code style.
138 | * @see #setExceptionHandler(ExceptionHandler)
139 | */
140 | public NetworkHandler withExceptionHandler(ExceptionHandler exceptionHandler) {
141 | setExceptionHandler(exceptionHandler);
142 | return this;
143 | }
144 |
145 | /**
146 | * Represents the state of the {@link NetworkHandler}.
147 | *
148 | * During the lifecycle of a {@link NetworkHandler}, it passes three states: {@link #Initialized}, {@link #Running}
149 | * and {@link #Stopped}. Once stopped, a {@link NetworkHandler} cannot be started again.
150 | *
151 | * @author Julian Rabe
152 | */
153 | public enum State {
154 |
155 | /**
156 | * After a {@link NetworkHandler} is initialized, the socket is open and the handler is ready to be used.
157 | *
158 | * When in this state, calling {@link NetworkHandler#stop()} is illegal.
159 | */
160 | Initialized,
161 |
162 | /**
163 | * When {@link NetworkHandler#start()} is called, the {@link NetworkHandler} starts its worker-threads.
164 | *
165 | * When in this state, calling {@link NetworkHandler#start()} is illegal.
166 | */
167 | Running,
168 |
169 | /**
170 | * When {@link NetworkHandler#stop()} is called, the {@link NetworkHandler} stops its worker-threads and closes
171 | * the underlying socket.
172 | *
173 | * When in this state, calling both {@link NetworkHandler#start()} and {@link NetworkHandler#stop()} is illegal.
174 | */
175 | Stopped
176 | }
177 | }
178 |
--------------------------------------------------------------------------------
/lib/src/main/java/de/deltaeight/libartnet/network/PacketReceiveDispatcher.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2018 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.network;
23 |
24 | import de.deltaeight.libartnet.builders.ArtNetPacketBuilder;
25 | import de.deltaeight.libartnet.packets.ArtNetPacket;
26 |
27 | import java.util.Set;
28 | import java.util.concurrent.ExecutorService;
29 |
30 | /**
31 | * Used to enforce strong typing in {@link ArtNetReceiver} when handling received packets.
32 | *
33 | * @param The {@link ArtNetPacket} this {@link PacketReceiveDispatcher} handles.
34 | * @author Julian Rabe
35 | * @see PacketReceiveHandler
36 | * @see ArtNetReceiver
37 | */
38 | class PacketReceiveDispatcher {
39 |
40 | private final ExecutorService workingPool;
41 | private final ArtNetPacketBuilder packetBuilder;
42 | private final Set> receiveHandlers;
43 |
44 | PacketReceiveDispatcher(ExecutorService workingPool,
45 | ArtNetPacketBuilder packetBuilder,
46 | Set> receiveHandlers) {
47 |
48 | this.workingPool = workingPool;
49 | this.packetBuilder = packetBuilder;
50 | this.receiveHandlers = receiveHandlers;
51 | }
52 |
53 | boolean handleReceive(byte[] packetData) {
54 | T packet = packetBuilder.buildFromBytes(packetData);
55 | if (packet != null) {
56 | receiveHandlers.forEach(receiveHandler -> workingPool.submit(() -> receiveHandler.handle(packet)));
57 | }
58 | return false;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/lib/src/main/java/de/deltaeight/libartnet/network/PacketReceiveHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2018 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.network;
23 |
24 | import de.deltaeight.libartnet.packets.ArtNetPacket;
25 |
26 | /**
27 | * Provides functionality for received {@link ArtNetPacket} instances.
28 | *
29 | * @param The {@link ArtNetPacket} implementation the implementing class is used for.
30 | */
31 | @FunctionalInterface
32 | public interface PacketReceiveHandler {
33 |
34 | /**
35 | * Is called by {@link ArtNetReceiver} when an {@link ArtNetPacket} of type {@link T} was received.
36 | *
37 | * @param packet The {@link ArtNetPacket} which was received.
38 | */
39 | void handle(T packet);
40 | }
41 |
--------------------------------------------------------------------------------
/lib/src/main/java/de/deltaeight/libartnet/packets/ArtDmx.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2020 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.packets;
23 |
24 | import de.deltaeight.libartnet.builders.ArtDmxBuilder;
25 |
26 | import java.util.Arrays;
27 | import java.util.Objects;
28 |
29 | /**
30 | * Represents an {@code ArtDmx} packet containing DMX values.
31 | *
32 | * See the Art-Net Specification for details.
33 | *
34 | * @author Julian Rabe
35 | * @see ArtDmxBuilder
36 | * @see Art-Net Specification
37 | */
38 | public class ArtDmx extends ArtNetPacket {
39 |
40 | private final int sequence;
41 | private final int physical;
42 | private final int netAddress;
43 | private final int subnetAddress;
44 | private final int universeAddress;
45 | private final byte[] data;
46 |
47 | public ArtDmx(int sequence,
48 | int physical,
49 | int netAddress,
50 | int subnetAddress,
51 | int universeAddress,
52 | byte[] data,
53 | byte[] bytes) {
54 |
55 | super(bytes);
56 |
57 | this.sequence = sequence;
58 | this.physical = physical;
59 | this.netAddress = netAddress;
60 | this.subnetAddress = subnetAddress;
61 | this.universeAddress = universeAddress;
62 | this.data = data;
63 | }
64 |
65 | @Override
66 | public int hashCode() {
67 | int result = Objects.hash(sequence, physical, netAddress, subnetAddress, universeAddress);
68 | result = 31 * result + Arrays.hashCode(data);
69 | return result;
70 | }
71 |
72 | @Override
73 | public boolean equals(Object o) {
74 | if (this == o) return true;
75 | if (o == null || getClass() != o.getClass()) return false;
76 | ArtDmx artDmx = (ArtDmx) o;
77 | return sequence == artDmx.sequence &&
78 | physical == artDmx.physical &&
79 | netAddress == artDmx.netAddress &&
80 | subnetAddress == artDmx.subnetAddress &&
81 | universeAddress == artDmx.universeAddress &&
82 | Arrays.equals(data, artDmx.data);
83 | }
84 |
85 | public int getSequence() {
86 | return sequence;
87 | }
88 |
89 | public int getPhysical() {
90 | return physical;
91 | }
92 |
93 | public int getNetAddress() {
94 | return netAddress;
95 | }
96 |
97 | public int getSubnetAddress() {
98 | return subnetAddress;
99 | }
100 |
101 | public int getUniverseAddress() {
102 | return universeAddress;
103 | }
104 |
105 | public byte[] getData() {
106 | return data;
107 | }
108 |
109 | public int[] getIntData() {
110 | int[] result = new int[data.length];
111 |
112 | for (int i = 0; i < data.length; i++) {
113 | result[i] = data[i] & 0xFF;
114 | }
115 |
116 | return result;
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/lib/src/main/java/de/deltaeight/libartnet/packets/ArtNetPacket.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2018 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.packets;
23 |
24 | import de.deltaeight.libartnet.builders.ArtNetPacketBuilder;
25 |
26 | /**
27 | * Represents Art-Net packets
28 | *
29 | * @author Julian Rabe
30 | * @see ArtNetPacketBuilder
31 | */
32 | public abstract class ArtNetPacket {
33 |
34 | private final byte[] bytes;
35 |
36 | ArtNetPacket(byte[] bytes) {
37 | this.bytes = bytes;
38 | }
39 |
40 | /**
41 | * @return Payload to send over the network.
42 | */
43 | public byte[] getBytes() {
44 | return bytes.clone();
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/lib/src/main/java/de/deltaeight/libartnet/packets/ArtPoll.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2018 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.packets;
23 |
24 | import de.deltaeight.libartnet.builders.ArtPollBuilder;
25 | import de.deltaeight.libartnet.descriptors.Priority;
26 |
27 | import java.util.Objects;
28 |
29 | /**
30 | * Represents an {@code ArtPoll} packet which requests other Art-Net nodes on the network to reply with
31 | * {@link ArtPollReply}.
32 | *
33 | * See the Art-Net Specification for details.
34 | *
35 | * @author Julian Rabe
36 | * @see ArtPollReply
37 | * @see ArtPollBuilder
38 | * @see Art-Net Specification
39 | */
40 | public class ArtPoll extends ArtNetPacket {
41 |
42 | private final boolean enableVlcTransmission;
43 | private final boolean unicastDiagnosticMessages;
44 | private final boolean sendDiagnosticMessages;
45 | private final boolean sendArtPollReplyOnChanges;
46 | private final Priority priority;
47 |
48 | public ArtPoll(boolean enableVlcTransmission,
49 | boolean unicastDiagnosticMessages,
50 | boolean sendDiagnosticMessages,
51 | boolean sendArtPollReplyOnChanges,
52 | Priority priority,
53 | byte[] bytes) {
54 |
55 | super(bytes);
56 |
57 | this.enableVlcTransmission = enableVlcTransmission;
58 | this.unicastDiagnosticMessages = unicastDiagnosticMessages;
59 | this.sendDiagnosticMessages = sendDiagnosticMessages;
60 | this.sendArtPollReplyOnChanges = sendArtPollReplyOnChanges;
61 | this.priority = priority;
62 | }
63 |
64 | @Override
65 | public int hashCode() {
66 | return Objects.hash(enableVlcTransmission, unicastDiagnosticMessages, sendDiagnosticMessages,
67 | sendArtPollReplyOnChanges, priority);
68 | }
69 |
70 | @Override
71 | public boolean equals(Object o) {
72 | if (this == o) return true;
73 | if (o == null || getClass() != o.getClass()) return false;
74 | ArtPoll artPoll = (ArtPoll) o;
75 | return enableVlcTransmission == artPoll.enableVlcTransmission &&
76 | unicastDiagnosticMessages == artPoll.unicastDiagnosticMessages &&
77 | sendDiagnosticMessages == artPoll.sendDiagnosticMessages &&
78 | sendArtPollReplyOnChanges == artPoll.sendArtPollReplyOnChanges &&
79 | priority == artPoll.priority;
80 | }
81 |
82 | public boolean isEnableVlcTransmission() {
83 | return enableVlcTransmission;
84 | }
85 |
86 | public boolean isUnicastDiagnosticMessages() {
87 | return unicastDiagnosticMessages;
88 | }
89 |
90 | public boolean isSendDiagnosticMessages() {
91 | return sendDiagnosticMessages;
92 | }
93 |
94 | public boolean isSendArtPollReplyOnChanges() {
95 | return sendArtPollReplyOnChanges;
96 | }
97 |
98 | public Priority getPriority() {
99 | return priority;
100 | }
101 | }
--------------------------------------------------------------------------------
/lib/src/main/java/de/deltaeight/libartnet/packets/ArtPollReply.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2020 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.packets;
23 |
24 | import java.util.Arrays;
25 | import java.util.Objects;
26 |
27 | import de.deltaeight.libartnet.builders.ArtPollReplyBuilder;
28 | import de.deltaeight.libartnet.descriptors.EquipmentStyle;
29 | import de.deltaeight.libartnet.descriptors.IndicatorState;
30 | import de.deltaeight.libartnet.descriptors.InputStatus;
31 | import de.deltaeight.libartnet.descriptors.OutputStatus;
32 | import de.deltaeight.libartnet.descriptors.PortAddressingAuthority;
33 | import de.deltaeight.libartnet.descriptors.PortType;
34 | import de.deltaeight.libartnet.descriptors.Product;
35 |
36 | /**
37 | * Represents an {@code ArtPollReply} packet containing node information about the sender. This is sent periodically or
38 | * as an answer to {@link ArtPoll} packets.
39 | *
40 | * See the Art-Net Specification for details.
41 | *
42 | * @author Julian Rabe
43 | * @see ArtPoll
44 | * @see ArtPollReplyBuilder
45 | * @see Art-Net Specification
46 | */
47 | public class ArtPollReply extends ArtNetPacket {
48 |
49 | private final byte[] ipAddress;
50 | private final int nodeVersion;
51 | private final int netAddress;
52 | private final int subnetAddress;
53 | private final Product product;
54 | private final int ubeaVersion;
55 | private final IndicatorState indicatorState;
56 | private final PortAddressingAuthority portAddressingAuthority;
57 | private final boolean bootedFromRom;
58 | private final boolean rdmSupport;
59 | private final boolean ubeaPresent;
60 | private final String estaManufacturer;
61 | private final String shortName;
62 | private final String longName;
63 | private final String nodeReport;
64 | private final PortType[] portTypes;
65 | private final InputStatus[] inputStatuses;
66 | private final OutputStatus[] outputStatuses;
67 | private final int[] inputUniverseAddresses;
68 | private final int[] outputUniverseAddresses;
69 | private final boolean[] macrosActive;
70 | private final boolean[] remotesActive;
71 | private final EquipmentStyle equipmentStyle;
72 | private final byte[] macAddress;
73 | private final byte[] bindIp;
74 | private final int bindIndex;
75 | private final boolean webBrowserConfigurationSupport;
76 | private final boolean ipIsDhcpConfigured;
77 | private final boolean dhcpSupport;
78 | private final boolean longPortAddressSupport;
79 | private final boolean canSwitchToSACN;
80 | private final boolean squawking;
81 |
82 | public ArtPollReply(byte[] ipAddress,
83 | int nodeVersion,
84 | int netAddress,
85 | int subnetAddress,
86 | Product product,
87 | int ubeaVersion,
88 | IndicatorState indicatorState,
89 | PortAddressingAuthority portAddressingAuthority,
90 | boolean bootedFromRom,
91 | boolean rdmSupport,
92 | boolean ubeaPresent,
93 | String estaManufacturer,
94 | String shortName,
95 | String longName,
96 | String nodeReport,
97 | PortType[] portTypes,
98 | InputStatus[] inputStatuses,
99 | OutputStatus[] outputStatuses,
100 | int[] inputUniverseAddresses,
101 | int[] outputUniverseAddresses,
102 | boolean[] macrosActive,
103 | boolean[] remotesActive,
104 | EquipmentStyle equipmentStyle,
105 | byte[] macAddress,
106 | byte[] bindIp,
107 | int bindIndex,
108 | boolean webBrowserConfigurationSupport,
109 | boolean ipIsDhcpConfigured,
110 | boolean dhcpSupport,
111 | boolean longPortAddressSupport,
112 | boolean canSwitchToSACN,
113 | boolean squawking,
114 | byte[] bytes) {
115 |
116 | super(bytes);
117 |
118 | this.ipAddress = ipAddress;
119 | this.nodeVersion = nodeVersion;
120 | this.netAddress = netAddress;
121 | this.subnetAddress = subnetAddress;
122 | this.product = product;
123 | this.ubeaVersion = ubeaVersion;
124 | this.indicatorState = indicatorState;
125 | this.portAddressingAuthority = portAddressingAuthority;
126 | this.bootedFromRom = bootedFromRom;
127 | this.rdmSupport = rdmSupport;
128 | this.ubeaPresent = ubeaPresent;
129 | this.estaManufacturer = estaManufacturer.substring(0, Math.min(estaManufacturer.length(), 2));
130 | this.shortName = shortName.substring(0, Math.min(shortName.length(), 17));
131 | this.longName = longName.substring(0, Math.min(longName.length(), 63));
132 | this.nodeReport = nodeReport;
133 | this.portTypes = portTypes;
134 | this.inputStatuses = inputStatuses;
135 | this.outputStatuses = outputStatuses;
136 | this.inputUniverseAddresses = inputUniverseAddresses;
137 | this.outputUniverseAddresses = outputUniverseAddresses;
138 | this.macrosActive = macrosActive;
139 | this.remotesActive = remotesActive;
140 | this.equipmentStyle = equipmentStyle;
141 | this.macAddress = macAddress;
142 | this.bindIp = bindIp;
143 | this.bindIndex = bindIndex;
144 | this.webBrowserConfigurationSupport = webBrowserConfigurationSupport;
145 | this.ipIsDhcpConfigured = ipIsDhcpConfigured;
146 | this.dhcpSupport = dhcpSupport;
147 | this.longPortAddressSupport = longPortAddressSupport;
148 | this.canSwitchToSACN = canSwitchToSACN;
149 | this.squawking = squawking;
150 | }
151 |
152 | @Override
153 | public int hashCode() {
154 |
155 | int result = Objects.hash(nodeVersion, netAddress, subnetAddress, product, ubeaVersion, indicatorState,
156 | portAddressingAuthority, bootedFromRom, rdmSupport, ubeaPresent, estaManufacturer, shortName, longName,
157 | nodeReport, equipmentStyle, bindIndex, webBrowserConfigurationSupport, ipIsDhcpConfigured, dhcpSupport,
158 | longPortAddressSupport, canSwitchToSACN, squawking);
159 |
160 | result = 31 * result + Arrays.hashCode(ipAddress);
161 | result = 31 * result + Arrays.hashCode(portTypes);
162 | result = 31 * result + Arrays.hashCode(inputStatuses);
163 | result = 31 * result + Arrays.hashCode(outputStatuses);
164 | result = 31 * result + Arrays.hashCode(inputUniverseAddresses);
165 | result = 31 * result + Arrays.hashCode(outputUniverseAddresses);
166 | result = 31 * result + Arrays.hashCode(macrosActive);
167 | result = 31 * result + Arrays.hashCode(remotesActive);
168 | result = 31 * result + Arrays.hashCode(macAddress);
169 | result = 31 * result + Arrays.hashCode(bindIp);
170 |
171 | return result;
172 | }
173 |
174 | @Override
175 | public boolean equals(Object o) {
176 | if (this == o) return true;
177 | if (o == null || getClass() != o.getClass()) return false;
178 | ArtPollReply that = (ArtPollReply) o;
179 | return nodeVersion == that.nodeVersion &&
180 | netAddress == that.netAddress &&
181 | subnetAddress == that.subnetAddress &&
182 | ubeaVersion == that.ubeaVersion &&
183 | bootedFromRom == that.bootedFromRom &&
184 | rdmSupport == that.rdmSupport &&
185 | ubeaPresent == that.ubeaPresent &&
186 | bindIndex == that.bindIndex &&
187 | webBrowserConfigurationSupport == that.webBrowserConfigurationSupport &&
188 | ipIsDhcpConfigured == that.ipIsDhcpConfigured &&
189 | dhcpSupport == that.dhcpSupport &&
190 | longPortAddressSupport == that.longPortAddressSupport &&
191 | canSwitchToSACN == that.canSwitchToSACN &&
192 | squawking == that.squawking &&
193 | Arrays.equals(ipAddress, that.ipAddress) &&
194 | product == that.product &&
195 | indicatorState == that.indicatorState &&
196 | portAddressingAuthority == that.portAddressingAuthority &&
197 | Objects.equals(estaManufacturer, that.estaManufacturer) &&
198 | Objects.equals(shortName, that.shortName) &&
199 | Objects.equals(longName, that.longName) &&
200 | Objects.equals(nodeReport, that.nodeReport) &&
201 | Arrays.equals(portTypes, that.portTypes) &&
202 | Arrays.equals(inputStatuses, that.inputStatuses) &&
203 | Arrays.equals(outputStatuses, that.outputStatuses) &&
204 | Arrays.equals(inputUniverseAddresses, that.inputUniverseAddresses) &&
205 | Arrays.equals(outputUniverseAddresses, that.outputUniverseAddresses) &&
206 | Arrays.equals(macrosActive, that.macrosActive) &&
207 | Arrays.equals(remotesActive, that.remotesActive) &&
208 | equipmentStyle == that.equipmentStyle &&
209 | Arrays.equals(macAddress, that.macAddress) &&
210 | Arrays.equals(bindIp, that.bindIp);
211 | }
212 |
213 | public byte[] getIpAddress() {
214 | return ipAddress;
215 | }
216 |
217 | public int getNodeVersion() {
218 | return nodeVersion;
219 | }
220 |
221 | public int getNetAddress() {
222 | return netAddress;
223 | }
224 |
225 | public int getSubnetAddress() {
226 | return subnetAddress;
227 | }
228 |
229 | public Product getProduct() {
230 | return product;
231 | }
232 |
233 | public int getUbeaVersion() {
234 | return ubeaVersion;
235 | }
236 |
237 | public IndicatorState getIndicatorState() {
238 | return indicatorState;
239 | }
240 |
241 | public PortAddressingAuthority getPortAddressingAuthority() {
242 | return portAddressingAuthority;
243 | }
244 |
245 | public boolean isBootedFromRom() {
246 | return bootedFromRom;
247 | }
248 |
249 | public boolean supportsRdm() {
250 | return rdmSupport;
251 | }
252 |
253 | public boolean isUbeaPresent() {
254 | return ubeaPresent;
255 | }
256 |
257 | public String getEstaManufacturer() {
258 | return estaManufacturer;
259 | }
260 |
261 | public String getShortName() {
262 | return shortName;
263 | }
264 |
265 | public String getLongName() {
266 | return longName;
267 | }
268 |
269 | public String getNodeReport() {
270 | return nodeReport;
271 | }
272 |
273 | public PortType[] getPortTypes() {
274 | return portTypes.clone();
275 | }
276 |
277 | public InputStatus[] getInputStatuses() {
278 | return inputStatuses.clone();
279 | }
280 |
281 | public OutputStatus[] getOutputStatuses() {
282 | return outputStatuses.clone();
283 | }
284 |
285 | public int[] getInputUniverseAddresses() {
286 | return inputUniverseAddresses.clone();
287 | }
288 |
289 | public int[] getOutputUniverseAddresses() {
290 | return outputUniverseAddresses.clone();
291 | }
292 |
293 | public boolean[] getMacrosActive() {
294 | return macrosActive.clone();
295 | }
296 |
297 | public boolean[] getRemotesActive() {
298 | return remotesActive.clone();
299 | }
300 |
301 | public EquipmentStyle getEquipmentStyle() {
302 | return equipmentStyle;
303 | }
304 |
305 | public byte[] getMacAddress() {
306 | return macAddress.clone();
307 | }
308 |
309 | public byte[] getBindIp() {
310 | return bindIp;
311 | }
312 |
313 | public int getBindIndex() {
314 | return bindIndex;
315 | }
316 |
317 | public boolean supportsWebBrowserConfiguration() {
318 | return webBrowserConfigurationSupport;
319 | }
320 |
321 | public boolean ipIsDhcpConfigured() {
322 | return ipIsDhcpConfigured;
323 | }
324 |
325 | public boolean supportsDhcp() {
326 | return dhcpSupport;
327 | }
328 |
329 | public boolean supportsLongAddresses() {
330 | return longPortAddressSupport;
331 | }
332 |
333 | public boolean canSwitchToSACN() {
334 | return canSwitchToSACN;
335 | }
336 |
337 | public boolean isSquawking() {
338 | return squawking;
339 | }
340 | }
341 |
--------------------------------------------------------------------------------
/lib/src/main/java/de/deltaeight/libartnet/packets/ArtTimeCode.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2018 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.packets;
23 |
24 | import de.deltaeight.libartnet.builders.ArtTimeCodeBuilder;
25 | import de.deltaeight.libartnet.descriptors.TimeCodeType;
26 |
27 | import java.util.Objects;
28 |
29 | /**
30 | * Represents an {@code ArtTimeCode} packet containing timecode information.
31 | *
32 | * See the Art-Net Specification for details.
33 | *
34 | * @author Julian Rabe
35 | * @see ArtTimeCodeBuilder
36 | * @see Art-Net Specification
37 | */
38 | public class ArtTimeCode extends ArtNetPacket {
39 |
40 | private final TimeCodeType type;
41 | private final int hours;
42 | private final int minutes;
43 | private final int seconds;
44 | private final int frames;
45 |
46 | public ArtTimeCode(TimeCodeType type, int hours, int minutes, int seconds, int frames, byte[] bytes) {
47 |
48 | super(bytes);
49 | this.type = type;
50 | this.hours = hours;
51 | this.minutes = minutes;
52 | this.seconds = seconds;
53 | this.frames = frames;
54 | }
55 |
56 | @Override
57 | public int hashCode() {
58 | return Objects.hash(frames, seconds, minutes, hours, type);
59 | }
60 |
61 | @Override
62 | public boolean equals(Object o) {
63 | if (this == o) return true;
64 | if (o == null || getClass() != o.getClass()) return false;
65 | ArtTimeCode that = (ArtTimeCode) o;
66 | return frames == that.frames &&
67 | seconds == that.seconds &&
68 | minutes == that.minutes &&
69 | hours == that.hours &&
70 | type == that.type;
71 | }
72 |
73 | public TimeCodeType getType() {
74 | return type;
75 | }
76 |
77 | public int getHours() {
78 | return hours;
79 | }
80 |
81 | public int getMinutes() {
82 | return minutes;
83 | }
84 |
85 | public int getSeconds() {
86 | return seconds;
87 | }
88 |
89 | public int getFrames() {
90 | return frames;
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/lib/src/test/java/de/deltaeight/libartnet/builders/AbstractPacketBuilderTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2018 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.builders;
23 |
24 | import de.deltaeight.libartnet.packets.ArtNetPacket;
25 |
26 | import static org.junit.jupiter.api.Assertions.assertArrayEquals;
27 | import static org.junit.jupiter.api.Assertions.assertEquals;
28 |
29 | abstract class AbstractPacketBuilderTest {
30 |
31 | static void assertPackets(byte[] expectedBytes, ArtNetPacketBuilder builder) {
32 |
33 | ArtNetPacket outboundPacket = builder.build();
34 | ArtNetPacket inboundPacket = builder.buildFromBytes(expectedBytes);
35 |
36 | assertArrayEquals(expectedBytes, outboundPacket.getBytes());
37 | assertEquals(outboundPacket, inboundPacket);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/lib/src/test/java/de/deltaeight/libartnet/builders/ArtDmxBuilderTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2018 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.builders;
23 |
24 | import org.junit.jupiter.api.Test;
25 |
26 | import static org.junit.jupiter.api.Assertions.*;
27 |
28 | class ArtDmxBuilderTest extends AbstractPacketBuilderTest {
29 |
30 | private static final byte[] DEFAULT_PACKET = getExpectedData(0x00, 0x00, 0x00, 0x00, 0x00, new byte[0]);
31 |
32 | private static byte[] getExpectedData(int sequence,
33 | int physical,
34 | int netAddress,
35 | int subnetAddress,
36 | int universeAddress,
37 | byte[] data) {
38 |
39 | byte[] bytes = new byte[18 + data.length];
40 |
41 | System.arraycopy(new byte[]{
42 | 0x41, 0x72, 0x74, 0x2D, 0x4E, 0x65, 0x74, 0x00, // Header
43 | 0x00, 0x50, // OpCode
44 | 0x00, 0x0E, // Protocol version
45 | }, 0, bytes, 0, 12);
46 |
47 | bytes[12] = (byte) sequence;
48 | bytes[13] = (byte) physical;
49 | bytes[14] = (byte) (subnetAddress << 4 | universeAddress);
50 | bytes[15] = (byte) netAddress;
51 | bytes[16] = (byte) (data.length >> 8);
52 | bytes[17] = (byte) data.length;
53 |
54 | System.arraycopy(data, 0, bytes, 18, data.length);
55 |
56 | return bytes;
57 | }
58 |
59 | @Test
60 | void build() {
61 | assertPackets(DEFAULT_PACKET, new ArtDmxBuilder());
62 | }
63 |
64 | @Test
65 | void sequence() {
66 |
67 | byte[] expectedDataSequence1 = getExpectedData(0x01, 0x00, 0x00, 0x00, 0x00, new byte[0]);
68 | byte[] expectedDataSequence255 = getExpectedData(0xff, 0x00, 0x00, 0x00, 0x00, new byte[0]);
69 |
70 | ArtDmxBuilder builder = new ArtDmxBuilder();
71 |
72 | assertEquals(0, builder.getSequence());
73 |
74 | builder.setSequence(1);
75 | assertEquals(1, builder.getSequence());
76 | assertPackets(expectedDataSequence1, builder);
77 |
78 | builder.setSequence(0);
79 | assertEquals(0, builder.getSequence());
80 | assertPackets(DEFAULT_PACKET, builder);
81 |
82 | builder.setSequence(255);
83 | assertEquals(255, builder.getSequence());
84 | assertPackets(expectedDataSequence255, builder);
85 |
86 | assertSame(builder, builder.withSequence(1));
87 | assertEquals(1, builder.getSequence());
88 | assertPackets(expectedDataSequence1, builder);
89 |
90 | assertSame(builder, builder.withSequence(0));
91 | assertEquals(0, builder.getSequence());
92 | assertPackets(DEFAULT_PACKET, builder);
93 |
94 | assertSame(builder, builder.withSequence(255));
95 | assertEquals(255, builder.getSequence());
96 | assertPackets(expectedDataSequence255, builder);
97 |
98 | assertThrows(IllegalArgumentException.class, () -> builder.setSequence(-1));
99 | assertThrows(IllegalArgumentException.class, () -> builder.withSequence(256));
100 | }
101 |
102 | @Test
103 | void physical() {
104 |
105 | byte[] expectedDataPhysical1 = getExpectedData(0x00, 0x01, 0x00, 0x00, 0x00, new byte[0]);
106 | byte[] expectedDataPhysical255 = getExpectedData(0x00, 0xff, 0x00, 0x00, 0x00, new byte[0]);
107 |
108 | ArtDmxBuilder builder = new ArtDmxBuilder();
109 |
110 | assertEquals(0, builder.getPhysical());
111 |
112 | builder.setPhysical(1);
113 | assertEquals(1, builder.getPhysical());
114 | assertPackets(expectedDataPhysical1, builder);
115 |
116 | builder.setPhysical(0);
117 | assertEquals(0, builder.getPhysical());
118 | assertPackets(DEFAULT_PACKET, builder);
119 |
120 | builder.setPhysical(255);
121 | assertEquals(255, builder.getPhysical());
122 | assertPackets(expectedDataPhysical255, builder);
123 |
124 | assertSame(builder, builder.withPhysical(1));
125 | assertEquals(1, builder.getPhysical());
126 | assertPackets(expectedDataPhysical1, builder);
127 |
128 | assertSame(builder, builder.withPhysical(0));
129 | assertEquals(0, builder.getPhysical());
130 | assertPackets(DEFAULT_PACKET, builder);
131 |
132 | assertSame(builder, builder.withPhysical(255));
133 | assertEquals(255, builder.getPhysical());
134 | assertPackets(expectedDataPhysical255, builder);
135 |
136 | assertThrows(IllegalArgumentException.class, () -> builder.setPhysical(-1));
137 | assertThrows(IllegalArgumentException.class, () -> builder.withPhysical(256));
138 | }
139 |
140 | @Test
141 | void subnetAddress() {
142 |
143 | byte[] expectedDataSubnet1 = getExpectedData(0x00, 0x00, 0x00, 0x01, 0x00, new byte[0]);
144 | byte[] expectedDataSubnet15 = getExpectedData(0x00, 0x00, 0x00, 0x0f, 0x00, new byte[0]);
145 |
146 | ArtDmxBuilder builder = new ArtDmxBuilder();
147 |
148 | assertEquals(0, builder.getSubnetAddress());
149 |
150 | builder.setSubnetAddress(1);
151 | assertEquals(1, builder.getSubnetAddress());
152 | assertPackets(expectedDataSubnet1, builder);
153 |
154 | builder.setSubnetAddress(0);
155 | assertEquals(0, builder.getSubnetAddress());
156 | assertPackets(DEFAULT_PACKET, builder);
157 |
158 | builder.setSubnetAddress(15);
159 | assertEquals(15, builder.getSubnetAddress());
160 | assertPackets(expectedDataSubnet15, builder);
161 |
162 | assertSame(builder, builder.withSubnetAddress(1));
163 | assertEquals(1, builder.getSubnetAddress());
164 | assertPackets(expectedDataSubnet1, builder);
165 |
166 | assertSame(builder, builder.withSubnetAddress(0));
167 | assertEquals(0, builder.getSubnetAddress());
168 | assertPackets(DEFAULT_PACKET, builder);
169 |
170 | assertSame(builder, builder.withSubnetAddress(15));
171 | assertEquals(15, builder.getSubnetAddress());
172 | assertPackets(expectedDataSubnet15, builder);
173 |
174 | assertThrows(IllegalArgumentException.class, () -> builder.setSubnetAddress(-1));
175 | assertThrows(IllegalArgumentException.class, () -> builder.withSubnetAddress(16));
176 | }
177 |
178 | @Test
179 | void universeAddress() {
180 |
181 | byte[] expectedDataUniverse1 = getExpectedData(0x00, 0x00, 0x00, 0x00, 0x01, new byte[0]);
182 | byte[] expectedDataUniverse15 = getExpectedData(0x00, 0x00, 0x00, 0x00, 0x0f, new byte[0]);
183 |
184 | ArtDmxBuilder builder = new ArtDmxBuilder();
185 |
186 | assertEquals(0, builder.getUniverseAddress());
187 |
188 | builder.setUniverseAddress(1);
189 | assertEquals(1, builder.getUniverseAddress());
190 | assertPackets(expectedDataUniverse1, builder);
191 |
192 | builder.setUniverseAddress(0);
193 | assertEquals(0, builder.getUniverseAddress());
194 | assertPackets(DEFAULT_PACKET, builder);
195 |
196 | builder.setUniverseAddress(15);
197 | assertEquals(15, builder.getUniverseAddress());
198 | assertPackets(expectedDataUniverse15, builder);
199 |
200 | assertSame(builder, builder.withUniverseAddress(1));
201 | assertEquals(1, builder.getUniverseAddress());
202 | assertPackets(expectedDataUniverse1, builder);
203 |
204 | assertSame(builder, builder.withUniverseAddress(0));
205 | assertEquals(0, builder.getUniverseAddress());
206 | assertPackets(DEFAULT_PACKET, builder);
207 |
208 | assertSame(builder, builder.withUniverseAddress(15));
209 | assertEquals(15, builder.getUniverseAddress());
210 | assertPackets(expectedDataUniverse15, builder);
211 |
212 | assertThrows(IllegalArgumentException.class, () -> builder.setUniverseAddress(-1));
213 | assertThrows(IllegalArgumentException.class, () -> builder.withUniverseAddress(16));
214 | }
215 |
216 | @Test
217 | void netAddress() {
218 |
219 | byte[] expectedDataNetAddress1 = getExpectedData(0x00, 0x00, 0x01, 0x00, 0x00, new byte[0]);
220 | byte[] expectedDataNetAddress127 = getExpectedData(0x00, 0x00, 0x7f, 0x00, 0x00, new byte[0]);
221 |
222 | ArtDmxBuilder builder = new ArtDmxBuilder();
223 |
224 | assertEquals(0, builder.getNetAddress());
225 |
226 | builder.setNetAddress(1);
227 | assertEquals(1, builder.getNetAddress());
228 | assertPackets(expectedDataNetAddress1, builder);
229 |
230 | builder.setNetAddress(0);
231 | assertEquals(0, builder.getNetAddress());
232 | assertPackets(DEFAULT_PACKET, builder);
233 |
234 | builder.setNetAddress(127);
235 | assertEquals(127, builder.getNetAddress());
236 | assertPackets(expectedDataNetAddress127, builder);
237 |
238 | builder.setNetAddress(0);
239 | assertEquals(0, builder.getNetAddress());
240 | assertPackets(DEFAULT_PACKET, builder);
241 |
242 | assertSame(builder, builder.withNetAddress(1));
243 | assertEquals(1, builder.getNetAddress());
244 | assertPackets(expectedDataNetAddress1, builder);
245 |
246 | assertSame(builder, builder.withNetAddress(0));
247 | assertEquals(0, builder.getNetAddress());
248 | assertPackets(DEFAULT_PACKET, builder);
249 |
250 | assertSame(builder, builder.withNetAddress(127));
251 | assertEquals(127, builder.getNetAddress());
252 | assertPackets(expectedDataNetAddress127, builder);
253 |
254 | assertThrows(IllegalArgumentException.class, () -> builder.setNetAddress(-1));
255 | assertThrows(IllegalArgumentException.class, () -> builder.withNetAddress(128));
256 | }
257 |
258 | @Test
259 | void data() {
260 |
261 | ArtDmxBuilder builder = new ArtDmxBuilder();
262 |
263 | assertEquals(0, builder.getDataSize());
264 | assertArrayEquals(new byte[0], builder.getData());
265 |
266 | assertEquals(0x00, builder.getData(0));
267 | assertEquals(0x00, builder.getData(511));
268 |
269 | assertThrows(IllegalArgumentException.class, () -> builder.getData(-1));
270 | assertThrows(IllegalArgumentException.class, () -> builder.getData(512));
271 |
272 | builder.setData(2, (byte) 0x0F);
273 | assertEquals(3, builder.getDataSize());
274 | assertEquals(0x0F, builder.getData(2));
275 | assertArrayEquals(new byte[]{0x00, 0x00, 0x0F}, builder.getData());
276 | assertPackets(getExpectedData(0x00, 0x00, 0x00, 0x00, 0x00, new byte[]{0x00, 0x00, 0x0F, 0x00}), builder);
277 |
278 | assertThrows(IllegalArgumentException.class, () -> builder.setData(512, (byte) 0xFF));
279 |
280 | builder.setData(new byte[]{0x0F});
281 | assertEquals(1, builder.getDataSize());
282 | assertArrayEquals(new byte[]{0x0F}, builder.getData());
283 | assertPackets(getExpectedData(0x00, 0x00, 0x00, 0x00, 0x00, new byte[]{0x0F, 0x00}), builder);
284 |
285 | assertThrows(IllegalArgumentException.class, () -> builder.setData(new byte[513]));
286 |
287 | assertSame(builder, builder.withData(2, (byte) 0x12));
288 | assertEquals(3, builder.getDataSize());
289 | assertEquals(0x12, builder.getData(2));
290 | assertArrayEquals(new byte[]{0x0F, 0x00, 0x12}, builder.getData());
291 | assertPackets(getExpectedData(0x00, 0x00, 0x00, 0x00, 0x00, new byte[]{0x0F, 0x00, 0x12, 0x00}), builder);
292 |
293 | assertThrows(IllegalArgumentException.class, () -> builder.withData(512, (byte) 0xFF));
294 |
295 | assertSame(builder, builder.withData(new byte[]{0x21, 0x22}));
296 | assertEquals(2, builder.getDataSize());
297 | assertArrayEquals(new byte[]{0x21, 0x22}, builder.getData());
298 | assertPackets(getExpectedData(0x00, 0x00, 0x00, 0x00, 0x00, new byte[]{0x21, 0x22}), builder);
299 |
300 | assertThrows(IllegalArgumentException.class, () -> builder.withData(new byte[513]));
301 | }
302 | }
303 |
--------------------------------------------------------------------------------
/lib/src/test/java/de/deltaeight/libartnet/builders/ArtPollBuilderTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2018 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.builders;
23 |
24 | import de.deltaeight.libartnet.descriptors.Priority;
25 | import org.junit.jupiter.api.Test;
26 |
27 | import static org.junit.jupiter.api.Assertions.*;
28 |
29 | class ArtPollBuilderTest extends AbstractPacketBuilderTest {
30 |
31 | private byte[] getExpectedData(int talkToMe, int priority) {
32 | return new byte[]{
33 | 0x41, 0x72, 0x74, 0x2D, 0x4E, 0x65, 0x74, 0x00, // Header
34 | 0x00, 0x20, // OpCode
35 | 0x00, 0x0E, // Protocol version
36 | (byte) talkToMe, (byte) priority
37 | };
38 | }
39 |
40 | @Test
41 | void build() {
42 | assertPackets(getExpectedData(0x00, 0x10), new ArtPollBuilder());
43 | }
44 |
45 | @Test
46 | void disableVlcTransmission() {
47 |
48 | ArtPollBuilder builder = new ArtPollBuilder();
49 |
50 | assertFalse(builder.vlcTransmissionDisabled());
51 |
52 | builder.setDisableVlcTransmission(true);
53 | assertTrue(builder.vlcTransmissionDisabled());
54 | assertPackets(getExpectedData(0x10, 0x10), builder);
55 |
56 | builder.setDisableVlcTransmission(false);
57 | assertFalse(builder.vlcTransmissionDisabled());
58 | assertPackets(getExpectedData(0x00, 0x10), builder);
59 |
60 | assertSame(builder, builder.withDisableVlcTransmission(true));
61 | assertTrue(builder.vlcTransmissionDisabled());
62 | assertPackets(getExpectedData(0x10, 0x10), builder);
63 |
64 | assertSame(builder, builder.withDisableVlcTransmission(false));
65 | assertFalse(builder.vlcTransmissionDisabled());
66 | assertPackets(getExpectedData(0x00, 0x10), builder);
67 | }
68 |
69 | @Test
70 | void unicastDiagnosticMessages() {
71 |
72 | ArtPollBuilder builder = new ArtPollBuilder();
73 |
74 | assertFalse(builder.unicastDiagnosticMessages());
75 |
76 | builder.setUnicastDiagnosticMessages(true);
77 | assertTrue(builder.unicastDiagnosticMessages());
78 | assertPackets(getExpectedData(0x08, 0x10), builder);
79 |
80 | builder.setUnicastDiagnosticMessages(false);
81 | assertFalse(builder.unicastDiagnosticMessages());
82 | assertPackets(getExpectedData(0x00, 0x10), builder);
83 |
84 | assertSame(builder, builder.withUnicastDiagnosticMessages(true));
85 | assertTrue(builder.unicastDiagnosticMessages());
86 | assertPackets(getExpectedData(0x08, 0x10), builder);
87 |
88 | assertSame(builder, builder.withUnicastDiagnosticMessages(false));
89 | assertFalse(builder.unicastDiagnosticMessages());
90 | assertPackets(getExpectedData(0x00, 0x10), builder);
91 | }
92 |
93 | @Test
94 | void sendDiagnosticMessages() {
95 |
96 | ArtPollBuilder builder = new ArtPollBuilder();
97 |
98 | assertFalse(builder.sendDiagnosticMessages());
99 |
100 | builder.setSendDiagnosticMessages(true);
101 | assertTrue(builder.sendDiagnosticMessages());
102 | assertPackets(getExpectedData(0x04, 0x10), builder);
103 |
104 | builder.setSendDiagnosticMessages(false);
105 | assertFalse(builder.sendDiagnosticMessages());
106 | assertPackets(getExpectedData(0x00, 0x10), builder);
107 |
108 | assertSame(builder, builder.withSendDiagnosticMessages(true));
109 | assertTrue(builder.sendDiagnosticMessages());
110 | assertPackets(getExpectedData(0x04, 0x10), builder);
111 |
112 | assertSame(builder, builder.withSendDiagnosticMessages(false));
113 | assertFalse(builder.sendDiagnosticMessages());
114 | assertPackets(getExpectedData(0x00, 0x10), builder);
115 | }
116 |
117 | @Test
118 | void sendArtPollReplyOnChanges() {
119 |
120 | ArtPollBuilder builder = new ArtPollBuilder();
121 |
122 | assertFalse(builder.sendArtPollReplyOnChanges());
123 |
124 | builder.setSendArtPollReplyOnChanges(true);
125 | assertTrue(builder.sendArtPollReplyOnChanges());
126 | assertPackets(getExpectedData(0x02, 0x10), builder);
127 |
128 | builder.setSendArtPollReplyOnChanges(false);
129 | assertFalse(builder.sendArtPollReplyOnChanges());
130 | assertPackets(getExpectedData(0x00, 0x10), builder);
131 |
132 | assertSame(builder, builder.withSendArtPollReplyOnChanges(true));
133 | assertTrue(builder.sendArtPollReplyOnChanges());
134 | assertPackets(getExpectedData(0x02, 0x10), builder);
135 |
136 | assertSame(builder, builder.withSendArtPollReplyOnChanges(false));
137 | assertFalse(builder.sendArtPollReplyOnChanges());
138 | assertPackets(getExpectedData(0x00, 0x10), builder);
139 | }
140 |
141 | @Test
142 | void booleanProperties() {
143 |
144 | ArtPollBuilder builder = new ArtPollBuilder()
145 | .withDisableVlcTransmission(true)
146 | .withUnicastDiagnosticMessages(true)
147 | .withSendDiagnosticMessages(true)
148 | .withSendArtPollReplyOnChanges(true);
149 |
150 | assertPackets(getExpectedData(0x1E, 0x10), builder);
151 | }
152 |
153 | @Test
154 | void priority() {
155 |
156 | Priority[] testValues = {Priority.Medium, Priority.High, Priority.Critical, Priority.Volatile, Priority.Low};
157 | byte[] testBytes = {0x40, (byte) 0x80, (byte) 0xE0, (byte) 0xF0, 0x10};
158 |
159 | ArtPollBuilder builder = new ArtPollBuilder();
160 |
161 | assertSame(Priority.Low, builder.getPriority());
162 |
163 | for (int i = 0; i < testValues.length; i++) {
164 |
165 | Priority testValue = testValues[i];
166 | byte testByte = testBytes[i];
167 |
168 | builder.setPriority(testValue);
169 | assertSame(builder.getPriority(), testValue);
170 | assertPackets(getExpectedData(0x00, testByte), builder);
171 |
172 | assertSame(builder, builder.withPriority(null));
173 | assertSame(builder.getPriority(), Priority.Low);
174 | assertPackets(getExpectedData(0x00, 0x10), builder);
175 | }
176 | }
177 | }
--------------------------------------------------------------------------------
/lib/src/test/java/de/deltaeight/libartnet/builders/ArtTimeCodeBuilderTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2018 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.builders;
23 |
24 | import de.deltaeight.libartnet.descriptors.TimeCodeType;
25 | import org.junit.jupiter.api.Test;
26 |
27 | import static org.junit.jupiter.api.Assertions.*;
28 |
29 | class ArtTimeCodeBuilderTest extends AbstractPacketBuilderTest {
30 |
31 | private static final byte[] DEFAULT_PACKET = getExpectedData(0, 0, 0, 0, 0);
32 |
33 | private static byte[] getExpectedData(int type, int hours, int minutes, int seconds, int frames) {
34 | return new byte[]{
35 | 0x41, 0x72, 0x74, 0x2D, 0x4E, 0x65, 0x74, 0x00, // Header
36 | 0x00, (byte) 0x97, // OpCode
37 | 0x00, 0x0E, // Protocol version
38 | 0x00, 0x00, // Filler
39 | (byte) frames, (byte) seconds, (byte) minutes,
40 | (byte) hours, (byte) type
41 | };
42 | }
43 |
44 | @Test
45 | void build() {
46 | assertPackets(DEFAULT_PACKET, new ArtTimeCodeBuilder());
47 | }
48 |
49 | @Test
50 | void type() {
51 |
52 | byte[] expectedData = getExpectedData(1, 0, 0, 0, 0);
53 |
54 | ArtTimeCodeBuilder builder = new ArtTimeCodeBuilder();
55 |
56 | assertSame(TimeCodeType.Film, builder.getType());
57 |
58 | builder.setType(TimeCodeType.EBU);
59 | assertSame(TimeCodeType.EBU, builder.getType());
60 | assertPackets(expectedData, builder);
61 |
62 | builder.setType(null);
63 | assertSame(TimeCodeType.Film, builder.getType());
64 | assertPackets(DEFAULT_PACKET, builder);
65 |
66 | assertSame(builder, builder.withType(TimeCodeType.EBU));
67 | assertSame(TimeCodeType.EBU, builder.getType());
68 | assertPackets(expectedData, builder);
69 |
70 | assertSame(builder, builder.withType(null));
71 | assertSame(TimeCodeType.Film, builder.getType());
72 | assertPackets(DEFAULT_PACKET, builder);
73 | }
74 |
75 | @Test
76 | void hours() {
77 |
78 | ArtTimeCodeBuilder builder = new ArtTimeCodeBuilder();
79 |
80 | assertEquals(0, builder.getHours());
81 |
82 | builder.setHours(23);
83 | assertEquals(23, builder.getHours());
84 | assertPackets(getExpectedData(0, 23, 0, 0, 0), builder);
85 |
86 | assertSame(builder, builder.withHours(0));
87 | assertEquals(0, builder.getHours());
88 | assertPackets(DEFAULT_PACKET, builder);
89 |
90 | assertThrows(IllegalArgumentException.class, () -> builder.setHours(-1));
91 | assertThrows(IllegalArgumentException.class, () -> builder.withHours(24));
92 | }
93 |
94 | @Test
95 | void minutes() {
96 |
97 | ArtTimeCodeBuilder builder = new ArtTimeCodeBuilder();
98 |
99 | assertEquals(0, builder.getMinutes());
100 |
101 | builder.setMinutes(59);
102 | assertEquals(59, builder.getMinutes());
103 | assertPackets(getExpectedData(0, 0, 59, 0, 0), builder);
104 |
105 | assertSame(builder, builder.withMinutes(0));
106 | assertEquals(0, builder.getMinutes());
107 | assertPackets(DEFAULT_PACKET, builder);
108 |
109 | assertThrows(IllegalArgumentException.class, () -> builder.setMinutes(-1));
110 | assertThrows(IllegalArgumentException.class, () -> builder.withMinutes(60));
111 | }
112 |
113 | @Test
114 | void seconds() {
115 |
116 | ArtTimeCodeBuilder builder = new ArtTimeCodeBuilder();
117 |
118 | assertEquals(0, builder.getSeconds());
119 |
120 | builder.setSeconds(59);
121 | assertEquals(59, builder.getSeconds());
122 | assertPackets(getExpectedData(0, 0, 0, 59, 0), builder);
123 |
124 | assertSame(builder, builder.withSeconds(0));
125 | assertEquals(0, builder.getSeconds());
126 | assertPackets(DEFAULT_PACKET, builder);
127 |
128 | assertThrows(IllegalArgumentException.class, () -> builder.setSeconds(-1));
129 | assertThrows(IllegalArgumentException.class, () -> builder.withSeconds(60));
130 | }
131 |
132 | @Test
133 | void frames() {
134 |
135 | ArtTimeCodeBuilder builder = new ArtTimeCodeBuilder();
136 |
137 | assertEquals(0, builder.getFrames());
138 |
139 | builder.setFrames(23);
140 | assertEquals(23, builder.getFrames());
141 | assertPackets(getExpectedData(0, 0, 0, 0, 23), builder);
142 |
143 | assertSame(builder, builder.withFrames(0));
144 | assertEquals(0, builder.getFrames());
145 | assertPackets(DEFAULT_PACKET, builder);
146 |
147 | assertThrows(IllegalArgumentException.class, () -> builder.setFrames(-1));
148 | assertThrows(IllegalArgumentException.class, () -> builder.withFrames(24));
149 |
150 | builder.setType(TimeCodeType.EBU);
151 | assertDoesNotThrow(() -> builder.setFrames(24));
152 | assertThrows(IllegalArgumentException.class, () -> builder.setFrames(25));
153 |
154 | builder.setType(TimeCodeType.DF);
155 | assertDoesNotThrow(() -> builder.setFrames(25));
156 | assertDoesNotThrow(() -> builder.setFrames(29));
157 | assertThrows(IllegalArgumentException.class, () -> builder.setFrames(30));
158 |
159 | builder.setType(TimeCodeType.SMPTE);
160 | assertDoesNotThrow(() -> builder.setFrames(29));
161 | assertThrows(IllegalArgumentException.class, () -> builder.setFrames(30));
162 |
163 | builder.setFrames(28);
164 | builder.setType(TimeCodeType.Film);
165 | assertEquals(23, builder.getFrames());
166 | }
167 | }
168 |
--------------------------------------------------------------------------------
/lib/src/test/java/de/deltaeight/libartnet/doc/Receiver.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2020 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.doc;
23 |
24 | import de.deltaeight.libartnet.network.ArtNetReceiver;
25 | import org.junit.jupiter.api.Test;
26 |
27 | import java.net.SocketException;
28 |
29 | class Receiver {
30 |
31 | @Test
32 | void usingTheReceiver() throws SocketException {
33 |
34 | ArtNetReceiver receiver = new ArtNetReceiver()
35 | .withArtDmxReceiveHandler(packet -> System.out.println("Channel 63 value: " + packet.getData()[62]));
36 |
37 | receiver.start();
38 |
39 | // Do other stuff
40 |
41 | receiver.stop();
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/lib/src/test/java/de/deltaeight/libartnet/doc/Sender.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2020 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.doc;
23 |
24 | import de.deltaeight.libartnet.builders.ArtPollReplyBuilder;
25 | import de.deltaeight.libartnet.descriptors.OemCode;
26 | import de.deltaeight.libartnet.network.ArtNetSender;
27 | import org.junit.jupiter.api.Test;
28 |
29 | import java.net.InetAddress;
30 | import java.net.SocketException;
31 | import java.net.UnknownHostException;
32 |
33 | class Sender {
34 |
35 | @Test
36 | void usingTheSender() throws SocketException, UnknownHostException {
37 |
38 | ArtPollReplyBuilder builder = new ArtPollReplyBuilder()
39 | .withProduct(OemCode.getProductByOemCode("OemRobertJulDalis1"))
40 | .withBindIp(new byte[]{127, 0, 0, 1});
41 |
42 | ArtNetSender sender = new ArtNetSender();
43 | sender.start();
44 |
45 | sender.send(InetAddress.getByName("127.0.0.1"), builder.build());
46 |
47 | // Do other stuff
48 |
49 | sender.stop();
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/lib/src/test/java/de/deltaeight/libartnet/network/AbstractNetworkHandlerTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2020 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.network;
23 |
24 | import org.junit.jupiter.api.Test;
25 |
26 | import java.io.IOException;
27 | import java.net.DatagramSocket;
28 | import java.net.SocketException;
29 | import java.util.concurrent.CountDownLatch;
30 | import java.util.concurrent.TimeUnit;
31 | import java.util.concurrent.atomic.AtomicReference;
32 |
33 | import static org.hamcrest.CoreMatchers.*;
34 | import static org.hamcrest.MatcherAssert.assertThat;
35 | import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
36 | import static org.junit.jupiter.api.Assertions.assertThrows;
37 |
38 | abstract class AbstractNetworkHandlerTest {
39 |
40 | abstract T getNewInstance(DatagramSocket datagramSocket);
41 |
42 | abstract void provokeException(T networkHandler) throws Exception;
43 |
44 | @Test
45 | final void states() throws SocketException {
46 |
47 | DatagramSocketMockup datagramSocketMockup = new DatagramSocketMockup();
48 | T networkHandler = getNewInstance(datagramSocketMockup);
49 |
50 | assertThat(networkHandler.getState(), is(sameInstance(NetworkHandler.State.Initialized)));
51 | assertThrows(IllegalStateException.class, networkHandler::stop);
52 |
53 | assertDoesNotThrow(networkHandler::start);
54 |
55 | assertThat(networkHandler.getState(), is(sameInstance(NetworkHandler.State.Running)));
56 | assertThrows(IllegalStateException.class, networkHandler::start);
57 |
58 | assertDoesNotThrow(networkHandler::stop);
59 |
60 | assertThat(networkHandler.getState(), is(sameInstance(NetworkHandler.State.Stopped)));
61 | assertThrows(IllegalStateException.class, networkHandler::start);
62 | assertThrows(IllegalStateException.class, networkHandler::stop);
63 | }
64 |
65 | @Test
66 | final void exceptionHandler() throws Exception {
67 |
68 | AtomicReference handledException = new AtomicReference<>();
69 | CountDownLatch latch = new CountDownLatch(1);
70 |
71 | T networkHandler = getNewInstance(new DatagramSocketMockup(true));
72 | networkHandler.setExceptionHandler(exception -> {
73 | handledException.set(exception);
74 | latch.countDown();
75 | });
76 |
77 | networkHandler.start();
78 |
79 | provokeException(networkHandler);
80 |
81 | assertThat(latch.await(3, TimeUnit.SECONDS), is(true));
82 | assertThat(handledException.get(), is(instanceOf(IOException.class)));
83 |
84 | networkHandler.stop();
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/lib/src/test/java/de/deltaeight/libartnet/network/ArtNetReceiverTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2020 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.network;
23 |
24 | import org.junit.jupiter.api.Test;
25 |
26 | import java.net.DatagramSocket;
27 | import java.net.SocketException;
28 | import java.util.concurrent.CountDownLatch;
29 | import java.util.concurrent.TimeUnit;
30 | import java.util.concurrent.atomic.AtomicReference;
31 |
32 | import de.deltaeight.libartnet.builders.ArtDmxBuilder;
33 | import de.deltaeight.libartnet.builders.ArtNetPacketBuilder;
34 | import de.deltaeight.libartnet.builders.ArtPollBuilder;
35 | import de.deltaeight.libartnet.builders.ArtPollReplyBuilder;
36 | import de.deltaeight.libartnet.builders.ArtTimeCodeBuilder;
37 | import de.deltaeight.libartnet.packets.ArtNetPacket;
38 |
39 | import static org.hamcrest.CoreMatchers.equalTo;
40 | import static org.hamcrest.CoreMatchers.is;
41 | import static org.hamcrest.MatcherAssert.assertThat;
42 | import static org.junit.jupiter.api.Assertions.assertThrows;
43 |
44 | class ArtNetReceiverTest extends AbstractNetworkHandlerTest {
45 |
46 | @Override
47 | ArtNetReceiver getNewInstance(DatagramSocket datagramSocket) {
48 | return new ArtNetReceiver(datagramSocket);
49 | }
50 |
51 | @Override
52 | void provokeException(ArtNetReceiver networkHandler) {
53 | // Do nothing
54 | }
55 |
56 | @Test
57 | final void constructor() {
58 | assertThrows(IllegalArgumentException.class, () -> getNewInstance(new DatagramSocketMockup(666)));
59 | }
60 |
61 | private void testReceiveHandler(ArtNetReceiverPreparation artNetReceiverPreparation,
62 | ArtNetPacketBuilder packetBuilder)
63 |
64 | throws SocketException, InterruptedException {
65 |
66 | AtomicReference packetReference = new AtomicReference<>();
67 | CountDownLatch latch = new CountDownLatch(1);
68 |
69 | DatagramSocketMockup datagramSocketMockup = new DatagramSocketMockup();
70 |
71 | artNetReceiverPreparation.prepare(new ArtNetReceiver(datagramSocketMockup), packet -> {
72 | packetReference.set(packet);
73 | latch.countDown();
74 | }).start();
75 |
76 | T packet = packetBuilder.build();
77 |
78 | datagramSocketMockup.injectPacket(packet);
79 |
80 | assertThat(latch.await(3, TimeUnit.SECONDS), is(true));
81 | assertThat(packet, is(equalTo(packetReference.get())));
82 | }
83 |
84 | @Test
85 | void receiveHandlers() throws SocketException, InterruptedException {
86 | testReceiveHandler(ArtNetReceiver::withArtDmxReceiveHandler, new ArtDmxBuilder());
87 | testReceiveHandler(ArtNetReceiver::withArtPollReceiveHandler, new ArtPollBuilder());
88 | testReceiveHandler(ArtNetReceiver::withArtPollReplyReceiveHandler, new ArtPollReplyBuilder());
89 | testReceiveHandler(ArtNetReceiver::withArtTimeCodeReceiveHandler, new ArtTimeCodeBuilder());
90 | }
91 |
92 | @FunctionalInterface
93 | private interface ArtNetReceiverPreparation {
94 |
95 | ArtNetReceiver prepare(ArtNetReceiver artNetReceiver, PacketReceiveHandler packetReceiveHandler);
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/lib/src/test/java/de/deltaeight/libartnet/network/ArtNetSenderTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2019 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.network;
23 |
24 | import de.deltaeight.libartnet.builders.ArtDmxBuilder;
25 | import de.deltaeight.libartnet.packets.ArtDmx;
26 | import org.junit.jupiter.api.Test;
27 |
28 | import java.net.*;
29 | import java.util.concurrent.CountDownLatch;
30 | import java.util.concurrent.TimeUnit;
31 | import java.util.concurrent.atomic.AtomicReference;
32 |
33 | import static org.hamcrest.CoreMatchers.equalToObject;
34 | import static org.hamcrest.CoreMatchers.is;
35 | import static org.hamcrest.MatcherAssert.assertThat;
36 |
37 | class ArtNetSenderTest extends AbstractNetworkHandlerTest {
38 |
39 | @Override
40 | ArtNetSender getNewInstance(DatagramSocket datagramSocket) {
41 | return new ArtNetSender(datagramSocket);
42 | }
43 |
44 | @Override
45 | void provokeException(ArtNetSender networkHandler) throws Exception {
46 | networkHandler.send(InetAddress.getByName("127.0.0.1"), new ArtDmxBuilder().build());
47 | }
48 |
49 | @Test
50 | final void send() throws SocketException, UnknownHostException, InterruptedException {
51 |
52 | AtomicReference receivedPacket = new AtomicReference<>();
53 | CountDownLatch latch = new CountDownLatch(1);
54 |
55 | ArtDmx artDmx = new ArtDmxBuilder().build();
56 |
57 | DatagramSocketMockup datagramSocketMockup = new DatagramSocketMockup();
58 | datagramSocketMockup.setOnPacketSent(packet -> {
59 | receivedPacket.set(packet);
60 | latch.countDown();
61 | });
62 |
63 | ArtNetSender artNetSender = new ArtNetSender(datagramSocketMockup);
64 | artNetSender.start();
65 | artNetSender.send(InetAddress.getByName("127.0.0.1"), artDmx);
66 |
67 | assertThat(latch.await(3, TimeUnit.SECONDS), is(true));
68 | assertThat(artDmx.getBytes(), is(equalToObject(receivedPacket.get().getData())));
69 |
70 | artNetSender.stop();
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/lib/src/test/java/de/deltaeight/libartnet/network/DatagramSocketMockup.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2018 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.network;
23 |
24 | import de.deltaeight.libartnet.packets.ArtNetPacket;
25 |
26 | import java.io.IOException;
27 | import java.net.DatagramPacket;
28 | import java.net.DatagramSocket;
29 | import java.net.SocketException;
30 |
31 | class DatagramSocketMockup extends DatagramSocket {
32 |
33 | private final int localPort;
34 | private boolean throwIoException;
35 | private ArtNetPacket injectArtNetPacket;
36 | private boolean closed;
37 | private PacketSentHandler onPacketSent;
38 |
39 | DatagramSocketMockup() throws SocketException {
40 | this.localPort = 0x1936;
41 | }
42 |
43 | DatagramSocketMockup(int localPort) throws SocketException {
44 | this.localPort = localPort;
45 | }
46 |
47 | DatagramSocketMockup(boolean throwIoException) throws SocketException {
48 | this();
49 | this.throwIoException = throwIoException;
50 | }
51 |
52 | @Override
53 | public void send(DatagramPacket p) throws IOException {
54 | if (throwIoException) {
55 | throw new IOException();
56 | } else if (onPacketSent != null) {
57 | onPacketSent.handle(p);
58 | }
59 | }
60 |
61 | @Override
62 | public synchronized void receive(DatagramPacket packet) throws IOException {
63 | boolean wait = true;
64 | while (!closed && wait) {
65 | try {
66 | if (throwIoException) {
67 | throwIoException = false;
68 | throw new IOException();
69 | } else if (injectArtNetPacket != null) {
70 | packet.setData(injectArtNetPacket.getBytes());
71 | packet.setPort(0x1936);
72 | packet.setLength(injectArtNetPacket.getBytes().length);
73 | injectArtNetPacket = null;
74 | wait = false;
75 | }
76 | if (wait) {
77 | Thread.sleep(10);
78 | }
79 | } catch (InterruptedException ignored) {
80 | }
81 | }
82 | }
83 |
84 | @Override
85 | public int getLocalPort() {
86 | return localPort;
87 | }
88 |
89 | @Override
90 | public void close() {
91 | closed = true;
92 | }
93 |
94 | void injectPacket(ArtNetPacket packet) {
95 | injectArtNetPacket = packet;
96 | }
97 |
98 | void setOnPacketSent(PacketSentHandler onPacketSent) {
99 | this.onPacketSent = onPacketSent;
100 | }
101 |
102 | @FunctionalInterface
103 | interface PacketSentHandler {
104 |
105 | void handle(DatagramPacket packet);
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/lib/src/test/java/de/deltaeight/libartnet/network/NetworkPacketIntegrityTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2020 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.network;
23 |
24 | import org.junit.jupiter.api.Test;
25 |
26 | import java.net.DatagramSocket;
27 | import java.net.InetAddress;
28 | import java.net.SocketException;
29 | import java.net.UnknownHostException;
30 | import java.util.ArrayList;
31 | import java.util.HashMap;
32 | import java.util.concurrent.ConcurrentLinkedQueue;
33 |
34 | import de.deltaeight.libartnet.builders.ArtDmxBuilder;
35 | import de.deltaeight.libartnet.packets.ArtDmx;
36 |
37 | import static org.hamcrest.MatcherAssert.assertThat;
38 | import static org.hamcrest.Matchers.equalTo;
39 | import static org.hamcrest.Matchers.is;
40 |
41 | class NetworkPacketIntegrityTest {
42 |
43 | @Test
44 | void networkPacketIntegrityTest()
45 | throws SocketException, UnknownHostException, InterruptedException {
46 |
47 | // Adjust number of test packets. 512 * 256 is maximum for discrete packet numbering.
48 | // Too many packets may increase packet loss.
49 | int numberOfTestPackets = 10000;
50 |
51 | ArrayList builders = new ArrayList<>(128 * 16 * 16);
52 | for (int i = 0; i < 128; i++) {
53 | for (int j = 0; j < 16; j++) {
54 | for (int k = 0; k < 16; k++) {
55 | builders.add(new ArtDmxBuilder()
56 | .withNetAddress(i)
57 | .withSubnetAddress(j)
58 | .withUniverseAddress(k));
59 | }
60 | }
61 | }
62 |
63 | byte[][] dataSources = new byte[numberOfTestPackets][];
64 | for (int i = 0; i < numberOfTestPackets; i++) {
65 | dataSources[i] = getDataArray(i);
66 | }
67 |
68 | ConcurrentLinkedQueue receivedPackets = new ConcurrentLinkedQueue<>();
69 | ArtNetReceiver receiver = new ArtNetReceiver()
70 | .withArtDmxReceiveHandler(receivedPackets::add);
71 | receiver.start();
72 |
73 | Thread.sleep(2000);
74 |
75 | HashMap sentPackets = new HashMap<>();
76 | ArtNetSender sender = new ArtNetSender(new DatagramSocket());
77 | sender.start();
78 | InetAddress ip = InetAddress.getByName("127.0.0.1");
79 | int builderCounter = 0;
80 | for (int i = 0; i < numberOfTestPackets; i++) {
81 | byte[] data = dataSources[i];
82 | ArtDmx packet = builders.get(builderCounter)
83 | .withData(data)
84 | .build();
85 | sentPackets.put(getHash(packet), packet);
86 | sender.send(ip, packet);
87 |
88 | if (++builderCounter == builders.size()) {
89 | builderCounter = 0;
90 | }
91 | }
92 |
93 | int receivedPacketCounter = 0;
94 | long end = System.currentTimeMillis() + 2000;
95 | while (System.currentTimeMillis() < end) {
96 | ArtDmx receivedPacket = receivedPackets.poll();
97 | if (receivedPacket != null) {
98 | ArtDmx sentPacket = sentPackets.get(getHash(receivedPacket));
99 | assertThat(receivedPacket, is(equalTo(sentPacket)));
100 | assertThat(receivedPacket.getData(), is(equalTo(sentPacket.getData())));
101 | assertThat(receivedPacket.getBytes(), is(equalTo(sentPacket.getBytes())));
102 | receivedPacketCounter++;
103 | }
104 | }
105 |
106 | System.out.println("Sent packets: " + sentPackets.size());
107 | System.out.println("Received packets: " + receivedPacketCounter);
108 | System.out.println("Loss: " + (1 - ((receivedPacketCounter * 1d) / sentPackets.size())));
109 |
110 | sender.stop();
111 | receiver.stop();
112 | }
113 |
114 | private String getHash(byte[] data, int netAddress, int subnetAddress, int universeAddress) {
115 | int sum = 0;
116 | for (byte datum : data) {
117 | sum += datum & 0xFF;
118 | }
119 | return sum + " " + netAddress + " " + subnetAddress + " " + universeAddress;
120 | }
121 |
122 | private String getHash(ArtDmx packet) {
123 | return getHash(packet.getData(), packet.getNetAddress(), packet.getSubnetAddress(),
124 | packet.getUniverseAddress());
125 | }
126 |
127 | private byte[] getDataArray(int index) {
128 | byte[] result = new byte[512];
129 | for (int i = 0; i < 512; i++) {
130 | result[i] = (byte) (index >>> 8 * i);
131 | if (result[i] == 0) {
132 | break;
133 | }
134 | }
135 | return result;
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/maven-key.gpg.enc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deltaeight/LibArtNet/90e4b834b44de6740cec11e2021bb61c05c447f4/maven-key.gpg.enc
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include 'lib'
2 | include 'util'
3 |
4 | rootProject.name = 'LibArtNet'
5 | project(':lib').name = 'LibArtNet'
--------------------------------------------------------------------------------
/util/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'java'
3 | }
4 |
5 | group 'de.deltaeight'
6 | version '1.0-beta'
7 |
8 | sourceCompatibility = 1.8
9 | targetCompatibility = 1.8
10 |
11 | dependencies {
12 |
13 | // Test framework
14 | testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.2'
15 | testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.6.2'
16 | }
17 |
18 | test {
19 | useJUnitPlatform()
20 | }
21 |
--------------------------------------------------------------------------------
/util/src/main/java/de/deltaeight/libartnet/util/OemJsonGenerator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * LibArtNet
3 | *
4 | * Art-Net(TM) Designed by and Copyright Artistic Licence Holdings Ltd
5 | *
6 | * Copyright (c) 2020 Julian Rabe
7 | *
8 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
9 | * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
10 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
14 | * the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | */
21 |
22 | package de.deltaeight.libartnet.util;
23 |
24 | import java.io.IOException;
25 | import java.net.URISyntaxException;
26 | import java.nio.file.Files;
27 | import java.nio.file.Paths;
28 | import java.util.LinkedList;
29 | import java.util.List;
30 | import java.util.StringJoiner;
31 | import java.util.regex.Matcher;
32 | import java.util.regex.Pattern;
33 |
34 | /**
35 | * This is a nifty tool to auto-generate the {@code OemCode} enum. All you need is {@code Art-NetOemCodes.h} from
36 | * Artistic License Ltd. which you can obtain
37 | * here. You will then need
38 | * to put it into the resources of this package. {@link #main(String...)} will then generate the enum under
39 | * {@code lib/src/main/java/de/deltaeight/libartnet/descriptors/OemCode.java}.
40 | *
41 | * @author Julian Rabe
42 | */
43 | public class OemJsonGenerator {
44 |
45 | private static final Pattern pattern = Pattern.compile("#define (Oem[a-zA-Z0-9_]+)[ \\xA0]+" +
46 | "0x([a-fA-F0-9]{4})[ \\xA0]+" +
47 | "//Manufacturer:[ \\xA0](.+)[ \\xA0]+" +
48 | "ProductName:[ \\xA0](.+)[ \\xA0]+" +
49 | "NumDmxIn:[ \\xA0](\\d+)[ \\xA0]+" +
50 | "NumDmxOut:[ \\xA0](\\d+)[ \\xA0]+" +
51 | "DmxPortPhysical:[ \\xA0]((?:[jnyJNY])|(?:[nN]o)|(?:[yY]es)|(?:[pP]hysical)|\\d).*[ \\xA0]+" +
52 | "RdmSupported:[ \\xA0]((?:[jnyJNY])|(?:[nN]o)|(?:[yY]es)|(?:RDM))[ \\xA0]+" +
53 | "SupportEmail:[ \\xA0](.*)[ \\xA0]+" +
54 | "SupportName:[ \\xA0](.*)[ \\xA0]+" +
55 | "CoWeb:.*");
56 |
57 | public static void main(String... args) throws IOException, URISyntaxException {
58 |
59 | List lines = Files.readAllLines(Paths.get(OemJsonGenerator.class
60 | .getResource("Art-NetOemCodes.h").toURI()));
61 |
62 | StringJoiner parsedLines = new StringJoiner(",\n");
63 | LinkedList unparsedLines = new LinkedList<>();
64 |
65 | int productCounter = 0;
66 |
67 | for (String line : lines) {
68 |
69 | String codeEntry = createCodeEntry(line);
70 |
71 | if (codeEntry != null) {
72 | parsedLines.add(codeEntry);
73 | productCounter++;
74 | } else {
75 | unparsedLines.add(line);
76 | }
77 | }
78 |
79 | Files.write(Paths.get("lib/src/main/resources/de/deltaeight/libartnet/descriptors/OemCodes.json"),
80 | ("[\n" + parsedLines.toString() + "\n]").getBytes());
81 |
82 | System.out.println("Result written to OemCodes.json!");
83 | System.out.println("Products parsed: " + productCounter);
84 | System.out.println("Unparsed lines: " + unparsedLines.size());
85 | System.out.println();
86 | System.out.println("Unparsed lines follow:");
87 | System.out.println("######################");
88 |
89 | for (String line : unparsedLines) {
90 | if (!line.replaceAll("\\s", "").isEmpty()) {
91 | System.out.println(line);
92 | }
93 | }
94 | }
95 |
96 | private static String createCodeEntry(String line) {
97 |
98 | Matcher matcher = pattern.matcher(line);
99 | if (matcher.matches()) {
100 |
101 | boolean dmxPortsPhysical;
102 | try {
103 | dmxPortsPhysical = Integer.parseInt(matcher.group(7)) > 0;
104 | } catch (NumberFormatException e) {
105 | dmxPortsPhysical = matcher.group(7).equalsIgnoreCase("y")
106 | || matcher.group(7).equalsIgnoreCase("yes")
107 | || matcher.group(7).equalsIgnoreCase("physical");
108 | }
109 |
110 | boolean supportsRdm = matcher.group(8).equalsIgnoreCase("y")
111 | || matcher.group(8).equalsIgnoreCase("yes")
112 | || matcher.group(8).equalsIgnoreCase("rdm");
113 |
114 | return " { " +
115 | "\"oemCode\": \"" + matcher.group(1) + "\", " +
116 | "\"productCode\": " + Integer.parseInt(matcher.group(2), 16) + ", " +
117 | "\"manufacturer\": \"" + matcher.group(3) + "\", " +
118 | "\"name\": \"" + matcher.group(4) + "\", " +
119 | "\"dmxOutputs\": " + Integer.parseInt(matcher.group(5)) + ", " +
120 | "\"dmxInputs\": " + Integer.parseInt(matcher.group(6)) + ", " +
121 | "\"dmxPortsPhysical\": \"" + dmxPortsPhysical + "\", " +
122 | "\"supportsRdm\": \"" + supportsRdm + "\", " +
123 | "\"supportEmail\": \"" + matcher.group(9) + "\", " +
124 | "\"supportName\": \"" + matcher.group(10) + "\" " +
125 | "}";
126 | }
127 |
128 | return null;
129 | }
130 | }
131 |
--------------------------------------------------------------------------------