/*
* Player Java Client 3 - MCommInterface.java
* Copyright (C) 2002-2006 Radu Bogdan Rusu, Maxim Batalin
*
* 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 of the License, 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; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id$
*
*/
package javaclient3;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javaclient3.structures.PlayerMsgHdr;
import javaclient3.structures.mcom.PlayerMcomConfig;
import javaclient3.structures.mcom.PlayerMcomData;
import javaclient3.xdr.OncRpcException;
import javaclient3.xdr.XdrBufferDecodingStream;
import javaclient3.xdr.XdrBufferEncodingStream;
/**
* The mcom interface is designed for exchanging information between clients.
* A client sends a message of a given "type" and "channel". This device
* stores adds the message to that channel's stack. A second client can then
* request data of a given "type" and "channel". Push, Pop, Read, and Clear
* operations are defined, but their semantics can vary, based on the stack
* discipline of the underlying driver. For example, the lifomcom driver
* enforces a last-in-first-out stack.
* @author Radu Bogdan Rusu
* @version
* <ul>
* <li>v2.0 - Player 2.0 supported
* </ul>
*/
public class MComInterface extends PlayerDevice {
private static final boolean isDebugging = PlayerClient.isDebugging;
// Logging support
private Logger logger = Logger.getLogger (MComInterface.class.getName ());
private PlayerMcomData pmdata;
private boolean readyPmdata = false;
/**
* Constructor for MComInterface.
* @param pc a reference to the PlayerClient object
*/
public MComInterface (PlayerClient pc) { super(pc); }
/**
* Read the MCOM data.
*/
public synchronized void readData (PlayerMsgHdr header) {
try {
this.timestamp = header.getTimestamp();
// Buffer for reading full, data_count, array_count
byte[] buffer = new byte[12];
// Read full, data_count, array_count
is.readFully (buffer, 0, 12);
pmdata = new PlayerMcomData ();
// Begin decoding the XDR buffer
XdrBufferDecodingStream xdr = new XdrBufferDecodingStream (buffer);
xdr.beginDecoding ();
pmdata.setFull ((char)xdr.xdrDecodeByte ());
int dataCount = xdr.xdrDecodeInt ();
xdr.endDecoding ();
xdr.close ();
// Buffer for reading the MCom data
buffer = new byte[MCOM_DATA_LEN];
// Read the MCom data
is.readFully (buffer, 0, dataCount);
pmdata.setData_count (dataCount);
pmdata.setData (new String (buffer).toCharArray ());
// Take care of the residual zero bytes
if ((dataCount % 4) != 0)
is.readFully (buffer, 0, 4 - (dataCount % 4));
readyPmdata = true;
} catch (IOException e) {
throw new PlayerException
("[MCom] : Error reading payload: " +
e.toString(), e);
} catch (OncRpcException e) {
throw new PlayerException
("[MCOM] : Error while XDR-decoding payload: " +
e.toString(), e);
}
}
/**
* Configuration request to the device.
* <br><br>
* @param pmconfig a PlayerMcomConfig structure filled with the
* required data
* @param whichReq the appropriate request (PUSH, POP, READ, CLEAR,
* SET_CAPACITY)
*/
public void sendConfigReq (PlayerMcomConfig pmconfig, int whichReq) {
try {
int total = 12 + 4 + pmconfig.getChannel_count () + 8 + 4 +
pmconfig.getData ().getData_count ();
sendHeader (PLAYER_MSGTYPE_REQ, whichReq, total); /* payload */
XdrBufferEncodingStream xdr = new XdrBufferEncodingStream (24);
xdr.beginEncoding (null, 0);
xdr.xdrEncodeInt (pmconfig.getCommand ());
xdr.xdrEncodeInt (pmconfig.getType ());
xdr.xdrEncodeInt (pmconfig.getChannel_count ());
xdr.xdrEncodeByte((byte)pmconfig.getChannel_count ());
xdr.endEncoding ();
os.write (xdr.getXdrData (), 0, xdr.getXdrLength ());
xdr.close ();
// Need to finish this after Player 2 gets updated in CVS!!!
os.flush ();
} catch (Exception e) {
String subtype = "";
switch (whichReq) {
case PLAYER_MCOM_PUSH: {
subtype = "PLAYER_MCOM_PUSH";
break;
}
case PLAYER_MCOM_POP: {
subtype = "PLAYER_MCOM_POP";
break;
}
case PLAYER_MCOM_READ: {
subtype = "PLAYER_MCOM_READ";
break;
}
case PLAYER_MCOM_CLEAR: {
subtype = "PLAYER_MCOM_CLEAR";
break;
}
case PLAYER_MCOM_SET_CAPACITY: {
subtype = "PLAYER_MCOM_SET_CAPACITY";
break;
}
default: {
logger.log (Level.FINEST, "[MCom] : Couldn't send " + subtype +
" command: " + e.toString ());
}
}
}
}
/**
* Configuration request: Push (PLAYER_MCOM_PUSH_REQ)
*/
public void Push (int type, String channel, char[] dataT) {
// sendConfigReq (PLAYER_MCOM_PUSH, type, channel, true, dataT);
}
/**
* Configuration request: Pop (PLAYER_MCOM_POP_REQ)
*/
public void Pop (int type, String channel) {
// char[] dataT = new char[MCOM_DATA_LEN];
// sendConfigReq (PLAYER_MCOM_POP, type, channel, false, dataT);
}
/**
* Configuration request: Read (PLAYER_MCOM_READ_REQ)
*/
public void Read (int type, String channel) {
// char[] dataT = new char[MCOM_DATA_LEN];
// sendConfigReq (PLAYER_MCOM_READ, type, channel, false, dataT);
}
/**
* Configuration request: Clear (PLAYER_MCOM_CLEAR_REQ)
*/
public void Clear (int type, String channel) {
// char[] dataT = new char[MCOM_DATA_LEN];
// sendConfigReq (PLAYER_MCOM_CLEAR, type, channel, false, dataT);
}
/**
* Configuration request: Set capacity (PLAYER_MCOM_SET_CAPACITY_REQ)
*/
public void setCapacity (int type, String channel, char capacity) {
char[] dataT = new char[MCOM_DATA_LEN];
dataT[0] = capacity;
// sendConfigReq (PLAYER_MCOM_SET_CAPACITY, type, channel, false, dataT);
}
/**
* Handle acknowledgement response messages (threaded mode).
* @param size size of the payload
*/
public void handleResponse (int size) {
if (size == 0) {
if (isDebugging)
System.err.println ("[MCom][Debug] : Unexpected response of size 0!");
return;
}
try {
/*byte subtype = is.readByte ();
switch (subtype) {
case PLAYER_MCOM_PUSH: {
break;
}
case PLAYER_MCOM_POP: {
//dataType = (short)is.readUnsignedShort ();
//for (int i = 0; i < MCOM_CHANNEL_LEN; i++)
// channelName[i] = is.readChar (); // the name of the channel
//fullF = is.readChar (); // a flag (boolean 0/1)
//for (int i = 0; i < MCOM_DATA_LEN; i++)
// dataF[i] = is.readChar (); // the data
//readyData = true;
break;
}
case PLAYER_MCOM_READ: {
//dataType = (short)is.readUnsignedShort ();
//for (int i = 0; i < MCOM_CHANNEL_LEN; i++)
// channelName[i] = is.readChar (); // the name of the channel
//fullF = is.readChar (); // a flag (boolean 0/1)
//for (int i = 0; i < MCOM_DATA_LEN; i++)
// dataF[i] = is.readChar (); // the data
//readyData = true;
break;
}
case PLAYER_MCOM_CLEAR: {
break;
}
case PLAYER_MCOM_SET_CAPACITY: {
break;
}
default: {
System.err.println ("[MCom] : Unexpected response " + subtype +
" of size = " + size);
break;
}
}*/
} catch (Exception e) {
logger.log (Level.FINEST, "[MCom] : Error when reading payload " + e.toString ());
}
}
/**
* Get the MCom data.
* @return an object of type PlayerMcomData containing the requested data
*/
public PlayerMcomData getData () { return this.pmdata; }
/**
* Check if data is available.
* @return true if ready, false if not ready
*/
public boolean isDataReady () {
if (readyPmdata) {
readyPmdata = false;
return true;
}
return false;
}
}