import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.BoxLayout;
import javax.swing.JDesktopPane;
import javax.swing.JOptionPane;
import javax.swing.JPasswordField;

import java.awt.Color;

import javax.swing.JTextField;
import javax.swing.JLabel;
import javax.swing.JButton;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

import javax.swing.border.LineBorder;
import javax.swing.JRadioButton;
import javax.swing.ButtonGroup;

import java.awt.event.ItemListener;
import java.awt.event.ItemEvent;

import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JProgressBar;

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

public class DemoApp {

	private JFrame frmDemo;
	private final ButtonGroup buttonGroup = new ButtonGroup();
	private JTextField txtLiveURL;
	private JRadioButton liveRadioButton;
	private JRadioButton archiveRadioButton;
	private JRadioButton stratusRadioButton;
	private JButton btnStop;
	private JTextField txtArchiveStart;
	private JTextField txtStratusServer;
	private JTextField txtStratusUser;
	private JTextField txtStratusPass;
	private JLabel label;
	private JTextField txtArchiveEnd;
	private JButton btnArchiveExport;
	private JButton btnArchiveGotoTime;
	private JButton btnStratusConnect;
	private JTextField txtArchiveGotoTime;
	private JProgressBar progressBar;
	private JCheckBox cbAnalytics;
	private JComboBox cbSpeed;
	private JButton btnPlayBackward;
	private JLabel lblSpeed_1;
	private JButton btnPause;
	private JButton btnPlayForward;
	private JButton btnSnapshot;
	private JLabel lblStatus;
	private JLabel lblNewLabel;
	private JLabel lblTime;
	private JCheckBox cbRTPoverTCP;
	private JCheckBox cbHWDecoder;
	
	private JComboBox boxCameraList = new JComboBox();
	private int selectedCam = 101;

	com.videonext.mplayer.MediaPlayer player = null;
	PlayerListener playerListener = null;

	com.videonext.mplayer.MediaExporter exporter = null;
	ExporterListener exporterListener = null;
	private JTextField txtJitterBuf;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					DemoApp demo = new DemoApp();

					File currDir = new File(".");
					String libDir = currDir.getCanonicalPath() + "/lib";

					demo.init(libDir, "");

					demo.frmDemo.setVisible(true);

				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	public void init(String playerLibDir, String playerVersion)
			throws Exception {

		playerListener = new PlayerListener();
		player.setMediaPlayerListener(playerListener);
		

		player.setCacheSize(10000000); // 10 MB

		exporterListener = new ExporterListener();
		exporter = new com.videonext.mplayer.MediaExporter();
		exporter.setMediaExporterListener(exporterListener);

	}

