/**
* ======================== legal notice ======================
*
* File: MediaClient.java
* Created:
* Author: Geronimo
* Project: cmpc - a java frontend (client) part of compound media player
* uses external players to play the media
*
* CMP - compound media player
*
* is a client/server mediaplayer intended to play any media from any workstation
* without the need to export or mount shares. cmps is an easy to use backend
* with a (ready to use) HTML-interface. Additionally the backend supports
* authentication via HTTP-digest authorization.
* cmpc is a client with vdr-like osd-menues.
*
* Copyright (c) 2012 Reinhard Mantey, some rights reserved!
* published under Creative Commons by-sa
* For details see http://creativecommons.org/licenses/by-sa/3.0/
*
* The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp
*
* --------------------------------------------------------------
*/
package de.schwarzrot.cmpc.ui;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableCellRenderer;
import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.FilterList;
import ca.odell.glazedlists.SortedList;
import ca.odell.glazedlists.swing.DefaultEventTableModel;
import ca.odell.glazedlists.swing.GlazedListsSwing;
import ca.odell.glazedlists.swing.TableComparatorChooser;
import ca.odell.glazedlists.swing.TextComponentMatcherEditor;
import de.schwarzrot.cmpc.app.IMediaPlayer;
import de.schwarzrot.cmpc.domain.Media;
import de.schwarzrot.cmpc.domain.PlayerDefinition;
import de.schwarzrot.cmpc.util.MediaClientExecutor;
import de.schwarzrot.cmpc.util.MediaComparator;
import de.schwarzrot.cmpc.util.MediaExecutor;
import de.schwarzrot.cmpc.util.MediaListLoader;
import de.schwarzrot.cmpc.util.MediaTableFormat;
import de.schwarzrot.cmpc.util.MediaTextFilterator;
import de.schwarzrot.cmpc.util.MediaTypeSelect;
public class MediaClient extends JComponent implements MediaClientExecutor {
private static final long serialVersionUID = 713L;
public MediaClient(String id, IMediaPlayer player) {
this.myPanelName = id;
this.player = player;
setLayout(new BorderLayout());
listLoader = new MediaListLoader();
mediaPool = listLoader.getMediaPool();
}
@Override
public String getName() {
return myPanelName;
}
public boolean isActive() {
return active;
}
@Override
public void playMedia(Media m) {
List command = new ArrayList();
PlayerDefinition pd = player.getConfig().getPlayerMap().get(m.getType());
StringBuilder sb = new StringBuilder("http://");
sb.append(curHostName);
sb.append(":");
sb.append(curPort);
sb.append(m.getPath());
command.add(pd.getExecutable());
for (String param : pd.getParameters()) {
command.add(param);
}
command.add(sb.toString());
ProcessBuilder pb = new ProcessBuilder(command);
pb.redirectErrorStream(true);
try {
Process proc = pb.start();
BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line;
if (player.isDebug()) {
while ((line = br.readLine()) != null) {
System.err.println(line);
}
} else {
while ((line = br.readLine()) != null)
;
}
} catch (Throwable t) {
t.printStackTrace();
}
}
public void setActive(boolean active) {
this.active = active;
}
public void setup(final IMediaPlayer mp) {
add(createClientPane(), BorderLayout.CENTER);
}
public void startConnection(String hostname, int port) {
setHost(hostname);
setPort(port);
mediaPool.getReadWriteLock().writeLock().lock();
mediaPool.clear();
mediaPool.getReadWriteLock().writeLock().unlock();
listLoader.loadMedia(curHostName, curPort);
}
protected JComponent createClientPane() {
JPanel clientPane = new JPanel();
loadImages();
mediaPool.getReadWriteLock().readLock().lock();
try {
SortedList sortedMedias = new SortedList(GlazedListsSwing.swingThreadProxyList(mediaPool),
new MediaComparator());
MediaTypeSelect mtSelect = new MediaTypeSelect(sortedMedias);
FilterList filteredMedias = new FilterList(sortedMedias, mtSelect);
JTextField filterEdit = new JTextField(30);
FilterList textFilteredMedia = new FilterList(filteredMedias,
new TextComponentMatcherEditor(filterEdit, new MediaTextFilterator()));
DefaultEventTableModel mediaTableModel = new DefaultEventTableModel(textFilteredMedia,
new MediaTableFormat());
JTable mediaJTable = new JTable(mediaTableModel);
@SuppressWarnings({ "unused", "rawtypes" })
TableComparatorChooser tableSorter = TableComparatorChooser.install(mediaJTable, sortedMedias,
TableComparatorChooser.MULTIPLE_COLUMN_MOUSE_WITH_UNDO);
JScrollPane mediaTableScrollPane = new JScrollPane(mediaJTable);
JScrollPane mediaTypesScrollPane = new JScrollPane(mtSelect.getJList());
JLabel filter = new JLabel(" Filter: ");
JButton exitButton = new JButton(images[0]);
JButton preferences = new JButton(images[1]);
filter.setForeground(Color.GRAY);
filterEdit.setBackground(Color.LIGHT_GRAY);
exitButton.setBackground(Color.BLACK);
preferences.setBackground(Color.BLACK);
exitButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
player.selectApp();
}
});
mediaTypesScrollPane.setPreferredSize(new Dimension(100, 100));
mediaTypesScrollPane.setBackground(Color.BLACK);
mediaJTable.getColumnModel().getColumn(0).setMaxWidth(80);
mediaJTable.getColumnModel().getColumn(0).setCellRenderer(new DefaultTableCellRenderer());
mediaJTable.getColumnModel().getColumn(1).setCellRenderer(new DefaultTableCellRenderer());
mediaJTable.addMouseListener(new MediaExecutor(mediaJTable, textFilteredMedia, this));
clientPane.setLayout(new GridBagLayout());
clientPane.add(exitButton, new GridBagConstraints(0, 0, 1, 2, 0.0, 0.0, GridBagConstraints.CENTER,
GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
clientPane.add(preferences, new GridBagConstraints(1, 0, 1, 2, 0.0, 0.0, GridBagConstraints.CENTER,
GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
clientPane.add(mediaTypesScrollPane, new GridBagConstraints(0, 2, 2, 1, 0.0, 0.0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
clientPane.add(filter, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER,
GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 10, 0));
clientPane.add(filterEdit, new GridBagConstraints(3, 0, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER,
GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
clientPane.add(mediaTableScrollPane, new GridBagConstraints(2, 1, 2, 2, 1.0, 1.0,
GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
clientPane.setOpaque(true);
clientPane.setBackground(Color.BLACK);
} finally {
mediaPool.getReadWriteLock().readLock().unlock();
}
return clientPane;
}
protected void loadImages() {
BufferedImage img = null;
ClassLoader cl = getClass().getClassLoader();
URL url;
images = new ImageIcon[iconFiles.length];
for (int i = 0; i < iconFiles.length; ++i) {
try {
url = cl.getResource(iconFiles[i]);
img = ImageIO.read(url);
images[i] = new ImageIcon(img.getScaledInstance(64, 64, Image.SCALE_SMOOTH));
} catch (Throwable t) {
System.err.println("failed to read image from " + iconFiles[i]);
t.printStackTrace();
}
}
}
protected void setHost(String hostname) {
curHostName = hostname;
}
protected void setPort(Integer port) {
curPort = port;
}
private IMediaPlayer player;
private MediaListLoader listLoader;
private EventList mediaPool;
private String myPanelName;
private int curPort;
private String curHostName;
private boolean active;
private ImageIcon[] images;
private static final String[] iconFiles;
static {
iconFiles = new String[] { "images/black_exit.png", "images/black_preferences.png" };
}
}