/*
   COPYRIGHT (C) 2010 - 2013 by Alexander Wait. All Rights Reserved.

   This class creates the GUI for the Transceiver.

   @site http://www.javaika.com
   @author Alexander Wait
   @version 2014-07-25
*/



import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.URL;
import java.util.ArrayList;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;



public class OnlineMessagingGui extends JApplet
{
   private static final String copyright = "Copyright (c) 2012 by Alexander Wait - All Rights Reserved";

   private static final long serialVersionUID = 1L;
   

   static boolean isApplication = false;
   
   static boolean runRestricted = false;
   
   static boolean isVisible = false;
   

   /* Interface Settings */

   private static final int FRAME_SIZE_X = 520;
   
   private static final int FRAME_SIZE_Y = 590;
   
   private static final int APPLET_SIZE_Y = 560;
   
   
   /* Set Poll Settings */

   private static final int PING_TIMEOUT = 3000;
   
   
   /* Validation Settings */
   
   private static final int MAX_PORT_LENGTH = 5;
   
   private static final int MAX_VIDEO_ID_LENGTH = 8;
   
   private static final int MIN_CHANNEL_ID_LENGTH = 6;
   
   private static final int MAX_CHANNEL_ID_LENGTH = 20;
   

   private static final String MESSAGE_CLEAR_ALL = "http://" + Domain.getDomain()
   
   + "/bridge/record-message-clear-all.php" + Domain.getPort(); // Port:80

   
   private static final String MESSAGE_CLEAR_ID = "http://" + Domain.getDomain() 
   
   + "/bridge/record-message-clear-id.php" + Domain.getPort(); // Port:80
   
   
   //************************************** START INITIALISATION CODE **************************************//

   
   /**
    * Browser constructor.
    */
   public void init()
   {  
      String copyrightParam = getParameter("copyright");
       
      if ((copyrightParam == null) || !copyrightParam.equals(copyright)) 
      {
         Message.showMessage("Invalid Copyright", "WARNING", "warning"); 
      }       
       
      else if (!getDocumentBase().getHost().equals(Domain.getDomain()))
      {
         Message.showMessage("Unauthorised Applet Use", "ERROR", "error");
      }

      else
      {
         try {getToolkit().getSystemClipboard();}
          
         catch (java.security.AccessControlException e) {runRestricted = true;} 
 

         userId = getParameter("id"); userPw = getParameter("pw");

         
         initialiser(); includeResizeEvent(); setJMenuBar(menuBar); 
         
         setSize(FRAME_SIZE_X,FRAME_SIZE_Y);
      }
   }
   
   
   
   /**
    * Application constructor.
    */
   public OnlineMessagingGui()
   {
      if (isApplication)
      { 
         initialiser();  
      
      
         frame = new JFrame();

         frame.setMinimumSize(new Dimension(FRAME_SIZE_X, FRAME_SIZE_Y));
         
         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

         frame.setSize(FRAME_SIZE_X, FRAME_SIZE_Y);

         frame.setTitle("Transceiver Program");
      
         frame.setLocationRelativeTo(null); 
      
         frame.setJMenuBar(menuBar);

         frame.add(contentPane);  
      
      
         setVisibility();
      }
      
   }
   
   
   
   /**
    * GUI initializer.
    * ESCA-JAVA0076:
    */
   private void initialiser()
   {
      validation = new Validation();
      
      filter = new UppercaseDocumentFilter();
      

      // Initialize content pane and layout.

      contentPane = getContentPane();
      
      contentPane.setLayout(new GridBagLayout());
      
      
      // Initialize JLabel video window.
      
      label = new JLabel();
      
      label.setBorder(BorderFactory.createLineBorder(new Color(240, 0, 0)));
      
      label.setIcon(new ImageIcon(this.getClass().getResource
  
      ("files/images/VideoMessagingImageBlank.png")));
      
      
      // Initialize button GUI components.
      
      start = new JButton(new ImageIcon(this.getClass().getResource
      (
         "files/images/TransmitReceiveStartNormal.png"))
      ); 
      
      
      start.setRolloverIcon(new ImageIcon(this.getClass().getResource
      (
         "files/images/TransmitReceiveStartRollover.png"))
      );

      
      start.setPressedIcon(new ImageIcon(this.getClass().getResource
      (
         "files/images/TransmitReceiveStartPressed.png"))
      );
      
      
      start.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
      
      start.setPreferredSize(new Dimension(115, 25)); 
      
      start.addActionListener(new StartButtonListener());
      
      
      stop = new JButton(new ImageIcon(this.getClass().getResource
      (
         "files/images/TransmitReceiveStopNormal.png"))
      ); 
      
      
      stop.setRolloverIcon(new ImageIcon(this.getClass().getResource
      (
         "files/images/TransmitReceiveStopRollover.png"))
      );

      
      stop.setPressedIcon(new ImageIcon(this.getClass().getResource
      (
         "files/images/TransmitReceiveStopPressed.png"))
      );
      
      
      stop.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
      
      stop.setPreferredSize(new Dimension(115, 25)); 
      
      stop.addActionListener(new StopButtonListener());
      
      
      delete = new JButton("Delete"); delete.setFocusPainted(false); 
      
      delete.setPreferredSize(new Dimension(70, 30));
      
      delete.addActionListener(new DeleteMessageListener());
      
      
      // Initialize text field GUI components.
      
      videoId = new JTextField(); videoId.setText("1");
      
      videoId.setPreferredSize(new Dimension(93, 60));
      
      videoId.setHorizontalAlignment(JTextField.CENTER);
      
      videoId.setBorder(BorderFactory.createTitledBorder("Video ID"));
      
      
      channelId = new JTextField();
      
      channelId.setPreferredSize(new Dimension(93, 60));
      
      channelId.setHorizontalAlignment(JTextField.CENTER);

      channelId.setBorder(BorderFactory.createTitledBorder("Channel ID"));
      
      ((AbstractDocument) channelId.getDocument()).setDocumentFilter(filter);
      
      
      deleteId = new JTextField(); deleteId.setText("1");
      
      deleteId.setPreferredSize(new Dimension(93, 60));
      
      deleteId.setHorizontalAlignment(JTextField.CENTER);
      
      deleteId.setBorder(BorderFactory.createTitledBorder("Video ID"));
      
      
      ipAddress = new JTextField(); ipAddress.setText("127.0.0.1");
      
      ipAddress.setPreferredSize(new Dimension(97, 60));
      
      ipAddress.setHorizontalAlignment(JTextField.CENTER);
      
      ipAddress.setBorder(BorderFactory.createTitledBorder("Address"));
      
      
      dataTransmitPorts = new JTextField(); dataTransmitPorts.setText("300:800");
      
      dataTransmitPorts.setPreferredSize(new Dimension(70, 60));
      
      dataTransmitPorts.setHorizontalAlignment(JTextField.CENTER);
      
      dataTransmitPorts.setBorder(BorderFactory.createTitledBorder("Ports"));
      
      
      // Initialize radio button GUI components.

      mono = new JRadioButton("1", true); mono.setFocusPainted(false); 

      mono.setSelected(true); 
      
      
      stereo = new JRadioButton("2", true); stereo.setFocusPainted(false); 
      
      stereo.setSelected(false);
      
      
      minBytes = new JRadioButton("1", true); minBytes.setFocusPainted(false); 
      
      minBytes.setSelected(false);
      
      
      maxBytes = new JRadioButton("2", true); maxBytes.setFocusPainted(false); 
      
      maxBytes.setSelected(true);
      
      
      // Initialize button group GUI components.
      
      channelsGroup = new ButtonGroup(); 
      
      channelsGroup.add(mono); channelsGroup.add(stereo);
      
      
      bytesGroup = new ButtonGroup(); 
      
      bytesGroup.add(minBytes); bytesGroup.add(maxBytes); 
 
      
      // Initialize combo box GUI components.
      
      protocol = new JComboBox(protocolChoices);
      
      protocol.setPreferredSize(new Dimension(50, 19));
      
      protocol.setMaximumRowCount(2); protocol.setSelectedIndex(0);
      
      
      camera = new JComboBox(cameraChoices);
      
      camera.setPreferredSize(new Dimension(50, 19));
      
      camera.setMaximumRowCount(2); camera.setSelectedIndex(0);
      

      samples = new JComboBox(samplesChoices);
      
      samples.setPreferredSize(new Dimension(65, 19));
      
      samples.setMaximumRowCount(2); samples.setSelectedIndex(1);
      
      
      size = new JComboBox(sizeChoices);
      
      size.setPreferredSize(new Dimension(80, 19));
      
      size.setMaximumRowCount(2); size.setSelectedIndex(2);

      
      // Initialize check box GUI components.
      
      transmit = new JCheckBox(); transmit.setFocusPainted(false);

      transmit.addChangeListener(new SelectListener(0));
      
      transmit.setSelected(true);

      
      receive = new JCheckBox(); receive.setFocusPainted(false);
      
      receive.addChangeListener(new SelectListener(1));
      
      receive.setSelected(true);
      
      
      deleteAll = new JCheckBox(); deleteAll.setFocusPainted(false);

      deleteAll.addChangeListener(new SelectListener(0));
      
      deleteAll.setSelected(true);
      
      
      record = new JCheckBox(); record.setFocusPainted(false);
      
      record.setSelected(true);
      
      
      play = new JCheckBox(); play.setFocusPainted(false);
     
      video = new JCheckBox(); video.setFocusPainted(false); video.setSelected(true);
      
      
      ButtonGroup group = new ButtonGroup(); 
      
      group.add(record); group.add(play);
      
      
      // Initialize slider GUI components.
      
      rate = new JSlider();
      
      rate.setPreferredSize(new Dimension(60, 30));
      
      rate.setMajorTickSpacing(25); rate.setValue(75);

      rate.setPaintTicks(true);
      

      quality = new JSlider();
      
      quality.setPreferredSize(new Dimension(60, 30));
      
      quality.setMajorTickSpacing(25); quality.setValue(50);

      quality.setPaintTicks(true);
      
      
      chunks = new JSlider();
      
      chunks.setPreferredSize(new Dimension(60, 30));   
      
      chunks.setMajorTickSpacing(25); chunks.setValue(50);

      chunks.setPaintTicks(true);

      
      // Initialize progress bar GUI components.
      
      progressBar = new JProgressBar();  
      
      progressBar.setPreferredSize(new Dimension(180, 25));
      
      progressBar.setStringPainted(true); progressBar.setString("Pending");   
      
      
      // Initialize text area GUI components.
      
      textOutput = new JTextArea(); textOutput.setEditable(false);
      
      textOutput.setFont(new Font("Verdana", Font.ITALIC, 11)); 
      
      textOutput.setForeground(Color.GRAY);
      
      
      textPane = new JScrollPane(textOutput, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, 

      JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);


      textPane.setBorder(BorderFactory.createEmptyBorder(13, 10, 13, 10));
      

      // Initialize JPanel GUI components.
      
      imagePanel = new JPanel(); imagePanel.setLayout(new FlowLayout());
      
      imagePanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
      
      imagePanel.add(label);
      
      
      imagePane = new JScrollPane(imagePanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
      
      JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
      
      
      imagePane.setPreferredSize(new Dimension(465, 325));
      
      
      transmitPanel = new JPanel(); transmitPanel.add(transmit);
      
      transmitPanel.setPreferredSize(new Dimension(70, 60));

      transmitPanel.setBorder(BorderFactory.createTitledBorder("Transmit"));
      
      
      receivePanel = new JPanel(); receivePanel.add(receive);
      
      receivePanel.setPreferredSize(new Dimension(70, 60));

      receivePanel.setBorder(BorderFactory.createTitledBorder("Receive"));
      
      
      protocolPanel = new JPanel(); protocolPanel.add(protocol);
      
      protocolPanel.setPreferredSize(new Dimension(70, 60));

      protocolPanel.setBorder(BorderFactory.createTitledBorder("Protocol"));
      
      
      deleteAllPanel = new JPanel(); deleteAllPanel.add(deleteAll);
      
      deleteAllPanel.setPreferredSize(new Dimension(93, 60));

      deleteAllPanel.setBorder(BorderFactory.createTitledBorder("Delete All"));
      

      recordPanel = new JPanel(); recordPanel.add(record);
      
      recordPanel.setPreferredSize(new Dimension(93, 60));

      recordPanel.setBorder(BorderFactory.createTitledBorder("Record"));
      
      
      playPanel = new JPanel(); playPanel.add(play);
      
      playPanel.setPreferredSize(new Dimension(93, 60));

      playPanel.setBorder(BorderFactory.createTitledBorder("Play"));
      
      
      cameraPanel = new JPanel(); cameraPanel.add(camera);
      
      cameraPanel.setPreferredSize(new Dimension(70,60));
      
      cameraPanel.setBorder(BorderFactory.createTitledBorder("Camera"));
      
      
      samplesPanel = new JPanel(); samplesPanel.add(samples);
      
      samplesPanel.setPreferredSize(new Dimension(90,60));
      
      samplesPanel.setBorder(BorderFactory.createTitledBorder("Samples"));
      
      
      channelsPanel = new JPanel(); channelsPanel.add(mono); channelsPanel.add(stereo);
      
      channelsPanel.setPreferredSize(new Dimension(100,60));
      
      channelsPanel.setBorder(BorderFactory.createTitledBorder("Channels"));
      
      
      bytesPanel = new JPanel(); bytesPanel.add(minBytes); bytesPanel.add(maxBytes);
      
      bytesPanel.setPreferredSize(new Dimension(100,60));
      
      bytesPanel.setBorder(BorderFactory.createTitledBorder("Bytes"));
      
      
      videoIdPanel = new JPanel(); videoIdPanel.add(videoId);
      
      videoIdPanel.setPreferredSize(new Dimension(97, 60));

      videoIdPanel.setBorder(BorderFactory.createTitledBorder("Video ID"));
      
      
      videoIncPanel = new JPanel(); videoIncPanel.add(video);
      
      videoIncPanel.setPreferredSize(new Dimension(97, 60));

      videoIncPanel.setBorder(BorderFactory.createTitledBorder("Include Video"));
      
      
      frameRatePanel = new JPanel(); frameRatePanel.add(rate);
      
      frameRatePanel.setPreferredSize(new Dimension(85, 60));

      frameRatePanel.setBorder(BorderFactory.createTitledBorder("Frame Rate"));
      
      
      videoQualityPanel = new JPanel(); videoQualityPanel.add(quality);
      
      videoQualityPanel.setPreferredSize(new Dimension(70, 60));

      videoQualityPanel.setBorder(BorderFactory.createTitledBorder("Quality"));
      
      
      chunkSizePanel = new JPanel(); chunkSizePanel.add(chunks);
      
      chunkSizePanel.setPreferredSize(new Dimension(97, 60));

      chunkSizePanel.setBorder(BorderFactory.createTitledBorder("Chunk Size"));
      
      
      videoSizePanel = new JPanel(); videoSizePanel.add(size);
      
      videoSizePanel.setPreferredSize(new Dimension(97,60));
      
      videoSizePanel.setBorder(BorderFactory.createTitledBorder("Video Size"));
      

      transceiverPanel = new JPanel(); transceiverPanel.setLayout(new FlowLayout());
      
      transceiverPanel.add(transmitPanel); transceiverPanel.add(receivePanel);
      
      transceiverPanel.add(ipAddress); transceiverPanel.add(dataTransmitPorts);
      
      transceiverPanel.add(protocolPanel);
      
     
      messagingPanel = new JPanel(); messagingPanel.setLayout(new FlowLayout());
      
      messagingPanel.add(recordPanel); messagingPanel.add(playPanel); 
      
      messagingPanel.add(videoId); messagingPanel.add(channelId); 
      
      
      deletePanel = new JPanel(); deletePanel.setLayout(new FlowLayout());
      
      deletePanel.add(deleteAllPanel); deletePanel.add(deleteId); deletePanel.add(delete);
      
      
      videoPanel = new JPanel(); videoPanel.setLayout(new FlowLayout());
      
      videoPanel.add(videoIncPanel); videoPanel.add(frameRatePanel);
      
      videoPanel.add(videoSizePanel); videoPanel.add(cameraPanel);
      
      videoPanel.add(videoQualityPanel);
      
      
      audioPanel = new JPanel(); videoPanel.setLayout(new FlowLayout());
      
      audioPanel.add(channelsPanel); audioPanel.add(bytesPanel); 
      
      audioPanel.add(chunkSizePanel); audioPanel.add(samplesPanel);
      
      
      feedbackPanel = new JPanel(); feedbackPanel.setLayout(new GridLayout(1, 1));
      
      feedbackPanel.add(textPane);
      
     
      buttonPanel = new JPanel(); 
      
      buttonPanel.setLayout (new FlowLayout(FlowLayout.LEADING));
      
      buttonPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
      
      
      // Initialize tab pane GUI components.
      
      tabbedPane = new JTabbedPane(); 
      
      
      tabbedPane.setFocusable(false);
      
      tabbedPane.setPreferredSize(new Dimension(450, 115));
      
      tabbedPane.addTab("Transceiver", transceiverPanel); 
      
      tabbedPane.addTab("Messaging", messagingPanel);
      
      tabbedPane.addTab("Delete", deletePanel);
      
      tabbedPane.addTab("Video", videoPanel);
      
      tabbedPane.addTab("Audio", audioPanel);
      
      tabbedPane.addTab("Feedback", feedbackPanel);
      
      tabbedPane.setSelectedIndex(0);
      

      // Add GUI components to JPanels.
      
      buttonPanel.add(progressBar);
      
      buttonPanel.add(start); buttonPanel.add(stop); 
 
     
      // Initialize menu bar GUI components.
      
      menuBar = new JMenuBar(); menuBar.add(createSettingsMenu());
      
      
      // Method calls for GUI initialization.
      
      gridBagConstraints(); setColors(); setGraphicIcons();
   }
   
   
   
   /**
    * Sets the background color.
    */
   private void setColors()
   {
      contentPane.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      label.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      textOutput.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      transmit.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      receive.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      video.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );

      record.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );

