package mil.navy.nps.logger; // Standard java stuff import java.applet.*; import java.awt.*; import java.awt.event.*; import java.io.*; import java.net.*; import java.util.*; import java.lang.Runtime; // Swing stuff import javax.swing.*; import javax.swing.event.*; // DIS stuff and other packages import mil.navy.nps.dis.*; import mil.navy.nps.util.*; import mil.navy.nps.testing.*; import mil.navy.nps.disEnumerations.*; /** * Main class for the PduPlayer application. Creates user interface. * Calls the appropriate methods for each button - play, fast forward, * rewind, stop, record. * @author Millie Ives * @author David Holland * @author DMcG * @version Version 3.0 *

* * Invocation: *

*    java mil.navy.nps.logger.PduPlayer *
or
*    c:\vrtp\demo\pduRecordings> PduPlayer.bat *
or
*    unix/vrtp/demo/pduRecordings> PduPlayer.sh */ public class PduPlayer extends JFrame //Applet // Panel { public static final String DEFAULT_MULTICAST_ADDRESS = "224.2.181.145"; public static final int DEFAULT_PORT = 62040; public static final int DEFAULT_TTL = 16; public static final String DEFAULT_FILENAME = "_newRecording.pdu"; protected JPanel drawArea; protected Frame drawFrame; // Threads for replay, play, record, etc. protected Play autoObject = null; protected Play playObject = null; protected Record recordObject = null; protected Rewind rewindObject = null; protected FFwd ffwdObject = null; // GUI fields that reflect the state of the logger protected JSlider pduSlider; protected JTextField totalPdus; protected String multicastAddress = DEFAULT_MULTICAST_ADDRESS; protected int portNo = DEFAULT_PORT; protected int timeToLive = DEFAULT_TTL; protected String filename = DEFAULT_FILENAME; protected BehaviorStreamBufferInfo fileInfo = new BehaviorStreamBufferInfo(false); transient int state, mode; transient String msg; // Menu items for the application protected MenuItem newMenuItem; protected MenuItem quitMenuItem; protected MenuItem openMenuItem; protected MenuItem saveMenuItem; protected MenuItem saveAsMenuItem; protected MenuItem fileInfoMenuItem; protected MenuItem usersGuideMenuItem; protected MenuItem aboutMenuItem; protected MenuItem supportMenuItem; protected MenuItem toggleModeMenuItem; protected MenuItem clearPdusMenuItem; protected MenuItem networkParamsMenuItem; protected MenuItem editMenuItem; // Top level menus transient Menu fileMenu; transient Menu optionsMenu; transient Menu helpMenu; // File open dialog transient FileDialog file; // Buffer that holds received pdus. static Vector pduBuffer = new Vector(); static Scrollbar horizontal; //DEBUG // Buttons for replay, rewind, other VCR functions protected JToggleButton rewButton = new JToggleButton (""); protected JToggleButton playButton = new JToggleButton (""); protected JToggleButton ffwdButton = new JToggleButton (""); protected JToggleButton recButton = new JToggleButton (""); protected JToggleButton stopButton = new JToggleButton (""); protected JToggleButton autoButton = new JToggleButton (""); protected ButtonGroup buttonGroup; // Holds the buttons, only one of which can be selected at a time. protected int pduIndex = 0; // pointer to current pdu protected int pduCount = 0; // total number of pdus in memory protected boolean changedFromMethod = false; // file name and directories private String directory = ""; // Constants defined to identify various states. public static final int STOP = 0; public static final int REWIND = 1; public static final int PLAY = 2; public static final int FFWD = 3; public static final int RECORD = 4; public static final int AUTOREPEAT = 5; /** * Returns the pdu buffer used to record pdus. Contains any type of PDU, * not limited to just ESPDUs. Any access to the variable should be through * this method. */ public static Vector getPduBuffer() { return pduBuffer; } public void addPdu(ProtocolDataUnit pPdu) { pduBuffer.add(pPdu); this.syncPduCount(); } public void syncPduCount() { int pduCount = pduBuffer.size(); totalPdus.setText("Total PDUs: " + (new Integer(pduCount)).toString()); } /** * Sets the current index of PDUs, the next PDU to be read. * Also updates the display of the current PDU. */ public void setPduIndex(int pNewIndex) { int position; // whacked to int value int bufferSize = pduBuffer.size(); double percentage = (double)pNewIndex / (double)bufferSize; pduIndex = pNewIndex; position = (int)(percentage * 100.0); // We use the boolean to modify the behavior of the sliderChanged method. changedFromMethod = true; pduSlider.setValue(position); changedFromMethod = false; } /** * Returns the current index of PDUs, the index of the next PDU in memory. */ public int getPduIndex() { return pduIndex; } /** * finds the directory in which the image icons are saved. */ private String getImageDirectory() { // This has the effect of looking in several directories for the images. // the first image, the rewind button, is used for a test case to find // the directory the other images are kept in. there should be a better // way to do this--my guess would be to return the class path from the // system properties list, then search the classpath for the files. This // would allow arbitrary directory placement, rather than in specific // directory or disk placement. int idx = 0; String subdirectory; String fullPathname; // Full pathname to gif file String directories[] = {"", "file:///C|/vrtp/mil/navy/nps/logger/", "d:/vrtp/mil/navy/nps/logger/", "/vrtp/mil/navy/nps/logger/", "/vrtp/mil/navy/nps/logger/", "c:/work/vrtp/mil/navy/nps/logger/"}; // extra special mcgredo directory // Loop through the direcotries, looking for one in which the rewind button gif is kept. while(idx < directories.length) { subdirectory = directories[idx]; fullPathname = subdirectory + "images/rew_dn.gif"; ImageIcon rew_dn = new ImageIcon(fullPathname); if (rew_dn.getImageLoadStatus() == MediaTracker.COMPLETE) { return subdirectory; } idx++; } subdirectory = null; return subdirectory; } /** * Adds assorted menus to the menu bar. */ private void setupMenus() { // Set up the top menu bar, the main menus fileMenu = new Menu("File",true); optionsMenu = new Menu("Options", true); helpMenu = new Menu("Help",true); // File menu additions, using anonymous classes as event handlers. // New fileMenu.add(newMenuItem = new MenuItem("New")); newMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JFrame newWindow; newWindow = new PduPlayer(); newWindow.setVisible(true); } }); // Right. These menus use anonymous inner classes to define event // handlers for the buttons. The problem is that the mass of code // here hides what's going on--several button handler anonymous // classes strung together would run to several pages of code. // So here we keep the anonymous inner classes as event handlers, // but simply use them to call dedicated methods in this class instance. // there's a special syntax for referring to the enclosing instance // of the inner anonymous class, "PduPlayer.this". This looks like // a static method call or class variable, reference, but it's not. // It's a reference to the _instance_ of the class (ie, this instance) // that encloses the _instance_ of the anonymous class. // (inner class instances are special in that they can refer to even // private variables of their enclosing class.) // Open recorded file. PduPlayer.this refers to this object itself; openFile() is an // instance method in this object. fileMenu.add(openMenuItem = new MenuItem("Open")); openMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { PduPlayer.this.openFile(); } }); // Save buffer of pdus to a file. fileMenu.add(saveMenuItem = new MenuItem("Save")); saveMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { PduPlayer.this.saveFile(); } }); // Save As menu item. fileMenu.add(saveAsMenuItem = new MenuItem("Save as")); saveAsMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { PduPlayer.this.saveAsFile(); } }); // File info--bring up an editable window with the various // prepended data from the file included. This is turned // off until they actually open or save a file. fileMenu.add(fileInfoMenuItem = new MenuItem("File Info")); fileInfoMenuItem.setEnabled(false); fileInfoMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { PduPlayer.this.runPropertiesDialog(); } }); // Quit menu item. Just Do It. fileMenu.add(quitMenuItem = new MenuItem("Quit")); quitMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.exit(0); } }); // Toggle options in menu that turn modes on or off. //optionsMenu.add(toggleModeMenuItem = new MenuItem("Mode")); optionsMenu.add(networkParamsMenuItem = new MenuItem("Network Parameters")); optionsMenu.add(editMenuItem = new MenuItem("Edit PDUs")); optionsMenu.add(clearPdusMenuItem = new MenuItem("Clear PDUs")); // Menu item for clearing out saved up in memory PDUs. clearPdusMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { pduSlider.setValue(0); pduBuffer = new Vector(); PduPlayer.this.syncPduCount(); JOptionPane.showMessageDialog(PduPlayer.this, "PDUs cleared and playlist reset."); } }); // Run the dialog box that asks the user for networking parameters, such // as ttl, multicast address, etc. networkParamsMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { NetworkDialog dialog = new NetworkDialog(PduPlayer.this, multicastAddress, portNo, timeToLive); dialog.setVisible(true); // If they hit "OK", get the values from the dialog box that they entered. if(dialog.getResult() == NetworkDialog.OK) { multicastAddress = dialog.getMulticastAddress(); portNo = dialog.getPort(); timeToLive = dialog.getTTL(); } } }); editMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { EditFrame editor = new EditFrame(PduPlayer.this); editor.setTitle("PDU Editing"); editor.setVisible(true); } }); // Help menu and user guide menu helpMenu.add(usersGuideMenuItem = new MenuItem("User's Guide")); usersGuideMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { PduPlayer.this.helpMenu(); } }); // Help menu additions. Just Do It. helpMenu.add(aboutMenuItem = new MenuItem("About PduPlayer")); aboutMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JOptionPane.showMessageDialog(PduPlayer.this, "PduPlayer Version 2.0, Updated 12/31/99\nAuthors: Millie Ives, David Holland\nGeorge Mason University"); } }); // Suport menu item, user's support guide. Just Do It. helpMenu.add(supportMenuItem = new MenuItem("User's Guide Support")); supportMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JOptionPane.showMessageDialog(PduPlayer.this, "Note: You must close all Netscape windows\nto pull up the support page."); } }); // Add the menu bar; put all the menus in, then add the menu bar to the application. MenuBar mb = new MenuBar(); mb.add (fileMenu); mb.add (optionsMenu); mb.add (helpMenu); this.setMenuBar(mb); } /** * Adds buttons to the application with the correct icons in them */ private void createButtons() { directory = this.getImageDirectory(); // found the image and the directory the live in. Load all the images. ImageIcon rew_dn = new ImageIcon(directory + "images/rew_dn.gif"); ImageIcon rew_up = new ImageIcon(directory + "images/rew_up.gif"); ImageIcon play_dn = new ImageIcon(directory + "images/play_dn.gif"); ImageIcon play_up = new ImageIcon(directory + "images/play_up.gif"); ImageIcon ffwd_dn = new ImageIcon(directory + "images/ffwd_dn.gif"); ImageIcon ffwd_up = new ImageIcon(directory + "images/ffwd_up.gif"); ImageIcon rec_dn = new ImageIcon(directory + "images/rec_dn.gif"); ImageIcon rec_up = new ImageIcon(directory + "images/rec_up.gif"); ImageIcon stop_dn = new ImageIcon(directory + "images/stop_dn.gif"); ImageIcon stop_up = new ImageIcon(directory + "images/stop_up.gif"); ImageIcon auto_dn = new ImageIcon(directory + "images/auto_dn.gif"); ImageIcon auto_up = new ImageIcon(directory + "images/auto_up.gif"); // Fire up the button, with the loaded image. Rewind. rewButton.setIcon(rew_up); rewButton.setSelectedIcon(rew_dn); rewButton.setDisabledIcon(rew_up); // Play button playButton.setIcon(play_up); playButton.setSelectedIcon(play_dn); playButton.setDisabledIcon(play_up); // fast forward button ffwdButton.setIcon(ffwd_up); ffwdButton.setSelectedIcon(ffwd_dn); ffwdButton.setDisabledIcon(ffwd_up); // Record button recButton.setIcon(rec_up); recButton.setSelectedIcon(rec_dn); recButton.setDisabledIcon(rec_up); // Stop button stopButton.setIcon(stop_up); stopButton.setSelectedIcon(stop_dn); stopButton.setDisabledIcon(stop_up); stopButton.setSelected(true); // auto button autoButton.setIcon(auto_up); autoButton.setSelectedIcon(auto_dn); autoButton.setDisabledIcon(auto_up); // All the buttons are put in a button group, only one of which can be // selected at a time. buttonGroup = new ButtonGroup(); buttonGroup.add(rewButton); buttonGroup.add(playButton); buttonGroup.add(ffwdButton); buttonGroup.add(recButton); buttonGroup.add(stopButton); buttonGroup.add(autoButton); } /** * Constructor for the PDU logger. */ public PduPlayer() { // Set up action handler for window close. This shuts down the // threads that may be running. this.addWindowListener( new WindowAdapter() { public void windowClosing(WindowEvent e) { PduPlayer.this.performStopButtonHit(); pduBuffer = new Vector(); // maybe speed up GC a bit } }); // Lays out buttons and meters. this.createButtons(); this.setupMenus(); // Text fields that reflect various options for user entry or to reflect // current state. totalPdus = new JTextField(12); // total number of PDUs loaded totalPdus.setEditable(false); // user no touchee with grubby fingers pduSlider = new JSlider(); // Slider for current PDU position pduSlider.setValue(0); // move slider all the way to the left // Set up labels for the slider Hashtable labelTable = new Hashtable(); labelTable.put( new Integer( 0 ), new JLabel("0%") ); labelTable.put( new Integer( 50 ), new JLabel("50%") ); labelTable.put( new Integer( 100 ), new JLabel("100%") ); pduSlider.setLabelTable( labelTable ); pduSlider.setPaintLabels(true); pduSlider.setBorder(BorderFactory.createEmptyBorder(0,0,0,10)); // Tick marks for slider pduSlider.setMajorTickSpacing(25); pduSlider.setMinorTickSpacing(5); pduSlider.setPaintTicks(true); // Set up change listener for the slider. This is called whenever the // slider is dragged. pduSlider.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { int sliderValue = pduSlider.getValue(); // value from zero to 100 int bufferSize = pduBuffer.size(); double percentage = ((double)sliderValue / 100.0); // set the current PDU position based on the position of the slider if(changedFromMethod == false) { pduIndex = (int)(bufferSize * percentage); //System.out.println("new index is " + pduIndex); } } }); // Begin constructing the GUI. Lay out buttons, etc. These use anonymous classes // as action handlers for the button. drawArea = new JPanel(); drawArea.setLayout(new BorderLayout() ); // Set up the left panel. Panel left = new Panel(); left.setLayout(new GridLayout(2,1)); left.add(totalPdus); left.add(new Label("PDU Position")); drawArea.add("West", left); // Set up the right panel. Panel right = new Panel(); right.setLayout(new GridLayout(2,1)); //right.add(fileName); right.add(new JLabel(" ")); // Filler to keep alignment nice right.add(pduSlider); drawArea.add("East",right); //right.add(pduLocation); // Set up the bottom row of buttons. Panel parent = new Panel (); parent.setLayout(new BorderLayout()); Panel p = new Panel(); p.setLayout(new FlowLayout()); parent.add("North",p); p.add(rewButton); // The rewind, ffwd, stop, etc buttons are set up in a ButtonGroup. // A buttonGroup can have only one button selected at any one time. // The button group also handles sending select and deselect messages // to all the members of the button group, so that clicking on // another button automatically does all the scut work of picking // a new button and deselecting the old one. We have to implement // two handlers here, one for actions (actionListener) and one for // ItemSelection, which turns buttons on and off. // Action listener for rewind button rewButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { PduPlayer.this.rewindButtonHit(); } }); // The item selection button for the rewind button; called when the item // button selection changes. rewButton.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { if (e.getStateChange() != ItemEvent.SELECTED) { rewindObject.setRunDone(true); } } }); // Play button. Play the items in the in-memory buffer, possibly // augmented by more PDUs from the file. p.add(playButton); playButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { PduPlayer.this.playButtonHit(); } }); // play button item selection playButton.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { if (e.getStateChange() != ItemEvent.SELECTED) { System.out.println("play button deselected"); playObject.setRunDone(true); } } }); p.add(ffwdButton); ffwdButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { PduPlayer.this.ffwdButtonHit(); } }); // ffwd button item selection ffwdButton.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { if (e.getStateChange() != ItemEvent.SELECTED) { ffwdObject.setRunDone(true); } } }); p.add(recButton); recButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { PduPlayer.this.recordButtonHit(); System.out.println ("Record..."); } }); // button selection/deselection, called automatically by button group recButton.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { if (e.getStateChange() != ItemEvent.SELECTED) { recordObject.setStillRunning(false); } } }); // Stop button actions. What happens here is not really important; the // shutdown of whatever was going on (play, record, whatever) when this // button was hit is handled in the item selection code of the appropriate // button. In other words, the logic for shutdown is in the state transition // from the other button, not here. p.add(stopButton); stopButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.out.println ("Stop."); } }); stopButton.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { if (e.getStateChange() == ItemEvent.SELECTED) { System.out.println("stop button selected"); } else { System.out.println("stop button deselected"); } } }); // Auto button p.add(autoButton); autoButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { PduPlayer.this.autoButtonHit(); } }); autoButton.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { if (e.getStateChange() != ItemEvent.SELECTED) { //recButton.setSelected(false); autoObject.setRunDone(true); } } }); drawArea.add("South",parent); // Put it all together. this.setTitle("PduPlayer " + filename); this.getContentPane().add(drawArea); this.setSize(385,150); this.syncPduCount(); this.setVisible(true); } /** * Handles an "openFile" event. Called from the anonymous inner class * created in the constructor. */ public void openFile() { BehaviorStreamBufferFile bsbf; ProtocolDataUnit pdu; // Run a file dialog panel to get the file to open. // Run a file dialog box to get the pathname to the PDU file the user wants to open. msg = "Open File"; file = new FileDialog(PduPlayer.this, msg, state); file.setDirectory("C:\\vrtp\\demo\\pduRecordings"); file.show(); String currFile, tempstr = ""; if( (currFile = file.getFile()) != null) { tempstr = currFile; filename = tempstr; this.setTitle("PduPlayer: " + filename); pduBuffer = new Vector(); this.setPduIndex(0); } try { //pduCount = newFile.Open(currFile, arrayIndex, totalPdusRecorded); System.out.println ("file " + filename + " loaded. "); } catch (Exception open_exception) { System.out.println("Error opening file " + filename); System.out.println(open_exception); } bsbf = new BehaviorStreamBufferFile(file.getFile(), true); fileInfo = bsbf.getInfo(); fileInfoMenuItem.setEnabled(true); while((pdu=bsbf.getNextPdu()) != null) { pduBuffer.add(pdu); //System.out.println("one more added, total now " + pduBuffer.size()); } this.syncPduCount(); bsbf.cleanup(); String load_message = pduBuffer.size() + " PDUs loaded into memory."; System.out.println (load_message); //JOptionPane.showMessageDialog(PduPlayer.this, load_message); } /** * Save file menu selection action. Called from the anonymous inner class action * handler. */ public void saveFile() { BehaviorStreamBufferFile bsbf = new BehaviorStreamBufferFile(filename, fileInfo, false); bsbf.setInfo(fileInfo); fileInfoMenuItem.setEnabled(true); Enumeration enum = pduBuffer.elements(); //int idx = 0; while(enum.hasMoreElements()) { ProtocolDataUnit pdu = (ProtocolDataUnit)enum.nextElement(); bsbf.sendPdu(pdu); //System.out.println("saved " + idx); //idx++; } bsbf.cleanup(); } /** * SaveAs menu operation. Open up a file dialog, then write out the contents of * the pduBuffer to the file. */ public void saveAsFile() { BehaviorStreamBufferFile bsbf; Enumeration enum = pduBuffer.elements(); String currFile, tempstr = ""; // Throw up a dialog to get the file name to save to. msg = "Save File As"; file = new FileDialog(this, msg, state); file.setDirectory("C:\\vrtp\\demo\\pduRecordings"); file.show(); if((currFile = file.getFile()) != null) { tempstr = currFile; //fileName.setText(tempstr); filename = tempstr; } bsbf = new BehaviorStreamBufferFile(filename, fileInfo, false); bsbf.setInfo(fileInfo); fileInfoMenuItem.setEnabled(true); while(enum.hasMoreElements()) { ProtocolDataUnit pdu = (ProtocolDataUnit)enum.nextElement(); bsbf.sendPdu(pdu); } bsbf.cleanup(); } /** * Action handler for the help menu, called from an anonymous inner class * in the constructor. Launches the default web browser, with an argument * that includes the help HTML file. */ public void helpMenu() { System.out.println(directory); String BrowserNT1 = "cmd /k " + directory + "cd html"; String BrowserNT2 = "cmd /c " + directory + "guidds2.htm"; String Browser95 = "start " + directory + "html/guidds2.htm"; try { Process p1 = Runtime.getRuntime().exec(BrowserNT1); Process p2 = Runtime.getRuntime().exec(BrowserNT2); } catch (IOException err1) { System.out.println("NT Operating System not found, trying 95..."); try { Process p = Runtime.getRuntime().exec(Browser95); } catch (IOException err2) { System.out.println(err2); } } } // end helpMenu /** * Stop button hit. This calls code to perform the click on the * stop button. A thread doing some operation, such as playing * or rewinding, should call this method after finishing its * task, just before exiting. It selects the stop button, and * de-selects the current button. */ public void performStopButtonHit() { stopButton.doClick(); } /** * Rewind button hit. Checks the state and toggles intelligently. * The rewind operation actually replays the PDUs in reverse order, * from the current position. So if we're at PDU 42 currently, IN * THE PDU LIST IN MEMORY, the pdus would be replayed back as 42, 41, * 40, etc.