	/**
	 * Create the application.
	 */
	public DemoApp() {
		initialize();
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		frmDemo = new JFrame();
		frmDemo.setTitle("Demo");
		frmDemo.setBounds(100, 100, 720, 681);
		frmDemo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frmDemo.getContentPane().setLayout(
				new BoxLayout(frmDemo.getContentPane(), BoxLayout.X_AXIS));

		JDesktopPane desktopPane = new JDesktopPane();
		desktopPane.setBackground(Color.WHITE);
		frmDemo.getContentPane().add(desktopPane);

		try {
			player = new com.videonext.mplayer.MediaPlayer("DemoPlayer");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		player.setBackground(Color.LIGHT_GRAY);
		player.setBounds(6, 10, 704, 450);
		desktopPane.add(player);

		btnPlayForward = new JButton(">");
		btnPlayForward.addMouseListener(new BtnPlayForwardMouseListener());

		btnPlayForward.setBounds(6, 570, 45, 29);
		desktopPane.add(btnPlayForward);

		btnPause = new JButton("Pause");
		btnPause.setEnabled(false);
		btnPause.addActionListener(new BtnPauseActionListener());
		btnPause.setBounds(90, 570, 82, 29);
		desktopPane.add(btnPause);

		btnSnapshot = new JButton("Snapshot");
		btnSnapshot.setEnabled(false);
		btnSnapshot.addActionListener(new BtnSnapshotActionListener());
		btnSnapshot.setToolTipText("Save snapshot on Desktop");
		btnSnapshot.setBounds(539, 570, 127, 29);
		desktopPane.add(btnSnapshot);

		JDesktopPane desktopPane_1 = new JDesktopPane();
		desktopPane_1.setBorder(new LineBorder(new Color(0, 0, 0)));
		desktopPane_1.setBackground(Color.WHITE);
		desktopPane_1.setBounds(6, 467, 704, 91);
		desktopPane.add(desktopPane_1);

		txtLiveURL = new JTextField();
		// txtLiveURL.setText("rtsp://207.207.163.78/stream1");
		txtLiveURL.setText("rtsp://demo-12.videonext.com:8554/xmedia?dev=126&authorizationid=0");
		txtLiveURL.setToolTipText("RTSP URL");
		txtLiveURL.setBounds(83, 4, 615, 28);
		desktopPane_1.add(txtLiveURL);
		txtLiveURL.setColumns(10);

		txtArchiveStart = new JTextField();
		txtArchiveStart.setToolTipText("Start time");
		txtArchiveStart.setText("17:00:00");
		txtArchiveStart.setBounds(83, 31, 79, 28);
		desktopPane_1.add(txtArchiveStart);
		txtArchiveStart.setColumns(10);

		label = new JLabel("-");
		label.setBounds(161, 37, 15, 16);
		desktopPane_1.add(label);

		txtArchiveEnd = new JTextField();
		txtArchiveEnd.setToolTipText("End time");
		txtArchiveEnd.setText("17:10:00");
		txtArchiveEnd.setColumns(10);
		txtArchiveEnd.setBounds(171, 31, 79, 28);
		desktopPane_1.add(txtArchiveEnd);

		btnArchiveExport = new JButton("Export");
		btnArchiveExport
				.addActionListener(new BtnArchiveExportActionListener());
		btnArchiveExport.setToolTipText("Export media clip to Desktop");
		btnArchiveExport.setBounds(419, 32, 85, 29);
		desktopPane_1.add(btnArchiveExport);

		btnArchiveGotoTime = new JButton("Goto time");
		btnArchiveGotoTime
				.addActionListener(new BtnArchiveGotoTimeActionListener());
		btnArchiveGotoTime.setBounds(250, 32, 91, 29);
		desktopPane_1.add(btnArchiveGotoTime);

		txtArchiveGotoTime = new JTextField();
		txtArchiveGotoTime.setText("17:05:00");
		txtArchiveGotoTime.setColumns(10);
		txtArchiveGotoTime.setBounds(342, 31, 79, 28);
		desktopPane_1.add(txtArchiveGotoTime);

		progressBar = new JProgressBar();
		progressBar.setBounds(505, 36, 182, 20);
		progressBar.setVisible(false);
		desktopPane_1.add(progressBar);

		btnStop = new JButton("Stop");
		btnStop.setEnabled(false);
		btnStop.addActionListener(new BtnStopActionListener());
		btnStop.setBounds(169, 570, 62, 29);
		desktopPane.add(btnStop);

		cbAnalytics = new JCheckBox("Analytics");
		cbAnalytics.setToolTipText("Switch analytics");
		cbAnalytics.addActionListener(new CbAnalyticsActionListener());
		cbAnalytics.setBounds(393, 602, 90, 23);
		desktopPane.add(cbAnalytics);

		JLabel lblSpeed = new JLabel("Speed:");
		lblSpeed.setBounds(302, 543, 45, 16);
		desktopPane.add(lblSpeed);

		cbSpeed = new JComboBox();
		cbSpeed.addActionListener(new CbSpeedActionListener());
		cbSpeed.setToolTipText("Stream speed");
		cbSpeed.setModel(new DefaultComboBoxModel(new String[] { "0.3", "0.6",
				"1.0", "1.3", "1.6", "2.0", "2.3", "2.6", "3.0", "3.3", "3.6",
				"4.0" }));
		cbSpeed.setSelectedIndex(2);
		cbSpeed.setBounds(286, 571, 76, 27);
		desktopPane.add(cbSpeed);

		btnPlayBackward = new JButton("<");
		btnPlayBackward.addActionListener(new BtnPlayBackwardActionListener());
		btnPlayBackward.setEnabled(false);
		btnPlayBackward.setBounds(44, 570, 45, 29);
		desktopPane.add(btnPlayBackward);

		lblSpeed_1 = new JLabel("Speed:");
		lblSpeed_1.setBounds(243, 575, 45, 16);
		desktopPane.add(lblSpeed_1);

		liveRadioButton = new JRadioButton("Live");
		liveRadioButton.addItemListener(new LiveRadioButtonItemListener());
		buttonGroup.add(liveRadioButton);
		liveRadioButton.setBounds(6, 6, 57, 23);
		desktopPane_1.add(liveRadioButton);

		archiveRadioButton = new JRadioButton("Archive");
		archiveRadioButton.addItemListener(new ArchiveRadioButtonItemListener());
		buttonGroup.add(archiveRadioButton);
		archiveRadioButton.setBounds(6, 31, 79, 23);
		desktopPane_1.add(archiveRadioButton);
		
		//////////
		
		stratusRadioButton = new JRadioButton("Stratus");
		stratusRadioButton.addItemListener(new StratusRadioButtonItemListener());
		buttonGroup.add(stratusRadioButton);
		stratusRadioButton.setBounds(6, 57, 79, 23);
		desktopPane_1.add(stratusRadioButton);
		
		txtStratusServer = new JTextField();
		txtStratusServer.setToolTipText("Server");
		txtStratusServer.setText("demo-12.videonext.com");
		txtStratusServer.setBounds(83, 57, 171, 28);
		desktopPane_1.add(txtStratusServer);
		txtStratusServer.setColumns(10);

		label = new JLabel("-");
		label.setBounds(161, 37, 15, 16);
		desktopPane_1.add(label);
		
		txtStratusPass = new JPasswordField();
		txtStratusPass.setText("topse");
		txtStratusPass.setColumns(10);
		txtStratusPass.setBounds(342, 57, 79, 28);
		desktopPane_1.add(txtStratusPass);
		
		txtStratusUser = new JTextField();
		txtStratusUser.setToolTipText("User");
		txtStratusUser.setText("admin");
		txtStratusUser.setColumns(10);
		txtStratusUser.setBounds(260, 57, 79, 28);
		desktopPane_1.add(txtStratusUser);

		btnStratusConnect = new JButton("Connect");
		btnStratusConnect
				.addActionListener(new BtnStratusConnectActionListener());
		btnStratusConnect.setToolTipText("Connect to Stratus");
		btnStratusConnect.setBounds(419, 57, 85, 29);
		desktopPane_1.add(btnStratusConnect);

		
		boxCameraList.setEditable(false);
		boxCameraList.addActionListener(new BoxStratusUseActionListener());
		boxCameraList.setLightWeightPopupEnabled(false);
		boxCameraList.setBounds(505, 57, 185, 29);
		desktopPane_1.add(boxCameraList);
		
		//////////// ^^^^^^^

		stratusRadioButton.setSelected(true);

		lblStatus = new JLabel("IDLE");
		lblStatus.setForeground(Color.GREEN);
		lblStatus.setBounds(54, 606, 163, 16);
		desktopPane.add(lblStatus);

		lblNewLabel = new JLabel("State:");
		lblNewLabel.setBounds(16, 606, 61, 16);
		desktopPane.add(lblNewLabel);

		lblTime = new JLabel("");
		lblTime.setForeground(Color.GREEN);
		lblTime.setBounds(210, 606, 319, 16);
		desktopPane.add(lblTime);

		cbRTPoverTCP = new JCheckBox("RTP over TCP");
		cbRTPoverTCP.addActionListener(new CbRTPoverTCPActionListener());
		cbRTPoverTCP.setToolTipText("Switch RTP over TCP");
		cbRTPoverTCP.setBounds(393, 571, 119, 23);
		desktopPane.add(cbRTPoverTCP);

		JLabel lblJitterms = new JLabel("Jitter buf (ms)");
		lblJitterms.setBounds(510, 606, 113, 16);
		desktopPane.add(lblJitterms);

		txtJitterBuf = new JTextField();
		txtJitterBuf.setText("0");
		txtJitterBuf.setColumns(10);
		txtJitterBuf.setBounds(599, 600, 79, 28);
		desktopPane.add(txtJitterBuf);

		cbHWDecoder = new JCheckBox("Use HW decoder");
		cbHWDecoder.setSelected(true);
		cbHWDecoder.setToolTipText("Switch analytics");
		cbHWDecoder.setBounds(393, 630, 163, 23);
		desktopPane.add(cbHWDecoder);

	}

	private void play() {
		DemoApp.this.btnPlayForward.setEnabled(false);
		DemoApp.this.btnPlayBackward.setEnabled(false);
		DemoApp.this.btnPause.setEnabled(true);
		DemoApp.this.btnStop.setEnabled(true);
		DemoApp.this.cbAnalytics.setEnabled(false);
		DemoApp.this.lblTime.setVisible(true);

		if (DemoApp.this.cbRTPoverTCP.isSelected()) {
			DemoApp.this.player.setParameter("streamOverTCP", "1");
			DemoApp.this.player.setParameter("streamOverHTTP", "0");
		} else {
			DemoApp.this.player.setParameter("streamOverTCP", "0");
			DemoApp.this.player.setParameter("streamOverHTTP", "0");
		}

		if (DemoApp.this.cbHWDecoder.isSelected()) {
			DemoApp.this.player.setUseHWDecoder(1);
		} else {
			DemoApp.this.player.setUseHWDecoder(0);
		}

		if (archiveRadioButton.isSelected()) {
			playArchive();
		} else {
			playLive();
		}

	}

	private String getArchiveURL() {
		String url = DemoApp.this.txtLiveURL.getText();
		SimpleDateFormat df = new SimpleDateFormat("yyyy:MM:dd:HH:mm:ss");
		try {
			String dayDate = Calendar.getInstance().get(Calendar.YEAR) + ":" +
					 (Calendar.getInstance().get(Calendar.MONTH)+1) + ":" +
					 Calendar.getInstance().get(Calendar.DAY_OF_MONTH) + ":";
			
			System.out.println("Start Time: "+dayDate+txtArchiveStart.getText());
			
			Date start = df.parse(dayDate+txtArchiveStart.getText());

			Date end = df.parse(dayDate+txtArchiveEnd.getText());

			System.out.println(start.toString());
			System.out.println(end.toString());

			
			url += "&start=" + (start.getTime() / 1000) + "&end="
					+ (end.getTime() / 1000);
			
			url = AuthMng.getMediaURL(selectedCam, true, start.getTime(), end.getTime(), DemoApp.this.cbAnalytics.isSelected());
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			System.err.println("Could not parse time correctly");
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return url;
	}

	private void playLive() {
		String url = DemoApp.this.txtLiveURL.getText();

		DemoApp.this.player.setJitterBuffer(Integer.parseInt(txtJitterBuf
				.getText())); // ms
		DemoApp.this.player.setParameter("videoURL", url);

		DemoApp.this.player.sendCommand("play");

	}

	private void playArchive() {
		String url = getArchiveURL();
		DemoApp.this.player.setParameter("videoURL", url);
		DemoApp.this.player.sendCommand("play");
	}

	private class LiveRadioButtonItemListener implements ItemListener {

		public void itemStateChanged(ItemEvent arg0) {

			if (liveRadioButton.isSelected()) {
				txtArchiveStart.setVisible(false);
				txtArchiveEnd.setVisible(false);
				txtArchiveGotoTime.setVisible(false);
				btnArchiveExport.setVisible(false);
				btnArchiveGotoTime.setVisible(false);
				label.setVisible(false);
				
				txtStratusServer.setVisible(false);
				txtStratusUser.setVisible(false);
				txtStratusPass.setVisible(false);
				btnStratusConnect.setVisible(false);
				boxCameraList.setVisible(false);

				txtLiveURL.setVisible(true);
			}
		}
	}
	
	private class StratusRadioButtonItemListener implements ItemListener {

		public void itemStateChanged(ItemEvent arg0) {

			if (stratusRadioButton.isSelected()) {
				txtArchiveStart.setVisible(false);
				txtArchiveEnd.setVisible(false);
				txtArchiveGotoTime.setVisible(false);
				btnArchiveExport.setVisible(false);
				btnArchiveGotoTime.setVisible(false);
				label.setVisible(false);
				
				txtStratusServer.setVisible(true);
				txtStratusUser.setVisible(true);
				txtStratusPass.setVisible(true);
				btnStratusConnect.setVisible(true);
				boxCameraList.setVisible(true);

				txtLiveURL.setVisible(false);
			} 
		}
	}
	
	private class ArchiveRadioButtonItemListener implements ItemListener {

		public void itemStateChanged(ItemEvent arg0) {

			if (archiveRadioButton.isSelected()) {
				txtArchiveStart.setVisible(true);
				txtArchiveEnd.setVisible(true);
				txtArchiveGotoTime.setVisible(true);
				btnArchiveExport.setVisible(true);
				btnArchiveGotoTime.setVisible(true);
				label.setVisible(true);
				
				txtStratusServer.setVisible(false);
				txtStratusUser.setVisible(false);
				txtStratusPass.setVisible(false);
				btnStratusConnect.setVisible(false);
				boxCameraList.setVisible(false);

				txtLiveURL.setVisible(false);
			} 
		}
	}

	private class BtnPlayForwardMouseListener extends MouseAdapter {
		@Override
		public void mouseClicked(MouseEvent arg0) {
			DemoApp.this.player.setParameter("direction", "1");
			DemoApp.this.btnSnapshot.setEnabled(true);

			play();

		}
	}

	private class BtnPlayBackwardActionListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {

			DemoApp.this.player.setParameter("direction", "-1");

			play();

		}
	}

	private class BtnPauseActionListener implements ActionListener {
		public void actionPerformed(ActionEvent arg0) {
			DemoApp.this.player.sendCommand("pause");

			DemoApp.this.btnPlayForward.setEnabled(true);
			DemoApp.this.btnPlayBackward.setEnabled(true);
			DemoApp.this.btnPause.setEnabled(false);

			DemoApp.this.lblStatus.setText("IDLE");

		}
	}

	private class BtnStopActionListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			DemoApp.this.player.sendCommand("stop");

			DemoApp.this.btnPlayForward.setEnabled(true);
			DemoApp.this.btnPlayBackward.setEnabled(false);
			DemoApp.this.btnPause.setEnabled(false);
			DemoApp.this.btnStop.setEnabled(false);
			DemoApp.this.cbAnalytics.setEnabled(true);
			DemoApp.this.lblTime.setVisible(false);

			DemoApp.this.lblStatus.setText("IDLE");
		}
	}

	private class CbSpeedActionListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			DemoApp.this.player.setParameter("streamSpeed",
					(String) DemoApp.this.cbSpeed.getSelectedItem());
		}
	}

	private class BtnSnapshotActionListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {

			DemoApp.this.player.setParameter("showSnapshotDialog", "0");

			String desktopPath = System.getProperty("user.home") + "/Desktop";
			DemoApp.this.player.setParameter("snapshotFileName", desktopPath
					+ "/vn_snapshot.jpg");

			DemoApp.this.player.sendCommand("snapshot");

		}
	}

	private class BtnArchiveGotoTimeActionListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {

			SimpleDateFormat df = new SimpleDateFormat("yyyy:MM:dd:HH:mm:ss");
			String dayDate = Calendar.getInstance().get(Calendar.YEAR) + ":" +
							 Calendar.getInstance().get(Calendar.MONTH) + ":" +
							 Calendar.getInstance().get(Calendar.DAY_OF_MONTH) + ":";
			Date d;
			try {
				d = df.parse(dayDate + txtArchiveGotoTime.getText());
				DemoApp.this.player.setParameter("jump2timestamp",
						Long.toString(d.getTime() / 1000));
			} catch (ParseException e1) {
				e1.printStackTrace();
			}

		}
	}
	
	private class BtnStratusConnectActionListener implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent arg0) {
			AppContext context = AppContext.getInstance();
			
			if(context.init(DemoApp.this.txtStratusServer.getText(),
					DemoApp.this.txtStratusUser.getText(),
					DemoApp.this.txtStratusPass.getText())){
				try {
					boxCameraList.removeActionListener(boxCameraList.getActionListeners()[0]);
					boxCameraList.removeAllItems();
					boxCameraList.addActionListener(new BoxStratusUseActionListener());
					for(CameraListRequestor.CameraInfo o : CameraListRequestor.getCameraList()){
						boxCameraList.addItem(o);
					}
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			} 
		}
		
	}
	
	private class BoxStratusUseActionListener implements ActionListener {
		
		public void actionPerformed(ActionEvent arg0) {
			
			DemoApp.this.selectedCam = ((CameraListRequestor.CameraInfo) boxCameraList.getSelectedItem()).objid;
			
			try {
				DemoApp.this.txtLiveURL.setText(AuthMng.getMediaURL(selectedCam, false, 0, 0, DemoApp.this.cbAnalytics.isSelected()));
			} catch (Exception e) {
				// TODO Auto-generated catch block
				System.err.println(e.getMessage());
			}
			
		}
	}

	private class BtnArchiveExportActionListener implements ActionListener {
		public void actionPerformed(ActionEvent arg0) {
			String url = getArchiveURL();
			String file = System.getProperty("user.home")
					+ "/Desktop/vn_export.mov";

			exporter.startExport(url, file);

			DemoApp.this.progressBar.setValue(0);
			DemoApp.this.progressBar.setVisible(true);

			DemoApp.this.btnArchiveExport.setEnabled(false);

		}
	}

	private class CbAnalyticsActionListener implements ActionListener {
		public void actionPerformed(ActionEvent arg0) {
			if(DemoApp.this.cbAnalytics.isSelected()){
				System.out.println("Analytics visualization enabled");
			}else{
				System.out.println("Analytics visualization disabled");
			}
		}
	}
	
	private class CbRTPoverTCPActionListener implements ActionListener {
		public void actionPerformed(ActionEvent arg0) {
		}
	}

	protected class PlayerListener implements
			com.videonext.mplayer.MediaPlayerListener {
		public void statusChanged(int status) {

			System.out.println("status changed: " + status);
			if (status == 0) {
				DemoApp.this.btnPlayForward.setEnabled(true);
				DemoApp.this.btnPlayBackward.setEnabled(true);
				DemoApp.this.btnPause.setEnabled(false);
				DemoApp.this.btnSnapshot.setEnabled(false);
				DemoApp.this.lblStatus.setText("IDLE");
			} else if (status == 1) {
				DemoApp.this.lblStatus.setText("PLAYING");
			} else if (status == 2) {
				DemoApp.this.lblStatus.setText("PLAYING FROM CACHE");
			} else if (status == 3) {
				DemoApp.this.lblStatus.setText("STOP");

				DemoApp.this.btnStop.setEnabled(false);
				DemoApp.this.btnPlayForward.setEnabled(true);
				DemoApp.this.btnPlayBackward.setEnabled(false);
				DemoApp.this.btnPause.setEnabled(false);
				DemoApp.this.lblTime.setVisible(false);

			} else if (status == 5) {
				DemoApp.this.lblStatus.setText("BUFFERING");
			}

		}

		public void newFrame(long frameTimestamp, long bufStartTimestamp,
				long bufEndTimestamp, BufferedImage im) {

			if (frameTimestamp != 0) {
				Calendar tsFormatCalendar = Calendar.getInstance(TimeZone
						.getTimeZone("UTC"));

				tsFormatCalendar.setTimeInMillis(frameTimestamp);
				DemoApp.this.lblTime.setText(String.format(
						"  %1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%1$tL",
						tsFormatCalendar));
			}

		}

		public void bufferChanged(long startTimestamp, long endTimestamp) {

		}

		public void snapshotFinished() {

		}

		public void mouseClicked(java.awt.event.MouseEvent M, boolean b) {

		}

	}

	protected class ExporterListener implements
			com.videonext.mplayer.MediaExporterListener {
		public void newDataChunk(long bytesCompleted, int percentsCompleted,
				String error) {
			if (!error.isEmpty()) {
				JOptionPane.showMessageDialog(DemoApp.this.frmDemo, error,
						"Export failed", JOptionPane.ERROR_MESSAGE);
				DemoApp.this.progressBar.setVisible(false);

				DemoApp.this.btnArchiveExport.setEnabled(true);
				return;
			}

			if (bytesCompleted == 0 && percentsCompleted == 100) {
				// Export completed
				JOptionPane.showMessageDialog(DemoApp.this.frmDemo,
						"Export finished!", "Media Export",
						JOptionPane.INFORMATION_MESSAGE);
				DemoApp.this.progressBar.setVisible(false);

				DemoApp.this.btnArchiveExport.setEnabled(true);
			} else {
				DemoApp.this.progressBar.setValue(percentsCompleted);
			}
		}
	}
}