      mono.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      stereo.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      chunks.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      play.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      rate.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      quality.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      minBytes.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      maxBytes.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      channelId.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      videoId.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      ipAddress.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      deleteId.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      deleteAll.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );

      dataTransmitPorts.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      tabbedPane.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      progressBar.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      textPane.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      imagePanel.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      imagePane.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      cameraPanel.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );

      samplesPanel.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      protocolPanel.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );

      buttonPanel.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      recordPanel.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      playPanel.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      channelsPanel.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
         
      bytesPanel.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      bytesPanel.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      transceiverPanel.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      messagingPanel.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      videoPanel.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      audioPanel.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      deletePanel.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      feedbackPanel.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      transmitPanel.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      receivePanel.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      videoIncPanel.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      videoSizePanel.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      deleteAllPanel.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      chunkSizePanel.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      frameRatePanel.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      videoQualityPanel.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
   }
   
   
   
   /**
    * Sets icons for graphical elements.
    */
   private void setGraphicIcons()
   {
      mono.setIcon(new ImageIcon
      (this.getClass().getResource("files/images/RadioButtonNormalUnselected.png")));
            
      mono.setSelectedIcon(new ImageIcon
      (this.getClass().getResource("files/images/RadioButtonNormalSelected.png")));

      mono.setDisabledIcon(new ImageIcon
      (this.getClass().getResource("files/images/RadioButtonDisabledUnselected.png")));

      mono.setDisabledSelectedIcon(new ImageIcon
      (this.getClass().getResource("files/images/RadioButtonDisabledSelected.png")));
         
         
      stereo.setIcon(new ImageIcon
      (this.getClass().getResource("files/images/RadioButtonNormalUnselected.png")));
                     
      stereo.setSelectedIcon(new ImageIcon
      (this.getClass().getResource("files/images/RadioButtonNormalSelected.png")));

      stereo.setDisabledIcon(new ImageIcon
      (this.getClass().getResource("files/images/RadioButtonDisabledUnselected.png")));

      stereo.setDisabledSelectedIcon(new ImageIcon
      (this.getClass().getResource("files/images/RadioButtonDisabledSelected.png")));
      
      
      minBytes.setIcon(new ImageIcon
      (this.getClass().getResource("files/images/RadioButtonNormalUnselected.png")));
            
      minBytes.setSelectedIcon(new ImageIcon
      (this.getClass().getResource("files/images/RadioButtonNormalSelected.png")));

      minBytes.setDisabledIcon(new ImageIcon
      (this.getClass().getResource("files/images/RadioButtonDisabledUnselected.png")));

      minBytes.setDisabledSelectedIcon(new ImageIcon
      (this.getClass().getResource("files/images/RadioButtonDisabledSelected.png")));
         
         
      maxBytes.setIcon(new ImageIcon
      (this.getClass().getResource("files/images/RadioButtonNormalUnselected.png")));
                     
      maxBytes.setSelectedIcon(new ImageIcon
      (this.getClass().getResource("files/images/RadioButtonNormalSelected.png")));

      maxBytes.setDisabledIcon(new ImageIcon
      (this.getClass().getResource("files/images/RadioButtonDisabledUnselected.png")));

      maxBytes.setDisabledSelectedIcon(new ImageIcon
      (this.getClass().getResource("files/images/RadioButtonDisabledSelected.png")));
   
   
      transmit.setIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxNormalUnselected.png")));
                                                              
      transmit.setSelectedIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxNormalSelected.png")));
                                     
      transmit.setDisabledIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxDisabledUnselected.png")));
                                  
      transmit.setDisabledSelectedIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxDisabledSelected.png")));
      
      
      receive.setIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxNormalUnselected.png")));
                                                              
      receive.setSelectedIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxNormalSelected.png")));
                                     
      receive.setDisabledIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxDisabledUnselected.png")));
                                  
      receive.setDisabledSelectedIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxDisabledSelected.png")));
      
      
      record.setIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxNormalUnselected.png")));
                                                              
      record.setSelectedIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxNormalSelected.png")));
                                     
      record.setDisabledIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxDisabledUnselected.png")));
                                  
      record.setDisabledSelectedIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxDisabledSelected.png")));
   
   
      video.setIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxNormalUnselected.png")));
                                                               
      video.setSelectedIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxNormalSelected.png")));
                                      
      video.setDisabledIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxDisabledUnselected.png")));
                                  
      video.setDisabledSelectedIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxDisabledSelected.png")));
      
      
      play.setIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxNormalUnselected.png")));
                                                              
      play.setSelectedIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxNormalSelected.png")));
                                     
      play.setDisabledIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxDisabledUnselected.png")));
                                  
      play.setDisabledSelectedIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxDisabledSelected.png")));
      
      
      deleteAll.setIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxNormalUnselected.png")));
                                                              
      deleteAll.setSelectedIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxNormalSelected.png")));
                                     
      deleteAll.setDisabledIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxDisabledUnselected.png")));
                                  
      deleteAll.setDisabledSelectedIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxDisabledSelected.png")));
   }
   

   
   /**
    * Sets the grid bag layout.
    * ESCA-JAVA0076:
    */
   private void gridBagConstraints()
   {
      // Initialize grid bag layout of GUI.
      
      constraints = new GridBagConstraints();
      
      constraints.fill = GridBagConstraints.HORIZONTAL;
      
      
      
      // Grid bag constraints 1.
      
      constraints.insets = new Insets(10,0,0,0);
      
      
      constraints.ipadx = 0; 
      
      constraints.ipady = 0;

      constraints.gridwidth = 2;
      
      constraints.weightx = 0; 
      
      constraints.weighty = 1; 
      
      constraints.gridx = 0; 
      
      constraints.gridy = 0;
      
      
      contentPane.add(imagePane, constraints);
      
      
      // Grid bag constraints 2.
      
      constraints.insets = new Insets(10,1,0,1);
      
      
      constraints.ipadx = 0; 
      
      constraints.ipady = 0;

      constraints.gridwidth = 2;
      
      constraints.weightx = 0; 
      
      constraints.weighty = 0; 
      
      constraints.gridx = 0; 
      
      constraints.gridy = 1;
      
      
      contentPane.add(tabbedPane, constraints);
      
      
      // Grid bag constraints 3.
      
      constraints.insets = new Insets(20,1,10,1);
      
      
      constraints.ipadx = 0; 
      
      constraints.ipady = 0;

      constraints.gridwidth = 4;
      
      constraints.weightx = 0; 
      
      constraints.weighty = 0; 
      
      constraints.gridx = 0; 
      
      constraints.gridy = 2;
      
      
      contentPane.add(buttonPanel, constraints);
   }
   
   
   //*************************************** END INITIALISATION CODE ***************************************//
   
   
   //**************************************** START PUBLIC METHODS *****************************************//
   
   
   /**
    * Sets the visibility of the frame.
    */
   public void setVisibility()
   {
   
      if (isVisible) {frame.setVisible(true);}
      
      else {frame.setVisible(false);} 
   }
   
   
   
   /**
    * Clears the label icon.
    * @param icon
    */
   public static void clearLabelIcon(ImageIcon icon)
   {
      label.setIcon(icon); label.revalidate();
   }
   
   
   
   /**
    * Sets the label icon using a byte array.
    * @param videoArray
    * ESCA-JAVA0266:
    * ESCA-JAVA0166:
    */
   public static void setLabelIcon(byte[] videoArray)
   {
      try 
      {
         label.setIcon(new ImageIcon
         (
            ImageIO.read(new ByteArrayInputStream(videoArray)))
         );
      }
      
      catch (Exception e) 
      {
         System.out.println("Error refreshing the interface image frame.");
      }
   }
   
   
   
   /**
    * Appends information to the text output area.
    * @param value
    */
   public static void appendTextOutput(String value)
   {
      textOutput.append(value); textOutput.selectAll();
      
      int x = textOutput.getSelectionEnd();
      
      textOutput.select(x,x);
   }
   
   
   
   /**
    * Sets the messaging boolean variable.
    * @param value
    */
   public static void setIsMessaging(boolean value) {isMessaging = value;}
   
   
   
   /**
    * Returns the user id.
    * @return
    */
   public static String getUserId() {return userId;}
   
   
   
   /**
    * Returns the user id.
    * @return
    */
   public static String getUserPw() {return userPw;}
   
   
   //***************************************** END PUBLIC METHODS ******************************************//
   
   
   //**************************************** START PRIVATE METHODS ****************************************//
   
   
   /**
    * Sets the type of camera for the transceiver.
    */
   private void initialiseTransceiverWebcam()
   {
      if (camera.getSelectedItem().equals("1"))
      {
         avTransmit.setWebcamCamera(0);
      }
      
      if (camera.getSelectedItem().equals("2"))
      {
         avTransmit.setWebcamCamera(1);
      }
      
      if (camera.getSelectedItem().equals("3"))
      {
         avTransmit.setWebcamCamera(2);
      }
   }
   
   
   
   /**
    * Sets the type of camera for messaging.
    */
   private void initialiseMessagingWebcam()
   {
      if (camera.getSelectedItem().equals("1"))
      {
         avProcessor.setWebcamCamera(0);
      }
      
      if (camera.getSelectedItem().equals("2"))
      {
         avProcessor.setWebcamCamera(1);
      }
      
      if (camera.getSelectedItem().equals("3"))
      {
         avProcessor.setWebcamCamera(2);
      }
   }
   
   
   
   private class StartTransmitter extends Thread 
   {

      /** 
       * Thread that starts the transmitter.
       */
      private StartTransmitter()
      {
         setDaemon(false);
      }
      
      
      
      /**
       * ESCA-JAVA0166:
       * ESCA-JAVA0266:
       */
      public void run()
      {
         startTransmitter();  
      }
   }
   
   
   
   private class StartReceiver extends Thread 
   {

      /** 
       * Thread that starts the receiver.
       */
      private StartReceiver()
      {
         setDaemon(false);
      }
      
      
      
      /**
       * ESCA-JAVA0166:
       * ESCA-JAVA0266:
       */
      public void run()
      {
         startReceiver();
      }
   }
   
   
   
   private class StartMessaging extends Thread 
   {

      /** 
       * Thread that starts the receiver.
       */
      private StartMessaging()
      {
         setDaemon(false);
      }
      
      
      
      /**
       * ESCA-JAVA0166:
       * ESCA-JAVA0266:
       */
      public void run()
      {
         startMessaging();
      }
   }
   
   
   
   private class StopTransmitter extends Thread 
   {

      /** 
       * Thread that stops the transmitter.
       */
      private StopTransmitter()
      {
         setDaemon(false);
      }
      
      
      
      /**
       * ESCA-JAVA0166:
       * ESCA-JAVA0266:
       */
      public void run()
      {
         stopTransmitter();  
      }
   }
   
   
   
   private class StopReceiver extends Thread 
   {

      /** 
       * Thread that stops the receiver.
       */
      private StopReceiver()
      {
         setDaemon(false);
      }
      
      
      
      /**
       * ESCA-JAVA0166:
       * ESCA-JAVA0266:
       */
      public void run()
      {
         stopReceiver();  
      }
   }
   
   

   private class StopMessaging extends Thread 
   {

      /** 
       * Thread that starts the receiver.
       */
      private StopMessaging()
      {
         setDaemon(false);
      }
      
      
      
      /**
       * ESCA-JAVA0166:
       * ESCA-JAVA0266:
       */
      public void run()
      {
         stopMessaging();
      }
   }
   
   
   
   static class UppercaseDocumentFilter extends DocumentFilter 
   {
      
      /**
       * Tests the channel id insertion string for upper case.
       * @throws BadLocationException
       */
      public void insertString
      (
         DocumentFilter.FilterBypass fb, int offset, String text, AttributeSet attrs
      ) 
   
      throws BadLocationException {fb.insertString(offset, text.toUpperCase(), attrs);}

      
      /**
       * Converts the channel id insertion string to upper case.
       * @throws BadLocationException
       */
      public void replace
      (
         DocumentFilter.FilterBypass fb, int offset, int length, String text, AttributeSet attrs
      ) 
   
      throws BadLocationException {fb.replace(offset, length, text.toUpperCase(), attrs);}
   }
   
   
   
   /**
    * Starts the transmitter.
    * ESCA-JAVA0266:
    * ESCA-JAVA0166:
    */
   private void startTransmitter()
   {
      try
      {
         if (isPortValid())
         {
            // Create a audio transmit object with the specified parameters.
         
            String[] ports = dataTransmitPorts.getText().split(":");
            
            String transmitProtocol = (String)protocol.getSelectedItem();
            

            avTransmit = new AudioVideoTransmit
            (
               transmitProtocol, ipAddress.getText(), Integer.parseInt(ports[0]), Integer.parseInt(ports[1])
            );
            
            setTransmitterSettings();
      
         
            // Start the transmission.
      
            if (video.isSelected()) 
            {
               avTransmit.setIncludeVideo(true); initialiseTransceiverWebcam();
            }
         
         
            avTransmit.transmit(); appendTextOutput("\n Transmission has started.");
         
            transmit.setEnabled(false); receive.setEnabled(false);
         }

         else
         {
            appendTextOutput("\n Transmitter could not be started.");
         
            appendTextOutput("\n The port number may be invalid.");
            
            appendTextOutput("\n Port can't excede 5 digits.");
         }
      }
  
      catch (Exception e)
      {
         appendTextOutput("\n Transmitter could not be started.");
         
         appendTextOutput("\n The transmitter error is unknown.");
      }
   }
   
   
   
   /**
    * Stops the transmitter.
    * ESCA-JAVA0266:
    * ESCA-JAVA0166:
    */
   private void stopTransmitter()
   {
      try
      {  
         // Stop the transmission.
      
         avTransmit.setStopTransmit(true); avTransmit.cancel();
         
         
         appendTextOutput("\n Transmission has stopped."); 
         
         transmit.setEnabled(true); receive.setEnabled(true);
         
         
         setIsTransmitting(false); // Turns off the transmitter.
      }
 
      catch (Exception e)
      {
         appendTextOutput("\n Transmitter could not be stopped.");
         
         appendTextOutput("\n The transmitter error is unknown.");
      }
   }
   
   
   
   /**
    * Runs the receiver.
    * ESCA-JAVA0267:
    * ESCA-JAVA0166:
    * ESCA-JAVA0266:
    * ESCA-JAVA0076:
    * ESCA-JAVA0087:
    */
   private void startReceiver()
   {
      try
      {
         if (isPortValid() && isAddressValid())
         {
            // Create a audio receive object with the specified parameters.

            String[] ports = dataTransmitPorts.getText().split(":");
            
            String receiveProtocol = (String)protocol.getSelectedItem();
            
         
            avReceive = new AudioVideoReceive
            (
               receiveProtocol, ipAddress.getText(), Integer.parseInt(ports[0]), Integer.parseInt(ports[1])
            );

               
            // Start the reception.     
           
            avReceive.receive(); appendTextOutput("\n Reception has started.");
         
            transmit.setEnabled(false); receive.setEnabled(false);
         }
         
         else
         {
            appendTextOutput("\n Receiver could not be started.");
            
            appendTextOutput("\n The entered address may be invalid.");
         }
      }
        
      catch (Exception e)
      {
         appendTextOutput("\n Receiver could not be started.");
          
         appendTextOutput("\n The receiver error is unknown.");
      }
   }
   
   
   
   /**
    * Stops the receiver.
    * ESCA-JAVA0266:
    * ESCA-JAVA0166:
    */
   private void stopReceiver()
   {
      try
      {  
         // Stop the reception.
      
         avReceive.setStopReceive(true); avReceive.cancel();
      

         appendTextOutput("\n Reception has stopped.");
         
         transmit.setEnabled(true); receive.setEnabled(true);
         
         
         setIsReceiving(false); // Turns off the receiver.
      }
 
      catch (Exception e)
      {
         appendTextOutput("\n Receiver could not be stopped.");
         
         appendTextOutput("\n The receiver error is unknown.");
      }
   }
   
   
   
   /**
    * Starts the messaging.
    * ESCA-JAVA0266:
    * ESCA-JAVA0166:
    */
   private void startMessaging()
   {
      try
      {
         if (isVideoIdValid())
         {
            if (isWebServerReachable())
            {
               // Create a messaging object.

               avProcessor = new AudioVideoProcessor(videoId.getText());
         
         
               // Sets the mode of operation.
         
               if (play.isSelected()) 
               {
                  if (isChannelIdValid())
                  {
                     avProcessor.setModePlayback(true);
                     
                     avProcessor.setChannelId(channelId.getText());

                     
                     avProcessor.runProcessor(); // Start the messaging.
                  }
                  
                  else
                  {
                     setIsMessaging(false);
                  
                     appendTextOutput("\n Message could not be received.");
                      
                     appendTextOutput("\n A valid channel id is required.");
                  }
               }
         
               if (record.isSelected()) 
               {
                  avProcessor.setModeRecord(true);                
                  
                  setProcessorSettings(); initialiseMessagingWebcam();

                  
                  avProcessor.runProcessor(); // Start the messaging.
               }
            }
         }
         
         else
         {
            setIsMessaging(false); 
         
            appendTextOutput("\n Messaging could not be started.");
             
            appendTextOutput("\n The video id number may be invalid.");
              
            appendTextOutput("\n Video id can't excede 8 digits.");
            
            appendTextOutput("\n The video image size may be invalid.");
            
            appendTextOutput("\n Maximum video size is 350 x 240.");
         }
      }
  
      catch (Exception e)
      {
         setIsMessaging(false); 
      
         appendTextOutput("\n Messaging could not be started.");
         
         appendTextOutput("\n The messaging error is unknown.");
      }
   }
   
   
   
   /**
    * Stops the messaging.
    * ESCA-JAVA0266:
    * ESCA-JAVA0166:
    */
   private void stopMessaging()
   {
      try
      {
         if (getIsMessaging())
         {
            if (record.isSelected())
            {
               avProcessor.setStopRecord(true);

               appendTextOutput("\n Recording has stopped.");
            }
         
            if (play.isSelected())
            {
               avProcessor.setStopPlayback(true);
            
               appendTextOutput("\n Playback has stopped."); 
            }
         
            setIsMessaging(false);
         }
      }
 
      catch (Exception e)
      {
         appendTextOutput("\n Messaging could not be stopped.");
         
         appendTextOutput("\n The messaging error is unknown.");
      }
   }
   
   
   
   private class DeleteMessageListener implements ActionListener
   {
   
      /** 
       * Listener to delete recorded messages from database.
       * ESCA-JAVA0266 
       */
      public void actionPerformed(ActionEvent event)
      {  
         if ((userId != null) && (!runRestricted)
         && (!userId.equals("NON_MEMBER")))
         {
            clearDatabase();
         }
      }
   }
   
   
   
   private class SelectListener 
   implements ChangeListener
   {   
      
      /**
       * Listener constructor.
       * @param value
       */
      private SelectListener(int value)
      {
         checkBox = value;  
      }
   
      
      
      /**
       * Listener to enforce at least one
       * selection for transmit or receive.
       */
      public void stateChanged(ChangeEvent changeEvent) 
      {
         if (!isTransceiverChecked())
         {
            switch (checkBox)
            {
               case 0: 
        
                  transmit.setSelected(true); 
                  
               break;
        
                  
               case 1: 
               
                  receive.setSelected(true); 
                  
               break;
                  
                  
               default:
              
                  transmit.setSelected(true);
             
                  receive.setSelected(true); 
             
               break;
            }
         }
      }
      
      
      private int checkBox;
   };
   
   
   
   private class StartButtonListener
   implements ActionListener
   {
      /** 
       * Listener to start transmission or reception.
       * ESCA-JAVA0266 
       */
      public void actionPerformed(ActionEvent event)
      {
         if (transceiver.isSelected())
         {
            if (transmit.isSelected())
            {
               if (!getIsTransmitting())
               {
                  appendTextOutput("\n Starting transmitter."); 
               
                  Thread startTransmitter = new StartTransmitter();
               
                  startTransmitter.start(); setIsTransmitting(true);
               }
            }

         
            if (receive.isSelected())
            {
               if (!getIsReceiving())
               {
                  appendTextOutput("\n Starting receiver."); 
               
                  Thread startReceiver = new StartReceiver();
                
                  startReceiver.start(); setIsReceiving(true);
               }
            } 
         }
         
         
         if (messaging.isSelected())
         {
            if (!getIsMessaging())
            {
               appendTextOutput("\n Starting messaging.");
               
               Thread startMessaging = new StartMessaging();
             
               startMessaging.start(); setIsMessaging(true);
            }
         } 
         
          
         tabbedPane.setSelectedIndex(5);
      }
   }
   
   
   
   private class StopButtonListener
   implements ActionListener
   {
      /** 
       * Listener to stop transmission or reception.
       * ESCA-JAVA0266 
       */
      public void actionPerformed(ActionEvent event)
      {
         if (transceiver.isSelected())
         {
            if (transmit.isSelected())
            {
               if (getIsTransmitting())
               {
                  appendTextOutput("\n Stopping transmitter.");
               
                  Thread stopTransmitter = new StopTransmitter();
                
                  stopTransmitter.start();
               }
            }
         
            if (receive.isSelected())
            {
               if (getIsReceiving())
               {
                  appendTextOutput("\n Stopping receiver.");
               
                  Thread stopReceiver = new StopReceiver();
                
                  stopReceiver.start();
               }
            }          
         }
         
         
         if (messaging.isSelected())
         {
            if (getIsMessaging())
            {
               appendTextOutput("\n Stopping messaging.");             
               
               Thread stopMessaging = new StopMessaging();

               stopMessaging.start();
            }
         }
      }
   }
   
   

   /**
    * Adds a settings menu. 
    * @return menu
    */
   private JMenu createSettingsMenu()
   {
      JMenu menu = new JMenu("Mode"); 
      

      transceiver = new JRadioButtonMenuItem("Transceiver");
      
      messaging = new JRadioButtonMenuItem("Messaging");
      

      ButtonGroup group = new ButtonGroup();
      
      
      group.add(transceiver); group.add(messaging);
      
      group.add(delete); menu.add(transceiver); 
      
      menu.add(messaging);
      
      
      if ((userId == null) || (runRestricted)
      || (userId.equals("NON_MEMBER")))
      {
         messaging.setEnabled(false);
      }
      
      
      transceiver.setSelected(true);

      
      return menu;
   }
   
   
   
   /**
    * Tests if an address is reachable.
    * ESCA-JAVA0266:
    * @param address
    * @return
    */
   @SuppressWarnings("unused")
   private static boolean isAddressReachable(String address)
   {
      boolean reachable = false;
      
      
      try
      {
         if (InetAddress.getByName(address).isReachable(PING_TIMEOUT))
         {
            reachable = true;
         }
      }
      
      
      catch (IOException e)
      {
         appendTextOutput("\n An unknown connection error occured.");
      }
      

      return reachable;   
   }
   
   
   
   /**
    * Tests if the web server is reachable.
    * @return
    */
   private static boolean isWebServerReachable()
   {
      boolean valid = false; 

      
      if (isWebServerReachable(DataUploadDownload.getFileDownloadAddress())
      && isWebServerReachable(DataUploadDownload.getFileUploadAddress()))
      {
         valid = true;
      }
      
      
      return valid;  
   }
   
   
   
   /**
    * Validation test for channel id.
    * @return
    */
   private boolean isChannelIdValid()
   {
      boolean valid = false; 

      
      if (validation.alphanumericValidation(channelId.getText()) 
      && (channelId.getText().length() <= MAX_CHANNEL_ID_LENGTH)
      && (channelId.getText().length() >= MIN_CHANNEL_ID_LENGTH))
      {
         valid = true;
      }
      
      
      return valid;
   }
   
   
   
   /**
    * Validation test for video id.
    * @return
    */
   private boolean isVideoIdValid()
   {
      boolean valid = false; 

      
      if (validation.integerValidation(videoId.getText()) 
      && (videoId.getText().length() <= MAX_VIDEO_ID_LENGTH))
      {
         valid = true;
      }
      
      
      return valid;
   }
   
   
   
   /**
    * Validation test for port.
    * @return
    */
   private boolean isPortValid()
   {
      boolean valid = false; 

      
      String[] ports = dataTransmitPorts.getText().split(":");
      
      if ((validation.integerValidation(ports[0])) && (ports[0].length() <= MAX_PORT_LENGTH)
      && (validation.integerValidation(ports[1])) && (ports[1].length() <= MAX_PORT_LENGTH))
      {
         valid = true;
      }
      
      
      return valid;
   }
   
   
   
   /**
    * Validation test for address.
    * @return
    */
   private boolean isAddressValid()
   {
      boolean valid = false; 

      
      if (validation.ipAddressValidation(ipAddress.getText()))
      {
         valid = true;
      }
      
      
      return valid;
   }
   
   
   
   /**
    * Tests if the web server is reachable.
    * ESCA-JAVA0266:
    * @param address
    * @return
    */
   private static boolean isWebServerReachable(String address)
   {
      final int SUCCESS_CODE = 200; boolean reachable = false;
      
      
      try
      {  
         URL url = new URL(address);
    
         HttpURLConnection huc = (HttpURLConnection)url.openConnection(); 
    
         huc.setRequestMethod("GET");  // or huc.setRequestMethod("HEAD"); 
    
         huc.connect(); int code = huc.getResponseCode();
         
         
         if (code == SUCCESS_CODE) {reachable = true;}
      }
      
     
      catch (IOException e)
      {
         setIsMessaging(false); // Turns off the messaging. 
      
         appendTextOutput("\n Messaging could not be started.");
          
         appendTextOutput("\n Could not connect to the web server.");
      }
      

      return reachable;   
   }
   
   
   
   /**
    * Updates the progress bar.
    * @param text
    * @param indeterminate
    */
   public static void updateProgressBar(String text, boolean indeterminate)
   {
      progressBar.setIndeterminate(indeterminate);
   
      progressBar.setString(text);   
   }
   
   
   
   /**
    * Sets the settings for the processor.
    */
   private void setProcessorSettings()
   {
      final int videoQualityDivider = 100; final float maxVideoQualityFactor = 0.75f;
      
      final int frameRateDivider = 3;
 
      
      avProcessor.setAudioSamples(Integer.parseInt((String)samples.getSelectedItem()));
      
      avProcessor.setFrameRate((chunks.getValue()+frameRateDivider)/frameRateDivider);
      
      
      avProcessor.setVideoQuality
      (
         ((float)(quality.getValue())/videoQualityDivider) * maxVideoQualityFactor
      );
      
      
      videoSizeInfo = ((String)size.getSelectedItem()).split("x");
      
      
      avProcessor.setVideoHeight(Integer.parseInt(videoSizeInfo[1]));
      
      avProcessor.setVideoWidth(Integer.parseInt(videoSizeInfo[0]));
       
       
      if (mono.isSelected()) {avProcessor.setAudioChannels(1);}
       
      if (stereo.isSelected()) {avProcessor.setAudioChannels(2);}
       
       
      if (minBytes.isSelected()) {avProcessor.setAudioBytes(1);}
       
      if (maxBytes.isSelected()) {avProcessor.setAudioBytes(2);}
      
      
      if (video.isSelected()) {avProcessor.setIncludeVideo(true);}
      
      else {avProcessor.setIncludeVideo(false);}
   }
   

   
   /**
    * Sets the settings for the transmitter.
    */
   private void setTransmitterSettings()
   {
      final int videoQualityDivider = 100; final float maxVideoQualityFactor = 0.75f;
      
      final int minFrameRate = 25; final double rateMultiplyFactor = 4.75;
      
      final int frameRateInvert = 100;
      

      avTransmit.setAudioSamples(Float.parseFloat((String)samples.getSelectedItem()));
      
      avTransmit.setAudioChunkFactor(chunks.getValue());
      
      
      avTransmit.setFrameRate
      (
         minFrameRate + (int)((frameRateInvert - rate.getValue()) * rateMultiplyFactor)
      );
      
      
      avTransmit.setVideoQuality
      (
         ((float)(quality.getValue())/videoQualityDivider) * maxVideoQualityFactor
      );
     
      
      videoSizeInfo = ((String)size.getSelectedItem()).split("x");
      
      
      avTransmit.setVideoHeight(Integer.parseInt(videoSizeInfo[1]));
      
      avTransmit.setVideoWidth(Integer.parseInt(videoSizeInfo[0]));
       
       
      if (mono.isSelected()) {avTransmit.setAudioChannels(1);}
       
      if (stereo.isSelected()) {avTransmit.setAudioChannels(2);}
       
       
      if (minBytes.isSelected()) {avTransmit.setAudioBytes(1);}
       
      if (maxBytes.isSelected()) {avTransmit.setAudioBytes(2);}
      
      
      if (video.isSelected()) {avTransmit.setIncludeVideo(true);}
      
      else {avTransmit.setIncludeVideo(false);}
   }
   
   
   
   /**
    * Clears the messages from the database.
    */
   private void clearDatabase()
   {
      ArrayList data = new ArrayList();   

      
      if (deleteAll.isSelected())
      {
         Portal.clearFromDatabase(MESSAGE_CLEAR_ALL, userId, userPw, null); 
      }
       
      else
      {
         data.add(videoId.getText());
      
         Portal.clearFromDatabase(MESSAGE_CLEAR_ID, userId, userPw, data); 
      }   
   }

   
   
   /**
    * Window resize event.
    */
   private void includeResizeEvent()
   {
      this.addComponentListener 
      (
         new ComponentAdapter() 
         {
            public void componentResized(ComponentEvent e) 
            {
               appletDisplayHandler();
            }
          
         }
      ); 
   }
   
   
   
   /**
    * Controls the JApplet component visibility. 
    * ESCA-JAVA0266:
    */
   private void appletDisplayHandler()
   {
      final String ZOOM_WARNING = 
   
      "It appears that web pages in your browser are zoomed out. \n\n" +
      "In order to display the applet, your browser needs to be set \n" +
      "at its default zoom level of 100% or greater. \n\n" +
      "Sorry about that.";
   
   
      if ((getWidth() < FRAME_SIZE_X) || (getHeight() < APPLET_SIZE_Y))
      {
         contentPane.setVisible(false); menuBar.setVisible(false);
      
         
         if (!zoomWarningShown) 
         {
            Message.showMessage(ZOOM_WARNING, "Browser zoom setting", "warning");
            
            zoomWarningShown = true;
         } 
      }
       
      else 
      {
         contentPane.setVisible(true); menuBar.setVisible(true);
      } 
   }
   
   
   
   /**
    * Tests if at least one transceiver check box is selected.
    * @return
    */
   private boolean isTransceiverChecked()
   {
      if (transmit.isSelected()) {return true;}
      
      else if (receive.isSelected()) {return true;}
      
      else {return false;}
   }
   
   
   
   /**
    * Sets the transmission boolean variable.
    * @param value
    */
   private void setIsTransmitting(boolean value) {isTransmitting = value;}
   
   
   
   /**
    * Sets the reception boolean variable.
    * @param value
    */
   private void setIsReceiving(boolean value) {isReceiving = value;}
   
   
   
   /**
    * Gets the recording boolean variable.
    * @return
    */
   private static boolean getIsMessaging() {return isMessaging;}
   
   

   /**
    * Gets the transmission boolean variable.
    * @return
    */
   private boolean getIsTransmitting() {return isTransmitting;}
   
   
   
   /**
    * Gets the reception boolean variable.
    * @return
    */
   private boolean getIsReceiving() {return isReceiving;}
   

   //***************************************** END PRIVATE METHODS *****************************************//
   
   
   //********************************************** START MAIN *********************************************//
   
   
   /**
    * Main
    * @param args
    */
   public static void main(String[] args)
   {
      isApplication = true;
      
      isVisible = true;
   
      new OnlineMessagingGui();
   }
   
   
   //*********************************************** END MAIN **********************************************//
   
  
   /**
    * ESCA-JAVA0007:
    */
   public JFrame frame;

   private JMenuBar menuBar;
   private static JLabel label;
   private Validation validation;
   private Container contentPane;
   private DocumentFilter filter;
   private String[] videoSizeInfo;
   private JTabbedPane tabbedPane;
   private static boolean isMessaging;
   private static JTextArea textOutput;
   private AudioVideoReceive avReceive;
   private JButton delete, start, stop;
   private static JScrollPane textPane;
   private static JScrollPane imagePane;
   private static String userId, userPw;
   private JSlider quality, rate, chunks;
   private AudioVideoTransmit avTransmit;
   private GridBagConstraints constraints;
   private AudioVideoProcessor avProcessor;
   private static JProgressBar progressBar;
   private ButtonGroup channelsGroup, bytesGroup;
   private JRadioButtonMenuItem transceiver, messaging;
   private JRadioButton mono, stereo, minBytes, maxBytes;
   private JComboBox protocol, camera, samples, size;
   private boolean isTransmitting, isReceiving, zoomWarningShown;
   private JCheckBox deleteAll, transmit, receive, video, record, play;
   private JTextField channelId, videoId, deleteId, ipAddress, dataTransmitPorts;

   private String[] cameraChoices = {"1", "2", "3"};
   private String[] protocolChoices = {"TCP", "UDP"};
   private String[] sizeChoices = {"176x144", "320x240", "432x240"};
   private String[] samplesChoices = {"8000", "16000", "32000", "44100", "48000"};

   private JPanel imagePanel, buttonPanel, transceiverPanel, frameRatePanel,
   recordPanel, protocolPanel, playPanel, chunkSizePanel, deletePanel, videoQualityPanel,
   videoSizePanel, messagingPanel, videoPanel, audioPanel, channelsPanel, feedbackPanel, bytesPanel,
   transmitPanel, receivePanel, videoIdPanel, videoIncPanel, cameraPanel, samplesPanel, deleteAllPanel;
   

   //********************************************** END CLASS **********************************************//

}


/*
   COPYRIGHT (C) 2010 - 2014 by Alexander Wait. All Rights Reserved.

   This class records and plays video and audio.

   @site http://www.javaika.com
   @author Alexander Wait
   @version 2014-07-25
*/



import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.TargetDataLine;
import javax.swing.ImageIcon;
import javax.swing.JFrame;

import com.github.sarxos.webcam.Webcam;



public class AudioVideoProcessor extends JFrame
{

   private static final long serialVersionUID = 1L;
   
   
   private static final int SQL_TABLE_COLUMN_A = 0;
   
   private static final int SQL_TABLE_COLUMN_B = 1;
   
   private static final int SQL_TABLE_COLUMN_C = 2;
   
   private static final int SQL_TABLE_COLUMN_D = 3;
   
   private static final int SQL_TABLE_COLUMN_E = 4;


   /* Configuration Settings */
   
   private static final int MAX_RECORD_BYTE_SIZE = 30000000; // 30 Megabyte maximum.

   private static final String FLAG = "*-^-*"; // Key to separate multiplex frames.
   
   private static boolean VIDEO = false; // Video recording is disabled by default.
   
   
   private static final String MESSAGE_WRITE_ADDRESS = "http://" + Domain.getDomain() 
   
   + "/bridge/record-message-config-write.php" + Domain.getPort(); // Port:80
   
   
   private static final String MESSAGE_READ_ADDRESS = "http://" + Domain.getDomain() 
   
   + "/bridge/record-message-config-read.php" + Domain.getPort(); // Port:80
   

   //************************************** START INITIALISATION CODE **************************************//


   /**
    * Class constructor.
    * @param videoId
    * ESCA-JAVA0266:
    */
   public AudioVideoProcessor(String videoId)
   {
      videoThumbnail = new ImageIcon(this.getClass().getResource
      
      ("files/images/VideoMessagingImageBlank.png"));
   
   
      dataUploadDownload = new DataUploadDownload();

      videoStream = new ByteArrayOutputStream();
      
      setMessageId(videoId);
   }
   
   
   //*************************************** END INITIALISATION CODE ***************************************//
   
   
   //**************************************** START PUBLIC METHODS *****************************************//
   
   
   /**
    * Runs the message processor.
    * ESCA-JAVA0166:
    * ESCA-JAVA0266:
    */
   public void runProcessor()
   {
      try
      {
         if (getModeRecord())
         {
            setBufferArray(); record(); 
            
            transferToDatabase(); encodeBytes(); exportBytes(); 
         }   
      
         if (getModePlayback())
         {
            importBytes(); readFromDatabase();
            
            setBufferArray(); decodeBytes(); playback();
         }
      }
      
      
      catch (Exception e) 
      { 
         System.out.println("Error running the processor.");
      }
   }
   
   
   
   /**
    * Stops the recording.
    * ESCA-JAVA0266:
    * ESCA-JAVA0166:
    */
   public void cancel()
   { 
      stopRefresh = true;  
   
   
      try
      { 
         if (targetDataLine != null)  
         { 
            if (targetDataLine.isOpen()) {targetDataLine.close();}
         }
         
         if (sourceDataLine != null)  
         { 
            if (sourceDataLine.isOpen()) {sourceDataLine.close();}
         }

         if (videoStream != null) {videoStream.close();}
         
         if (webcam != null) {webcam.close();}
      }
      
      catch (IOException e) {System.out.println(e);} 
   }
   
   
   
   /**
    * Sets the video inclusion boolean variable.
    * @param value
    */
   public void setIncludeVideo(boolean value) {VIDEO = value;}
   
   
   
   /**
    * Sets the current record size.
    * @param val
    */
   public void setCurrentSize(int val) {currentSize = val;}
   
   
   
   /**
    * Sets the audio samples.
    * @param val
    */
   public void setAudioSamples(int val) {audioSamples = val;}
   
   
   
   /**
    * Sets the video quality.
    * @param val
    */
   public void setVideoQuality(float val) {videoQuality = val;}
   
   
   
   /**
    * Sets the channel id.
    * @param val
    */
   public void setChannelId(String val) {channelId = val;}
   
   
   
   /**
    * Sets the message id.
    * @param val
    */
   public void setMessageId(String val) {messageId = val;}
   
   
   
   /**
    * Sets the audio channels.
    * @param val
    */
   public void setAudioChannels(int val) {audioChannels = val;}
   
   
   
   /**
    * Sets the frame rate.
    * @param val
    */
   public void setFrameRate(int val) {frameRate = val;}
   
   
   
   /**
    * Sets the audio byte number.
    * @param val
    */
   public void setAudioBytes(int val) {audioBytes = val;}
   
   
   
   /**
    * Sets the video width.
    * @param val
    */
   public void setVideoWidth(int val) {videoWidth = val;}
   
   
   
   /**
    * Sets the video height.
    * @param val
    */
   public void setVideoHeight(int val) {videoHeight = val;}
   
   
   
   /**
    * Sets the record boolean.
    * @param val
    */
   public void setModeRecord(boolean val) {modeRecord = val;}
   
   
   
   /**
    * Sets the play boolean.
    * @param val
    */
   public void setModePlayback(boolean val) {modePlayback = val;}
   
   
   
   /**
    * Sets the record boolean.
    * @param val
    */
   public void setStopRecord(boolean val) {stopRecord = val;}
   
   
   
   /**
    * Sets the play boolean.
    * @param val
    */
   public void setStopPlayback(boolean val) {stopPlayback = val;}
   
   
   
   /**
    * Sets the camera variable.
    * @param value
    */
   public void setWebcamCamera(int value) {webcamCamera = value;}
   
   
   //***************************************** END PUBLIC METHODS ******************************************//
   
   
   //**************************************** START PRIVATE METHODS ****************************************//  

   
   private class StartRefreshing extends Thread 
   {

      /** 
       * Thread that starts frame refreshing.
       */
      private StartRefreshing() 
      {
         setDaemon(false);
      }
      
      
      
      /**
       * ESCA-JAVA0166:
       * ESCA-JAVA0266:
       */
      public void run()
      {
         refreshImageFrame();  
      }
   }
   
   
   
   /**
    * Sets the label icon using a byte array.
    * @param videoArray
    * ESCA-JAVA0266:
    */
   private static void setLabelIcon(byte[] videoArray)
   {
      OnlineMessagingGui.setLabelIcon(videoArray);
   }
   
   
   
   /**
    * Starts the web camera.
    * ESCA-JAVA0266:
    */
   private void startWebcam()
   {
      webcam = Webcam.getWebcams().get(getWebcamCamera());
      
      webcam.setCustomViewSizes(new Dimension[] {new Dimension(getVideoWidth(), getVideoHeight())});

      webcam.setViewSize(new Dimension(getVideoWidth(), getVideoHeight())); webcam.open();
   }
   
   
   
   /**
    * Sets the audio buffer array.
    */
   private void setBufferArray()
   {
      int testSize = (int)Math.floor
      (
         (double)(getAudioSamples() * getAudioBytes() * getAudioChannels()) / getFrameRate()
      ); 
      

      int frameSize = getAudioBytes() * getAudioChannels();
      
     
      for (int i = 0; i < frameSize; i ++)
      {
         if ((testSize % frameSize) == 0)
         {
            audioBufferSize = testSize; break;
         }
         
         else {testSize --;}
      }
      

      audioByteArray = new byte[getAudioBufferSize()];
   }
   
   
   
   /**
    * Starts the target data line.
    * ESCA-JAVA0266:
    */
   private void startTargetLine()
   {   
      DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, getAudioFormat());
      
        
      try
      {
         targetDataLine = (TargetDataLine) AudioSystem.getLine(dataLineInfo);
         
         targetDataLine.open(getAudioFormat());
      }
         
