

import java.io.*;
import java.awt.*;
import java.net.*;
import java.awt.event.*;
import java.util.Vector;

import javax.media.*;
import javax.media.rtp.*;
import javax.media.rtp.event.*;
import javax.media.rtp.rtcp.*;
import javax.media.protocol.*;
import javax.media.protocol.DataSource;
import javax.media.format.AudioFormat;
import javax.media.Format;
import javax.media.format.FormatChangeEvent;
import javax.media.control.BufferControl;

public class Receptor implements ReceiveStreamListener, SessionListener, ControllerListener
{
    String direccionIP = null;
    int puerto;
    RTPManager mgrs[] = null;
    PlayerWindow pw;
    boolean dataReceived = false;
    Object dataSync = new Object();

    public Receptor(String IP, int puer) {
	this.direccionIP = IP;
        this.puerto = puer;
    }

    protected boolean initialize() {

        try {
	    SessionAddress dirLocal = new SessionAddress();
	    SessionAddress dirDestino;
	    mgrs = new RTPManager[1];
	    mgrs[0] = (RTPManager) RTPManager.newInstance(); 
	    mgrs[0].addSessionListener(this);
	    mgrs[0].addReceiveStreamListener(this);
	    dirLocal= new SessionAddress( InetAddress.getLocalHost(),puerto);
            dirDestino = new SessionAddress( InetAddress.getByName(direccionIP), puerto);
	    mgrs[0].initialize( dirLocal);
	    BufferControl bc = (BufferControl)mgrs[0].getControl("javax.media.control.BufferControl");
	    if (bc != null)
		    bc.setBufferLength(350);
	    mgrs[0].addTarget(dirDestino);
        } catch (Exception e){
            return false;
        }

	long hora = System.currentTimeMillis();
	long espera = 30000;  

	try{
	    synchronized (dataSync) {
		while (!dataReceived && System.currentTimeMillis() - hora < espera) {
		    dataSync.wait(1000);
		}
	    }
	} catch (Exception e) {}

	if (!dataReceived) {
	    close();
	    return false;
	}

        return true;
    }

    protected void close() {
        pw.close();
        if (mgrs[0] != null) {
            mgrs[0].dispose();
	    mgrs[0] = null;
	}
    }

    public synchronized void update(SessionEvent evt) {
	if (evt instanceof NewParticipantEvent) {
	    Participant p = ((NewParticipantEvent)evt).getParticipant();
	    System.err.println("El usuario " + p.getCNAME()+" se ha unido a la conversación");
	}
    }

    public synchronized void update( ReceiveStreamEvent evt) {

	RTPManager mgr = (RTPManager)evt.getSource();
	Participant participant = evt.getParticipant();	
	ReceiveStream stream = evt.getReceiveStream();  

	if (evt instanceof RemotePayloadChangeEvent) {
	    System.exit(0);
	}
	else if (evt instanceof NewReceiveStreamEvent) {

	    try {
		stream = ((NewReceiveStreamEvent)evt).getReceiveStream();
		DataSource ds = stream.getDataSource();
		RTPControl ctl = (RTPControl)ds.getControl("javax.media.rtp.RTPControl");
		Player p = javax.media.Manager.createPlayer(ds);
		if (p == null)
		    return;
		p.addControllerListener(this);
		p.realize();
		pw = new PlayerWindow(p, stream);
		synchronized (dataSync) {
		    dataReceived = true;
		    dataSync.notifyAll();
		}
	    } catch (Exception e) {
		System.err.println("NewReceiveStreamEvent exception " + e.getMessage());
		return;
	    }
        
	}
	else if (evt instanceof ByeEvent) {
	     System.err.println(" Conexion cerrada con " + participant.getCNAME());
	     if (pw != null) {
		pw.close();
	     }
	}

    }

    public synchronized void controllerUpdate(ControllerEvent ce) {

	Player p = (Player)ce.getSourceController();

	if (p == null)
	    return;
        if (ce instanceof RealizeCompleteEvent) {
	    if (pw == null) {
		System.err.println("Error interno");
		System.exit(-1);
	    }
	    pw.initialize();
	    pw.setVisible(true);
	    p.start();
	}

	if (ce instanceof ControllerErrorEvent) {
	    if (pw != null) {
		pw.close();	
	    }
	}

    }

    class PlayerWindow extends Frame {

	Player player;
	ReceiveStream stream;

	PlayerWindow(Player p, ReceiveStream strm) {
	    player = p;
	    stream = strm;
	}

	public void initialize() {
	    add(new PlayerPanel(player));
	}

	public void close() {
	    player.close();
	    setVisible(false);
	    dispose();
	}

	public void addNotify() {
	    super.addNotify();
	    pack();
	}
    }

    class PlayerPanel extends Panel {

	Component vc, cc;

	PlayerPanel(Player p) {
	    setLayout(new BorderLayout());
	    if ((vc = p.getVisualComponent()) != null)
		add("Center", vc);
	    if ((cc = p.getControlPanelComponent()) != null)
		add("South", cc);
	}

	public Dimension getPreferredSize() {
	    int w = 0, h = 0;
	    if (vc != null) {
		Dimension size = vc.getPreferredSize();
		w = size.width;
		h = size.height;
	    }
	    if (cc != null) {
		Dimension size = cc.getPreferredSize();
		if (w == 0)
		    w = size.width;
		h += size.height;
	    }
	    if (w < 160)
		w = 160;
	    return new Dimension(w, h);
	}
    }
}




