// Path: TCC/src/Dependencias/Message.java
// public class Message implements Serializable {
// 
//     private long chId; //-1 means from client to server, otherwise chId generated by the server
//     private long timestamp, //-1 means from client to server, otherwise timeStamp of the moment when the server receives the message
//             ttl = 2000; //2 seconds TTL
//     private Object data; //can carry any type of object. in this program, i used a sound packet, but it could be a string, a chunk of video, ...
// 
//     public Message(long chId, long timestamp, Object data) {
//         this.chId = chId;
//         this.timestamp = timestamp;
//         this.data = data;
//     }
// 
//     public void setTimestamp(long timestamp) {
//         this.timestamp = timestamp;
//     }
// 
//     public long getChId() {
//         return chId;
//     }
// 
//     public Object getData() {
//         return data;
//     }
// 
//     public long getTimestamp() {
//         return timestamp;
//     }
// 
//     public long getTtl() {
//         return ttl;
//     }
// 
//     public void setTtl(long ttl) {
//         this.ttl = ttl;
//     }
// 
//     public void setChId(long chId) {
//         this.chId = chId;
//     }
// 
// }
// 
// Path: TCC/src/Dependencias/SoundPacket.java
// public class SoundPacket implements Serializable {
// 
//     public static AudioFormat defaultFormat = new AudioFormat(11025f, 8, 1, true, true); //11.025khz, 8bit, mono, signed, big endian (changes nothing in 8 bit) ~8kb/s
//     public static int defaultDataLenght = 1200; //send 1200 samples/packet by default
//     private byte[] data; //actual data. if null, comfort noise will be played
// 
//     public SoundPacket(byte[] data) {
//         this.data = data;
//     }
// 
//     public byte[] getData() {
//         return data;
//     }
// 
// }
// 
// Path: TCC/src/Dependencias/Utils.java
// public class Utils {
// 
//     public static void sleep(int ms) {
//         try {
//             Thread.sleep(ms);
//         } catch (InterruptedException ex) {
//         }
//     }
// 
//     public static String getExternalIP() {
//         try {
//             URL myIp = new URL("http://checkip.dyndns.org/");
//             BufferedReader in = new BufferedReader(new InputStreamReader(myIp.openStream()));
//             String s = in.readLine();
//             return s.substring(s.lastIndexOf(":") + 2, s.lastIndexOf("</body>"));
//         } catch (Exception ex) {
//             return "error " + ex;
//         }
//     }
// 
//     public static String getInternalIP() {
//         try {
//             return InetAddress.getLocalHost().getHostAddress();
//         } catch (UnknownHostException ex) {
//             return "error";
//         }
//     }
// }


import Dependencias.Message;
import Dependencias.SoundPacket;
import Dependencias.Utils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.zip.GZIPInputStream;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.SourceDataLine;
package ClienteVoIP;


public class AudioChannel extends Thread {

    private long chId; //an id unique for each user. generated by IP and port
    private ArrayList<Message> queue = new ArrayList<Message>(); //queue of messages to be played
    private int lastSoundPacketLen = SoundPacket.defaultDataLenght;
    private long lastPacketTime = System.nanoTime();

    public boolean canKill() { //returns true if it's been a long time since last received packet
        if (System.nanoTime() - lastPacketTime > 5000000000L) {
            return true; //5 seconds with no data
        } else {
            return false;
        }
    }

    public void closeAndKill() {
        if (speaker != null) {
            speaker.close();
        }
        stop();
    }

    public AudioChannel(long chId) {
        this.chId = chId;
    }

    public long getChId() {
        return chId;
    }

// Path: TCC/src/Dependencias/Message.java
// public class Message implements Serializable {
// 
//     private long chId; //-1 means from client to server, otherwise chId generated by the server
//     private long timestamp, //-1 means from client to server, otherwise timeStamp of the moment when the server receives the message
//             ttl = 2000; //2 seconds TTL
//     private Object data; //can carry any type of object. in this program, i used a sound packet, but it could be a string, a chunk of video, ...
// 
//     public Message(long chId, long timestamp, Object data) {
//         this.chId = chId;
//         this.timestamp = timestamp;
//         this.data = data;
//     }
// 
//     public void setTimestamp(long timestamp) {
//         this.timestamp = timestamp;
//     }
// 
//     public long getChId() {
//         return chId;
//     }
// 
//     public Object getData() {
//         return data;
//     }
// 
//     public long getTimestamp() {
//         return timestamp;
//     }
// 
//     public long getTtl() {
//         return ttl;
//     }
// 
//     public void setTtl(long ttl) {
//         this.ttl = ttl;
//     }
// 
//     public void setChId(long chId) {
//         this.chId = chId;
//     }
// 
// }
// 
// Path: TCC/src/Dependencias/SoundPacket.java
// public class SoundPacket implements Serializable {
// 
//     public static AudioFormat defaultFormat = new AudioFormat(11025f, 8, 1, true, true); //11.025khz, 8bit, mono, signed, big endian (changes nothing in 8 bit) ~8kb/s
//     public static int defaultDataLenght = 1200; //send 1200 samples/packet by default
//     private byte[] data; //actual data. if null, comfort noise will be played
// 
//     public SoundPacket(byte[] data) {
//         this.data = data;
//     }
// 
//     public byte[] getData() {
//         return data;
//     }
// 
// }
// 
// Path: TCC/src/Dependencias/Utils.java
// public class Utils {
// 
//     public static void sleep(int ms) {
//         try {
//             Thread.sleep(ms);
//         } catch (InterruptedException ex) {
//         }
//     }
// 
//     public static String getExternalIP() {
//         try {
//             URL myIp = new URL("http://checkip.dyndns.org/");
//             BufferedReader in = new BufferedReader(new InputStreamReader(myIp.openStream()));
//             String s = in.readLine();
//             return s.substring(s.lastIndexOf(":") + 2, s.lastIndexOf("</body>"));
//         } catch (Exception ex) {
//             return "error " + ex;
//         }
//     }
// 
//     public static String getInternalIP() {
//         try {
//             return InetAddress.getLocalHost().getHostAddress();
//         } catch (UnknownHostException ex) {
//             return "error";
//         }
//     }
// }


// Path: TCC/src/ClienteVoIP/AudioChannel.java
import Dependencias.Message;
import Dependencias.SoundPacket;
import Dependencias.Utils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.zip.GZIPInputStream;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.SourceDataLine;

package ClienteVoIP;


public class AudioChannel extends Thread {

    private long chId; //an id unique for each user. generated by IP and port
    private ArrayList<Message> queue = new ArrayList<Message>(); //queue of messages to be played
    private int lastSoundPacketLen = SoundPacket.defaultDataLenght;
    private long lastPacketTime = System.nanoTime();

    public boolean canKill() { //returns true if it's been a long time since last received packet
        if (System.nanoTime() - lastPacketTime > 5000000000L) {
            return true; //5 seconds with no data
        } else {
            return false;
        }
    }

    public void closeAndKill() {
        if (speaker != null) {
            speaker.close();
        }
        stop();
    }

    public AudioChannel(long chId) {
        this.chId = chId;
    }

    public long getChId() {
        return chId;
    }

    public void addToQueue(Message m) { //adds a message to the play queue