      catch (LineUnavailableException e)
      { 
         System.out.println("The audio system line is unavailable.");
      }
         
         
      targetDataLine.start();         
   }
   
   
   
   /**
    * Starts the source data line.
    * ESCA-JAVA0266:
    */
   private void startSourceLine()
   {
      DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, getAudioFormat());
      
      
      try
      {      
         sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
      
         sourceDataLine.open(getAudioFormat());        
      }
      
      catch (LineUnavailableException e)
      {
         System.out.println("The audio system line is unavailable.");
      }
      
      
      sourceDataLine.start();
   }
   
   

   /**
    * Returns the audio format.
    * @return
    */
   private AudioFormat getAudioFormat()
   {
      boolean signed = true; boolean bigEndian = false;
    
      
      return new AudioFormat
      (
         getAudioSamples(), (8 * getAudioBytes()), getAudioChannels(), signed, bigEndian
      );
   }
   
   

   /**
    * Refreshes the camera frame.
    */
   private void refreshImageFrame()
   {
      while (!stopRefresh)
      {  
         image = webcam.getImage();
      }
   }
   
   
   
   /**
    * Reads settings from the database.
    */
   private void readFromDatabase()
   {
      readSettings = new ArrayList<String>(); writeSettings = new ArrayList<String>();
      
      writeSettings.add(getMessageId()); writeSettings.add(getChannelId());
      
      
      readSettings = Portal.phpToJavaGate
      (
         MESSAGE_READ_ADDRESS, OnlineMessagingGui.getUserId(), 
         
         OnlineMessagingGui.getUserPw(), writeSettings
      );
      
      
      if (readSettings.size() != 0)
      {
         setAudioChannels(Integer.parseInt(readSettings.get(SQL_TABLE_COLUMN_A)));
         
         setAudioSamples(Integer.parseInt(readSettings.get(SQL_TABLE_COLUMN_B)));
         
         setAudioBytes(Integer.parseInt(readSettings.get(SQL_TABLE_COLUMN_C)));
         
         setFrameRate(Integer.parseInt(readSettings.get(SQL_TABLE_COLUMN_D)));
         
         
         if (readSettings.get(SQL_TABLE_COLUMN_E).equals("1")) // 1 = on, 0 = off
         {
            setIncludeVideo(true);
         }
      }
   }
   

   
   /**
    * Starts the recording.
    * ESCA-JAVA0265:
    * ESCA-JAVA0087:
    */
   private void record()
   {
      OnlineMessagingGui.appendTextOutput("\n Getting ready to record.");
      
      
      startTargetLine(); // Start the audio data line for audio/video recording.
      
      
      if (isIncludeVideo())
      {  
         startWebcam(); frameRefreshing = new StartRefreshing(); frameRefreshing.start();
      }
      
      
      try {Thread.sleep(5000);} catch (InterruptedException e1) {e1.printStackTrace();}
      
      
      OnlineMessagingGui.appendTextOutput("\n Recording has started.");
      
      messageBytes.add(getFlagBytes()); // Adds flag bytes before record start.

     
      while (!(getStopRecord()) && !(getCurrentSize() > MAX_RECORD_BYTE_SIZE))
      {
         OnlineMessagingGui.updateProgressBar
         (
            "Recording Message (" + returnProgressPercentage() + "%)", false
         );
      

         if (isIncludeVideo())
         {
            recordAudioVideo(); // Record audio and video bytes if video enabled.
         }
         
         
         else
         {
            recordAudio(); // Record only audio bytes if video is disabled.
         }
         
         
         messageBytes.add(getFlagBytes()); // Adds the break flag.
         
         
         setCurrentSize(getMessageSize()); // Sets current size.
      }
      

      OnlineMessagingGui.appendTextOutput("\n Recording has completed.");
      
      OnlineMessagingGui.updateProgressBar("Recording Complete", false);

      
      disableCameraRefresh(); cancel();
   }
   
   
   
   /**
    * Record both audio and video.
    */
   private void recordAudioVideo()
   {
      compressImage(image); audioByteArray = new byte[getAudioByteArrayLength()]; 
       

      targetDataLine.read(getAudioByteArray(), 0, getAudioByteArrayLength()); 
      
      
      byte[] audioData = getAudioByteArray(); byte[] videoData = getVideoByteArray();
      
      
      byte[] combine = new byte[audioData.length + videoData.length];
       
       
      System.arraycopy(audioData, 0, combine, 0, audioData.length);
       
      System.arraycopy(videoData, 0, combine, audioData.length, videoData.length);
      
      
      messageBytes.add(combine); resetVideoStream();   
   }
   
   
   
   /**
    * Play both audio and video.
    * @param index
    */
   private void playAudioVideo(int index)
   {
      byte[] audioData = Arrays.copyOfRange
      (
         messageBytes.get(index), 0, getAudioBufferSize()
      );

       
      byte[] videoData = Arrays.copyOfRange
      (
         messageBytes.get(index), getAudioBufferSize(), messageBytes.get(index).length
      );   


      sourceDataLine.write(audioData, 0, audioData.length); setLabelIcon(videoData);
   }
   
   
   
   /**
    * Record only the audio.
    */
   private void recordAudio()
   {
      audioByteArray = new byte[getAudioByteArrayLength()]; 
       

      targetDataLine.read(getAudioByteArray(), 0, getAudioByteArrayLength());  
   
      
      messageBytes.add(getAudioByteArray());   
   }
   
   
   
   /**
    * Play only the audio.
    * @param index
    */
   private void playAudio(int index)
   {
      sourceDataLine.write(messageBytes.get(index), 0, messageBytes.get(index).length);
   }
   
   
   
   /**
    * Returns the progress percentage.
    * @return
    */
   private int returnProgressPercentage()
   {
      double result = ((double)getCurrentSize() / MAX_RECORD_BYTE_SIZE) * 100;
      
      return (int)result;
   }
   
   
   
   /**
    * Compresses the buffered image before storage.
    * ESCA-JAVA0266:
    * @param img
    */
   private void compressImage(BufferedImage img)
   {     
      try
      {          
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         
         ImageOutputStream ios = ImageIO.createImageOutputStream(baos);
        
         
         Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg");
         
         ImageWriter writer = writers.next();
          
         
         ImageWriteParam param = writer.getDefaultWriteParam();
         
         
         param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
         
         param.setCompressionQuality(getVideoQuality()); writer.setOutput(ios); 
         
         writer.write(null, new IIOImage(img, null, null), param);
             
         
         byte[] dump = baos.toByteArray(); writer.dispose(); 
             
         getVideoStream().write(dump, 0, dump.length);         
      }
        
      catch (IOException e)
      { 
         System.out.println("An error has occured during image compression.");
      }
   }
   
   

   /**
    * Starts the play back.
    */
   private void playback()
   {
      startSourceLine(); OnlineMessagingGui.appendTextOutput("\n Playback has started.");
      
      
      OnlineMessagingGui.updateProgressBar("Playing Message", false); final int inc = 2;
      
      
      for (int i = 1; i < (indexes.size() / inc) * inc; i += inc)  
      {
         if (isIncludeVideo())
         {
            playAudioVideo(i); // Play audio and video bytes if video enabled. 
         }

         else
         {    
            playAudio(i); // Play only audio bytes if video is disabled.
         }
         
         
         if (getStopPlayback()) {break;} 
      }
      
      if (!getStopPlayback()) 
      {
         OnlineMessagingGui.appendTextOutput("\n Playback has completed.");
         
         OnlineMessagingGui.updateProgressBar("Playback Complete", false);
         
         OnlineMessagingGui.setIsMessaging(false);
      }
      
      
      OnlineMessagingGui.clearLabelIcon(videoThumbnail); cancel();
   }
   
   
   
   /**
    * Encodes bytes to an array.
    * ESCA-JAVA0266:
    */
   private void encodeBytes()
   {
      data = new byte[getMessageSize()]; 
      
      
      int index = 0; int size = messageBytes.size();
  
  
      for (int i = 0; i < size; i++)
      {
         byte[] dump = messageBytes.get(i);
         
            
         for (int j = 0; j < dump.length; j ++)
         {
            data[j + index] = dump[j];
         }
         
         
         index += dump.length; 
      }
   }
   
   
   
   /**
    * Decodes bytes to array lists.
    */
   private void decodeBytes()
   {
      addIndexes(); messageBytes.add(getFlagBytes()); final int inc = 2;


      for (int i = 0; i < (indexes.size() / inc) * inc; i += inc)
      {  
         messageBytes.add
         (
            Arrays.copyOfRange(data, indexes.get(i), indexes.get(i + 1) +1)
         );
         

         messageBytes.add(getFlagBytes());
      }
   }
   


   /**
    * Gets the size of message bytes.
    * @return
    */
   private int getMessageSize()
   {
      int size = 0;

      for (int i = 0; i < messageBytes.size(); i++)
      {
         size += messageBytes.get(i).length;
      }
      

      return size;
   }
   
   
   
   /**
    * Imports the bytes.
    */
   private void importBytes()
   {
      data = dataUploadDownload.importMessageData
      (
         OnlineMessagingGui.getUserId(),
         
         OnlineMessagingGui.getUserPw(),
         
         getMessageId(), getChannelId()
      );
   }
   
   
   
   /**
    * Exports the bytes.
    */
   private void exportBytes()
   {
      dataUploadDownload.exportMessageData
      (
         OnlineMessagingGui.getUserId(),
             
         OnlineMessagingGui.getUserPw(),
         
         getMessageId(), data
      );
   }
   
   
   
   /**
    * Gets the flag byte array.
    * @return
    */
   private static byte[] getFlagBytes()
   {
      byte[] flagArray = new byte[FLAG.length()];
   
      
      for (int i = 0; i < flagArray.length; i ++)
      {
         flagArray[i] = (byte) FLAG.charAt(i);
      }
      
      
      return flagArray;
   }
   
   
   
   /**'
    * Tests if an index position is the start of a frame.
    * @param index
    * @return
    */
   private boolean isFrameStart(int index)
   {
      int count = 0;
      
      
      if (index > (FLAG.length() -1))
      {   
         for (int i = 1; i <= FLAG.length(); i ++)
         {
            if ((char)data[index - i] == FLAG.charAt(FLAG.length() - i))
            {
               count ++;
            }
         }
      
         if (count == FLAG.length()) {return true;}
      
         else {return false;}
      }
      
      else {return false;}
   }
   
   
   
   /**'
    * Tests if an index position is the end of a frame.
    * @param index
    * @return
    */
   private boolean isFrameStop(int index)
   {
      int count = 0;
      
      
      if (index < (data.length - FLAG.length()))
      {   
         for (int i = 1; i <= FLAG.length(); i ++)
         {
            if ((char)data[index + i] == FLAG.charAt(i - 1))
            {
               count ++;
            }
         }
      
         if (count == FLAG.length()) {return true;}
      
         else {return false;}
      }
      
      else {return false;}
   }
   
   

   /**
    * Adds the frame start-stop indexes to array lists.
    */
   private void addIndexes()
   {
      for (int i = 0; i < data.length; i ++)
      {
         if (isFrameStart(i) || isFrameStop(i)) {indexes.add(i);}
      }
   }
   
   
   
   /**
    * Transfers the settings to the database.
    */
   private void transferToDatabase()
   {
      writeSettings = new ArrayList<String>();

      
      writeSettings.add(getMessageId());
      
      writeSettings.add(getIncludeVideo());
      
      writeSettings.add(Integer.toString(getAudioChannels()));
      
      writeSettings.add(Integer.toString(getAudioSamples()));
      
      writeSettings.add(Integer.toString(getAudioBytes()));
      
      writeSettings.add(Integer.toString(getFrameRate()));
      
      
      Portal.javaToPhpGate
      (
         MESSAGE_WRITE_ADDRESS, OnlineMessagingGui.getUserId(), 
         
         OnlineMessagingGui.getUserPw(), writeSettings
      );  
   }
   

   
   /**
    * Disables the camera refreshing.
    */
   private void disableCameraRefresh() {stopRefresh = true;}
   
   
   
   /**
    * Resets the byte array output stream.
    */
   private void resetVideoStream() {videoStream.reset();}
   
   
   
   /**
    * Gets the video inclusion boolean variable.
    * @return
    */
   private static boolean isIncludeVideo() {return (VIDEO);}
   
   
   
   /**
    * Returns 1 if video is included, otherwise 0.
    * @return
    */
   private static String getIncludeVideo() 
   {
      if (isIncludeVideo()) {return "1";} else {return "0";}
   }
   
   
   
   /**
    * Gets the current record size.
    * @return
    */
   private int getCurrentSize() {return currentSize;}
   

   
   /**
    * Gets the audio samples.
    * @return samples
    */
   private int getAudioSamples() {return audioSamples;}
   
   
   
   /**
    * Gets the audio quality.
    * @return quality
    */
   private float getVideoQuality() {return videoQuality;}
   
   
   
   /**
    * Gets the channel id.
    * @return channels
    */
   private String getChannelId() {return channelId;}
   
   
   
   /**
    * Gets the message id.
    * @return channels
    */
   private String getMessageId() {return messageId;}
   
   
   
   /**
    * Gets the audio channels.
    * @return channels
    */
   private int getAudioChannels() {return audioChannels;}
   
   
  
   /**
    * Gets the frame rate.
    * @return frames
    */
   private int getFrameRate() {return frameRate;}
   
   
   
   /**
    * Gets the audio byte number.
    * @return bytes
    */
   private int getAudioBytes() {return audioBytes;}
   
   
   
   /**
    * Gets the video width.
    * @return width
    */
   private int getVideoWidth() {return videoWidth;}
   

   
   /**
    * Gets the video height.
    * @return width
    */
   private int getVideoHeight() {return videoHeight;}
   
    
   
   /**
    * Gets the record boolean.
    * @return
    */
   private boolean getModeRecord() {return modeRecord;}
   
   
   
   /**
    * Gets the play boolean.
    * @return
    */
   private boolean getModePlayback() {return modePlayback;}
   
   
   
   /**
    * Gets the record boolean.
    * @return
    */
   private boolean getStopRecord() {return stopRecord;}
   
   
   
   /**
    * Gets the play boolean.
    * @return
    */
   private boolean getStopPlayback() {return stopPlayback;}
   
   
   
   /**
    * Gets the camera to use for the message.
    * @return
    */
   private int getWebcamCamera() {return (webcamCamera);}
   
   
   
   /**
    * Gets the video output stream.
    * @return
    */
   private ByteArrayOutputStream getVideoStream() {return (videoStream);}
   
   
   
   /**
    * Gets the audio buffer size.
    * ESCA-JAVA0029:
    * @return
    */
   private int getAudioBufferSize() {return audioBufferSize;}
   
   
   
   /**
    * Gets the audio byte array.
    * @return
    */
   private byte[] getAudioByteArray() {return (audioByteArray);}
   
   
   
   /**
    * Gets the audio byte array length.
    * @return
    */
   private int getAudioByteArrayLength() {return (audioByteArray.length);}
   
   
   
   /**
    * Gets the video byte array.
    * @return
    */
   private byte[] getVideoByteArray() {return (videoStream.toByteArray());}
   
     
   //***************************************** END PRIVATE METHODS *****************************************//
   
   
   private byte[] data;
   private Webcam webcam;
   private float videoQuality;
   private BufferedImage image;
   private byte[] audioByteArray;
   private Thread frameRefreshing;
   private ImageIcon videoThumbnail;
   private String messageId, channelId;
   private TargetDataLine targetDataLine;
   private SourceDataLine sourceDataLine;
   private int audioBufferSize, webcamCamera;
   private ByteArrayOutputStream videoStream;
   private DataUploadDownload dataUploadDownload;

   ArrayList<Integer> indexes = new ArrayList<Integer>();
   
   private ArrayList<String> writeSettings, readSettings;
   
   ArrayList<byte[]> messageBytes = new ArrayList<byte[]>();

   private boolean stopRecord, stopPlayback, stopRefresh, modeRecord, modePlayback;
   private int audioChannels, audioBytes, videoWidth, videoHeight, frameRate, audioSamples, currentSize;


   //********************************************** END CLASS **********************************************//

}


/*
   COPYRIGHT (C) 2010 - 2014 by Alexander Wait. All Rights Reserved.

   This class transmits audio/video to a receiver over TCP-IP.

   @site http://www.javaika.com
   @author Alexander Wait
   @version 2014-07-25
*/



import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.*;
import java.util.Arrays;
import java.util.Iterator;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.Port;
import javax.sound.sampled.TargetDataLine;

import com.github.sarxos.webcam.Webcam;



public class AudioVideoTransmit
{

   /* Configuration Settings */

   private static boolean VIDEO = false;
   
   
   /**
    * Class constructor.
    * @param audioDataPort
    * @param videoDataPort
    * ESCA-JAVA0265:
    * ESCA-JAVA0266:
    */
   public AudioVideoTransmit(int audioDataPort, int videoDataPort) 
   {
      this.audioDataPort = audioDataPort; this.videoDataPort = videoDataPort;

      videoStream = new ByteArrayOutputStream();
   }
   
   
   //**************************************** START PUBLIC METHODS *****************************************//
   
   
   /**
    * Starts the transmission.
    * ESCA-JAVA0266:
    */
   public void transmit() {setBufferArray(); transmissionCheck();}
   
   
   
   /**
    * Stops the transmission.
    * ESCA-JAVA0266:
    * ESCA-JAVA0166:
    */
   public void cancel()
   { 
      try
      { 
         if (targetDataLine != null)  
         { 
            if (targetDataLine.isOpen()) {targetDataLine.close();}
         }
         
         if (audioDataServerSocket != null)
         {
            if (audioDataServerSocket.isBound()) {audioDataServerSocket.close();}
         }
         
         if (videoDataServerSocket != null)
         {
            if (videoDataServerSocket.isBound()) {videoDataServerSocket.close();}
         }
         
         if (audioDataSocket != null)
         { 
            if (audioDataSocket.isBound()) {audioDataSocket.close();}
         }
         
         if (videoDataSocket != null)
         { 
            if (videoDataSocket.isBound()) {videoDataSocket.close();}
         }

         if (videoStream != null) {videoStream.close();}
         
         if (webcam != null) {webcam.close();}
      }
      
      catch (IOException e) {System.out.println(e);} 
   }
   
   
   
   /**
    * Sets the video inclusion boolean variable.
    * @param value
    */
   public void setIncludeVideo(boolean value) {VIDEO = value;}
   
   
   
   /**
    * Sets the audio samples.
    * @param val
    */
   public void setAudioSamples(float val) {audioSamples = val;}
   
   
   
   /**
    * Sets the video quality.
    * @param val
    */
   public void setVideoQuality(float val) {videoQuality = val;}
   
   
   
   /**
    * Sets the audio channels.
    * @param val
    */
   public void setAudioChannels(int val) {audioChannels = val;}
   
   
   
   /**
    * Sets the frame rate.
    * @param val
    */
   public void setFrameRate(int val) {frameRate = val;}
   
   
   
   /**
    * Sets the audio byte number.
    * @param val
    */
   public void setAudioBytes(int val) {audioBytes = val;}
   
   
   
   /**
    * Sets the video width.
    * @param val
    */
   public void setVideoWidth(int val) {videoWidth = val;}
   
   
   
   /**
    * Sets the video height.
    * @param val
    */
   public void setVideoHeight(int val) {videoHeight = val;}
   
   
   
   /**
    * Sets the transmission boolean variable.
    * @param value
    */
   public void setStopTransmit(boolean value) {stopTransmit = value;}
   
   
   
   /**
    * Sets the camera variable.
    * @param value
    */
   public void setWebcamCamera(int value) {webcamCamera = value;}
   
   
   //***************************************** END PUBLIC METHODS ******************************************//
    
   
   //**************************************** START PRIVATE METHODS ****************************************//
   
   
   private class StartAudioDataTransmission extends Thread 
   {

      /** 
       * Thread that starts the data transmission.
       */
      private StartAudioDataTransmission() 
      {
         setDaemon(false);
      }
       
      
      /**
       * ESCA-JAVA0166:
       * ESCA-JAVA0266:
       */
      public void run()
      {    
         transmitAudioData();  
      }
   }
   
   
   
   private class StartVideoDataTransmission extends Thread 
   {

      /** 
       * Thread that starts the data transmission.
       */
      private StartVideoDataTransmission() 
      {
         setDaemon(false);
      }
       
      
      /**
       * ESCA-JAVA0166:
       * ESCA-JAVA0266:
       */
      public void run()
      {    
         transmitVideoData();  
      }
   }
   
   
   
