package jconferencia;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import java.net.*;

import javax.media.*;
import javax.media.control.*;
import javax.media.protocol.*;
import javax.media.format.*;
import java.util.*;
import java.io.*;
import javax.swing.event.*;

public class PantallaPrincipal extends JFrame {

  // Propias de la audioconferencia
  private MediaLocator destino = null; // Sirve para indicar la dirección a la que vamos a enviar los datos
  private MediaLocator origen = null; // Sirve para indicar la dirección de la que provienen los datos
  private DataSink dataSink = null; // Objeto a través del cual enviamos los datos
  private Processor processor = null; // Objeto que convierte los datos para enviarlos
  private DataSource dataSource = null; // Objeto a través del cual recibimos los datos
  private Player player = null; // Objeto que reproduce los datos recibidos
  private static int puertoDest = 49150;
  private static int puertoOrig = 49150;

  private static final Format[] FORMATS = new Format[] {
    new AudioFormat(AudioFormat.G723_RTP,8000,16,1 )}; // Especifica la codificación y el formato que tendrán los datos que enviamos

  private static final ContentDescriptor CONTENT_DESCRIPTOR = new ContentDescriptor(
      ContentDescriptor.RAW_RTP);

  // Propias de la Interfaz Gráfica
  private JPanel contentPane;
  private BorderLayout borderLayout1 = new BorderLayout();
  private JPanel pConexion = new JPanel();
  private Border border1;
  private TitledBorder titledBorder1;
  private JLabel lIP = new JLabel();
  private JTextField tfIP = new JTextField();
  private JButton bConectar = new JButton();
  private FlowLayout flowLayout1 = new FlowLayout();
  private JPanel pEstado = new JPanel();
  private Border border2;
  private Border border3;
  private FlowLayout flowLayout2 = new FlowLayout();
  private JLabel lEstado = new JLabel();
  private String miIP;
  private Conexion conexion;
  private Object fLock;
  private boolean fNecesitaParar = false;
  private JPanel jPanel1 = new JPanel();
  private JSlider jSlider1 = new JSlider();
  private JLabel jLabel1 = new JLabel();
  private JLabel lVolumen = new JLabel();

