Package XOO_CODE

Source Code of XOO_CODE.SMClientThread

// copyright (c) 1997,1998 stephen f. white
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; see the file COPYING.  If not, write to
// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.

package XOO_CODE;
import java.io.*;
import java.net.*;
import java.util.*;
import rtpi.*;
import rtpi.util.*;
import rtpi.demoRtpi.*;
import rtpi.Message;
import vrml.*;
import vrml.external.*;
import vrml.external.field.*;
import vrml.external.FreeWRLEAI.*;
import vrml.external.FreeWRLEAI.VField;


public class SMClientThread extends Thread implements
    ProximityThreadObserver, RtpiRecipient
{
    // Base reliability transmission delay (in milliseconds)
    static long delay = 10000;

    // Toggle used to indicate whether this client is connected
    boolean    connected;

    // Reference to class which receives messages from the SMClientThread
    SMClientThreadObserver  observer;

    // Multicast Network stuff.
    Rtpi rtpi;
    MulticastSocket  iosocket;
    DatagramSocket  diosocket;

    // RTPI participant ID
    int  participantID;
    long subIDBase;

    // RTPI components
    long subcomponentNumber = 0;
    SyncQueue messages = new SyncQueue();
    Hashtable subcomponents = new Hashtable();
    Hashtable timers = new Hashtable();

    // Proximity Calculations
    ProximityThread  proximitythread;

    // link into the audio controller of RAT.
    DatagramSocket  RAT_out_socket;
    DatagramSocket  RAT_in_socket;
    int      RAT_port = 3333;
    InetAddress    localaddr;

    // Send RAT the following; it'll need them for
    // communicating to other participants!
    String    auaddress;
    int      auport;
    int      auttl;


    // RTPI variables: avatar subID, byte mask used to calculate RTP/I IDs
    private static final int BYTE_MASK = 0x000000FF;

    // Constructor for non-eye machines
    SMClientThread(SMClientThreadObserver observer, Rtpi rtpi,
  String auaddress, int auport, int auttl, int participantID) {
  this.observer = observer;
  this.rtpi = rtpi;
  this.auaddress = auaddress;
  this.auport = auport;
  this.auttl = auttl;
  this.participantID = participantID;
 
        // Set this class as the recipient for RTP/I packets
  rtpi.setRtpiRecipient(this);

  // Discover local host
        try {
          localaddr = InetAddress.getLocalHost();
        } catch (UnknownHostException e) {
          System.out.println ("SMClientThread - can't get local host!");
        }

  // Create base subcomponent ID
  byte[] baseBytes = localaddr.getAddress();
  //System.out.println("bytes: " + baseBytes);
  //System.out.println("3: " + baseBytes[3] + " 2: " + baseBytes[2] + " 1: " + baseBytes[1] + " 0: " + baseBytes[0]);
  subIDBase = (baseBytes[3] & BYTE_MASK) | ((baseBytes[2]&BYTE_MASK) << 8) | ((baseBytes[1]&BYTE_MASK) << 16) | ((baseBytes[0]&BYTE_MASK) <<  24);
  subIDBase = subIDBase & 0xFFFFFFFFl;
  subIDBase = subIDBase - 1000000000;
  //System.out.println("subIDBase: " + subIDBase);
    }

    // Set connected to false
    public void closeNet() {
      // stop this thing....
      connected = false;
    }

    // Main loop of this class
    public void run() {

  // Connecting to RAT UDP socket
  // Isabelle's code but in  UDP ipv4
  try {
           RAT_out_socket = new DatagramSocket();
           RAT_in_socket = new DatagramSocket(RAT_port+1);
  } catch (IOException e) {
           System.err.println("Failed connecting to RAT");
  }

  // Send to RAT the address/port/ttl needed.
  // Rat will return to us the SSRC that it is using;
  // we can use that SSRC as our own, or keep it for
  // sending out packets showing others what tools
  // we are using.

  try
    String init_code = auaddress + " " + auport + " " + auttl;
    int strlen = init_code.length();
          byte buf[] = new byte[strlen];
          buf = init_code.getBytes();
    RAT_out_socket.send(new DatagramPacket(buf,buf.length, localaddr,RAT_port));
    System.out.println("sent init code");
  } catch (IOException e) {
         System.err.println("Failed sending initial settings to RAT");
  }

  // wait for the ssrc ...
  try {
    byte[] buf = new byte[100];
    DatagramPacket recv = new DatagramPacket(buf, buf.length);
    System.out.println("about to ask for packet from rat");
    RAT_in_socket.receive(recv);
    String received = new String(recv.getData(), 0).trim();
    //String received = new String("12345");
    observer.setSSRC(received);
    System.out.println("participantID is: " + participantID);
    System.out.println("ssrc recieved is: " + received);
    Subcomponent comp = this.getSubcomponent(participantID);
    while (comp == null) {
      Thread.sleep(10);
      comp = this.getSubcomponent(participantID);
    }
       
    send(participantID, VIP.SSRC, new VSFString(received));
    System.out.println("after send");
  } catch (Exception e) {
    System.out.println(e + " Unable to get SSRC from RAT");
  }   

  // Start the Proximity calculations
  proximitythread = new ProximityThread (this,RAT_out_socket,RAT_port);
  proximitythread.start();

        connected = true;

  // RTP/I Application Message
  ApplicationMessage message = null;

  // While this computer is still connected using XOO process all incoming Application Messages
  while (connected)
  {
    System.out.println("In LOOP");
    // Get the next application message
    try {
      message = (ApplicationMessage)messages.get();
      System.out.println("Got Message " + message.opCode);
    }
    catch (Exception e) {
      System.out.println(e + " Could not get next message");
      System.exit(0);
    }
   
    // Determine which type of message has been received
    switch (message.opCode) {
   
    // An event packet has been received
    case ApplicationMessage.RECEIVE_EVENT:
    {
      ApplicationMessageArgs args = (ApplicationMessageArgs)message.args;
      execReceiveEvent(args.rtpi, (RtpiEvent)args.data);
      break;
   
   
    // A state update packet has been received
    case ApplicationMessage.RECEIVE_STATE:
    {
      ApplicationMessageArgs args = (ApplicationMessageArgs)message.args;
      execReceiveState(args.rtpi, (RtpiState)args.data);
      break;
    }

    // A delta state update packet has been received
    case ApplicationMessage.RECEIVE_DELTA_STATE:
    {
      ApplicationMessageArgs args = (ApplicationMessageArgs)message.args;
      execReceiveDeltaState(args.rtpi, (RtpiDeltaState)args.data);
      break;
    }

    // A state query packet has been received
    case ApplicationMessage.RECEIVE_STATE_QUERY:
    {
      ApplicationMessageArgs args = (ApplicationMessageArgs)message.args;
      execReceiveStateQuery(args.rtpi, (RtpiStateQuery)args.data);
      break;
    }
      }

      try {
        this.sleep(1);
      }
      catch (Exception e) {
    System.out.println(e + " Thread interrupted");
            }
  }

  // When the loop is exited we are disconnected
  observer.onNetDisconnect();
    }

    // Send state information to RTP/I
    public void send(long id, short field, VField value)
    {
  //System.out.println("In send, id: " + id + " field " + field + " value " + value);
  // We can only send information if we are connected
        if (connected) {
    RtpiDeltaState state = null;

    // Get the subcomponent information for the requested subID
    Subcomponent comp = this.getSubcomponent(id);

    // Store current state information in subcomponent
    if (field == VIP.POSITION)
      comp.setTranslation((VSFVec3f) value);
    if (field == VIP.ORIENTATION)
      comp.setRotation((VSFRotation) value);

    // Create a new RTP/I state for this subcomponent
    try {
      state = new RtpiDeltaState((int) participantID, (long) id, (int)comp.getNextStateSequenceNumber(), 10, 3, System.currentTimeMillis(), rtpi.getCombinedHeaderSize());
    }
    catch (Exception e) {
      System.out.println(e + " Could not create rtpi state for transmission");
      return;
    }
 
    // Write field type information (rotation or transformation), and data to state
    try {
      OutputStream os = state.getOutputStream();
      DataOutputStream dos = new DataOutputStream(os);
      dos.writeShort(field);
      value.write(dos);
    }
    catch (Exception e) {
      System.out.println(e + " Unable to print to packet");
      return;
    }
    state.outputComplete();

    // Transmit state using RTP/I
    rtpi.transmitDeltaState(state);
  }
    }

    public void sendEvent(long id, int field, VField value)
    {
  if (connected) {
    RtpiEvent event = null;

    Subcomponent comp = this.getSubcomponent(id);

    // If this event is a gesture then set the appropriate gesture flag
    if (field > VIP.NUM_FIELDS)
    {
      if (((VSFBool)value).getValue())
        comp.setGestureState((field - VIP.NUM_FIELDS), (short)1);
      else
        comp.setGestureState((field-VIP.NUM_FIELDS), (short)0);
    }
   
    try {
      event = new RtpiEvent((int) participantID, (long) id, (int) comp.getNextEventSequenceNumber(), 10, System.currentTimeMillis(), rtpi.getCombinedHeaderSize());
    } catch (Exception e) {
      System.err.println(e + " unable to create Rtpi Event");
      System.exit(0);
    }
    try {
      OutputStream os = event.getOutputStream();
      DataOutputStream dos = new DataOutputStream(os);
      dos.writeInt(field);
      value.write(dos);
    }
    catch (Exception e) {
      System.out.println("sendEvent");
      System.out.println(e + " Unable to print to packet");
      System.exit(0);
    }
    event.outputComplete();

    rtpi.transmitEvent(event);
  }
    }

    // An error has occurred, diconnect from XOO 
    public void onError(Exception e)
    {
        System.err.println(e + ", disconnecting");
        connected = false;
    }

    //Proximity calculation method.
    public String calculateProximity() {
      String names = observer.audioProximityDetect();
      return names;
    }

   // Create a new RTP/I subcomponent
   Subcomponent createSubcomponent(String avatar, String uname)
   {
  // New subID for subcomponent
  long id = subIDBase + (subcomponentNumber++);

  // Construct a new subcomponent object
  Subcomponent comp = new Subcomponent(this, "", id, participantID);

  // Set the fields for the subcomponent
  comp.setAvatar(avatar);
  comp.setUsername(uname);
  comp.setStateReceived();
  comp.setRotation(new VSFRotation((float) 0.0, (float) 0.0, (float) 0.0, (float) 0.0));
  comp.setTranslation(new VSFVec3f((float) 0.0, (float) 0.0, (float) 0.0));

  // Add this subcomponent to the hash table
  subcomponents.put(new Long(id), comp);

  // Start a timer thread for this subcomponent
  Timer timer = new Timer(true);
  timer.schedule(new XOOTimer(id, this, timer), delay);
  timers.put(new Long(id), timer);

  // Add this subcomponent to those monitored by RTP/I
  try {
    rtpi.addSubcomponent(id, null, true, false);
  }
  catch (Exception e) {
    System.out.println(e + " Unable to add subcomponent to RTP/I");
    System.exit(0);
  }

  // If this is not an eye computer then transmit an XOO  ADD_OBJECT packet
  sendState(id);
  return comp;
   }

    // Get the subcomponent information for the passed subID from the subcomponent hash table
    Subcomponent getSubcomponent(long id) {
  return (Subcomponent)subcomponents.get(new Long(id));
    }

    public String getSSRC(long id) {
  return observer.getSSRC(id);
    }

    // Make the subcomponent with the passed subID active
    public void activateSubcomponent(Rtpi urtpi, long id)
    {
  rtpi.activateSubcomponent(id);
    }

    // Add the subcomponent with the passed ID to the
    public void addSubcomponent(Rtpi rtpi, long id, boolean active, byte[] name)
    {
  RtpiStateQuery query = null;
 
  try {
    query = new RtpiStateQuery(participantID, id, 0, 0, 0, 0, rtpi.getCombinedHeaderSize());
   } catch (Exception e) {
    System.out.println("Unable to create new state query");
  }
  rtpi.transmitStateQuery(query);
    }

    // Change the source information for a participant
    public void changeSourceInfo(Rtpi rtpi, RtpiSourceInfo participant)
    {
  // We don't need to keep track of participant info at the moment, as we don't use this information.
    }

    // Exit this class
    public void connectionClosed(Rtpi rtpi)
    {
  System.exit(0);
    }

    // Set a subcomponent to be passive
    public void deactivateSubcomponent(Rtpi urtpi, long id)
    {
  rtpi.deactivateSubcomponent(id);
    }

    // A delta state has been received by RTP/I, add it to the queue of messages to be processed
    public void receiveDeltaState(Rtpi rtpi, RtpiDeltaState deltaState)
    {
  messages.put(new ApplicationMessage(ApplicationMessage.RECEIVE_DELTA_STATE, new ApplicationMessageArgs(rtpi, deltaState)));
    }

    // An event has been received by RTP/I, add it to the queue of messages to be processed
    public void receiveEvent(Rtpi rtpi, RtpiEvent event)
    {
  messages.put(new ApplicationMessage(ApplicationMessage.RECEIVE_EVENT, new ApplicationMessageArgs(rtpi, event)));
    }

    // A state has been received by RTP/I, add it to the queue of messages to be processed
    public void receiveState(Rtpi rtpi, RtpiState state)
    {
  messages.put(new ApplicationMessage(ApplicationMessage.RECEIVE_STATE, new ApplicationMessageArgs(rtpi, state)));
    }

    // A state query has been received by RTP/I, add it to the queue of messages to be processed
    public void receiveStateQuery(Rtpi rtpi, RtpiStateQuery stateQuery)
    {
   messages.put(new ApplicationMessage(ApplicationMessage.RECEIVE_STATE_QUERY, new ApplicationMessageArgs(rtpi, stateQuery)));
    }

    // A remove source message has been received by RTP/I
    public void removeSource(Rtpi rtpi, RtpiSourceInfo participant)
    {
   // We don't keep track of participant info at the moment.
    }

    // A remove subcomponent message has been received by RTP/I, add it to the queue of messages to be processed
    public void removeSubcomponent(Rtpi rtpi, long subcomponentID)
    {
   observer.removeSubcomponent(subcomponentID);
    }

    // A RTP/I ADU lost message has been received by RTP/I
    public void rtpiAduLost(Rtpi rtpi, int participantID, long subID, int type, int sequenceNumber, int timeStamp)
    {
    }

    // A RTP/I could not recover ADU message has been received by RTP/I
    public void rtpiCouldNotRecover(Rtpi rtpi, int participantID, long subID, int type, int sequenceNumber, int timestamp)
    {
    }

    // Process a received RTP/I state
    private void execReceiveState(Rtpi r, RtpiState state)
    {
  // Get the subcomponent ID associated with the received state
  long id = state.getSubcomponentID();

  // Get the subcomponent associated with the received state
  Subcomponent comp = getSubcomponent(id);

  // If the subcomponent is null this is a new subcomponent.  Create a new subcomponent and add it to the subcomponents
  // monitored by RTP/I and to the subcomponent hash table.
  if (comp == null) {
    comp = new Subcomponent(this, "", id, state.getParticipantID());
    subcomponents.put(new Long(id), comp);
    try {
      rtpi.addSubcomponent(id, null, false, true);
    }
    catch (Exception e) {
      System.out.println(e + " Unable to add subcomponent to rtpi");
    }
  }
 
  // Pass the state information to the observer thread so that it may update the VRML scene graph
  observer.onStateReceived(state);
    }

    // Process a received RTP/I event
    private void execReceiveEvent(Rtpi r, RtpiEvent event)
    {
  // Get the subcomponent ID associated with the received event
  long id = event.getSubcomponentID();

  // Get the subcomponent associated with the received event
  Subcomponent comp = getSubcomponent(id);

  // Check if this subcomponent exists
  if (comp == null) {
    System.out.println("Event received for null subcomponent");
    return;
  }
  else {
    observer.onEventReceived(event);
  }

    }

    // Process a received RTP/I delta state
    private void execReceiveDeltaState(Rtpi r, RtpiDeltaState state)
    {
  // Get the subcomponent ID associated with the received delta state
  long id = state.getSubcomponentID();

  // Get the subcomponent associated with the received delta state
  Subcomponent comp = getSubcomponent(id);

  // If the subcomponent is null this is a new subcomponent.  Create a new subcomponent and add it to the subcomponents
  // monitored by RTP/I and to the subcomponent hash table.
  if (comp == null) {
    comp = new Subcomponent(this, "", id, state.getParticipantID());
    subcomponents.put(new Long(id), comp);
    try {
      rtpi.addSubcomponent(id, null, false, true);
    }
    catch (Exception e) {
      System.out.println(e + " Unable to add subcomponent to rtpi");
    }
  }
 
  // Pass the state information to the observer thread so that it may update the VRML scene graph
  observer.onNetInput(state);
    }

    //Process a received RTP/I state query
    private void execReceiveStateQuery(Rtpi r, RtpiStateQuery query)
    { 
  // Get the subcomponent ID associated with the received state query
  long id = query.getSubcomponentID();

  // Get the subcomponent associated with the received delta state
  Subcomponent comp = getSubcomponent(id);

  // Check if this subcomponent exists
  if (comp == null) {
    System.out.println("State query received for null subcomponent");
    return;
  }
  else if (comp.getpid() == participantID) {
    sendState(id);
  }
    }

    private void sendState(long id)
    {

  VField value;
  VRMLObject obj;
 
  // We can only send information if we are connected
        if (connected) {
    RtpiState state = null;

    // Get the subcomponent information for the requested subID
    Subcomponent comp = this.getSubcomponent(id);
    obj = observer.getObject((int) id);
    System.out.println("In send STATE for sub: " + comp + " obj: " + obj);

    // Create a new RTP/I state for this subcomponent
    try {
      state = new RtpiState((int) participantID, (long) id, (int)comp.getNextStateSequenceNumber(), 10, 3, System.currentTimeMillis(), rtpi.getCombinedHeaderSize());
    }
    catch (Exception e) {
      System.out.println(e + " Could not create rtpi state for transmission");
      return;
    }
 
    // Write field type information (rotation or transformation), and data to state
    try {
      OutputStream os = state.getOutputStream();
      DataOutputStream dos = new DataOutputStream(os);
      //System.out.println("should be writing avatar: " + comp.getAvatar());
      //System.out.println("should be writing name: " + comp.getUsername());
      //System.out.println("should be writing ssrc: " + observer.getSSRC(id));
      //System.out.println("should be writing translation: " + comp.getTranslation());
      //System.out.println("should be writing rotation: " + comp.getRotation());
      dos.writeUTF(comp.getAvatar());
      dos.writeUTF(comp.getUsername());
      dos.writeUTF(observer.getSSRC(id));
      value = comp.getTranslation();
      value.write(dos);
      value = comp.getRotation();
      value.write(dos);
     
      // Fake event & owned object fields for now

      dos.writeInt(comp.getNumActions());
      for (int i = 0; i < comp.getNumActions(); i++) {
        dos.writeShort(comp.getGestureState(i));
      }
      dos.writeInt((int)obj.getParent());
    }
    catch (Exception e) {
      System.out.println(e + " Unable to print to packet");
      return;
    }
    state.outputComplete();

    // Transmit state using RTP/I
    rtpi.transmitState(state);
  }
    }

    public long getDelay() {
  return delay;
    }

    public void timedSendState(long id) {

  // We only send out info for this object if the world is the parent
  VRMLObject obj = observer.getObject((int) id);
  if (obj == null)
    return;
 
  sendState(id);
    }

    public void removeSubcomponent(long id) {
  Long longID = new Long(id);
  Timer timer = (Timer) timers.get(longID);
  timer.cancel();
  timers.remove(longID);
    }

    public void addTimer(long id) {
  Timer timer = new Timer(true);
  timer.schedule(new XOOTimer(id, this, timer), delay);
  timers.put(new Long(id), timer);
    }
    public void setNumGestures(long id, int numGestures) {
  Subcomponent comp =  (Subcomponent) subcomponents.get(new Long(id));
  comp.setNumActions(numGestures);
    }

    public void setGesture(long id, int index, short value) {
  VSFBool boolValue;
  Subcomponent comp = this.getSubcomponent(id);
  short currentValue = comp.getGestureState(index);
  if (currentValue != value) {
    comp.setGestureState(index, value);
    if (value == 1)
      boolValue = new VSFBool(true);
    else
      boolValue = new VSFBool(false);

    observer.setField(id, (short)(index + VIP.NUM_FIELDS), (VField) boolValue);
  }
    }
}
TOP

Related Classes of XOO_CODE.SMClientThread

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.