   /**
    * Starts the audio transmission thread.
    * ESCA-JAVA0087:
    * ESCA-JAVA0266:
    */
   private void startAudioTransmissionThread()
   {
      audioDataTransmit = new StartAudioDataTransmission();
      
      audioDataTransmit.start();
   }
   
   
   
   /**
    * Starts the video transmission thread.
    * ESCA-JAVA0087:
    * ESCA-JAVA0266:
    */
   private void startVideoTransmissionThread()
   {
      videoDataTransmit = new StartVideoDataTransmission();
      
      videoDataTransmit.start();
   }
   
   
   
   /**
    * Starts data transmission if audio can be at least transmitted. 
    * ESCA-JAVA0087:
    * ESCA-JAVA0266:
    */
   private void transmissionCheck()
   {
      if (isMicrophoneAvailable())
      { 
         startTargetLine(); // Starts the target data line if microphone is available.
   
         
         if (getIncludeVideo()) 
         {
            startWebcam(); // Attempts to start the web camera if enabled.
         } 
         
         else
         {
            OnlineMessagingGui.appendTextOutput("\n Camera checkbox is unselected.");
          
            OnlineMessagingGui.appendTextOutput("\n Video transmission is disabled.");
         }
         
         
         if (getIncludeVideo() && (webcam != null))
         {
            videoDataServerSocketStart(); startVideoTransmissionThread();
         }  
         
         else
         {
            OnlineMessagingGui.appendTextOutput("\n Camera could not be started.");
      
            OnlineMessagingGui.appendTextOutput("\n Video can not be transmitted.");
         }
         
         
         if (targetDataLine != null)
         {
            audioDataServerSocketStart(); startAudioTransmissionThread();
         }
         
         else
         {
            OnlineMessagingGui.appendTextOutput("\n Microphone could not be loaded.");
             
            OnlineMessagingGui.appendTextOutput("\n Audio can not be transmitted.");
         }
      }
      
      else
      {
         OnlineMessagingGui.appendTextOutput("\n A microphone is not available.");
          
         OnlineMessagingGui.appendTextOutput("\n Audio can not be transmitted.");
      }
   }
   
   
   
   /**
    * Starts the web camera.
    * ESCA-JAVA0266:
    */
   private void startWebcam()
   {
      webcam = Webcam.getWebcams().get(getWebcamCamera());
      
      webcam.setCustomViewSizes(new Dimension[] {new Dimension(getVideoWidth(), getVideoHeight())});

      webcam.setViewSize(new Dimension(getVideoWidth(), getVideoHeight())); webcam.open();
   }

   
   
   /**
    * Sets the audio buffer array.
    */
   private void setBufferArray()
   {
      int testSize = (int)Math.floor
      (
         (getAudioSamples() * getAudioBytes() * getAudioChannels()) / getFrameRate()
      ); 
      

      int frameSize = getAudioBytes() * getAudioChannels();
      
     
      for (int i = 0; i < frameSize; i ++)
      {
         if ((testSize % frameSize) == 0)
         {
            audioBufferSize = testSize; break;
         }
         
         else {testSize --;}
      }
      

      audioByteArray = new byte[getAudioBufferSize()];  
   }
   
   
   
   /**
    * Starts the audio data server socket.
    * ESCA-JAVA0266:
    */
   private void audioDataServerSocketStart()
   {
      try
      {   
         audioDataServerSocket = new ServerSocket(audioDataPort); 
      }
      
      catch (IOException e)
      {
         System.out.println("Error initialising audio data server socket.");
      }
   }
   
   
   
   /**
    * Starts the video data server socket.
    * ESCA-JAVA0266:
    */
   private void videoDataServerSocketStart()
   {
      try
      {   
         videoDataServerSocket = new ServerSocket(videoDataPort); 
      }
      
      catch (IOException e)
      {
         System.out.println("Error initialising video data server socket.");
      }
   }


   
   /**
    * Sends text output to client.
    * @param message
    * ESCA-JAVA0266:
    * ESCA-JAVA0029:
    * ESCA-JAVA0166:
    */
   private void transmitMessage(String message)
   {
      try
      {
         audioDataSocket = audioDataServerSocket.accept();
       
         
         audioPrintStream = new PrintStream(audioDataSocket.getOutputStream());
         
         audioPrintStream.println(message);
      }
   
      catch (Exception e)
      {
         System.out.println("Error running text output server module.");
      }
   }
   
   
   
   /**
    * Transmits the audio data to the client.
    * ESCA-JAVA0166:
    * ESCA-JAVA0266:
    */
   private void transmitAudioData()
   {
      try
      { 
         transmitMessage // Send audio configuration information to the receiver for decode.
         (
            getAudioSamples()+","+getAudioChannels()+","+getAudioBytes()
         );

         
         while (!getStopTransmit())
         {
            readAudio(); writeAudioData = Arrays.toString(audioData);
          
            audioPrintStream.println(writeAudioData);
         }
      }
      
      catch (NullPointerException e)
      {
         System.out.println("An error has occured writing audio data.");
      } 
      
      finally
      {
         audioDataSocketClose(); // Closes the audio data socket.
 
         targetDataLine.close(); // Closes the audio line.
      }
   }
   
   
   
   /**
    * Transmits the video data to the client.
    * ESCA-JAVA0166:
    * ESCA-JAVA0266:
    */
   private void transmitVideoData()
   {
      try
      {
         videoDataSocket = videoDataServerSocket.accept();
         
         videoPrintStream = new PrintStream(videoDataSocket.getOutputStream());

         
         while (!getStopTransmit())
         {
            readVideo(); writeVideoData = Arrays.toString(videoData);
          
            videoPrintStream.println(writeVideoData);
         }
      }
      
      catch (NullPointerException | IOException e)
      {
         System.out.println("An error has occured writing video data.");
      } 
      
      finally
      {
         videoDataSocketClose(); // Closes the video data socket.
      }
   }
   
   
   
   /**
    * Reads the video data.
    */
   private void readVideo()
   { 
      if ((image = webcam.getImage()) != null)
      {   
         compressImage(image); videoData = getVideoByteArray();
      
         resetVideoStream();
      }
   }
   
   
   
   /**
    * Reads the audio data.
    */
   private void readAudio()
   {
      audioByteArray = new byte[audioBufferSize]; 
       

      targetDataLine.read(getAudioByteArray(), 0, getAudioByteArrayLength()); 

      audioData = getAudioByteArray(); 
   }
   

   
   /**
    * Closes the active audio data socket.
    * ESCA-JAVA0266:
    */
   private void audioDataSocketClose()
   {
      try
      {
         audioDataSocket.close();
      }
      
      catch (IOException e)
      {
         System.out.println("Error closing audio data socket on server side.");
      }
   }
   
   
   
   /**
    * Closes the active video data socket.
    * ESCA-JAVA0266:
    */
   private void videoDataSocketClose()
   {
      try
      {
         videoDataSocket.close();
      }
      
      catch (IOException e)
      {
         System.out.println("Error closing video data socket on server side.");
      }
   }
   
   
   
   /**
    * Resets the byte array output stream.
    */
   private void resetVideoStream()
   {
      videoStream.reset();
   }
   
   
   
   /**
    * Tests if a microphone is available.
    * @return
    */
   private static boolean isMicrophoneAvailable()
   {
      if (AudioSystem.isLineSupported(Port.Info.MICROPHONE))
      {
         return true;
      }
      
      else
      {
         return false;
      }
   }
   

   
   /**
    * Compresses the buffered image before storage.
    * ESCA-JAVA0266:
    * @param img
    */
   private void compressImage(BufferedImage img)
   {     
      try
      {          
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         
         ImageOutputStream ios = ImageIO.createImageOutputStream(baos);
        
         
         Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg");
         
         ImageWriter writer = writers.next();
          
         
         ImageWriteParam param = writer.getDefaultWriteParam();
         
         
         param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
         
         param.setCompressionQuality(getVideoQuality()); writer.setOutput(ios); 
         
         writer.write(null, new IIOImage(img, null, null), param);
             
         
         byte[] imgBytes = baos.toByteArray(); writer.dispose(); 
             
         getVideoStream().write(imgBytes, 0, imgBytes.length);         
      }
        
      catch (IOException e)
      {
         System.out.println("An error has occured during image compression.");
      }
   }
   
   
   
   /**
    * Starts the target data line.
    * ESCA-JAVA0266:
    */
   private void startTargetLine()
   {   
      DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, getAudioFormat());
      
        
      try
      {
         targetDataLine = (TargetDataLine) AudioSystem.getLine(dataLineInfo);
         
         targetDataLine.open(getAudioFormat());
      }
         
      catch (LineUnavailableException e)
      { 
         System.out.println("The audio system line is unavailable.");
      }
         
         
      targetDataLine.start();         
   }
   


   /**
    * Returns the audio format.
    * @return
    */
   private AudioFormat getAudioFormat()
   {
      boolean signed = true; boolean bigEndian = false;
    
      
      return new AudioFormat
      (
         getAudioSamples(), (8 * getAudioBytes()), getAudioChannels(), signed, bigEndian
      );
   }
   

   
   /**
    * Gets the video inclusion boolean variable.
    * @return
    */
   private static boolean getIncludeVideo() {return (VIDEO);}
   
   
   
   /**
    * Gets the audio samples.
    * @return samples
    */
   private float getAudioSamples() {return audioSamples;}
   
   
   
   /**
    * Gets the audio quality.
    * @return quality
    */
   private float getVideoQuality() {return videoQuality;}
   
   
   
   /**
    * Gets the audio channels.
    * @return channels
    */
   private int getAudioChannels() {return audioChannels;}
   
   
  
   /**
    * Gets the frame rate.
    * @return frames
    */
   private int getFrameRate() {return frameRate;}
   
   
   
   /**
    * Gets the audio byte number.
    * @return bytes
    */
   private int getAudioBytes() {return audioBytes;}
   
   
   
   /**
    * Gets the video width.
    * @return width
    */
   private int getVideoWidth() {return videoWidth;}
   

   
   /**
    * Gets the video height.
    * @return width
    */
   private int getVideoHeight() {return videoHeight;}
   
   
   
   /**
    * Gets the audio buffer size.
    * ESCA-JAVA0029:
    * @return
    */
   private int getAudioBufferSize() {return audioBufferSize;}
   
   
   
   /**
    * Gets the video output stream.
    * @return
    */
   private ByteArrayOutputStream getVideoStream() {return (videoStream);}
   
   
   
   /**
    * Gets the camera to use for transmission.
    * @return
    */
   private int getWebcamCamera() {return (webcamCamera);}
   
   
   
   /**
    * Gets the transmission boolean variable.
    * @return
    */
   private boolean getStopTransmit() {return (stopTransmit);}
   
   

   /**
    * Gets the audio byte array.
    * @return
    */
   private byte[] getAudioByteArray() {return (audioByteArray);}
   
   
   
   /**
    * Gets the audio byte array length.
    * @return
    */
   private int getAudioByteArrayLength() {return (audioByteArray.length);}
   
   
   
   /**
    * Gets the video byte array.
    * @return
    */
   private byte[] getVideoByteArray() {return (videoStream.toByteArray());}
   
   
   //***************************************** END PRIVATE METHODS *****************************************//


   private Webcam webcam;
   private BufferedImage image;
   private boolean stopTransmit;
   private TargetDataLine targetDataLine;
   private float audioSamples, videoQuality;
   private ByteArrayOutputStream videoStream;
   private String writeAudioData, writeVideoData;
   private Socket audioDataSocket, videoDataSocket;
   private byte[] audioByteArray, audioData, videoData;
   private Thread audioDataTransmit, videoDataTransmit;
   private PrintStream audioPrintStream, videoPrintStream;
   private ServerSocket audioDataServerSocket, videoDataServerSocket;
   private int audioDataPort, videoDataPort, webcamCamera, audioBufferSize;
   private int audioChannels, audioBytes, videoWidth, videoHeight, frameRate;


   //********************************************** END CLASS **********************************************//

}


/*
   COPYRIGHT (C) 2010 - 2014 by Alexander Wait. All Rights Reserved.

   This class receives audio/video from a transmitter over TCP-IP.

   @site http://www.javaika.com
   @author Alexander Wait
   @version 2014-07-25
*/



import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.swing.ImageIcon;



public class AudioVideoReceive
{

   /* Configuration Settings */

   private static int PORT_POLLING_DELAY = 1000;
   

   /**
    * Class constructor.
    * @param ipAddress
    * @param audioDataPort
    * @param videoDataPort
    * ESCA-JAVA0265:
    * ESCA-JAVA0266:
    */
   public AudioVideoReceive(String ipAddress, int audioDataPort, int videoDataPort)
   {
      this.ipAddress = ipAddress; this.audioDataPort = audioDataPort;
      
      this.videoDataPort = videoDataPort;
      
      
      videoThumbnail = new ImageIcon(this.getClass().getResource
      
      ("files/images/VideoMessagingImageBlank.png"));
   }
   
   
   //**************************************** START PUBLIC METHODS *****************************************//
   
   
   /**
    * Starts the reception.
    */
   public void receive() {startAudioReceptionThread(); startVideoReceptionThread();}
   
   
   
   /**
    * Stops the reception.
    * ESCA-JAVA0266:
    * ESCA-JAVA0166:
    */
   public void cancel()
   { 
      try
      {
         if (sourceDataLine != null)
         { 
            if (sourceDataLine.isOpen()) {sourceDataLine.close();}
         }
         
         
         if (audioDataSocket != null)
         { 
            if (audioDataSocket.isBound()) {audioDataSocket.close();}
         }
         
         
         if (videoDataSocket != null)
         { 
            if (videoDataSocket.isBound()) {videoDataSocket.close();}
         }
      }
      
      catch (IOException e) {System.out.println(e);} 
   }
   
   
   
   /**
    * Sets the reception boolean variable.
    * @param value
    */
   public void setStopReceive(boolean value) {stopReceive = value;}
   
   
   //***************************************** END PUBLIC METHODS ******************************************//
   
   
   //**************************************** START PRIVATE METHODS ****************************************//
   

   private class StartAudioDataReception extends Thread 
   {

      /** 
       * Thread that starts the audio data reception.
       */
      private StartAudioDataReception() 
      {
         setDaemon(false);
      }
  
      
      /**
       * ESCA-JAVA0166:
       * ESCA-JAVA0266:
       */
      public void run()
      {
         receiveAudioData();  
      }
   }
   
   
   
   private class StartVideoDataReception extends Thread 
   {

      /** 
       * Thread that starts the video data reception.
       */
      private StartVideoDataReception() 
      {
         setDaemon(false);
      }
  
      
      /**
       * ESCA-JAVA0166:
       * ESCA-JAVA0266:
       */
      public void run()
      {
         receiveVideoData();  
      }
   }
   
   
   
   /**
    * Starts the audio reception thread.
    * ESCA-JAVA0087:
    * ESCA-JAVA0266:
    */
   public void startAudioReceptionThread()
   {
      audioDataReceive = new StartAudioDataReception(); 
      
      audioDataReceive.start();
   }
   
   
   
   /**
    * Starts the video reception thread.
    * ESCA-JAVA0087:
    * ESCA-JAVA0266:
    */
   public void startVideoReceptionThread()
   {
      videoDataReceive = new StartVideoDataReception(); 
      
      videoDataReceive.start();
   }
   
   
   
   /**
    * Connects to the audio data socket.
    * ESCA-JAVA0266:
    * ESCA-JAVA0087:
    * ESCA-JAVA0166:
    */
   private void audioDataSocketConnect()
   {
      try 
      {
         Thread.sleep(PORT_POLLING_DELAY); // Wait half a second until next poll.
      
         audioDataSocket = new Socket(ipAddress, audioDataPort);
      }
      
      catch (IOException | InterruptedException e) 
      {
         audioDataSocketConnect(); // Recursive call to instantiate audio socket.
      }
   }
   
   
   
