package com.netthreads.network.osc.client; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelOption; import io.netty.channel.socket.DatagramPacket; import io.netty.channel.socket.nio.NioDatagramChannel; import io.netty.channel.socket.nio.NioEventLoopGroup; import java.net.InetSocketAddress; import com.google.inject.Singleton; import com.netthreads.osc.common.domain.OSCBundle; import com.netthreads.osc.common.domain.OSCEncoder; @Singleton public class OSCClientImpl implements OSCClient { private final OSCEncoder encoder; private Bootstrap bootstrap; private boolean connected; private InetSocketAddress socket; private Channel channel; /** * OSC Client. * */ public OSCClientImpl() { connected = false; encoder = new OSCEncoder(); channel = null; } /** * Connect to OSC server. * * @return True if connected. */ @Override public boolean connect(String host, int port) { // We are going to have to revisit this as I want to be able to reuse this. bootstrap = new Bootstrap(); bootstrap.group(new NioEventLoopGroup()).channel(NioDatagramChannel.class).localAddress(new InetSocketAddress(0)).option(ChannelOption.SO_BROADCAST, true).handler(new OSCClientHandler()); try { channel = bootstrap.bind().sync().channel(); socket = new InetSocketAddress(host, port); if (socket.getAddress() != null) { connected = true; } else { connected = false; } } catch (InterruptedException e) { connected = false; } return connected; } /** * Disconnect. * */ @Override public void disconnect() { if (connected) { try { if (channel != null) { channel.close().awaitUninterruptibly(); } } finally { if (bootstrap != null) { bootstrap.shutdown(); } connected = false; } } } /** * Send message. * * Note, the future listener handles re-pooling the bundle and datagram packet objects. * * @param oscBundle */ @Override public synchronized void send(OSCBundle oscBundle) { OSCBundleFutureListener oscBundleFutureListener = OSCBundleFutureListener.$(oscBundle, socket); DatagramPacket datagramPacket = oscBundleFutureListener.getDatagramPacket(); encoder.encode(oscBundle, datagramPacket.data()); ChannelFuture channelFuture = channel.write(datagramPacket); oscBundleFutureListener.setOscBundle(oscBundle); channelFuture.addListener(oscBundleFutureListener); } /** * Return connection status. * * @return connection status. */ public boolean isConnected() { return connected; } }