toxiclibs 2.0.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 946268fb6e50b2556be590d1cf0b733f3915e31c98b19e436ec50bd872006a41
4
- data.tar.gz: '09522b131b7f1b8047dce50b62e39f8b7795383c028155e0d7236ef4baeb419c'
3
+ metadata.gz: ea1e1885aff507b0bb35cf61ddab9b086553d07b35be64e3b1673cbacc7846ce
4
+ data.tar.gz: dc1955313145c89dafbe4ace7b55d15af37f0d6fafee423a3a700e423ed14fca
5
5
  SHA512:
6
- metadata.gz: c86c4b5dd436f79bed4d9ba21ca7c2f14e822e13a7eeeabdab677b0b93f67ce8d4b3da915632a9cafa29fddb0720be53f5c19ff253bbcbce55b6ca9b4b0bc94f
7
- data.tar.gz: 13a197bc603117f7a863b2d32d658aae44d23080f5b4cd1fddd490706ec66739c91ad57efa87020f00546ff55431423482376b658fff905eac713913b9533152
6
+ metadata.gz: 466378a7a6896aad508c6de8928253695fa891aca794a90906e9481021195f556cd42363a79f50bf33e4d9c7dd4e65ff4ab7d4dd48f4a54acd8696abaae76a84
7
+ data.tar.gz: c1b115629d788cc547cc37fedeb07406c9f55d572f4553bc842bc7b07aa00cbf5b17a961fd523463924adca4e593273248bb9f072e8cc3c3d2de3a50058cb27e
data/.mvn/extensions.xml CHANGED
@@ -3,6 +3,6 @@
3
3
  <extension>
4
4
  <groupId>io.takari.polyglot</groupId>
5
5
  <artifactId>polyglot-ruby</artifactId>
6
- <version>0.4.0</version>
6
+ <version>0.4.6</version>
7
7
  </extension>
8
8
  </extensions>
data/CHANGELOG.md CHANGED
@@ -1,3 +1,5 @@
1
+ **v2.1.0** Add module-info.
2
+
1
3
  **v2.0.0** Bump to target minimum of jdk11 thus removing JAXB annotations (possibly esoteric and underused anyway).
2
4
 
3
5
  **v1.0.1** Bump processing to 3.4, support toxiclibs Voronoi etc
data/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
  gem install toxiclibs