   /**
    * Connects to the video data socket.
    * ESCA-JAVA0266:
    * ESCA-JAVA0087:
    * ESCA-JAVA0166:
    */
   private void videoDataSocketConnect()
   {
      try 
      {
         Thread.sleep(PORT_POLLING_DELAY); // Wait half a second until next poll.
      
         videoDataSocket = new Socket(ipAddress, videoDataPort);
      }
      
      catch (IOException | InterruptedException e) 
      {
         videoDataSocketConnect(); // Recursive call to instantiate video socket.
      }
   }
   
   
   
   /**
    * Receives message from server.
    * ESCA-JAVA0266:
    * ESCA-JAVA0166:
    * ESCA-JAVA0029:
    */
   private void receiveMessage()
   { 
      try
      {
         audioDataSocketConnect();
         
         
         audioBufferedReader = new BufferedReader
         (
            new InputStreamReader(audioDataSocket.getInputStream())
         );
         

         String temp = audioBufferedReader.readLine();
         
         if (temp != null) {setMessage(temp);}
      }
   
      catch (Exception e) 
      {
         System.out.println("An error has occured receiving message.");
      }
   }
   
   
   
   /**
    * Receives the audio data from the server.
    * ESCA-JAVA0266:
    * ESCA-JAVA0166:
    * ESCA-JAVA0087:
    */
   public void receiveAudioData()
   { 
      try
      {
         receiveMessage(); setAudioFormat(getMessage()); startSourceLine();
   
         ByteArrayOutputStream audioByteStream = new ByteArrayOutputStream();
         

         while (!getStopReceive())
         {
            if ((audioReadData = audioBufferedReader.readLine()) != null)
            {
               audioByteStream.reset(); list = Arrays.asList
               (
                  audioReadData.substring(1, audioReadData.length() - 1).split(", ")
               );
            

               for (String element : list) 
               {
                  audioByteStream.write(Byte.valueOf(element));
               }

               
               audioData = audioByteStream.toByteArray();
               
               writeAudio(); audioByteStream.flush();
            }
         }
      }
      
      catch (NullPointerException | IOException e)
      {
         System.out.println("An error has occured reading audio data.");
      }
      
      finally
      {
         cancel(); setMessage(null); audioDataSocketClose(); // Cancel the reception.
      }
   }
   
   
   
   /**
    * Receives the video data from the server.
    * ESCA-JAVA0266:
    * ESCA-JAVA0166:
    * ESCA-JAVA0087:
    */
   public void receiveVideoData()
   { 
      try
      {
         videoDataSocketConnect();
         
         
         videoBufferedReader = new BufferedReader
         (
            new InputStreamReader(videoDataSocket.getInputStream())
         );
         
   
         ByteArrayOutputStream videoByteStream = new ByteArrayOutputStream();
         

         while (!getStopReceive())
         {
            if ((videoReadData = videoBufferedReader.readLine()) != null)
            {
               videoByteStream.reset(); list = Arrays.asList
               (
                  videoReadData.substring(1, videoReadData.length() - 1).split(", ")
               );
            

               for (String element : list) 
               {
                  videoByteStream.write(Byte.valueOf(element));
               }

               
               videoData = videoByteStream.toByteArray();
               
               writeVideo(); videoByteStream.flush();
            }
         }
      }
      
      catch (NullPointerException | IOException e)
      {
         System.out.println("An error has occured reading data.");
      }
      
      finally
      {
         cancel(); videoDataSocketClose(); // Cancel the reception.
         
         OnlineMessagingGui.clearLabelIcon(videoThumbnail); // Reset Video view port.
      }
   }
   

   
   /**
    * Writes the video data.
    */
   private void writeVideo()
   {
      setVideoByteArray(videoData);

      OnlineMessagingGui.setLabelIcon(getVideoByteArray());
   }
   
   
   
   /**
    * Writes the audio data.
    */
   private void writeAudio()
   {
      setAudioByteArray(audioData);

      sourceDataLine.write(getAudioByteArray(), 0, getAudioByteArrayLength());
   }
   

  
   /**
    * Closes the audio data socket.
    * ESCA-JAVA0266:
    */
   private void audioDataSocketClose()
   {
      try
      {
         audioDataSocket.close();
      }
  
      catch (IOException e)
      {
         System.out.println("Error closing audio data socket on client side.");
      } 
   }
   
   
   
   /**
    * Closes the video data socket.
    * ESCA-JAVA0266:
    */
   private void videoDataSocketClose()
   {
      try
      {
         videoDataSocket.close();
      }
  
      catch (IOException e)
      {
         System.out.println("Error closing video data socket on client side.");
      } 
   }
   


   /**
    * Starts the source data line.
    * ESCA-JAVA0266:
    * ESCA-JAVA0166:
    */
   private void startSourceLine()
   {
      DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, getAudioFormat());
 
      
      try
      {      
         sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
      
         sourceDataLine.open(getAudioFormat());
         
         sourceDataLine.start();
      }
      
      catch (LineUnavailableException | IllegalArgumentException e)
      {
         System.out.println("The audio system line is unavailable.");
      }
      
   }
   
   
   
   /**
    * Extracts and sets the audio format.
    * ESCA-JAVA0166:
    * ESCA-JAVA0266:
    * @param format
    */
   private void setAudioFormat(String format)
   { 
      try
      {   
         // Split the string into individual components.
   
         String[] parts = format.split(",");
      
      
         // Initialize audio format settings.
      
         samples = (float)Double.parseDouble(parts[0]);

         channels = Integer.parseInt(parts[1]);
      
         bytes = Integer.parseInt(parts[2]);
      }
      
      catch (NullPointerException e)
      { 
         System.out.println("Error extracting audio settings.");
      }
   }
   
   
   
   /**
    * Returns the audio format.
    * @return
    */
   private AudioFormat getAudioFormat()
   {
      boolean signed = true; boolean bigEndian = false;
      

      return new AudioFormat(samples, (8 * bytes), channels, signed, bigEndian);
   }
   

   
   /**
    * Sets the message.
    * @param val
    */
   private void setMessage(String val) {message = val;}
   
   
   
   /**
    * Sets the audio byte array.
    * @param array
    */
   private void setAudioByteArray(byte[] array) {audioByteArray = array.clone();}
   
   
   
   /**
    * Sets the video byte array.
    * @param array
    */
   private void setVideoByteArray(byte[] array) {videoByteArray = array.clone();}
   

   
   /**
    * Gets the message.
    * @return
    */
   private String getMessage() {return message;}
   
   
   
   /**
    * Returns the reception boolean variable.
    * @return
    */
   private boolean getStopReceive() {return stopReceive;}
   
   
   
   /**
    * Gets the audio byte array.
    * @return
    */
   private byte[] getAudioByteArray() {return (audioByteArray);}
   
   
   
   /**
    * Gets the video byte array.
    * @return
    */
   private byte[] getVideoByteArray() {return (videoByteArray);}
   
   
   
   /**
    * Gets the audio byte array length.
    * @return
    */
   private int getAudioByteArrayLength() {return (audioByteArray.length);}
   

   //***************************************** END PRIVATE METHODS *****************************************//


   private float samples;
   private boolean stopReceive;
   private ImageIcon videoThumbnail;
   private SourceDataLine sourceDataLine;
   private Socket audioDataSocket, videoDataSocket;
   private Thread audioDataReceive, videoDataReceive;
   private int audioDataPort, videoDataPort, channels, bytes;
   private BufferedReader audioBufferedReader, videoBufferedReader;
   private String message, ipAddress, audioReadData, videoReadData;
   private byte[] audioByteArray, videoByteArray, audioData, videoData;

   List<String> list = new ArrayList<String>();

   
   //********************************************** END CLASS **********************************************//
  
}


/*
   COPYRIGHT (C) 2010 - 2014 by Alexander Wait. All Rights Reserved.

   This class uploads/downloads video/audio to/from the server.

   @site http://www.javaika.com
   @author Alexander Wait
   @version 2014-07-25
*/



import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;



public class DataUploadDownload 
{
   private static final String FILE_DOWNLOAD_ADDRESS = "http://" + Domain.getDomain()
   
   + "/bridge/record-message-data-read.php" + Domain.getPort(); // Port:80 
   

   private static final String FILE_UPLOAD_ADDRESS = "http://" + Domain.getDomain()
   
   + "/bridge/record-message-data-write.php" + Domain.getPort(); // Port:80 
   

   private static final String BOUNDARY = "*****";
   
   private static final String LINE_END = "\r\n";
   
   private static final String HYPHENS = "--";

   
   private static final int BUFFER_SIZE = 1024;
   
   

   /**
    * Class constructor.
    * ESCA-JAVA0057:
    */
   public DataUploadDownload() {}
   
   
   
   /**
    * Writes a message object to the server.
    * @param userId
    * @param userPw
    * @param messageId
    * ESCA-JAVA0166:
    * ESCA-JAVA0266:
    * @param data
    */
   public void exportMessageData(String userId, String userPw, String messageId, byte[] data)
   {
      OnlineMessagingGui.appendTextOutput("\n Message send started.");
      
      OnlineMessagingGui.updateProgressBar("Sending Message", true);
 
      
      try
      {
         URL url = new URL(FILE_UPLOAD_ADDRESS);
         
         
         con = (HttpURLConnection) url.openConnection(); 

         con.setDoInput(true); con.setDoOutput(true); con.setUseCaches(false); 
         
         
         con.setRequestMethod("POST");   

         con.setRequestProperty("Connection", "Keep-Alive"); 

         con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
         

         dos = new DataOutputStream(con.getOutputStream()); 


         dos.writeBytes(HYPHENS + BOUNDARY + LINE_END);

         dos.writeBytes("Content-Disposition: form-data; name=userId;" + LINE_END + LINE_END);

         dos.writeBytes(userId + LINE_END);
         
         
         dos.writeBytes(HYPHENS + BOUNDARY + LINE_END);

         dos.writeBytes("Content-Disposition: form-data; name=userPw;" + LINE_END + LINE_END);

         dos.writeBytes(userPw + LINE_END);
         
         
         dos.writeBytes(HYPHENS + BOUNDARY + LINE_END);

         dos.writeBytes("Content-Disposition: form-data; name=messageId;" + LINE_END + LINE_END);

         dos.writeBytes(messageId + LINE_END);
         
         
         dos.writeBytes(HYPHENS + BOUNDARY + LINE_END);

         dos.writeBytes("Content-Disposition: form-data; name=message; filename=output.dat" + LINE_END); 

         dos.writeBytes(LINE_END); dos.write(data); dos.writeBytes(LINE_END); 
         
         
         dos.writeBytes(HYPHENS + BOUNDARY + HYPHENS + LINE_END);

         bre = new BufferedReader(new InputStreamReader(con.getInputStream())); 
         
 
         while ((rec = bre.readLine()) != null) {OnlineMessagingGui.appendTextOutput("\n " + rec);}
         
         
         OnlineMessagingGui.appendTextOutput("\n Message send completed.");
         
         OnlineMessagingGui.updateProgressBar("Message Sent", false);

         
         dos.flush(); dos.close(); bre.close();
      }
   
      
      catch (Exception e) 
      {
         System.out.println("Could not upload to host.");
      }
   }
   
   
   
   /**
    * Reads a message object from the server.
    * @param userId
    * @param userPw
    * @param messageId
    * @param channelId
    * ESCA-JAVA0166:
    * ESCA-JAVA0266:
    * @return
    */
   public byte[] importMessageData(String userId, String userPw, String messageId, String channelId)
   {
      OnlineMessagingGui.appendTextOutput("\n Message receive started.");
      
      OnlineMessagingGui.updateProgressBar("Receiving Message", true);
      
      byte[] data = null;

      
      try 
      {
         URL url = new URL(FILE_DOWNLOAD_ADDRESS);
         

         con = (HttpURLConnection) url.openConnection(); 

         con.setDoInput(true); con.setDoOutput(true); con.setUseCaches(false); 


         con.setRequestMethod("POST"); 

         con.setRequestProperty("Connection", "Keep-Alive"); 

         con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY); 


         dos = new DataOutputStream(con.getOutputStream()); 
         
         
         dos.writeBytes(HYPHENS + BOUNDARY + LINE_END); 

         dos.writeBytes("Content-Disposition: form-data; name=userId" + LINE_END + LINE_END);

         dos.writeBytes(userId + LINE_END);
         
         
         dos.writeBytes(HYPHENS + BOUNDARY + LINE_END); 

         dos.writeBytes("Content-Disposition: form-data; name=userPw" + LINE_END + LINE_END);

         dos.writeBytes(userPw + LINE_END);
         
         
         dos.writeBytes(HYPHENS + BOUNDARY + LINE_END); 

         dos.writeBytes("Content-Disposition: form-data; name=messageId" + LINE_END + LINE_END);

         dos.writeBytes(messageId + LINE_END);
         
         
         dos.writeBytes(HYPHENS + BOUNDARY + LINE_END); 

         dos.writeBytes("Content-Disposition: form-data; name=channelId" + LINE_END + LINE_END);

         dos.writeBytes(channelId + LINE_END);
        
         
         dos.writeBytes(HYPHENS + BOUNDARY + HYPHENS + LINE_END); 
         
        
         dis = new DataInputStream(con.getInputStream());

         
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         
         byte[] buffer = new byte[BUFFER_SIZE]; int n = 0;
         
         
         while (-1 != (n = dis.read(buffer))) {baos.write(buffer, 0, n);}
         
         
         data = baos.toByteArray(); baos.reset();
         
         
         OnlineMessagingGui.appendTextOutput("\n Message receive completed."); 
         
         OnlineMessagingGui.updateProgressBar("Message Received", false);
         
         
         dos.flush(); dos.close(); dis.close();
      } 
      
      
      catch (Exception e) 
      {
         System.out.println("Could not download from host.");
      }


      return data;
   }
   
   
   
   /**
    * Returns the file download address.
    * @return
    */
   public static String getFileDownloadAddress()
   {
      return FILE_DOWNLOAD_ADDRESS;
   }
   
   
   
   /**
    * Returns the file download address.
    * @return
    */
   public static String getFileUploadAddress()
   {
      return FILE_UPLOAD_ADDRESS;
   }
   

   private String rec;
   private BufferedReader bre;
   private DataInputStream dis;
   private DataOutputStream dos;
   private HttpURLConnection con;

}


/*
   COPYRIGHT (C) 2010 -2013 by Alexander Wait. All Rights Reserved.

   This class defines colors and color methods.

   @site http://www.javaika.com
   @author Alexander Wait
   @version 2012-05-18
*/



public class ColorFunctions
{

   private static final int HEXADECIMAL_BASE = 16;
   
   private static final int COLOR_COMPONENT_RED = 250;
   
   private static final int COLOR_COMPONENT_GREEN = 250;
   
   private static final int COLOR_COMPONENT_BLUE = 250;
   
   
   
   private ColorFunctions() {}
   
   
   //**************************************** START PUBLIC METHODS *****************************************//

   
   /**
    * Returns the color in hexadecimal format.
    * @param sliderValue
    * @return
    */
   public static String returnHexadecimalColor(int sliderValue)
   {
      String compFirst = ""; String compSecond = ""; int counter = -1;
 
      for (int i = 0; i < HEXADECIMAL_BASE; i ++)
      {
         compFirst = returnComponent(i);

          for (int j = 0; j < HEXADECIMAL_BASE; j ++)
          {
             compSecond = returnComponent(j); counter ++; 
  
             if (counter == sliderValue)
             {
                break;
             }
             
          }
  
          if (counter == sliderValue)
          {
             break;
          }
  
       }
   
       return 
       (
          "#" + compFirst + compSecond + compFirst + 
          
          compSecond + compFirst + compSecond
       );
   
   }
   
   
   
   /**
    * Return the set red color component 
    * for setting the programs background color. 
    * @return
    */
   public static int red()
   {
      return COLOR_COMPONENT_RED;
   }
   
   
   
   /**
    * Return the set green color component 
    * for setting the programs background color. 
    * @return
    */
   public static int green()
   {
      return COLOR_COMPONENT_GREEN;
   }
   
   
   
