Advertisement
Guest User

Untitled

a guest
Jul 23rd, 2018
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 11.29 KB | None | 0 0
  1. //package cs.sun.ac.za.voip;
  2.  
  3. import java.awt.GridBagConstraints;
  4. import java.awt.GridBagLayout;
  5. import java.awt.Insets;
  6. import java.awt.event.ActionEvent;
  7. import java.awt.event.ActionListener;
  8. import java.io.BufferedReader;
  9. import java.io.ByteArrayInputStream;
  10. import java.io.InputStream;
  11. import java.io.InputStreamReader;
  12. import java.io.OutputStream;
  13. import java.net.DatagramPacket;
  14. import java.net.DatagramSocket;
  15. import java.net.InetAddress;
  16. import java.net.Socket;
  17.  
  18. import javax.sound.sampled.AudioFormat;
  19. import javax.sound.sampled.AudioInputStream;
  20. import javax.sound.sampled.AudioSystem;
  21. import javax.sound.sampled.DataLine;
  22. import javax.sound.sampled.SourceDataLine;
  23. import javax.sound.sampled.TargetDataLine;
  24. import javax.swing.JFrame;
  25. import javax.swing.JList;
  26. import javax.swing.JPanel;
  27. import javax.swing.JScrollPane;
  28. import javax.swing.JTextArea;
  29. import javax.swing.JTextField;
  30. import javax.swing.SwingUtilities;
  31.  
  32. public class VoipClient implements ActionListener{
  33.  
  34.     //gui
  35.     private static JFrame frame;
  36.     private static JTextField textField;
  37.     private static JTextArea textArea;
  38.     private static JScrollPane scrollPane;
  39.     private static JList userList;
  40.  
  41.     private InetAddress client_ip; //the ip address the client wishes to call
  42.     private InetAddress server_ip; //the ip of the server
  43.     private int receive_port = 3001; //the port to which the client wishes to send
  44.     private int send_port = 3002; //the clients own port, to listen on for traffic
  45.     private int server_port; //the port with which to connect to the server
  46.     private DatagramSocket receive_socket; //the socket to receive on
  47.     private DatagramSocket send_socket; //the socket to send on
  48.     private Socket server_socket; //TCP socket to server
  49.  
  50.     private OutputStream out = null;
  51.     private BufferedReader in = null;
  52.  
  53.     private static boolean connected = false;
  54.     private static boolean stopCapture;
  55.     private static boolean stopPlay;
  56.  
  57.     AudioFormat audioFormat;
  58.     TargetDataLine targetDataLine;
  59.     AudioInputStream audioInputStream;
  60.     SourceDataLine sourceDataLine;
  61.  
  62.     public VoipClient(){
  63.  
  64.         //build the gui
  65.         frame = new JFrame("VOIP");
  66.  
  67.         JPanel pane = new JPanel(new GridBagLayout());
  68.         GridBagConstraints c1 = new GridBagConstraints();
  69.         GridBagConstraints c2 = new GridBagConstraints();
  70.         GridBagConstraints c3 = new GridBagConstraints();
  71.  
  72.         textArea = new JTextArea("Commands: \n \\call <ip> \n \\dc \n \\msg <text message>\n");
  73.         textArea.setEditable(false);
  74.         textArea.setLineWrap(true);
  75.         scrollPane = new JScrollPane(textArea);
  76.         scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
  77.  
  78.         textField = new JTextField();
  79.         textField.addActionListener(this);
  80.         textField.setText("\\call 127.0.0.1");
  81.         userList = new JList();
  82.  
  83.         c1.fill = GridBagConstraints.BOTH;
  84.         c1.insets = new Insets(10, 10, 5, 5); //top, left, bottom, right
  85.         c1.gridwidth = 1;
  86.         c2.gridheight = 1;
  87.         c1.ipadx = 350;
  88.         c1.ipady = 400;
  89.         c1.weightx = 1;
  90.         c1.weighty = 1;
  91.         c1.gridx = 0;
  92.         c1.gridy = 0;
  93.         pane.add(scrollPane, c1);
  94.  
  95.         c2.fill = GridBagConstraints.BOTH;
  96.         c2.insets = new Insets(5, 10, 10, 10);
  97.         c2.gridwidth = 1;
  98.         c2.gridheight = 1;
  99.         c2.ipadx = 350;
  100.         c2.ipady = 70;
  101.         c2.weightx = 0.3;
  102.         c2.weighty = 0.3;
  103.         c2.gridx = 0;
  104.         c2.gridy = 1;
  105.         pane.add(textField, c2);
  106.  
  107.         c3.fill = GridBagConstraints.BOTH;
  108.         c3.insets = new Insets(10, 5, 10, 10);
  109.         c3.gridwidth = 1;
  110.         c3.gridheight = 1;
  111.         c3.ipadx = 150;
  112.         c3.ipady = 400;
  113.         c3.weightx = 0.2;
  114.         c3.weighty = 0.2;
  115.         c3.gridx = 1;
  116.         c3.gridy = 0;
  117.         pane.add(userList, c3);
  118.  
  119.         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  120.         frame.getContentPane().add(pane);
  121.         frame.pack();
  122.         /*
  123.          * requestFocusInWindow must be called after component realization,
  124.          * frame.pack() and before the frame is displayed.
  125.          */
  126.         textField.requestFocusInWindow();
  127.         textField.setSelectionStart(6);
  128.         textField.setSelectionEnd(15);
  129.         frame.setSize(500, 500);
  130.         frame.setVisible(true);
  131.  
  132.         stopCapture = false;
  133.         stopPlay = false;
  134.     }
  135.  
  136.     /*
  137.      * This method creates and returns an AudioFormat object for a given set
  138.      * of format parameters.
  139.      */
  140.     private AudioFormat getAudioFormat(){
  141.         float sampleRate = 8000.0F;
  142.         //8000,11025,16000,22050,44100
  143.         int sampleSizeInBits = 16;
  144.         //8,16
  145.         int channels = 1;
  146.         //1,2
  147.         boolean signed = true;
  148.         //true,false
  149.         boolean bigEndian = false;
  150.         //true,false
  151.         return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed, bigEndian);
  152.     }
  153.  
  154.     /*
  155.      * This method captures audio input
  156.      * from a microphone and sends it as a UDP packet.
  157.      */
  158.     class CaptureAudio implements Runnable  {
  159.  
  160.         private byte[] tempBuffer;
  161.         private DatagramSocket socket;
  162.         private InetAddress ip;
  163.         private int port;
  164.  
  165.         public CaptureAudio(DatagramSocket socket, InetAddress ip, int port)    {
  166.             this.socket = socket;
  167.             this.ip = ip;
  168.             this.port = port;
  169.             this.tempBuffer = new byte[4000];
  170.         }
  171.  
  172.         public void run()   {  
  173.             try {
  174.  
  175.                 stopCapture = false;
  176.  
  177.                 //Get everything set up for capture
  178.                 audioFormat = getAudioFormat();
  179.                 DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, audioFormat);
  180.                 targetDataLine = (TargetDataLine)
  181.                 AudioSystem.getLine(dataLineInfo);
  182.                 targetDataLine.open(audioFormat);
  183.                 targetDataLine.start();
  184.  
  185.                 try{
  186.                     //Loop until stopCapture is set by another thread.
  187.                     while(!stopCapture){
  188.                         //Read data from the internal buffer of the data line.
  189.                         int cnt = targetDataLine.read(tempBuffer, 0, tempBuffer.length);
  190.                         if(cnt > 0){
  191.                             DatagramPacket outPacket = new DatagramPacket(tempBuffer, tempBuffer.length, this.ip, this.port);
  192.                             this.socket.send(outPacket);
  193.                         }
  194.                     }
  195.                 }catch (Exception e) {}
  196.  
  197.             } catch (Exception e) {}
  198.         }
  199.     }
  200.  
  201.     /* This method receives audio input
  202.      * from a UDP packet and plays it.
  203.      */
  204.     class PlayAudio implements Runnable {
  205.  
  206.         private DatagramSocket socket;
  207.         private byte[] tempBuffer;
  208.  
  209.         public PlayAudio(DatagramSocket socket) {
  210.             this.socket = socket;
  211.             this.tempBuffer = new byte[4000];
  212.         }
  213.  
  214.         public void run()   {
  215.             try{
  216.  
  217.                 DatagramPacket inPacket;
  218.                 stopPlay = false;
  219.  
  220.                 //Loop until stopPlay is set by another thread.
  221.                 while (!stopPlay)   {
  222.  
  223.                     //Put received data into a byte array object
  224.                     inPacket = new DatagramPacket(tempBuffer, tempBuffer.length);
  225.                     this.socket.receive(inPacket);
  226.  
  227.                     byte[] audioData = inPacket.getData();
  228.  
  229.                     //Get an input stream on the byte array containing the data
  230.                     InputStream byteArrayInputStream = new ByteArrayInputStream(audioData);
  231.                     AudioFormat audioFormat = getAudioFormat();
  232.                     audioInputStream = new AudioInputStream(byteArrayInputStream, audioFormat, audioData.length/audioFormat.getFrameSize());
  233.                     DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, audioFormat);
  234.                     sourceDataLine = (SourceDataLine)
  235.                     AudioSystem.getLine(dataLineInfo);
  236.                     sourceDataLine.open(audioFormat);
  237.                     sourceDataLine.start();
  238.  
  239.                     try {
  240.                         int cnt;
  241.                         //Keep looping until the input read method returns -1 for empty stream.
  242.                         while((cnt = audioInputStream.read(tempBuffer, 0, tempBuffer.length)) != -1){
  243.                             if(cnt > 0){
  244.                                 //Write data to the internal buffer of the data line where it will be delivered to the speaker.
  245.                                 sourceDataLine.write(tempBuffer, 0, cnt);
  246.                             }
  247.                         }
  248.                         //Block and wait for internal buffer of the data line to empty.
  249.                         sourceDataLine.drain();
  250.                         sourceDataLine.close();
  251.                     }catch (Exception e) {}
  252.                 }
  253.             } catch (Exception e) {}
  254.         }
  255.  
  256.     }
  257.  
  258.     /*
  259.      * Initiates a call between two clients.
  260.      */
  261.     private void clientConnect(String ip)   {
  262.  
  263.         //Assign the target IP address
  264.         try {
  265.             client_ip = InetAddress.getByName(ip);
  266.         } catch (Exception e)   {
  267.             appendToTextArea("Error: Client received invalid IP address.");
  268.         }
  269.  
  270.         //Initiate sockets to use for audio streaming
  271.         try {
  272.             receive_socket = new DatagramSocket(receive_port);
  273.             send_socket = new DatagramSocket(send_port);
  274.         } catch (Exception e)   {}
  275.  
  276.         Thread CaptureAudio = new Thread(new CaptureAudio(send_socket, client_ip, receive_port));
  277.         CaptureAudio.start();
  278.  
  279.         Thread PlayAudio = new Thread(new PlayAudio(receive_socket));
  280.         PlayAudio.start();
  281.     }
  282.  
  283.     /*
  284.      * Disconnects the client from the current call.
  285.      */
  286.     private void clientDisconnect() {
  287.  
  288.         try {
  289.             //stop the threads
  290.             stopCapture = true;
  291.             stopPlay = true;
  292.  
  293.             //wait for threads to terminate
  294.             try {
  295.                 Thread.sleep(200);
  296.             } catch (Exception e) {}
  297.  
  298.             //close the sockets
  299.             try {
  300.                 send_socket.close();
  301.                 receive_socket.close();
  302.             } catch (Exception e) {}
  303.         } catch (Exception e)   {}
  304.     }
  305.  
  306.     /*
  307.      * Establishes a TCP connection between client and server.
  308.      */
  309.     private void serverConnect(String ip_string, int port)  {
  310.         try {
  311.             server_ip = InetAddress.getByName(ip_string);
  312.             server_port = port;
  313.             server_socket = new Socket(server_ip, server_port);
  314.             out = server_socket.getOutputStream();
  315.             in =  new BufferedReader(new InputStreamReader(server_socket.getInputStream()));
  316.  
  317.             appendToTextArea("Connected to server at: " + ip_string);
  318.             connected = true;
  319.  
  320.             Thread listenLoop = new Thread(new ConnectionListener());
  321.             listenLoop.start();
  322.  
  323.         } catch (Exception e) {
  324.             appendToTextArea("Error: Connection refused, could not connect to server.");
  325.         }
  326.     }
  327.  
  328.     private void serverSend(String message) {
  329.         try {
  330.             out.write(message.getBytes());
  331.         } catch (Exception e){         
  332.             appendToTextArea("Error: Connection to server lost.");
  333.         }
  334.     }
  335.  
  336.     /*
  337.      * A method for adding text to the text area.
  338.      * The append method is thread safe.
  339.      * The setCaretPosition method is not thread safe and
  340.      * is called on the event-dispatching thread.
  341.      */
  342.     private void appendToTextArea(String text)  {
  343.         textArea.append(text + "\n");
  344.  
  345.         SwingUtilities.invokeLater(new Runnable() {
  346.             public void run() {
  347.                 textArea.setCaretPosition(textArea.getDocument().getLength());
  348.             }
  349.         });
  350.     }
  351.  
  352.     public void actionPerformed(ActionEvent a)  {
  353.         if (a.getSource() == textField) {
  354.             String text = textField.getText();
  355.             serverSend(text);
  356.             textField.setText("");
  357.         }
  358.     }
  359.  
  360.     /*
  361.      * listens to incoming messages from the server
  362.      */
  363.     private class ConnectionListener implements Runnable {
  364.  
  365.         public void run() {
  366.             Boolean listen = true;
  367.             try {
  368.                 while(listen) {
  369.  
  370.                     String data = in.readLine();
  371.  
  372.                     if (data != null) {
  373.                         if (data.substring(0, 4).equals("ca__"))    {
  374.                             String ip_string = data.split(" ")[1];
  375.                             clientConnect(ip_string);
  376.                         } else if (data.substring(0,4).equals("ul__"))  {
  377.                             String[] users = data.substring(5).split(" ");
  378.                             userList.clearSelection();
  379.                             userList.setListData(users);
  380.                         } else if (data.substring(0,4).equals("dc__"))  {
  381.                             clientDisconnect();
  382.                         } else  {
  383.                             appendToTextArea(data);
  384.                         }
  385.                     } else  {
  386.                         //when server disconnects, stop listening
  387.                         listen = false;
  388.                     }
  389.                 }
  390.             } catch (Exception e) {
  391.                 appendToTextArea("Error: An error occurred with the connection.");
  392.             }
  393.         }
  394.     }
  395.  
  396.     public static void main(String args[]){
  397.         String server_ip = args[0]; //server ip address
  398.         String server_port = args[1]; //port for tcp connection to server
  399.  
  400.         VoipClient c = new VoipClient();
  401.  
  402.         c.serverConnect(server_ip, Integer.parseInt(server_port));
  403.  
  404.         while(connected);
  405.     }
  406. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement