Class OSCReceiver

  • All Implemented Interfaces:
    Runnable, OSCChannel

    public abstract class OSCReceiver
    extends Object
    implements OSCChannel, Runnable
    An OSCReceiver manages reception of incoming OSC messages. A receiver can be either revivable or non-revivable.
    • A non-revivable receiver is bound to one particular network channel (DatagramChannel (for UDP) or SocketChannel (for TCP)). When the channel is closed, the receiver cannot be restarted. The network channel is closed for example when a TCP server shuts down, but also when trying to connect to a TCP server that is not yet reachable.
    • It is therefore recommended to use revivable receivers. A revivable receiver is created through one of the newUsing constructors that takes a protocol and address argument. A revivable receiver can be restarted because it recreates the network channel if necessary.

    The receiver launches a listening Thread when startListening is called.

    The OSCReceiver has methods for registering and unregistering listeners that get informed about incoming messages. Filtering out specific messages must be done by the listeners.

    The listening thread is stopped using stopListening method.

    Note that as of v0.3, you will most likely want to use preferably one of OSCClient or OSCServer over OSCReceiver. Also note that as of v0.3, OSCReceiver is abstract, which renders direct instantiation impossible. To update old code, occurrences of new OSCReceiver() must be replaced by one of the OSCReceiver.newUsing methods! The "filter" functionality of NetUtil 0.2 is now implied by calling setTarget( SocketAddress ).

    Here is an example that also demonstrates message sending using an instance of OSCTransmitter:

          OSCReceiver     rcv     = null;
          OSCTransmitter  trns;
          DatagramChannel dch     = null;
    
          try {
              final SocketAddress addr    = new InetSocketAddress( InetAddress.getLocalHost(), 57110 );
              final Object notify         = new Object();
              
              // note: using constructors with SelectableChannel implies the receivers and
              // transmitters cannot be revived. to create revivable channels on the same socket,
              // you must use one of the newUsing methods that take an IP address and/or port
              // number.
              dch     = DatagramChannel.open();
              dch.socket().bind( null );    // assigns an automatic local socket address
              rcv     = OSCReceiver.newUsing( dch );
              trns    = OSCTransmitter.newUsing( dch );
    
              rcv.addOSCListener( new OSCListener() {
                  public void messageReceived( OSCMessage msg, SocketAddress sender, long time )
                  {
                      if( msg.getName().equals( "status.reply" )) {
                          System.out.println( "scsynth is running. contains " +
                              msg.getArg( 1 ) + " unit generators, " +
                              msg.getArg( 2 ) + " synths, " +
                              msg.getArg( 3 ) + " groups, " +
                              msg.getArg( 4 ) + " synth defs.\n" +
                              "CPU load is " + msg.getArg( 5 ) + "% (average) / " +
                              msg.getArg( 6 ) + "% (peak)" );
                          synchronized( notify ) {
                              notify.notifyAll();
                          }
                      }
                  }
              });
              rcv.startListening();
              trns.send( new OSCMessage( "/status", OSCMessage.NO_ARGS ), addr );
    
              synchronized( notify ) {
                  notify.wait( 5000 );
              }
          }
          catch( InterruptedException e1 ) {}
          catch( IOException e2 ) {
              System.err.println( e2.getLocalizedMessage() );
          }
          finally {
              if( rcv != null ) {
                  rcv.dispose();
              } else if( dch != null ) {
                  try {
                      dch.close();
                  }
                  catch( IOException e4 ) {};
              }
          }
            
    Note that the datagram channel needs to be bound to a valid reachable address, because stopListening will be sending a terminating message to this channel. You can bind the channel using dch.socket().bind(), as shown in the example above.

    Note that someone has reported trouble with the InetAddress.getLocalHost() method on a machine that has no proper IP configuration or DNS problems. In such a case when you need to communicate only on this machine and not a network, use the loopback address "127.0.0.1" as the filtering address or bind the socket to the loop address manually before calling new OSCReceiver().

    Version:
    0.37, 12-May-09
    Author:
    Hanns Holger Rutz
    See Also:
    OSCClient, OSCServer, OSCTransmitter
    • Field Detail

      • thread

        protected Thread thread
      • generalSync

        protected final Object generalSync
      • threadSync

        protected final Object threadSync
      • isListening

        protected boolean isListening
      • allocBuf

        protected boolean allocBuf
      • revivable

        protected final boolean revivable
    • Method Detail

      • newUsing

        public static OSCReceiver newUsing​(String protocol)
                                    throws IOException
        Creates a new instance of a revivable OSCReceiver, using default codec and a specific transport protocol. It picks an arbitrary free port and uses the local machine's IP. To determine the resulting port, you can use getLocalAddress afterwards.

        TCP receivers are required to be connected to one particular target, so setTarget is must be called prior to connect or startListening!

        Parameters:
        protocol - the protocol to use, currently either UDP or TCP
        Returns:
        the newly created receiver
        Throws:
        IOException - if a networking error occurs while creating the socket
        IllegalArgumentException - if an illegal protocol is used
        See Also:
        OSCChannel.UDP, OSCChannel.TCP, getLocalAddress()
      • newUsing

        public static OSCReceiver newUsing​(OSCPacketCodec c,
                                           String protocol)
                                    throws IOException
        Creates a new instance of a revivable OSCReceiver, using a specific codec and transport protocol. It picks an arbitrary free port and uses the local machine's IP. To determine the resulting port, you can use getLocalAddress afterwards.

        TCP receivers are required to be connected to one particular target, so setTarget is must be called prior to connect or startListening!

        Parameters:
        c - the codec to use
        protocol - the protocol to use, currently either UDP or TCP
        Returns:
        the newly created receiver
        Throws:
        IOException - if a networking error occurs while creating the socket
        IllegalArgumentException - if an illegal protocol is used
        Since:
        NetUtil 0.33
        See Also:
        OSCChannel.UDP, OSCChannel.TCP, getLocalAddress()
      • newUsing

        public static OSCReceiver newUsing​(String protocol,
                                           int port)
                                    throws IOException
        Creates a new instance of a revivable OSCReceiver, using default codec and a specific transport protocol and port. It uses the local machine's IP. Note that the port specifies the local socket (at which the receiver listens), it does not determine the remote sockets from which messages can be received. If you want to filter out a particular remote (or target) socket, this can be done using the setTarget method!

        TCP receivers are required to be connected to one particular target, so setTarget is must be called prior to connect or startListening!

        Parameters:
        protocol - the protocol to use, currently either UDP or TCP
        port - the port number for the OSC socket, or 0 to use an arbitrary free port
        Returns:
        the newly created receiver
        Throws:
        IOException - if a networking error occurs while creating the socket
        IllegalArgumentException - if an illegal protocol is used
      • newUsing

        public static OSCReceiver newUsing​(OSCPacketCodec c,
                                           String protocol,
                                           int port)
                                    throws IOException
        Creates a new instance of a revivable OSCReceiver, using a specific codec and transport protocol and port. It uses the local machine's IP. Note that the port specifies the local socket (at which the receiver listens), it does not determine the remote sockets from which messages can be received. If you want to filter out a particular remote (or target) socket, this can be done using the setTarget method!

        TCP receivers are required to be connected to one particular target, so setTarget is must be called prior to connect or startListening!

        Parameters:
        c - the codec to use
        protocol - the protocol to use, currently either UDP or TCP
        port - the port number for the OSC socket, or 0 to use an arbitrary free port
        Returns:
        the newly created receiver
        Throws:
        IOException - if a networking error occurs while creating the socket
        IllegalArgumentException - if an illegal protocol is used
        Since:
        NetUtil 0.33
      • newUsing

        public static OSCReceiver newUsing​(String protocol,
                                           int port,
                                           boolean loopBack)
                                    throws IOException
        Creates a new instance of a revivable OSCReceiver, using default codec and a specific transport protocol and port. It uses the local machine's IP or the "loopback" address. Note that the port specifies the local socket (at which the receiver listens), it does not determine the remote sockets from which messages can be received. If you want to filter out a particular remote (or target) socket, this can be done using the setTarget method!

        TCP receivers are required to be connected to one particular target, so setTarget is must be called prior to connect or startListening!

        Parameters:
        protocol - the protocol to use, currently either UDP or TCP
        port - the port number for the OSC socket, or 0 to use an arbitrary free port
        loopBack - if true, the "loopback" address ("127.0.0.1") is used which limits communication to the local machine. If false, the special IP "0.0.0.0" is used which means messages from any IP as well as from the loopback are accepted
        Returns:
        the newly created receiver
        Throws:
        IOException - if a networking error occurs while creating the socket
        IllegalArgumentException - if an illegal protocol is used
      • newUsing

        public static OSCReceiver newUsing​(OSCPacketCodec c,
                                           String protocol,
                                           int port,
                                           boolean loopBack)
                                    throws IOException
        Creates a new instance of a revivable OSCReceiver, using a specific codec and transport protocol and port. It uses the local machine's IP or the "loopback" address. Note that the port specifies the local socket (at which the receiver listens), it does not determine the remote sockets from which messages can be received. If you want to filter out a particular remote (or target) socket, this can be done using the setTarget method!

        TCP receivers are required to be connected to one particular target, so setTarget is must be called prior to connect or startListening!

        Parameters:
        c - the codec to use
        protocol - the protocol to use, currently either UDP or TCP
        port - the port number for the OSC socket, or 0 to use an arbitrary free port
        loopBack - if true, the "loopback" address ("127.0.0.1") is used which limits communication to the local machine. If false, the special IP "0.0.0.0" is used which means messages from any IP as well as from the loopback are accepted
        Returns:
        the newly created receiver
        Throws:
        IOException - if a networking error occurs while creating the socket
        IllegalArgumentException - if an illegal protocol is used
        Since:
        NetUtil 0.33
      • newUsing

        public static OSCReceiver newUsing​(String protocol,
                                           InetSocketAddress localAddress)
                                    throws IOException
        Creates a new instance of a revivable OSCReceiver, using default codec and a specific transport protocol and local socket address. Note that localAdress specifies the local socket (at which the receiver listens), it does not determine the remote sockets from which messages can be received. If you want to filter out a particular remote (or target) socket, this can be done using the setTarget method!

        TCP receivers are required to be connected to one particular target, so setTarget is must be called prior to connect or startListening!

        Parameters:
        protocol - the protocol to use, currently either UDP or TCP
        localAddress - a valid address to use for the OSC socket. If the port is 0, an arbitrary free port is picked when the receiver is started. (you can find out the actual port in this case by calling getLocalAddress() after the receiver was started).
        Returns:
        the newly created receiver
        Throws:
        IOException - if a networking error occurs while creating the socket
        IllegalArgumentException - if an illegal protocol is used
      • newUsing

        public static OSCReceiver newUsing​(OSCPacketCodec c,
                                           String protocol,
                                           InetSocketAddress localAddress)
                                    throws IOException
        Creates a new instance of a revivable OSCReceiver, using a specific codec and transport protocol and local socket address. Note that the port specifies the local socket (at which the receiver listens), it does not determine the remote sockets from which messages can be received. If you want to filter out a particular remote (or target) socket, this can be done using the setTarget method!

        TCP receivers are required to be connected to one particular target, so setTarget is must be called prior to connect or startListening!

        Parameters:
        c - the codec to use
        protocol - the protocol to use, currently either UDP or TCP
        localAddress - a valid address to use for the OSC socket. If the port is 0, an arbitrary free port is picked when the receiver is started. (you can find out the actual port in this case by calling getLocalAddress() after the receiver was started).
        Returns:
        the newly created receiver
        Throws:
        IOException - if a networking error occurs while creating the socket
        IllegalArgumentException - if an illegal protocol is used
        Since:
        NetUtil 0.33
      • newUsing

        public static OSCReceiver newUsing​(DatagramChannel dch)
                                    throws IOException
        Creates a new instance of a non-revivable OSCReceiver, using default codec and UDP transport on a given channel. The caller should ensure that the provided channel's socket was bound to a valid address (using dch.socket().bind( SocketAddress )). Note that dch specifies the local socket (at which the receiver listens), it does not determine the remote sockets from which messages can be received. If you want to filter out a particular remote (or target) socket, this can be done using the setTarget method!
        Parameters:
        dch - the DatagramChannel to use as UDP socket.
        Returns:
        the newly created receiver
        Throws:
        IOException - if a networking error occurs while configuring the socket
      • newUsing

        public static OSCReceiver newUsing​(OSCPacketCodec c,
                                           DatagramChannel dch)
                                    throws IOException
        Creates a new instance of a non-revivable OSCReceiver, using a specific codec and UDP transport on a given channel. The caller should ensure that the provided channel's socket was bound to a valid address (using dch.socket().bind( SocketAddress )). Note that dch specifies the local socket (at which the receiver listens), it does not determine the remote sockets from which messages can be received. If you want to filter out a particular remote (or target) socket, this can be done using the setTarget method!
        Parameters:
        c - the codec to use
        dch - the DatagramChannel to use as UDP socket.
        Returns:
        the newly created receiver
        Throws:
        IOException - if a networking error occurs while configuring the socket
        Since:
        NetUtil 0.33
      • newUsing

        public static OSCReceiver newUsing​(SocketChannel sch)
                                    throws IOException
        Creates a new instance of a non-revivable OSCReceiver, using default codec and TCP transport on a given channel. The caller should ensure that the provided channel's socket was bound to a valid address (using sch.socket().bind( SocketAddress )). Furthermore, the channel must be connected (using connect()) before being able to receive messages. Note that sch specifies the local socket (at which the receiver listens), it does not determine the remote sockets from which messages can be received. The remote (or target) socket must be explicitly specified using setTarget before trying to connect!
        Parameters:
        sch - the SocketChannel to use as TCP socket.
        Returns:
        the newly created receiver
        Throws:
        IOException - if a networking error occurs while configuring the socket
      • newUsing

        public static OSCReceiver newUsing​(OSCPacketCodec c,
                                           SocketChannel sch)
                                    throws IOException
        Creates a new instance of a non-revivable OSCReceiver, using a specific codec and TCP transport on a given channel. The caller should ensure that the provided channel's socket was bound to a valid address (using sch.socket().bind( SocketAddress )). Furthermore, the channel must be connected (using connect()) before being able to receive messages. Note that sch specifies the local socket (at which the receiver listens), it does not determine the remote sockets from which messages can be received. The remote (or target) socket must be explicitly specified using setTarget before trying to connect!
        Parameters:
        c - the codec to use
        sch - the SocketChannel to use as TCP socket.
        Returns:
        the newly created receiver
        Throws:
        IOException - if a networking error occurs while configuring the socket
        Since:
        NetUtil 0.33
      • getLocalAddress

        public abstract InetSocketAddress getLocalAddress()
                                                   throws IOException
        Queries the receiver's local socket address. You can determine the host and port from the returned address by calling getHostName() (or for the IP getAddress().getHostAddress()) and getPort(). This port number may be 0 if the receiver was called with an unspecified port and has not yet been started. In this case, to determine the port actually used, call this method after the receiver has been started.

        Note that if the receiver is bound to the accept-any IP "0.0.0.0", which happens for example when calling newUsing( <protocol>, 0, false ), the returned IP will be the localhost's IP, so you can patch the result directly into any setTarget call.

        Specified by:
        getLocalAddress in interface OSCChannel
        Returns:
        the address of the receiver's local socket.
        Throws:
        IOException - if the local host could not be resolved
        See Also:
        InetSocketAddress.getHostName(), InetSocketAddress.getAddress(), InetSocketAddress.getPort()
      • setTarget

        public abstract void setTarget​(SocketAddress target)
      • setCodec

        public void setCodec​(OSCPacketCodec c)
        Description copied from interface: OSCChannel
        Specifies which codec is used in packet coding and decoding.
        Specified by:
        setCodec in interface OSCChannel
        Parameters:
        c - the codec to use
      • addOSCListener

        public void addOSCListener​(OSCListener listener)
        Registers a listener that gets informed about incoming messages. You can call this both when listening was started and stopped.
        Parameters:
        listener - the listener to register
      • removeOSCListener

        public void removeOSCListener​(OSCListener listener)
        Unregisters a listener that gets informed about incoming messages
        Parameters:
        listener - the listener to remove from the list of notified objects.
      • startListening

        public void startListening()
                            throws IOException
        Starts to wait for incoming messages. See the class constructor description to learn how connected and unconnected channels are handled. You should never modify the the channel's setup between the constructor and calling startListening. This method will check the connection status of the channel, using isConnected and establish the connection if necessary. Therefore, calling connect prior to startListening is not necessary.

        To find out at which port we are listening, call getLocalAddress().getPort().

        If the OSCReceiver is already listening, this method does nothing.

        Throws:
        IOException - when an error occurs while establishing the channel connection. In that case, no thread has been started and hence stopListening() needn't be called
        IllegalStateException - when trying to call this method from within the OSC receiver thread (which would obviously cause a loop)
      • isListening

        public boolean isListening()
        Queries whether the OSCReceiver is listening or not.
      • stopListening

        public void stopListening()
                           throws IOException
        Stops waiting for incoming messages. This method returns when the receiving thread has terminated. To prevent deadlocks, this method cancels after five seconds, calling close() on the datagram channel, which causes the listening thread to die because of a channel-closing exception.
        Throws:
        IOException - if an error occurs while shutting down
        IllegalStateException - when trying to call this method from within the OSC receiver thread (which would obviously cause a loop)
      • setBufferSize

        public void setBufferSize​(int size)
        Description copied from interface: OSCChannel
        Adjusts the buffer size for OSC messages. This is the maximum size an OSC packet (bundle or message) can grow to.
        Specified by:
        setBufferSize in interface OSCChannel
        Parameters:
        size - the new size in bytes.
        See Also:
        OSCChannel.getBufferSize()
      • getBufferSize

        public int getBufferSize()
        Description copied from interface: OSCChannel
        Queries the buffer size used for coding or decoding OSC messages. This is the maximum size an OSC packet (bundle or message) can grow to.
        Specified by:
        getBufferSize in interface OSCChannel
        Returns:
        the buffer size in bytes.
        See Also:
        OSCChannel.setBufferSize( int )
      • dumpOSC

        public void dumpOSC​(int mode,
                            PrintStream stream)
        Description copied from interface: OSCChannel
        Changes the way processed OSC messages are printed to the standard err console. By default messages are not printed.
        Specified by:
        dumpOSC in interface OSCChannel
        Parameters:
        mode - one of kDumpOff (don't dump, default), kDumpText (dump human readable string), kDumpHex (hexdump), or kDumpBoth (both text and hex)
        stream - the stream to print on, or null which is shorthand for System.err
        See Also:
        OSCChannel.kDumpOff, OSCChannel.kDumpText, OSCChannel.kDumpHex, OSCChannel.kDumpBoth
      • dispose

        public void dispose()
        Description copied from interface: OSCChannel
        Disposes the resources associated with the OSC communicator. The object should not be used any more after calling this method.
        Specified by:
        dispose in interface OSCChannel
      • debugTimeString

        protected static String debugTimeString()
      • checkBuffer

        protected void checkBuffer()
      • connect

        public abstract void connect()
                              throws IOException
        Establishes connection for transports requiring connectivity (e.g. TCP). For transports that do not require connectivity (e.g. UDP), this ensures the communication channel is created and bound.

        Having a connected channel without actually listening to incoming messages is usually not making sense. You can call startListening without explicit prior call to connect, because startListening will establish the connection if necessary.

        When a UDP transmitter is created without an explicit DatagramChannel – say by calling OSCReceiver.newUsing( "udp" ), calling connect() will actually create and bind a DatagramChannel. For a UDP receiver which was created with an explicit DatagramChannel. However, for TCP receivers, this may throw an IOException if the receiver was already connected, therefore be sure to check isConnected() before.

        Throws:
        IOException - if a networking error occurs. Possible reasons: - the underlying network channel had been closed by the server. - the transport is TCP and the server is not available.
        IOException
        See Also:
        isConnected(), startListening()
      • isConnected

        public abstract boolean isConnected()
        Queries the connection state of the receiver.
        Returns:
        true if the receiver is connected, false otherwise. For transports that do not use connectivity (e.g. UDP) this returns false, if the underlying DatagramChannel has not yet been created.
        See Also:
        connect()