  //Construct the frame
  public PantallaPrincipal() {
    enableEvents(AWTEvent.WINDOW_EVENT_MASK);
    try {
      jbInit();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  }
  //Component initialization
  private void jbInit() throws Exception  {
    InetAddress hostIPaddress = InetAddress.getLocalHost();
    miIP = hostIPaddress.getHostAddress();

    border2 = BorderFactory.createBevelBorder(BevelBorder.LOWERED,Color.white,Color.white,new Color(103, 101, 98),new Color(148, 145, 140));
    border3 = BorderFactory.createCompoundBorder(new TitledBorder(new EtchedBorder(EtchedBorder.RAISED,Color.white,new Color(148, 145, 140)),"Conexión"),BorderFactory.createEmptyBorder(5,10,5,10));
    pConexion.setLayout(flowLayout1);
    flowLayout1.setAlignment(FlowLayout.LEFT);
    flowLayout1.setHgap(10);
    borderLayout1.setHgap(5);
    borderLayout1.setVgap(5);
    pConexion.setPreferredSize(new Dimension(300, 65));
    pEstado.setBorder(border2);
    pEstado.setPreferredSize(new Dimension(126, 20));
    pEstado.setLayout(flowLayout2);
    flowLayout2.setAlignment(FlowLayout.LEFT);
    flowLayout2.setVgap(0);
    lEstado.setText("No está conectado...");
    this.setLocale(new java.util.Locale("es", "ES", "EURO"));
    bConectar.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        bConectar_actionPerformed(e);
      }
    });
    jLabel1.setText("Volumen:");
    jSlider1.setPaintLabels(true);
    jSlider1.setPaintTicks(true);
    jSlider1.addChangeListener(new javax.swing.event.ChangeListener() {
      public void stateChanged(ChangeEvent e) {
        jSlider1_stateChanged(e);
      }
    });
    lVolumen.setText("50 %");
    pConexion.add(lIP, null);
    pConexion.add(tfIP, null);
    pConexion.add(bConectar,null);
    pEstado.add(lEstado, null);

    jPanel1.add(jLabel1, null);
    jPanel1.add(jSlider1, null);
    jPanel1.add(lVolumen, null);
    //setIconImage(Toolkit.getDefaultToolkit().createImage(PantallaPrincipal.class.getResource("[Your Icon]")));
    contentPane = (JPanel) this.getContentPane();
    border1 = new EtchedBorder(EtchedBorder.RAISED,Color.white,new Color(148, 145, 140));
    titledBorder1 = new TitledBorder(new EtchedBorder(EtchedBorder.RAISED,Color.white,new Color(148, 145, 140)),"Conexión");
    contentPane.setLayout(borderLayout1);
    this.setSize(new Dimension(344, 149));
    this.setTitle("JConferencia -  © Gerardo Parra - 2003");
    pConexion.setBorder(border3);
    lIP.setText("Dirección IP:");
    bConectar.setText("Conectar");
    tfIP.setPreferredSize(new Dimension(100, 21));
    contentPane.add(pConexion, BorderLayout.NORTH);
    contentPane.add(pEstado, BorderLayout.SOUTH);
    contentPane.add(jPanel1, BorderLayout.CENTER);
    fLock = new Object();

  }
  //Overridden so we can exit when window is closed
  protected void processWindowEvent(WindowEvent e) {
    super.processWindowEvent(e);
    if (e.getID() == WindowEvent.WINDOW_CLOSING) {
      System.exit(0);
    }
  }

  void bConectar_actionPerformed(ActionEvent e) {
    // Accion de conectar
    if (bConectar.getText()=="Conectar") {
      if (conexion == null) {
        conexion = new Conexion();
      }
      if (!conexion.isAlive()) {
        fNecesitaParar = false;
        conexion.start();
        bConectar.setText("Parar");
        lEstado.setText("Conectado a " + tfIP.getText());
      }
    } else {
      try {
        synchronized(fLock) {
          fNecesitaParar = true;
          fLock.notify();
          bConectar.setText("Conectar");
          lEstado.setText("No está conectado...");
          conexion = null;
        }
      }catch (Exception ex) {
        ex.printStackTrace();
      }
    }

}

  public class Conexion extends Thread {
    public void run() {
      try {
        if (tfIP.getText()!=null ) {
          String dirDest = "rtp://" + tfIP.getText() + ":" + puertoDest + "/audio";
          String dirOrig = "rtp://" + miIP + ":" + puertoOrig + "/audio";
          //String dirOrig = args[0] + ":" + puertoOrig + "/audio";
          destino = new MediaLocator(dirDest);
          origen = new MediaLocator(dirOrig);
          System.out.println("Creando el MediaLocator Destino: '" + destino + "'");
          System.out.println("Creando el MediaLocator Origen: '" + origen + "'");
          CaptureDeviceInfo di = null;
          Vector deviceList = CaptureDeviceManager.getDeviceList(new AudioFormat(AudioFormat.LINEAR,8000,8,1));
          if (deviceList.size()>0) {
         /*for (int i=0; i<deviceList.size();i++) {
                 System.out.println(deviceList.elementAt(i).toString());
         }*/
            di = (CaptureDeviceInfo)deviceList.firstElement();
          } else
            System.exit(-1);
          DataSource source = Manager.createDataSource(di.getLocator());
          System.out.println("Creado el DataSource: '" + di.getName() + "'");
          crearProcesador(source);
          crearPlayer();
          System.out.println("Conectado al destino");
          //ac.comenzarTransmision();
          System.out.println("Comunicando...");
          for (;;) {
            synchronized(fLock) {
            if (fNecesitaParar) {
              pararTransmision();
              break;
            }
            try {
              fLock.wait(100);
            } catch (InterruptedException e) {
            }
          }
          }
        } else {
          System.out.println("Sintaxis: java audioconferencia rtp://x.y.z.w");
        }
      } catch (Throwable t) {
        t.printStackTrace();
      }
    }

    public void comenzarTransmision() throws IOException {
      processor.start();
      dataSink.open();
      dataSink.start();
      player.start();
    }

    public void pararTransmision() throws IOException {
      player.stop();
      player.deallocate();
      player.close();

      dataSink.stop();
      dataSink.close();

      processor.stop();
      processor.close();
      processor.deallocate();
      System.out.println("Parando Transmision");
    }

    public void crearProcesador(DataSource ds) throws NoDataSinkException,
    CannotRealizeException, NoProcessorException, IOException {
      System.out.println("Antes de crear el procesador");
      processor = Manager.createRealizedProcessor(new ProcessorModel (ds,FORMATS,CONTENT_DESCRIPTOR));
      System.out.println("Se ha creado el procesador: '" + processor.toString() + "'");
      System.out.println("Ahora se va a crear el DataSink");
      dataSink = Manager.createDataSink(processor.getDataOutput(),destino);
      System.out.println("Se ha creado el DataSink: '" + dataSink.toString() + "'");
      processor.start();
      dataSink.open();
      dataSink.start();
    }

    public void crearPlayer() throws NoDataSourceException, CannotRealizeException, NoPlayerException, IOException{
      player = Manager.createRealizedPlayer(origen);
      System.out.println("Se ha creado el player: '" + player.toString() + "'");
      player.start();
    }
  }

  void jSlider1_stateChanged(ChangeEvent e) {
    lVolumen.setText(Integer.toString(jSlider1.getValue()) + " %");
    player.getGainControl().setLevel((float)jSlider1.getValue()/100);
  }
}

