/*
 *  Copyright (C) 2006  Takashi Kasuya <kasuya@sfc.keio.ac.jp>
 *
 * This library is free software; you can redistribute it and/or
 *　modify it under the terms of the GNU Lesser General Public
 *　License as published by the Free Software Foundation; either
 *　version 2.1 of the License, or (at your option) any later version.
 *　This library is distributed in the hope that it will be useful,
 *　but WITHOUT ANY WARRANTY; without even the implied warranty of
 *　MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *　Lesser General Public License for more details.
 *
 *　You should have received a copy of the GNU Lesser General Public
 *　License along with this library; if not, write to the Free Software
 *　Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */


package jp.ac.naka.ec.media;

import java.awt.Component;
import java.io.IOException;

import javax.media.ControllerEvent;
import javax.media.ControllerListener;
import javax.media.MediaException;
import javax.media.MediaLocator;
import javax.media.Player;
import javax.swing.JFrame;

import net.sourceforge.jsdp.Media;
import net.sourceforge.jsdp.MediaDescription;
import net.sourceforge.jsdp.SessionDescription;

/**
 * 指定のポートで音声の再生を行う。
 * @author Takashi Kasuya
 *
 */
public class AudioReceiver {

	MediaLocator locator;

	Player player;

	SessionDescription sdp;
	WaitingListener listener;
	
	/**
	 * 
	 * @param sdp
	 * @throws MediaException
	 */
	public void receiveMedia(SessionDescription sdp) throws MediaException {
		try {
			// MediaLocatorの作成
			int port = 0;
			MediaDescription[] mls = sdp.getMediaDescriptions();
			for (MediaDescription md : mls) {
				Media media = md.getMedia();
				if (media.getMediaType().equals("audio")) {
					port = media.getPort();
				}
			}
			String url = "rtp://:" + port + "/audio";
			locator = new MediaLocator(url);
			createPlayer();
			player.prefetch();
			player.start();
			listener.waitForEvent(Player.Started);
			
			this.sdp = sdp;
		} catch (IOException e) {
			player.close();
			throw new MediaException(e.getMessage());
		}
	}
	
	public void receiveMedia(int port) throws MediaException {
		try {
			// MediaLocatorの作成

			String url = "rtp://:" + port + "/audio";
			locator = new MediaLocator(url);
			createPlayer();
			player.prefetch();
			player.start();
			//テストの時は書かないとダメっぽい
			//listener.waitForEvent(Player.Started, player);
		} catch (IOException e) {
			player.close();
			throw new MediaException(e.getMessage());
		}
	}

	/**
	 * 再生中かどうか
	 * 
	 * @return
	 */
	public boolean isPlaying() {
		//System.out.println(Player.Started + "," + player.getState());
		return (player.getState() == Player.Started) ? true : false;
	}

	/**
	 * オーディオ受信を終了
	 * 
	 */
	public void stop() {
		player.close();
	}

	/**
	 * awtコンポーネントの取得
	 * 
	 * @return
	 */
	public Component getControlPanelComponent() {
		if (player != null) {
			return player.getControlPanelComponent();
		} else {
			throw new NullPointerException("Playerが作られていません");
		}
	}

	private void createPlayer() throws IOException, MediaException {
		if (locator == null)
			throw new NullPointerException("Locator is null");

		javax.media.protocol.DataSource dataSource;
		dataSource = javax.media.Manager.createDataSource(locator);

		player = javax.media.Manager.createPlayer(dataSource);
		listener = new WaitingListener();
		player.addControllerListener(listener);

		player.realize();
		/*
		while (player.getState() != Player.Realized) {
			;
		}
		*/
		listener.waitForEvent(Player.Realized);

	}

	class WaitingListener implements ControllerListener {

		Thread th;
		int state;
		int previous;

		public void waitForEvent(final int state) {
			this.state = state;
			th = new Thread() {
				public void run() {
					try {
						synchronized (this) {
							if (previous < state)
								wait();
						}
					} catch (InterruptedException e) {
						;
					}
				}
			};
			th.start();
			try {
				th.join();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

		public void controllerUpdate(ControllerEvent evt) {
			System.out.println(evt.toString());
			Player p = (Player) evt.getSourceController();
			// System.out.println(p.getState());
			previous = p.getState();
			if (th == null)
				return;
			if (p.getState() >= state) {
				synchronized (th) {
					th.notifyAll();
				}
			}

		}

	}
	public static void main (String args[]) {
		AudioReceiver receiver = new AudioReceiver();
		try {
			receiver.receiveMedia(22224);
			JFrame jf = new JFrame();
			jf.add(receiver.getControlPanelComponent());
			jf.setVisible(true);
			jf.pack();
			jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		} catch (MediaException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