   /**
    * Return the set blue color component 
    * for setting the programs background color. 
    * @return
    */
   public static int blue()
   {
      return COLOR_COMPONENT_BLUE;
   }
   
   
   //***************************************** END PUBLIC METHODS ******************************************//


   //**************************************** START PRIVATE METHODS ****************************************//
   
   
   /**
    * Returns the hexadecimal component.
    * ESCA-JAVA0076:
    * @param index
    * @return
    */
   private static String returnComponent(int index)
   {
      String component = "";
  
      switch (index)
      {
         case 10: component = "A"; break; case 11: component = "B"; break;  
         
         case 12: component = "C"; break; case 13: component = "D"; break; 
         
         case 14: component = "E"; break; case 15: component = "F"; break;
   
         default: component = Integer.toString(index); break;
      }
   
      return component;   
   }
   
 
   //***************************************** END PRIVATE METHODS *****************************************//

   
   //********************************************** END CLASS **********************************************//
   
}


/*
   COPYRIGHT (C) 2010 - 2013 by Alexander Wait. All Rights Reserved.

   This class returns the domain attributes.

   @site http://www.javaika.com
   @author Alexander Wait
   @version 2012-07-06
*/



public class Domain 
{
  
   private static final String DOMAIN = "javaika.com";

   private static final boolean RUN_LOCAL = false; 
   
   private static final boolean prefix = true;
   
   private static final String PORT = "80";
   
   
   private Domain() {}
   
   
   //**************************************** START PUBLIC METHODS *****************************************//
   
   
   /**
    * Returns the domain name.
    * @return
    */
   public static final String getDomain()
   {
      if (prefix)
      {
         return ("www." + DOMAIN);
      }
      
      else
      {
         return (DOMAIN);
      }
   }
   
   
   
   /**
    * Returns the port number.
    * @return
    */
   public static final String getPort()
   {
      if (RUN_LOCAL)
      {
         return (":" + PORT);
         
      }
      
      else {return ("");} 
   }
   
   
   //***************************************** END PUBLIC METHODS ******************************************//
   
   
   //********************************************** END CLASS **********************************************//

}


/*
   COPYRIGHT (C) 2010 - 2013 by Alexander Wait. All Rights Reserved.

   This class displays message dialogs.

   @site http://www.javaika.com
   @author Alexander Wait
   @version 2011-07-18
*/



import javax.swing.*;



public class Message
{

   private Message(){}
   
   
   //**************************************** START PUBLIC METHODS *****************************************//


   /**
    * Displays a message dialog.
    * @param text
    * @param heading
    * @param type 
    */
   public static void showMessage(String text, String heading, String type)
   {
      new JOptionPane(); Object[] options = {}; 

      if (type.equals("error"))
      {
         JOptionPane.showOptionDialog(null, text, heading,  
         JOptionPane.YES_OPTION, JOptionPane.ERROR_MESSAGE, null, options, null);
      }

      if (type.equals("information"))
      {
         JOptionPane.showOptionDialog(null, text, heading, 
         JOptionPane.YES_OPTION, JOptionPane.INFORMATION_MESSAGE, null, options, null);
      }

      if (type.equals("warning"))
      {
         JOptionPane.showOptionDialog(null, text, heading, 
         JOptionPane.YES_OPTION, JOptionPane.WARNING_MESSAGE, null, options, null);
      }

      if (type.equals("question"))
      {
         JOptionPane.showOptionDialog(null, text, heading, 
         JOptionPane.YES_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, null);
      }
   }
   
   
   //***************************************** END PUBLIC METHODS ******************************************//
   
   
   //********************************************** END CLASS **********************************************//
   
}


/*
   COPYRIGHT (C) 2010 - 2013 by Alexander Wait. All Rights Reserved.

   This class provides a bridge that connects java with PHP
   scripts on the server for writing information from the 
   java application to a remote database on the server. 
   The class also receives data from PHP server scripts
   upon request for this information.

   @site http://www.javaika.com
   @author Alexander Wait
   @version 2012-03-18
*/



import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.ArrayList;



public class Portal
{
   
 
   private Portal(){}
   
   
   //**************************************** START PUBLIC METHODS *****************************************//
   

   /**
    * Sends data to a specified PHP script address.
    * ESCA-JAVA0266:
    * @param address
    * @param userId
    * @param userPw
    * @param data
    */
   public static void javaToPhpGate(String address, String userId, String userPw, ArrayList<String> data) 
   {
      scriptAddress = address;


      try 
      {
         url = new URL(scriptAddress); conn = url.openConnection(); conn.setDoOutput(true); 
      

         dataSend = URLEncoder.encode("userId", "UTF-8") + "=" + URLEncoder.encode(userId, "UTF-8")

         + "&" + URLEncoder.encode("userPw", "UTF-8") + "=" + URLEncoder.encode(userPw, "UTF-8");
         
         
         if (data != null) {setVariableValues(data);} sendData(); 
         
         reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); 


         while ((dataRecieve = reader.readLine()) != null) 
         {

            System.out.println(dataRecieve);
         }


         reader.close();
         
      }
      
      catch (IOException e) {System.out.println(Tools.thisPathAndLine() + e + "\n");}

   }
   
  
   
   /**
    * Receives data from a specified PHP script address.
    * ESCA-JAVA0266:
    * @param address
    * @param userId
    * @param userPw
    * @param data
    * @return
    */ 
   public static ArrayList<String> phpToJavaGate(String address, String userId, String userPw, ArrayList<String> data)
   { 
      scriptAddress = address; 

      ArrayList<String> output = new ArrayList<String>();
   

      try
      { 
         url = new URL(scriptAddress); conn = url.openConnection(); conn.setDoOutput(true);
     

         dataSend = URLEncoder.encode("userId", "UTF-8") + "=" + URLEncoder.encode(userId, "UTF-8")

         + "&" + URLEncoder.encode("userPw", "UTF-8") + "=" + URLEncoder.encode(userPw, "UTF-8");
         
         
         if (data != null) {setVariableValues(data);} sendData(); 
         
         reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
       
         
         while ((dataRecieve = reader.readLine()) != null) 
         {
            output.add(dataRecieve);
         }
        

         reader.close();
        
      }
      
      catch (IOException e) {System.out.println(Tools.thisPathAndLine() + e + "\n");}
      

      return output;
         
   }
   
   
   
   /**
    * Clears database records using a specified PHP script address.
    * ESCA-JAVA0266:
    * @param address
    * @param userId
    * @param userPw
    * @param data
    */
   public static void clearFromDatabase(String address, String userId, String userPw, ArrayList<String> data) 
   {
      scriptAddress = address;


      try 
      {
         url = new URL(scriptAddress); conn = url.openConnection(); conn.setDoOutput(true); 
      

         dataSend = URLEncoder.encode("userId", "UTF-8") + "=" + URLEncoder.encode(userId, "UTF-8")

         + "&" + URLEncoder.encode("userPw", "UTF-8") + "=" + URLEncoder.encode(userPw, "UTF-8");
         
         
         if (data != null) {setVariableValues(data);} sendData();
         
         reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));


         while ((dataRecieve = reader.readLine()) != null) 
         {

            System.out.println(dataRecieve);
         }


         reader.close();
         
      }
      
      catch (IOException e) {System.out.println(Tools.thisPathAndLine() + e + "\n");}

   }
   
   
   //***************************************** END PUBLIC METHODS ******************************************//


   //**************************************** START PRIVATE METHODS ****************************************//

   
   /**
    * Sets the PHP variable values.
    * ESCA-JAVA0266:
    * @param data
    */
   private static void setVariableValues(ArrayList<String> data)
   {
      try
      {
         for (int i = 0; i < data.size(); i ++)
         {
            String variableName = "variable_" + Integer.toString(i+1);
       
            dataSend += "&" + URLEncoder.encode(variableName, "UTF-8") +

            "=" + URLEncoder.encode(data.get(i), "UTF-8");
         } 
      }
      
      catch (UnsupportedEncodingException e) {System.out.println(Tools.thisPathAndLine() + e + "\n");}
   }

   
   
   /**
    * Sends data to the appropriate PHP script.
    * ESCA-JAVA0266:
    */
   private static void sendData()
   {
      try
      {    
         writer = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream()));
  
         writer.write(dataSend); writer.flush(); writer.close();
      }
 
      catch (MalformedURLException e) {System.out.println(Tools.thisPathAndLine() + e + "\n");}

      catch (IOException e) {System.out.println(Tools.thisPathAndLine() + e + "\n");}
   
   }


   //***************************************** END PRIVATE METHODS *****************************************//
   
   
   private static URL url;
   private static String dataSend;
   private static URLConnection conn;
   private static String dataRecieve;
   private static String scriptAddress;
   private static BufferedReader reader;
   private static BufferedWriter writer;
   
   
   //********************************************** END CLASS **********************************************//
   
}


/*
   COPYRIGHT (C) 2010 - 2013 by Alexander Wait. All Rights Reserved.

   This class provides handy tools.

   @site http://www.javaika.com
   @author Alexander Wait
   @version 2012-02-01
*/



public class Tools 
{

   private static final int EXCEPTION_LINE_BEAK = 2;
   
   
   private Tools() {}
   
   
   //**************************************** START PUBLIC METHODS *****************************************//


   /**
    * This method returns the line number and path where it's called.
    * The syntax new Exception().getStackTrace()[0].getLineNumber() 
    * will only give the current line number of the source file.
    * @return
    */
   public static String thisPathAndLine()
   {
   
      String lineAndPath = ""; String stackTrace = "";
 
      stackTrace = new Exception().getStackTrace()[1].toString();
      
      
      for (int i = stackTrace.length()-1; i >= 0; i --)
      {
         if (stackTrace.charAt(i) == ')') {continue;} 
        
         else if (stackTrace.charAt(i) == '(') {break;}
        
         else {lineAndPath = (stackTrace.charAt(i) + lineAndPath);}
      }
         
      return lineAndPath + returnNewline(EXCEPTION_LINE_BEAK);
      
   }
   
   
   
   /**
    * Delays execution.
    * @param length
    */
   public static void delay(long length) 
   {
      for (long i = 0; i < length; i ++) {}
   }
   
  
 
   /**
    * This method returns a space.
    * @param length
    * @return
    */
   public static String returnSpace(int length)
   {
      String space = "";
      
      
      for (int i = 0; i < length; i ++)
      {
         space += " ";
      }
      
      return space;
   }
   
   
   
   /**
    * Assigns newlines to a string.
    * @param lines
    * @return
    */
   public static String returnNewline(int lines)
   {
      String newline = "";
      
      
      for (int i = 0; i < lines; i++)
      {
         newline += "\n";
      }
      
      
      return newline;
   
   }
   
   
   
   /**
    * Returns the users desktop path.
    * @return
    */
   public static String returnDesktopPath()
   {
      return (System.getProperty("user.home") + "/Desktop").replace("\\", "/") + "/"; 
   }
   

   //***************************************** END PUBLIC METHODS ******************************************//

   
   //********************************************** END CLASS **********************************************//
   
}


/*
   COPYRIGHT (C) 2010 - 2013 by Alexander Wait. All Rights Reserved.

   This class is used for sophisticated validation of data.

   @site http://www.javaika.com
   @author Alexander Wait
   @version 2010-07-18
*/



import java.util.regex.Pattern;



public class Validation
{

   //************************************** START INITIALISATION CODE **************************************//


   private static final String IP_ADDRESS_PATTERN = 
   
   "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +

   "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
   
   
   private static final String NUMBER_PATTERN = "[+-]?[0-9]*[.]?[0-9]*";
   
   private static final String ALPHANUMERIC_PATTERN = "[A-Za-z0-9]*";
   
   private static final String LETTER_PATTERN = "[A-Za-z]*";
   
   private static final String INTEGER_PATTERN = "[0-9]*";



   /**
    *  Validation constructor.
    */
   public Validation()
   {
      count = 0;
   }
   
   
   //*************************************** END INITIALISATION CODE ***************************************//

   
   //**************************************** START PUBLIC METHODS *****************************************//
   
   
   /**
    * Tests a string against a supplied mask string.
    * The key for testing a string is as follows.
    * '^' represents a upper case letter.
    * '#' represents a lower case letter.
    * '?' represents a digit.
    * @param maskString
    * @param testString 
    * @return result()
    */
   public boolean maskValidation(String maskString, String testString)
   {
      count = 0;

      
      if (maskString.length() == testString.length())
      {
         for (int i = 0; i < maskString.length(); i ++)
         {
            if (maskString.charAt(i) == testString.charAt(i))
            {
               count ++;
            }

            if (maskString.charAt(i) == '?')
            {
               for (char element : digit) 
               {
                  if (testString.charAt(i) == element) 
                  {
                     count ++;
                  }
               }
            }

            if (maskString.charAt(i) == '#')
            {
               for (char element : lowerCase) 
               {
                  if (testString.charAt(i) == element)
                  {
                     count ++;
                  }
               }
            }

            if (maskString.charAt(i) == '^')
            {
               for (char element : upperCase) 
               {
                  if (testString.charAt(i) == element)
                  {
                     count ++;
                  }
               }
            }
         }
      }
      
      
      if (count != testString.length()) {return false;}
      
      else {return true;}
   }
   
   
   
   /**
    * Checks the validation of an IP address.
    * @param testString
    * @return
    */
   public boolean ipAddressValidation(String testString)
   {
      pattern = Pattern.compile(IP_ADDRESS_PATTERN);
      
      
      return (pattern.matcher(testString).matches());
   }
   
   
   
   /**
    * Checks the validation of an integer.
    * @param testString
    * @return
    */
   public boolean integerValidation(String testString)
   {
      pattern = Pattern.compile(INTEGER_PATTERN);
      
      
      return (pattern.matcher(testString).matches());
   }
   
   
   
   /**
    * Checks the validation of a letter string.
    * @param testString
    * @return
    */
   public boolean letterValidation(String testString)
   {
      pattern = Pattern.compile(LETTER_PATTERN);
      
      
      return (pattern.matcher(testString).matches());
   }
   
   
   
   /**
    * Checks the validation of an alphanumeric string.
    * @param testString
    * @return
    */
   public boolean alphanumericValidation(String testString)
   {
      pattern = Pattern.compile(ALPHANUMERIC_PATTERN);
      
      
      return (pattern.matcher(testString).matches());
   }
   
   
   
   /**
    * Checks the validation of an alphanumeric string.
    * @param testString
    * @return
    */
   public boolean numberValidation(String testString)
   {
      pattern = Pattern.compile(NUMBER_PATTERN);
      
      
      return (pattern.matcher(testString).matches());
   }


   //***************************************** END PUBLIC METHODS ******************************************//


   private int count;
   
   private Pattern pattern;


   /**
    * ESCA-JAVA0007:
    */
   public static String[] numberOperator = {"PI", "e"};
   
   /**
    * ESCA-JAVA0007:
    */
   public static char[] digit = {'0','1','2','3','4','5','6','7','8','9'};
   
   /**
    * ESCA-JAVA0007:
    */
   public static char[] simpleOperator = {'-', '+', 'v', '^', '/', 'x', '*', ','};
   
   /**
    * ESCA-JAVA0007:
    */
   public static char[] number = 
   {'-','+','.','0','1','2','3','4','5','6','7','8','9','E','I','n','f','i','t','y'};
   
   /**
    * ESCA-JAVA0007:
    */
   public static String[] singleOperator = {"Sin", "Cos", "Tan", "Fac", "Inv", "Abs"};
   
   /**
    * ESCA-JAVA0007:
    */
   public static String[] doubleOperator = {"Log", "Mod", "Pwr", "Pnr", "Cwr", "Cnr"};
  
   /**
    * ESCA-JAVA0007:
    */
   public static char[] lowerCase = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o',
   'p','q','r','s','t','u','v','w','x','y','z'};
   
   /**
    * ESCA-JAVA0007:
    */
   public static char[] upperCase = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O',
   'P','Q','R','S','T','U','V','W','X','Y','Z'};
   
   
   //********************************************** END CLASS **********************************************//

}