9
9
  ```
10
10
 
11
- ### NB: Use version 0.4 for ruby-processing, and 1.0.0+ for propane and JRubyArt
11
+ ### NB: Use version 0.4 for ruby-processing, and 2.1.0+ for propane, PiCrate and JRubyArt
12
12
 
13
13
  NB: Build is only failing because current version of processing is not available at maven central.
14
14
  This gem provides Karsten Schmidts (aka toxi, @postspectacular) toxiclibs jars for JRubyArt. To compile the gem follow the instructions for [JRubyArt][]. Most parts of toxiclibs API is exposed in the latest version, (but only a few examples are included) in principle it should be possible to make all available!!! For this demonstration I have used up to date source code for version 21, since [toxis final release][] has not yet been released (although [Dan Shiffman][] has released a version for processing-3.0+). There are reported to be number of outstanding bugs with toxiclibs, if they affect you report it [here][] (or better fix them yourself and submit a pull request).
data/Rakefile CHANGED
@@ -18,7 +18,7 @@ end
18
18
 
19
19
  desc 'Build gem'
20
20
  task :gem do
21
- sh "gem build toxiclibs.gemspec"
21
+ sh "jgem build toxiclibs.gemspec"
22
22
  end
23
23
 
24
24
  desc 'Compile'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  # wrapper to give version a meaningful name
3
3
  module Toxiclibs
4
- VERSION = '2.0.0'.freeze
4
+ VERSION = '2.1.0'.freeze
5
5
  end
data/lib/toxiclibs.jar CHANGED
Binary file
data/pom.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  project 'toxiclibs' do
2
2
 
3
3
  model_version '4.0.0'
4
- id 'ruby-processing:toxiclibs:2.0.0'
4
+ id 'ruby-processing:toxiclibs:2.1.0'
5
5
  packaging 'jar'
6
6
 
7
7
  description 'toxiclibs-library for JRubyArt'
@@ -22,21 +22,17 @@ project 'toxiclibs' do
22
22
  'polyglot.dump.pom' => 'pom.xml',
23
23
  'project.build.sourceEncoding' => 'UTF-8',
24
24
  'target.release' => '11',
25
- 'polyglot.dump.pom' => 'pom.xml'
25
+ 'polyglot.dump.pom' => 'pom.xml',
26
+ 'maven.deploy.skip' => 'true'
26
27
  )
27
28
 
28
- jar 'org.processing:core:3.3.7'
29
+ jar 'org.processing:core:4.0.0'
29
30
 
30
31
  overrides do
31
32
  plugin( :compiler, '3.8.1',
32
33
  'release' => '11' )
33
34
  plugin :javadoc, '2.10.4'
34
- plugin(
35
- :jar, '3.2.0',
36
- 'archive' => {
37
- 'manifestFile' => 'MANIFEST.MF'
38
- }
39
- )
35
+ plugin :jar, '3.2.0'
40
36
  plugin :jdeps, '3.1.2' do
41
37
  execute_goals 'jdkinternals', 'test-jdkinternals'
42
38
  end
data/pom.xml CHANGED
@@ -2,7 +2,7 @@
2
2
  <!--
3
3
 
4
4
 
5
- DO NOT MODIFIY - GENERATED CODE
5
+ DO NOT MODIFY - GENERATED CODE
6
6
 
7
7
 
8
8
  -->
@@ -11,7 +11,7 @@ DO NOT MODIFIY - GENERATED CODE
11
11
  <modelVersion>4.0.0</modelVersion>
12
12
  <groupId>ruby-processing</groupId>
13
13
  <artifactId>toxiclibs</artifactId>
14
- <version>2.0.0</version>
14
+ <version>2.1.0</version>
15
15
  <name>toxiclibs</name>
16
16
  <description>toxiclibs-library for JRubyArt</description>
17
17
  <developers>
@@ -34,6 +34,7 @@ DO NOT MODIFIY - GENERATED CODE
34
34
  <url>https://github.com/ruby-processing/toxiclibs/issues</url>
35
35
  </issueManagement>
36
36
  <properties>
37
+ <maven.deploy.skip>true</maven.deploy.skip>
37
38
  <polyglot.dump.pom>pom.xml</polyglot.dump.pom>
38
39
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
39
40
  <source.directory>src</source.directory>
@@ -43,7 +44,7 @@ DO NOT MODIFIY - GENERATED CODE
43
44
  <dependency>
44
45
  <groupId>org.processing</groupId>
45
46
  <artifactId>core</artifactId>
46
- <version>3.3.7</version>
47
+ <version>4.0.0</version>
47
48
  </dependency>
48
49
  </dependencies>
49
50
  <build>
@@ -66,11 +67,6 @@ DO NOT MODIFIY - GENERATED CODE
66
67
  <plugin>
67
68
  <artifactId>maven-jar-plugin</artifactId>
68
69
  <version>3.2.0</version>
69
- <configuration>
70
- <archive>
71
- <manifestFile>MANIFEST.MF</manifestFile>
72
- </archive>
73
- </configuration>
74
70
  </plugin>
75
71
  <plugin>
76
72
  <artifactId>maven-jdeps-plugin</artifactId>
@@ -0,0 +1,22 @@
1
+ module toxiclibs{
2
+ exports toxi.color;
3
+ exports toxi.data.csv;
4
+ exports toxi.data.feeds;
5
+ exports toxi.geom;
6
+ exports toxi.image.util;
7
+ exports toxi.music.scale;
8
+ exports toxi.newmesh;
9
+ exports toxi.physics2d;
10
+ exports toxi.physics3d;
11
+ exports toxi.processing;
12
+ exports toxi.sim.automata;
13
+ exports toxi.sim.dla;
14
+ exports toxi.sim.erosion;
15
+ exports toxi.sim.fluids;
16
+ exports toxi.sim.grayscott;
17
+ exports toxi.util;
18
+ exports toxi.volume;
19
+ requires org.processing.core;
20
+ requires java.desktop;
21
+ requires java.logging;
22
+ }
@@ -0,0 +1,10 @@
1
+ /*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+
7
+ module ToxiclibsTest {
8
+ requires org.processing.core;
9
+ requires toxiclibs;
10
+ }
@@ -1,4 +1,4 @@
1
-
1
+ package toxi;
2
2
  import processing.core.*;
3
3
 
4
4
  import toxi.geom.*;
@@ -56,7 +56,7 @@ public class BooleanShapes extends PApplet {
56
56
  }
57
57
 
58
58
  static public void main(String[] passedArgs) {
59
- String[] appletArgs = new String[]{"BooleanShapes"};
59
+ String[] appletArgs = new String[]{"toxi.BooleanShapes"};
60
60
  if (passedArgs != null) {
61
61
  PApplet.main(concat(appletArgs, passedArgs));
62
62
  } else {
metadata CHANGED
@@ -1,18 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: toxiclibs
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Karsten Schmidt
8
8
  - Martin Prout
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-05-03 00:00:00.000000000 Z
12
+ date: 2021-09-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: rake
16
15
  requirement: !ruby/object:Gem::Requirement
17
16
  requirements:
18
17
  - - "~>"
@@ -21,8 +20,9 @@ dependencies:
21
20
  - - ">="
22
21
  - !ruby/object:Gem::Version
23
22
  version: 12.3.0
24
- type: :development
23
+ name: rake
25
24
  prerelease: false
25
+ type: :development
26
26
  version_requirements: !ruby/object:Gem::Requirement
27
27
  requirements:
28
28
  - - "~>"
@@ -31,8 +31,8 @@ dependencies:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: 12.3.0
34
- description: " Toxiclibs java libraries wrapped in a rubygem. Compiled and tested
35
- with JRubyArt-2.4 and processing-3.4\n"
34
+ description: " Toxiclibs java libraries wrapped in a rubygem. Compiled and tested\
35
+ \ with JRubyArt-2.4 and processing-3.4\n"
36
36
  email: mamba2928@yahoo.co.uk
37
37
  executables: []
38
38
  extensions: []
@@ -86,16 +86,7 @@ files:
86
86
  - lib/toxiclibs/version.rb
87
87
  - pom.rb
88
88
  - pom.xml
89
- - src/com/toxi/net/ClientListener.java
90
- - src/com/toxi/net/ServerListener.java
91
- - src/com/toxi/net/ServerListenerAdapter.java
92
- - src/com/toxi/net/ServerState.java
93
- - src/com/toxi/net/UDPConnection.java
94
- - src/com/toxi/net/UDPSyncClient.java
95
- - src/com/toxi/net/UDPSyncServer.java
96
- - src/com/toxi/nio/UDPClient.java
97
- - src/com/toxi/nio/UDPClientState.java
98
- - src/com/toxi/nio/UDPServer.java
89
+ - src/main/java/module-info.java
99
90
  - src/main/java/toxi/color/AccessCriteria.java
100
91
  - src/main/java/toxi/color/AlphaAccessor.java
101
92
  - src/main/java/toxi/color/CMYKAccessor.java
@@ -435,14 +426,15 @@ files:
435
426
  - src/main/java/toxi/volume/VolumetricHashMap.java
436
427
  - src/main/java/toxi/volume/VolumetricSpace.java
437
428
  - src/main/java/toxi/volume/VolumetricSpaceArray.java
438
- - src/test/java/BooleanShapes.java
429
+ - src/test/java/module-info.java
430
+ - src/test/java/toxi/BooleanShapes.java
439
431
  - toxiclibs.gemspec
440
432
  homepage: http://ruby-processing.github.io/toxicgem/
441
433
  licenses:
442
434
  - MIT
443
435
  - LGPL-3.0
444
436
  metadata: {}
445
- post_install_message:
437
+ post_install_message:
446
438
  rdoc_options: []
447
439
  require_paths:
448
440
  - lib
@@ -457,8 +449,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
457
449
  - !ruby/object:Gem::Version
458
450
  version: '0'
459
451
  requirements: []
460
- rubygems_version: 3.1.2
461
- signing_key:
452
+ rubygems_version: 3.2.14
453
+ signing_key:
462
454
  specification_version: 4
463
455
  summary: Updated and extended toxiclibs libraries for JRubyArt and propane
464
456
  test_files: []
@@ -1,41 +0,0 @@
1
- package com.toxi.net;
2
-
3
- /**
4
- *
5
- * @author tux
6
- */
7
- public interface ClientListener {
8
- /**
9
- * Callback to trigger an update of the server managed process. This might
10
- * be called several times in a row if the client has fallen behind in time.
11
- * There should be NO rendering related tasks being called from this
12
- * callback.
13
- */
14
- public void triggerUpdate();
15
-
16
- /**
17
- * Callback to trigger the rendering of a new frame. This method will ALWAYS
18
- * be called after {{@link #triggerUpdate()} and should be purely focused on
19
- * drawing/rendering specific tasks, but no CPU intensive model updates.
20
- */
21
- public void triggerFrame();
22
-
23
- /**
24
- * Callback to confirm client has successfully connected
25
- */
26
- public void notifyConnected();
27
-
28
- /**
29
- * Callback to notify client has disconnected from the server.
30
- */
31
- public void notifyDisconnected();
32
-
33
- /**
34
- * Callback to give the client a chance to react to the encountered
35
- * exception.
36
- *
37
- * @param e
38
- * the exception which caused the callback
39
- */
40
- public void handleError(Exception e);
41
- }
@@ -1,70 +0,0 @@
1
- package com.toxi.net;
2
-
3
- import java.net.DatagramPacket;
4
-
5
- /**
6
- *
7
- * @author tux
8
- */
9
- public interface ServerListener {
10
-
11
- /**
12
- * Notifies listener immediately after the server socket has been created.
13
- */
14
- public void serverStarted();
15
-
16
- /**
17
- * Notifies the listener server is shutting down.
18
- */
19
- public void serverShutdown();
20
-
21
- /**
22
- * Gives listener a chance to react to any fatal server errors.
23
- *
24
- * @param e
25
- */
26
- public void serverError(Exception e);
27
-
28
- /**
29
- * Notifies the listener of a new server state. The state info itself is
30
- * attached.
31
- *
32
- * @param s
33
- */
34
- public void serverStateChanged(ServerState s);
35
-
36
- /**
37
- * Notifies listener of a new client connection. Details are attached.
38
- *
39
- * @param conn
40
- */
41
- public void clientConnected(UDPConnection conn);
42
-
43
- /**
44
- * Notifies listener a client has disconnected. Connection details are
45
- * attached.
46
- *
47
- * @param conn
48
- */
49
- public void clientDisconnected(UDPConnection conn);
50
-
51
- /**
52
- * Notifies and forwards received client data to the listener for further
53
- * analysis.
54
- *
55
- * @param conn
56
- * client connection details
57
- * @param receivePacket
58
- * data sent by the client
59
- */
60
- public void clientUpdated(UDPConnection conn, DatagramPacket receivePacket);
61
-
62
- /**
63
- * Gives the listener a chance to add extra data to the payload packet
64
- * distributed to each client.
65
- *
66
- * @return additional data, or null if none required
67
- */
68
- public byte[] getSyncPayload();
69
-
70
- }
@@ -1,47 +0,0 @@
1
- /**
2
- *
3
- */
4
- package com.toxi.net;
5
-
6
- import java.net.DatagramPacket;
7
-
8
- /**
9
- * @author toxi
10
- *
11
- */
12
- public class ServerListenerAdapter implements ServerListener {
13
-
14
- @Override
15
- public void clientConnected(UDPConnection conn) {
16
-
17
- }
18
-
19
- @Override
20
- public void clientDisconnected(UDPConnection conn) {
21
- }
22
-
23
- @Override
24
- public void clientUpdated(UDPConnection conn, DatagramPacket receivePacket) {
25
- }
26
-
27
- @Override
28
- public byte[] getSyncPayload() {
29
- return new byte[0];
30
- }
31
-
32
- @Override
33
- public void serverError(Exception e) {
34
- }
35
-
36
- @Override
37
- public void serverShutdown() {
38
- }
39
-
40
- @Override
41
- public void serverStarted() {
42
- }
43
-
44
- @Override
45
- public void serverStateChanged(ServerState s) {
46
- }
47
- }
@@ -1,18 +0,0 @@
1
- package com.toxi.net;
2
-
3
- /**
4
- *
5
- * @author tux
6
- */
7
- public enum ServerState {
8
-
9
- /**
10
- *
11
- */
12
- WAITING_FOR_CLIENTS,
13
-
14
- /**
15
- *
16
- */
17
- SYNCHING
18
- }
@@ -1,66 +0,0 @@
1
- package com.toxi.net;
2
-
3
- import java.io.*;
4
- import java.net.*;
5
-
6
- /**
7
- * @author Karsten Schmidt <info@postspectacular.com>
8
- */
9
-
10
- class UDPConnection {
11
-
12
- /**
13
- * Default time-to-live duration
14
- */
15
- static int TTL = 10000;
16
-
17
- protected InetAddress ip;
18
- protected int port;
19
-
20
- protected long lastUpdate;
21
-
22
- UDPConnection(InetAddress ip, int port) {
23
- this.ip = ip;
24
- this.port = port;
25
- lastUpdate = System.currentTimeMillis();
26
- }
27
-
28
- public boolean isAlive() {
29
- return System.currentTimeMillis() - lastUpdate < TTL;
30
- }
31
-
32
- public void update() {
33
- lastUpdate = System.currentTimeMillis();
34
- }
35
-
36
- public void send(DatagramSocket socket, byte[] data) throws IOException {
37
- DatagramPacket sendPacket = new DatagramPacket(data, data.length, ip,
38
- port);
39
- socket.send(sendPacket);
40
- }
41
-
42
- public InetAddress getIP() {
43
- return ip;
44
- }
45
-
46
- public int getPort() {
47
- return port;
48
- }
49
-
50
- public long getLastUpdate() {
51
- return lastUpdate;
52
- }
53
-
54
- @Override
55
- public String toString() {
56
- return UDPConnection.buildHash(ip, port);
57
- }
58
-
59
- static final void setTTL(int ttl) {
60
- TTL = ttl;
61
- }
62
-
63
- public static final String buildHash(InetAddress ip, int port) {
64
- return ip.getHostAddress() + ":" + port;
65
- }
66
- }
@@ -1,81 +0,0 @@
1
- package com.toxi.net;
2
-
3
- import java.io.IOException;
4
- import java.net.*;
5
- import java.util.logging.Level;
6
- import java.util.logging.Logger;
7
-
8
- class UDPSyncClient extends Thread {
9
- private ClientListener listener;
10
-
11
- protected String serverName;
12
- protected int port;
13
- protected int clientID;
14
- protected int ttl;
15
-
16
- private int frameCount;
17
- protected long lastUpdate;
18
-
19
- private static final Logger logger = Logger.getLogger(UDPSyncClient.class
20
- .getName());
21
-
22
- UDPSyncClient(String serverName, int port, int clientID, int ttl) {
23
- this.serverName = serverName;
24
- this.port = port;
25
- this.clientID = clientID;
26
- this.ttl = ttl;
27
- }
28
-
29
- @Override
30
- public void run() {
31
- DatagramSocket clientSocket = null;
32
- lastUpdate = System.currentTimeMillis();
33
- try {
34
- clientSocket = new DatagramSocket();
35
- InetAddress ip = InetAddress.getByName(serverName);
36
- byte[] sendData = new byte[] { 1 };
37
- byte[] receiveData = new byte[8];
38
- // do initial sign on by sending a message to the server
39
- DatagramPacket sendPacket = new DatagramPacket(sendData,
40
- sendData.length, ip, port);
41
- clientSocket.send(sendPacket);
42
- while (true) {
43
- DatagramPacket receivePacket = new DatagramPacket(receiveData,
44
- receiveData.length);
45
- clientSocket.receive(receivePacket);
46
- String payload = new String(receivePacket.getData(), 0,
47
- receivePacket.getLength());
48
- if (logger != null)
49
- logger.finest(payload);
50
- int newFrameCount = Integer.parseInt(payload);
51
- if (newFrameCount > 0) {
52
- while (frameCount < newFrameCount) {
53
- if (listener != null)
54
- listener.triggerUpdate();
55
- frameCount++;
56
- }
57
- }
58
- if (listener != null)
59
- listener.triggerFrame();
60
- long now = System.currentTimeMillis();
61
- if (now - lastUpdate > ttl) {
62
- sendPacket = new DatagramPacket(sendData, sendData.length,
63
- ip, port);
64
- clientSocket.send(sendPacket);
65
- lastUpdate = now;
66
- if (logger != null)
67
- logger.log(Level.FINER, "TTL updated on: {0}", lastUpdate);
68
- }
69
- }
70
- } catch (IOException | NumberFormatException ex) {
71
- logger.log(Level.SEVERE, null, ex);
72
- } finally {
73
- if (clientSocket != null)
74
- clientSocket.close();
75
- }
76
- }
77
-
78
- public void setListener(ClientListener l) {
79
- listener = l;
80
- }
81
- }
@@ -1,450 +0,0 @@
1
- package com.toxi.net;
2
-
3
- import java.io.FileInputStream;
4
- import java.io.FileNotFoundException;
5
- import java.io.IOException;
6
- import java.net.DatagramPacket;
7
- import java.net.DatagramSocket;
8
- import java.net.InetAddress;
9
- import java.net.SocketTimeoutException;
10
- import java.util.HashMap;
11
- import java.util.Iterator;
12
- import java.util.logging.ConsoleHandler;
13
- import java.util.logging.Level;
14
- import java.util.logging.Logger;
15
-
16
- import org.kohsuke.args4j.CmdLineException;
17
- import org.kohsuke.args4j.CmdLineParser;
18
- import org.kohsuke.args4j.Option;
19
-
20
- import toxi.util.datatypes.TypedProperties;
21
-
22
- /**
23
- * <p>
24
- * An <a href="http://mostpixelsever.com">MPE</a> inspired synch server for
25
- * networked multi-screen applications. All communication is realised via UDP.
26
- * Clients are not requested to acknowledge every single packet received, but
27
- * need to send a heart beat in a regular (configurable) interval. The server
28
- * discards any data received from clients, so it doesn't matter what is being
29
- * sent back. A single byte will suffice.
30
- * </p>
31
- *
32
- * <p>
33
- * The server can be configured via CLI arguments and/or Java property files and
34
- * can be connected to an existing logger. When run on from the commandline a
35
- * console logger is automatically added.
36
- * </p>
37
- *
38
- * @author Karsten Schmidt <info@postspectacular.com>
39
- */
40
- public class UDPSyncServer {
41
-
42
- private static final int DEFAULT_RECEIVE_PACKET_SIZE = 32;
43
-
44
- private static final int DEFAULT_NUM_CLIENTS = 1;
45
-
46
- private static final int DEFAULT_FRAMERATE = 30;
47
-
48
- private static final int DEFAULT_PORT = 9002;
49
-
50
- private static final int DEFAULT_RECEIVE_TIMEOUT = 1;
51
-
52
- private ServerState state;
53
-
54
- DatagramSocket socket;
55
- HashMap<String, UDPConnection> connections = new HashMap<>();
56
-
57
- /**
58
- *
59
- */
60
- @Option(name = "-port", aliases = "-p", usage = "server socket port number")
61
- protected int port = DEFAULT_PORT;
62
-
63
- @Option(name = "-config", aliases = "-c", usage = "path to configuration file", metaVar = "PATH")
64
- private String configFile;
65
- private TypedProperties config;
66
-
67
- @Option(name = "-packetsize", aliases = "-s", usage = "receive packet size")
68
- private int receivePacketSize = DEFAULT_RECEIVE_PACKET_SIZE;
69
- private byte[] receiveData;
70
-
71
- /**
72
- *
73
- */
74
- @Option(name = "-rectimeout", aliases = "-rt", usage = "receive timeout (in ms), minimum 1ms")
75
- protected int receiveTimeOut = DEFAULT_RECEIVE_TIMEOUT;
76
-
77
- /**
78
- *
79
- */
80
- @Option(name = "-ttl", usage = "client time-to-live, max. time interval after which clients expire")
81
- protected int connectionTimeOut = UDPConnection.TTL;
82
-
83
- /**
84
- *
85
- */
86
- @Option(name = "-numclients", aliases = "-num", usage = "number of clients")
87
- protected int numClients = DEFAULT_NUM_CLIENTS;
88
-
89
- /**
90
- *
91
- */
92
- @Option(name = "-framerate", aliases = "-fps", usage = "target framerate")
93
- protected int frameRate = DEFAULT_FRAMERATE;
94
-
95
- /**
96
- *
97
- */
98
- protected int frameDuration;
99
-
100
- /**
101
- *
102
- */
103
- protected int frameCount;
104
-
105
- private static Logger LOGGER;
106
-
107
- /**
108
- * Optional server event listener
109
- */
110
- protected ServerListener listener;
111
-
112
- /**
113
- *
114
- */
115
- public UDPSyncServer() {
116
- config = new TypedProperties();
117
- setMaxReceivePacketSize(DEFAULT_RECEIVE_PACKET_SIZE);
118
- }
119
-
120
- /**
121
- *
122
- * @param args
123
- */
124
- public static void main(String args[]) {
125
- new UDPSyncServer().execute(args);
126
- }
127
-
128
- /**
129
- * Main entry point for CLI.
130
- *
131
- * @param args
132
- * command line arguments
133
- */
134
- public void execute(String[] args) {
135
- CmdLineParser parser = new CmdLineParser(this);
136
- parser.setUsageWidth(80);
137
- try {
138
- parser.parseArgument(args);
139
- } catch (CmdLineException e) {
140
- System.err.println(e.getMessage());
141
- System.err.println("java UDPSyncServer [options]");
142
- parser.printUsage(System.err);
143
- System.err.println();
144
- return;
145
- }
146
-
147
- try {
148
- if (configFile != null)
149
- config.load(new FileInputStream(configFile));
150
- LOGGER = Logger.getLogger("com.postspectacular");
151
- LOGGER.addHandler(new ConsoleHandler());
152
- LOGGER.setLevel(Level.CONFIG);
153
- configure(config);
154
- run();
155
- } catch (FileNotFoundException e) {
156
- System.err.println("cannot find config file @ " + args[0]);
157
- } catch (IOException e) {
158
- System.err.println("cannot read config file @ " + args[0]);
159
- }
160
- }
161
-
162
- /**
163
- * Configures the server with settings using the passed-in properties.
164
- *
165
- * @param config
166
- */
167
- public void configure(TypedProperties config) {
168
- this.config = config;
169
- port = config.getInt("server.port", port);
170
- setMaxReceivePacketSize(config.getInt("udp.packetsize",
171
- receivePacketSize));
172
- numClients = config.getInt("server.numclients", numClients);
173
- frameRate = config.getInt("server.framerate", frameRate);
174
- frameDuration = 1000 / frameRate;
175
- connectionTimeOut = config.getInt("udp.ttl", connectionTimeOut);
176
- UDPConnection.setTTL(connectionTimeOut);
177
- receiveTimeOut = config.getInt("udp.receivetimeout", receiveTimeOut);
178
- if (LOGGER != null) {
179
- LOGGER.log(Level.INFO, "configured server... port:{0} clients:{1} fps:{2} ttl:{3} rto:{4}", new Object[]{port, numClients, frameRate, connectionTimeOut, receiveTimeOut});
180
- }
181
- setState(ServerState.WAITING_FOR_CLIENTS);
182
- }
183
-
184
- /**
185
- * Main server loop/state machine. Creates socket and handles syncing of
186
- * connected clients.
187
- */
188
- public void run() {
189
- try {
190
- socket = new DatagramSocket(port);
191
- if (LOGGER != null)
192
- LOGGER.log(Level.INFO, "creating socket @ port {0}", port);
193
- if (listener != null) {
194
- listener.serverStarted();
195
- }
196
- while (true) {
197
- switch (state) {
198
-
199
- case WAITING_FOR_CLIENTS:
200
- if (LOGGER != null)
201
- LOGGER.info("Server running, waiting for connections...");
202
- // disable timeout, i.e socket will block indefinitely
203
- // until
204
- // a packet is received
205
- socket.setSoTimeout(0);
206
- while (connections.size() < numClients) {
207
- receiveAndAddConnection();
208
- }
209
- // all connected, start syncing...
210
- setState(ServerState.SYNCHING);
211
- break;
212
-
213
- case SYNCHING:
214
- socket.setSoTimeout(receiveTimeOut);
215
- if (connections.size() > 0) {
216
- doHeartBeat();
217
- byte[] payload = getSyncPayload();
218
- Iterator<UDPConnection> iter = connections.values()
219
- .iterator();
220
- // Uses nanoTime for better precision / more stable
221
- // framerate, but unavailable on OSX!!!
222
- long beginSynch = System.nanoTime();
223
- while (iter.hasNext()) {
224
- UDPConnection conn = iter.next();
225
- if (!conn.isAlive()) {
226
- iter.remove();
227
- if (LOGGER != null)
228
- LOGGER.log(Level.WARNING, "{0} disconnected", conn);
229
- if (listener != null)
230
- listener.clientDisconnected(conn);
231
- }
232
- conn.send(socket, payload);
233
- }
234
- int returnCount = 0;
235
- while (returnCount < numClients
236
- && returnCount < connections.size() + 1) {
237
- try {
238
- DatagramPacket receivePacket = new DatagramPacket(
239
- receiveData, receiveData.length);
240
- socket.receive(receivePacket);
241
- InetAddress ip = receivePacket.getAddress();
242
- int portDP = receivePacket.getPort();
243
- String connID = UDPConnection.buildHash(ip,
244
- portDP);
245
- UDPConnection conn = connections
246
- .get(connID);
247
- if (conn != null) {
248
- conn.update();
249
- returnCount++;
250
- } else {
251
- // renewed connection
252
- conn = new UDPConnection(ip, portDP);
253
- conn.send(socket, getSyncPayload());
254
- connections.put(connID, conn);
255
- if (LOGGER != null)
256
- LOGGER.log(Level.FINE, "re-adding connection: {0}", conn);
257
- }
258
- if (listener != null)
259
- listener.clientUpdated(conn,
260
- receivePacket);
261
- } catch (SocketTimeoutException e) {
262
- // no further packets available
263
- break;
264
- }
265
- }
266
- long endSynch = System.nanoTime();
267
- long delta = (endSynch - beginSynch) / 1000000;
268
- if (delta < frameDuration) {
269
- int sleep = frameDuration - (int) delta;
270
- if (LOGGER != null)
271
- LOGGER.log(Level.FINEST, "sleeping: {0}", sleep);
272
- Thread.sleep(sleep);
273
- }
274
- } else {
275
- if (LOGGER != null)
276
- LOGGER.info("all clients disconnected");
277
- setState(ServerState.WAITING_FOR_CLIENTS);
278
- }
279
- }
280
- }
281
- } catch (IOException | InterruptedException e) {
282
- handleException(e);
283
- } finally {
284
- if (LOGGER != null)
285
- LOGGER.info("server shutting down...");
286
- if (socket != null)
287
- socket.close();
288
- }
289
- }
290
-
291
- /**
292
- * Attempts to receive data sent from clients to confirm they're still
293
- * connected. The timeout for this action is set to 1ms by default, so
294
- * currently not more than 25 machines can be reliably connected & synched
295
- * at 25fps.
296
- *
297
- * If a connection times out it's removed from the list of active clients.
298
- * On the other hand if a new connection hash is found we know a client has
299
- * reconnected and will be added back to the pool.
300
- */
301
- protected void receiveAndAddConnection() {
302
- try {
303
- DatagramPacket receivePacket = new DatagramPacket(receiveData,
304
- receiveData.length);
305
- if (LOGGER != null)
306
- LOGGER.log(Level.INFO, "waiting for {0} more clients to reconnect...", (numClients - connections.size()));
307
- socket.receive(receivePacket);
308
- InetAddress ip = receivePacket.getAddress();
309
- int portDP = receivePacket.getPort();
310
- String connID = UDPConnection.buildHash(ip, portDP);
311
- if (connections.get(connID) == null) {
312
- if (connections.isEmpty()) {
313
- frameCount = 0;
314
- if (LOGGER != null)
315
- LOGGER.info("resetting frame count");
316
- }
317
- UDPConnection conn = new UDPConnection(ip, portDP);
318
- connections.put(connID, conn);
319
- conn.send(socket, getSyncPayload());
320
- if (LOGGER != null)
321
- LOGGER.log(Level.FINE, "added new connection: {0}", conn);
322
- if (listener != null) {
323
- listener.clientConnected(conn);
324
- }
325
- }
326
- } catch (SocketTimeoutException e) {
327
- } catch (IOException e) {
328
- handleException(e);
329
- }
330
- }
331
-
332
- private void handleException(Exception e) {
333
- if (listener != null)
334
- listener.serverError(e);
335
- if (LOGGER != null)
336
- LOGGER.log(Level.SEVERE, "Server error", e);
337
- else
338
- e.printStackTrace();
339
- }
340
-
341
- /**
342
- * Updates the internal state of the heartbeat info sent out later.
343
- */
344
- protected void doHeartBeat() {
345
- frameCount++;
346
- }
347
-
348
- /**
349
- * Collects and formats payload data sent via UDP to all clients. By default
350
- * only the current frame number is sent. If more data is required you can
351
- * either overwrite this method or append data via an attached
352
- * {@link ServerListener}.
353
- *
354
- * @return payload data as byte array
355
- */
356
- protected byte[] getSyncPayload() {
357
- StringBuilder sb = new StringBuilder();
358
- sb.append(frameCount);
359
- byte[] defaultPayload = sb.toString().getBytes();
360
- if (listener != null) {
361
- byte[] userPayload = listener.getSyncPayload();
362
- if (userPayload != null) {
363
- byte[] combinedPayload = new byte[defaultPayload.length
364
- + userPayload.length];
365
- System.arraycopy(defaultPayload, 0, combinedPayload, 0,
366
- defaultPayload.length);
367
- System.arraycopy(userPayload, 0, combinedPayload,
368
- defaultPayload.length, userPayload.length);
369
- return combinedPayload;
370
- }
371
- }
372
- return defaultPayload;
373
- }
374
-
375
- /**
376
- * Triggers and logs a new server state. If present, this will also notify
377
- * the {@link ServerListener}.
378
- *
379
- * @param s
380
- * new server state
381
- */
382
- private void setState(ServerState s) {
383
- state = s;
384
- if (LOGGER != null)
385
- LOGGER.log(Level.CONFIG, "new server state: {0}", state);
386
- if (listener != null)
387
- listener.serverStateChanged(s);
388
- }
389
-
390
- /**
391
- * @return Maximum size of UDP packets the server is able to receive
392
- */
393
- public int getMaxPacketSize() {
394
- return receiveData.length;
395
- }
396
-
397
- /**
398
- * Sets the max. size of UDP packets the server is able to receive
399
- *
400
- * @param size
401
- */
402
- public final void setMaxReceivePacketSize(int size) {
403
- receivePacketSize = size;
404
- if (receiveData == null) {
405
- receiveData = new byte[size];
406
- } else if (receiveData.length != size) {
407
- synchronized (receiveData) {
408
- receiveData = new byte[size];
409
- }
410
- }
411
- }
412
-
413
- /**
414
- * @return configured number of clients the server is expecting and
415
- * initially waiting for to connect before any syncing begins.
416
- */
417
- public int getNumClients() {
418
- return numClients;
419
- }
420
-
421
- /**
422
- * Sets the number of clients the server is expecting and initially waiting
423
- * for to connect before any syncing begins.
424
- *
425
- * @param numClients
426
- */
427
- public void setNumClients(int numClients) {
428
- this.numClients = numClients;
429
- }
430
-
431
- /**
432
- * Attaches a logger to the server.
433
- *
434
- * @param logger
435
- */
436
- public void setLogger(Logger logger) {
437
- UDPSyncServer.LOGGER = logger;
438
- }
439
-
440
- /**
441
- * Attaches an event listener to the server.
442
- *
443
- * @param listener
444
- */
445
- public void setListener(ServerListener listener) {
446
- this.listener = listener;
447
- if (LOGGER != null)
448
- LOGGER.log(Level.INFO, "new server listener: {0}", listener);
449
- }
450
- }
@@ -1,121 +0,0 @@
1
- package com.toxi.nio;
2
-
3
- import java.net.*;
4
- import java.io.*;
5
- import java.nio.*;
6
- import java.nio.channels.*;
7
- import java.nio.channels.spi.SelectorProvider;
8
- import java.util.*;
9
- import java.util.logging.Level;
10
- import java.util.logging.Logger;
11
-
12
- /**
13
- *
14
- * @author tux
15
- */
16
- public class UDPClient {
17
-
18
- /**
19
- *
20
- */
21
- public final static int DEFAULT_PORT = 9876;
22
-
23
- int port = DEFAULT_PORT;
24
- SocketAddress remote;
25
- DatagramChannel channel;
26
- Selector selector;
27
- ByteBuffer buffer1;
28
- ByteBuffer buffer2;
29
-
30
- int clientID;
31
-
32
- /**
33
- *
34
- * @param clientID
35
- */
36
- public UDPClient(int clientID) {
37
- this.clientID = clientID;
38
- System.out.println("new client ID: " + clientID);
39
- try {
40
- remote = new InetSocketAddress("192.168.1.64", port);
41
- channel = DatagramChannel.open();
42
- channel.configureBlocking(false);
43
- channel.connect(remote);
44
- selector = SelectorProvider.provider().openSelector();
45
- channel.register(selector, SelectionKey.OP_READ
46
- | SelectionKey.OP_WRITE);
47
- buffer1 = ByteBuffer.allocate(4);
48
- buffer2 = ByteBuffer.allocate(4);
49
- } catch (IOException ex) {
50
- System.err.println(ex);
51
- }
52
- }
53
-
54
- /**
55
- *
56
- * @param command
57
- */
58
- public void send(int command) {
59
- try {
60
- selector.select(clientID);
61
- Set readyKeys = selector.selectedKeys();
62
- Iterator iterator = readyKeys.iterator();
63
- if (iterator.hasNext()) {
64
- SelectionKey key = (SelectionKey) iterator.next();
65
- iterator.remove();
66
- if (key.isWritable()) {
67
- buffer1.clear();
68
- buffer1.putInt(command);
69
- buffer1.flip();
70
- channel.write(buffer1);
71
- }
72
- }
73
- } catch (IOException ex) {
74
- System.err.println(ex);
75
- }
76
- }
77
-
78
- /**
79
- *
80
- * @return
81
- */
82
- public int receive() {
83
- int r = 0;
84
- try {
85
- selector.select(clientID);
86
- Set readyKeys2 = selector.selectedKeys();
87
- Iterator iterator2 = readyKeys2.iterator();
88
- if (iterator2.hasNext()) {
89
- SelectionKey key2 = (SelectionKey) iterator2.next();
90
- iterator2.remove();
91
- if (key2.isReadable()) {
92
- buffer2.clear();
93
- channel.read(buffer2);
94
- buffer2.flip();
95
- int command = buffer2.getInt();
96
- r = command;
97
- }
98
- }
99
- } catch (IOException ex) {
100
- System.err.println(ex);
101
- }
102
- return r;
103
- }
104
-
105
- /**
106
- *
107
- * @param args
108
- */
109
- public static void main(String[] args) {
110
- UDPClient client = new UDPClient(Integer.parseInt(args[0]));
111
- client.send(1);
112
- while (true) {
113
- System.out.println(client.receive());
114
- try {
115
- Thread.sleep(33);
116
- } catch (InterruptedException ex) {
117
- Logger.getLogger(UDPClient.class.getName()).log(Level.SEVERE, null, ex);
118
- }
119
- }
120
- }
121
- }
@@ -1,32 +0,0 @@
1
- package com.toxi.nio;
2
-
3
- import java.net.SocketAddress;
4
-
5
- /**
6
- *
7
- * @author tux
8
- */
9
- public class UDPClientState {
10
- SocketAddress addr;
11
- boolean isReady;
12
- long lastUpdate;
13
-
14
- /**
15
- *
16
- * @param a
17
- */
18
- public UDPClientState(SocketAddress a) {
19
- addr = a;
20
- isReady = true;
21
- lastUpdate = System.currentTimeMillis();
22
- System.out.println("new client: " + addr);
23
- }
24
-
25
- /**
26
- *
27
- * @return
28
- */
29
- public SocketAddress getAddress() {
30
- return addr;
31
- }
32
- }
@@ -1,129 +0,0 @@
1
- package com.toxi.nio;
2
-
3
- import java.net.*;
4
- import java.io.*;
5
- import java.nio.*;
6
- import java.nio.channels.*;
7
- import java.util.ArrayList;
8
- import java.util.Iterator;
9
-
10
- /**
11
- *
12
- * @author tux
13
- */
14
- public class UDPServer extends Thread {
15
-
16
- /**
17
- *
18
- */
19
- public final static int DEFAULT_PORT = 9876;
20
-
21
- /**
22
- *
23
- */
24
- public final static int MAX_PACKET_SIZE = 32;
25
-
26
- private int port;
27
- private int packetSize;
28
- private int numClients;
29
-
30
- ArrayList<UDPClientState> clients;
31
- private int frameCount = 0;
32
- private int frameDuration;
33
-
34
- /**
35
- *
36
- * @param args
37
- */
38
- public static void main(String[] args) {
39
- new UDPServer(1, 25).start();
40
- try {
41
- while (true) {
42
- Thread.sleep(1000);
43
- // System.out.println("running.");
44
- }
45
- } catch (InterruptedException e) {
46
- e.printStackTrace();
47
- }
48
- }
49
-
50
- /**
51
- *
52
- * @param numClients
53
- * @param fps
54
- */
55
- public UDPServer(int numClients, int fps) {
56
- this(DEFAULT_PORT, numClients, MAX_PACKET_SIZE, fps);
57
- }
58
-
59
- /**
60
- *
61
- * @param port
62
- * @param numClients
63
- * @param maxPacketSize
64
- * @param fps
65
- */
66
- public UDPServer(int port, int numClients, int maxPacketSize, int fps) {
67
- this.port = port;
68
- this.numClients = numClients;
69
- this.packetSize = maxPacketSize;
70
- frameDuration = 1000 / fps;
71
- clients = new ArrayList<UDPClientState>();
72
- }
73
-
74
- /**
75
- *
76
- */
77
- public void run() {
78
- DatagramChannel channel = null;
79
- DatagramSocket socket = null;
80
- ByteBuffer buffer = null;
81
- try {
82
- channel = DatagramChannel.open();
83
- socket = channel.socket();
84
- SocketAddress address = new InetSocketAddress(
85
- InetAddress.getLocalHost(), port);
86
- socket.bind(address);
87
- buffer = ByteBuffer.allocateDirect(packetSize);
88
- System.out.println("Server running: " + address);
89
- System.out.println("Heartbeat interval: " + frameDuration);
90
- System.out.println("waiting for clients...");
91
-
92
- // get the addresses-initialisation phase
93
- while (clients.size() < numClients) {
94
- clients.add(new UDPClientState(channel.receive(buffer)));
95
- buffer.flip();
96
- buffer.clear();
97
- }
98
- // server now knows the clients
99
-
100
- // MAIN LOOP-server is working for the clients
101
- while (true) {
102
- long beginSynch = System.currentTimeMillis();
103
- buffer.clear();
104
- buffer.putInt(frameCount++);
105
- buffer.flip();
106
- Iterator<UDPClientState> iter = clients.iterator();
107
- while (iter.hasNext()) {
108
- channel.send(buffer, iter.next().getAddress());
109
- }
110
- long endSynch = System.currentTimeMillis();
111
- if (endSynch - beginSynch < frameDuration) {
112
- int sleep = frameDuration - (int) (endSynch - beginSynch);
113
- // System.out.println("sleeping: " + sleep);
114
- Thread.sleep(sleep);
115
- } else {
116
- Thread.sleep(2);
117
- }
118
- }
119
- } catch (Exception ex) {
120
- System.err.println(ex);
121
- } finally {
122
- if (socket != null)
123
- socket.close();
124
- if (buffer != null)
125
- buffer = null;
126
- System.out.println("server shutdown.");
127
- }
128
- }
129
- }