* * This has to launch a new thread (we can't process the lengthy rewind * action inside the action handler; that would stop the GUI.) */ public void rewindButtonHit() { Thread aThread; System.out.println("****In rewind button handler"); rewindObject = new Rewind(this, // us multicastAddress, // IP address to send to portNo, // port number to send to timeToLive); // ttl for mcast aThread = new Thread(rewindObject); aThread.start(); } /** * Handles a play button hit. Replays the pdus in memory, possibly * augmented by pdus from the file. */ public void playButtonHit() { Thread aThread; playObject = new Play(this, // us multicastAddress, // IP address to send to portNo, // port number to send to timeToLive); // ttl for mcast aThread = new Thread(playObject); aThread.start(); } /** * Automatic looping of the play button. This goes to the end * of the play, then loops back to the start of the in-memory * pdus. */ public void autoButtonHit() { Thread aThread; autoObject = new Play(this, // us multicastAddress, // IP address to send to portNo, // port number to send to timeToLive); // ttl for mcast autoObject.looping = true; aThread = new Thread(autoObject); aThread.start(); } // The fast forward button was hit. Play the pdus. public void ffwdButtonHit() { Thread aThread; ffwdObject = new FFwd(this, // us multicastAddress, // IP address to send to portNo, // port number to send to timeToLive); // ttl for mcast aThread = new Thread(ffwdObject); aThread.start(); } /** * The record button was hit; launch a thread to save the data to a * buffer. */ public void recordButtonHit() { Thread recordThread = null; recordObject = new Record(this, multicastAddress, portNo); recordThread = new Thread(recordObject); recordThread.setPriority(Thread.MIN_PRIORITY); System.out.println("starting record thread"); recordThread.start(); System.out.println("Exiting recordButtonHit"); } /** * Opens a dialog box with various properites from the prepend * data in the file displayed, for editing. */ public void runPropertiesDialog() { if(fileInfo == null) return; PropertiesDialog dialog = new PropertiesDialog(this, fileInfo); dialog.setVisible(true); if(dialog.getResult() == PropertiesDialog.OK) { String atVal = dialog.toString(); System.out.println("Got info from dialog of " + atVal); fileInfo = new BehaviorStreamBufferInfo(atVal); } } /** * Entry point for program. Lots of options ripped out here. In fact, all * options ripped out. Then the location salted, and no two stones left on * top of each other. */ public static void main(String args[]) { JFrame p = new PduPlayer(); p.setVisible(true); } }