summaryrefslogtreecommitdiff
path: root/cmpcj/src/de/schwarzrot/control
diff options
context:
space:
mode:
Diffstat (limited to 'cmpcj/src/de/schwarzrot/control')
-rw-r--r--cmpcj/src/de/schwarzrot/control/app/AboutDialog.java69
-rw-r--r--cmpcj/src/de/schwarzrot/control/app/CMPCJ.java736
-rw-r--r--cmpcj/src/de/schwarzrot/control/app/CMPMessageBundle.java73
-rw-r--r--cmpcj/src/de/schwarzrot/control/client/CMPClient.java171
-rw-r--r--cmpcj/src/de/schwarzrot/control/client/MediaClientExecutor.java34
-rw-r--r--cmpcj/src/de/schwarzrot/control/config/ConfigDialog.java131
-rw-r--r--cmpcj/src/de/schwarzrot/control/config/ConfigFactory.java225
-rw-r--r--cmpcj/src/de/schwarzrot/control/dnd/FilelistTransferable.java72
-rw-r--r--cmpcj/src/de/schwarzrot/control/dnd/ListSelectionSourceTransferHandler.java69
-rw-r--r--cmpcj/src/de/schwarzrot/control/dnd/TreePathTransferable.java74
-rw-r--r--cmpcj/src/de/schwarzrot/control/dnd/TreeSourceAndDestTransferHandler.java207
-rw-r--r--cmpcj/src/de/schwarzrot/control/support/GenreSelector.java46
-rw-r--r--cmpcj/src/de/schwarzrot/control/support/MediaList2TypeList.java61
-rw-r--r--cmpcj/src/de/schwarzrot/control/support/MediaTextFilterator.java41
-rw-r--r--cmpcj/src/de/schwarzrot/control/support/MediaTypeSelector.java157
-rw-r--r--cmpcj/src/de/schwarzrot/control/support/MediatypeMatcher.java55
-rw-r--r--cmpcj/src/de/schwarzrot/control/support/SelectedMedia.java85
-rw-r--r--cmpcj/src/de/schwarzrot/control/support/TreeSelectionFilter.java59
-rw-r--r--cmpcj/src/de/schwarzrot/control/table/MediaTableFormat.java91
-rw-r--r--cmpcj/src/de/schwarzrot/control/table/PlayerDefinitionTableFormat.java114
-rw-r--r--cmpcj/src/de/schwarzrot/control/table/ServerDefinitionTableFormat.java119
21 files changed, 2689 insertions, 0 deletions
diff --git a/cmpcj/src/de/schwarzrot/control/app/AboutDialog.java b/cmpcj/src/de/schwarzrot/control/app/AboutDialog.java
new file mode 100644
index 0000000..7a361cf
--- /dev/null
+++ b/cmpcj/src/de/schwarzrot/control/app/AboutDialog.java
@@ -0,0 +1,69 @@
+/**
+ * ======================== legal notice ======================
+ *
+ * File: AboutDialog.java
+ * Created: 13. June 2012, 04:57
+ * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a>
+ * 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.control.app;
+
+
+import java.awt.Dimension;
+import java.awt.Window;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.border.EmptyBorder;
+import de.schwarzrot.base.util.AbstractDialog;
+
+
+public class AboutDialog extends AbstractDialog {
+ private static final long serialVersionUID = 713L;
+
+
+ public AboutDialog(Window parent) {
+ super(parent, true, DialogMode.CLOSE, Orientation.Center);
+ }
+
+
+ @Override
+ public JComponent createContentPane() {
+ JPanel rv = new JPanel();
+
+ rv.setLayout(new BoxLayout(rv, BoxLayout.Y_AXIS));
+ rv.setBorder(new EmptyBorder(20, 20, 20, 20));
+ JLabel appInfo = new JLabel(msgBundle.getMessage(getClass().getSimpleName() + ".app.info"), JLabel.CENTER);
+
+ rv.add(appInfo);
+ JLabel aboutText = new JLabel(msgBundle.getMessage(getClass().getSimpleName() + ".about.text"), JLabel.CENTER);
+
+ rv.add(aboutText);
+ rv.add(Box.createRigidArea(new Dimension(0, 30)));
+ JLabel contribution = new JLabel(msgBundle.getMessage(getClass().getSimpleName() + ".contribution"),
+ JLabel.LEFT);
+
+ rv.add(contribution);
+
+ return rv;
+ }
+}
diff --git a/cmpcj/src/de/schwarzrot/control/app/CMPCJ.java b/cmpcj/src/de/schwarzrot/control/app/CMPCJ.java
new file mode 100644
index 0000000..639d9fc
--- /dev/null
+++ b/cmpcj/src/de/schwarzrot/control/app/CMPCJ.java
@@ -0,0 +1,736 @@
+/**
+ * ======================== legal notice ======================
+ *
+ * File: MCC.java Created: 13. June 2012, 04:57 Author: <a
+ * href="mailto:geronimo013@gmx.de">Geronimo</a> 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.control.app;
+
+
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.Point;
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.InputStreamReader;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import javax.swing.AbstractAction;
+import javax.swing.DropMode;
+import javax.swing.JComponent;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JSeparator;
+import javax.swing.JTable;
+import javax.swing.JTextField;
+import javax.swing.JTree;
+import javax.swing.KeyStroke;
+import javax.swing.UIManager;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreeModel;
+import bibliothek.gui.dock.common.CControl;
+import bibliothek.gui.dock.common.CGrid;
+import ca.odell.glazedlists.BasicEventList;
+import ca.odell.glazedlists.EventList;
+import ca.odell.glazedlists.FilterList;
+import ca.odell.glazedlists.GlazedLists;
+import ca.odell.glazedlists.SortedList;
+import ca.odell.glazedlists.event.ListEvent;
+import ca.odell.glazedlists.event.ListEventListener;
+import ca.odell.glazedlists.swing.DefaultEventSelectionModel;
+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.base.dock.BasicDockable;
+import de.schwarzrot.base.table.PropertyTableFormat;
+import de.schwarzrot.base.util.ActionManager;
+import de.schwarzrot.base.util.ApplicationServiceProvider;
+import de.schwarzrot.base.util.CallbackDefinition;
+import de.schwarzrot.base.util.ImageFactory;
+import de.schwarzrot.base.util.MessageBundle;
+import de.schwarzrot.base.util.SuccessHandler;
+import de.schwarzrot.control.client.CMPClient;
+import de.schwarzrot.control.client.MediaClientExecutor;
+import de.schwarzrot.control.config.ConfigDialog;
+import de.schwarzrot.control.config.ConfigFactory;
+import de.schwarzrot.control.dnd.ListSelectionSourceTransferHandler;
+import de.schwarzrot.control.dnd.TreeSourceAndDestTransferHandler;
+import de.schwarzrot.control.support.MediaTextFilterator;
+import de.schwarzrot.control.support.MediaTypeSelector;
+import de.schwarzrot.control.support.SelectedMedia;
+import de.schwarzrot.control.support.TreeSelectionFilter;
+import de.schwarzrot.control.table.MediaTableFormat;
+import de.schwarzrot.media.domain.AbstractMediaNode;
+import de.schwarzrot.media.domain.Config;
+import de.schwarzrot.media.domain.Genre;
+import de.schwarzrot.media.domain.Media;
+import de.schwarzrot.media.domain.MediaServer;
+import de.schwarzrot.media.domain.PlayerDefinition;
+import de.schwarzrot.media.service.DataManager;
+import de.schwarzrot.media.service.MediaExecutor;
+import de.schwarzrot.media.util.ListLoader;
+import de.schwarzrot.media.util.MedialistParser;
+
+
+public class CMPCJ extends WindowAdapter implements PropertyChangeListener, SuccessHandler,
+ ListEventListener<AbstractMediaNode>, MediaClientExecutor {
+ private static final String PREFFERRED_LOOK_N_FEEL = "Nimbus"; //$NON-NLS-1$
+ private static final String USER_HOME = "user.home"; //$NON-NLS-1$
+ private static final String DOCKING_CONFIG = "srdocking.conf"; //$NON-NLS-1$
+ enum Commands {
+ SrvOpen, SrvRefresh, SrvClose, SrvShutdown, TransmitChanges, Preferences, HelpHelp, HelpAbout
+ };
+
+
+ public CMPCJ(String[] args, ConfigFactory configFactory) {
+ nodeCache = new HashMap<File, DefaultMutableTreeNode>();
+ changes = new BasicEventList<AbstractMediaNode>();
+ rootNode = new DefaultMutableTreeNode(setupServices(args, configFactory));
+ changes.addListEventListener(this);
+ }
+
+
+ public void createAndShow() {
+ @SuppressWarnings("unchecked")
+ ActionManager<Commands> am = ApplicationServiceProvider.getService(ActionManager.class);
+ MessageBundle mb = ApplicationServiceProvider.getService(MessageBundle.class);
+
+ mediaList = new SortedList<Media>(GlazedListsSwing.swingThreadProxyList(new BasicEventList<Media>()));
+ try {
+ String lookNFeel = UIManager.getSystemLookAndFeelClassName();
+
+ for (UIManager.LookAndFeelInfo lfi : UIManager.getInstalledLookAndFeels()) {
+ if (PREFFERRED_LOOK_N_FEEL.equals(lfi.getName()))
+ lookNFeel = lfi.getClassName();
+ }
+ UIManager.setLookAndFeel(lookNFeel);
+ } catch (Exception e) {
+ System.err.println(mb.getMessage(CMPMessageBundle.MCC_6));
+ }
+ am.addCallbackDefinition(new CallbackDefinition<Commands>(Commands.SrvOpen) {
+ private static final long serialVersionUID = 713L;
+
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ doConnectServer();
+ }
+ });
+ am.addCallbackDefinition(new CallbackDefinition<Commands>(Commands.SrvRefresh, false) {
+ private static final long serialVersionUID = 713L;
+
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ doServerRescan();
+ }
+ });
+ am.addCallbackDefinition(new CallbackDefinition<Commands>(Commands.SrvClose, false) {
+ private static final long serialVersionUID = 713L;
+
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ doDisconnectServer();
+ }
+ });
+ am.addCallbackDefinition(new CallbackDefinition<Commands>(Commands.SrvShutdown, false) {
+ private static final long serialVersionUID = 713L;
+
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ doShutdownServer();
+ }
+ });
+ am.addCallbackDefinition(new CallbackDefinition<Commands>(Commands.TransmitChanges, false) {
+ private static final long serialVersionUID = 713L;
+
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ doTransmitChanges();
+ }
+ });
+ am.addCallbackDefinition(new CallbackDefinition<Commands>(Commands.Preferences) {
+ private static final long serialVersionUID = 713L;
+
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ doConfigureClient();
+ }
+ });
+ am.addCallbackDefinition(new CallbackDefinition<Commands>(Commands.HelpHelp, false) {
+ private static final long serialVersionUID = 713L;
+
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ doShowHelp();
+ }
+ });
+ am.addCallbackDefinition(new CallbackDefinition<Commands>(Commands.HelpAbout) {
+ private static final long serialVersionUID = 713L;
+
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ doShowAbout();
+ }
+ });
+ JMenuBar menuBar = new JMenuBar();
+ frame = new JFrame(mb.getMessage(CMPMessageBundle.MCC_7));
+ control = new CControl(frame);
+ frame.addWindowListener(this);
+ frame.add(setupPerspective(frame));
+ frame.setJMenuBar(menuBar);
+ frame.pack();
+ frame.setSize(1200, 800);
+ frame.setLocationRelativeTo(null);
+ restorePerspective();
+ createMenu(menuBar);
+ frame.setVisible(true);
+ }
+
+
+ @Override
+ public void handleFailure(Throwable t) {
+ // loading list from server failed ...
+ if (t instanceof UnknownHostException) {
+ //TODO: tell the user ...
+ }
+ t.printStackTrace();
+ tree.updateUI();
+ updateServerActions(false);
+ }
+
+
+ @Override
+ public void handleSuccess() {
+ // loading list from server was successful
+ tree.updateUI();
+ updateServerActions(true);
+ }
+
+
+ @Override
+ public void listChanged(ListEvent<AbstractMediaNode> arg0) {
+ // get rid of changes made by user
+ @SuppressWarnings("unchecked")
+ ActionManager<Commands> am = ApplicationServiceProvider.getService(ActionManager.class);
+ boolean changesExists = changes.size() > 0;
+
+ System.out.println("changes updated ...");
+ am.getAction(Commands.TransmitChanges).setEnabled(changesExists);
+ }
+
+
+ @Override
+ public void playMedia(Media m) {
+ Config config = ApplicationServiceProvider.getService(Config.class);
+ List<String> command = new ArrayList<String>();
+ PlayerDefinition pd = config.getPlayerMap().get(m.getType());
+ StringBuilder sb = new StringBuilder("http://");
+
+ sb.append(clientStub.getServerDefinition().getHostName());
+ sb.append(":");
+ sb.append(clientStub.getServerDefinition().getPort());
+ sb.append(m.getURI());
+
+ 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 (config.isDebug()) {
+ while ((line = br.readLine()) != null) {
+ System.err.println(line);
+ }
+ } else {
+ while ((line = br.readLine()) != null)
+ ;
+ }
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ }
+
+
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ propertyList.getReadWriteLock().writeLock().lock();
+ propertyList.clear();
+ if (selectedMedia.getMedia() != null)
+ propertyList.addAll(selectedMedia.getMedia().getProperties().entrySet());
+ propertyList.getReadWriteLock().writeLock().unlock();
+ }
+
+
+ @Override
+ public void windowClosing(WindowEvent e) {
+ savePerspective();
+ control.destroy();
+ System.exit(0);
+ }
+
+
+ @Override
+ public void windowOpened(WindowEvent e) {
+ doConnectServer();
+ }
+
+
+ protected JComponent createMediaTableView() {
+ MessageBundle mb = ApplicationServiceProvider.getService(MessageBundle.class);
+ JTextField filterEdit = new JTextField(30);
+ mediaTypeSelector = new MediaTypeSelector(mediaList);
+ FilterList<Media> typeFilteredMedias = new FilterList<Media>(mediaList, mediaTypeSelector);
+ FilterList<Media> filteredMedias = new FilterList<Media>(typeFilteredMedias, new TreeSelectionFilter(tree));
+ FilterList<Media> textFilteredMedias = new FilterList<Media>(filteredMedias,
+ new TextComponentMatcherEditor<Media>(filterEdit, new MediaTextFilterator()));
+ MediaTableFormat mtf = new MediaTableFormat();
+ DefaultEventTableModel<Media> mediaTableModel = new DefaultEventTableModel<Media>(textFilteredMedias, mtf);
+ selectedMedia = new SelectedMedia(textFilteredMedias);
+ DefaultEventSelectionModel<Media> selectionModel = new DefaultEventSelectionModel<Media>(textFilteredMedias);
+ JTable mediaJTable = new JTable(mediaTableModel);
+
+ selectedMedia.addPropertyChangeListener(this);
+ selectionModel.addListSelectionListener(selectedMedia);
+ mediaJTable.setDragEnabled(true);
+ mediaJTable.setTransferHandler(new ListSelectionSourceTransferHandler(selectionModel));
+ mediaJTable.setSelectionModel(selectionModel);
+ mediaJTable.addMouseListener(new MediaExecutor(mediaJTable, textFilteredMedias, this));
+ @SuppressWarnings({ "rawtypes", "unused" })
+ TableComparatorChooser tableSorter = TableComparatorChooser.install(mediaJTable, mediaList,
+ TableComparatorChooser.MULTIPLE_COLUMN_MOUSE_WITH_UNDO);
+ JScrollPane mediaTableScrollPane = new JScrollPane(mediaJTable);
+ int mx = mediaJTable.getColumnModel().getColumnCount();
+
+ for (int i = 0; i < mx; ++i) {
+ int cw = mtf.getColumnWidth(i);
+
+ if (cw > 0)
+ mediaJTable.getColumnModel().getColumn(i).setMaxWidth(cw);
+ }
+ JPanel tablePane = new JPanel();
+ JLabel lFilter = new JLabel(mb.getMessage(CMPMessageBundle.MCC_18));
+
+ tablePane.setLayout(new GridBagLayout());
+ tablePane.add(lFilter, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER,
+ GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
+ tablePane.add(filterEdit, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER,
+ GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
+ tablePane.add(mediaTableScrollPane, new GridBagConstraints(0, 1, 2, 1, 1.0, 1.0, GridBagConstraints.CENTER,
+ GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
+
+ return tablePane;
+ }
+
+
+ protected JComponent createMediaTypeList() {
+ JPanel rv = new JPanel();
+
+ return rv;
+ }
+
+
+ protected void createMenu(JMenuBar menuBar) {
+ MessageBundle mb = ApplicationServiceProvider.getService(MessageBundle.class);
+ @SuppressWarnings("unchecked")
+ ActionManager<Commands> am = ApplicationServiceProvider.getService(ActionManager.class);
+ JMenu mServer = new JMenu(mb.getMessage(CMPMessageBundle.MCC_19));
+ JMenu mEdit = new JMenu(mb.getMessage(CMPMessageBundle.MCC_20));
+ JMenu mWindow = new JMenu(mb.getMessage(CMPMessageBundle.MCC_21));
+ JMenu mHelp = new JMenu(mb.getMessage(CMPMessageBundle.MCC_22));
+
+ mServer.add(new JMenuItem(am.getAction(Commands.SrvOpen)));
+ mServer.add(new JMenuItem(am.getAction(Commands.SrvRefresh)));
+ mServer.add(new JMenuItem(am.getAction(Commands.SrvClose)));
+ mServer.add(new JSeparator());
+ mServer.add(new JMenuItem(am.getAction(Commands.SrvShutdown)));
+ mEdit.add(new JMenuItem(am.getAction(Commands.TransmitChanges)));
+ mEdit.add(new JSeparator());
+ mEdit.add(new JMenuItem(am.getAction(Commands.Preferences)));
+ mWindow.add(cdGenreTree.createMenuItem());
+ mWindow.add(cdMediaTypes.createMenuItem());
+ mWindow.add(cdProperties.createMenuItem());
+ //TODO: not yet
+ // mHelp.add(new JMenuItem(getAction(Commands.HelpHelp)));
+ // mHelp.add(new JSeparator());
+ mHelp.add(new JMenuItem(am.getAction(Commands.HelpAbout)));
+
+ menuBar.add(mServer);
+ menuBar.add(mEdit);
+ menuBar.add(mWindow);
+ menuBar.add(mHelp);
+ }
+
+
+ protected JComponent createPropertyView() {
+ if (selectedMedia.getMedia() != null)
+ propertyList = GlazedLists.eventList(selectedMedia.getMedia().getProperties().entrySet());
+ else
+ propertyList = new BasicEventList<Map.Entry<String, Object>>();
+ SortedList<Map.Entry<String, Object>> psl = new SortedList<Map.Entry<String, Object>>(propertyList,
+ new Comparator<Map.Entry<String, Object>>() {
+ @Override
+ public int compare(Entry<String, Object> a, Entry<String, Object> b) {
+ return a.getKey().compareToIgnoreCase(b.getKey());
+ }
+ });
+ PropertyTableFormat ptf = new PropertyTableFormat();
+ DefaultEventTableModel<Map.Entry<String, Object>> tm = new DefaultEventTableModel<Map.Entry<String, Object>>(
+ psl, ptf);
+ JTable propertyTable = new JTable(tm);
+ JScrollPane psp = new JScrollPane(propertyTable);
+ int mx = propertyTable.getColumnModel().getColumnCount();
+
+ for (int i = 0; i < mx; ++i) {
+ int cw = ptf.getColumnWidth(i);
+
+ if (cw > 0)
+ propertyTable.getColumnModel().getColumn(i).setMaxWidth(cw);
+ }
+ return psp;
+ }
+
+
+ protected JComponent createTreeView() {
+ TreeModel tm = new DefaultTreeModel(rootNode);
+ tree = new JTree(tm);
+ tree.setDragEnabled(true);
+ tree.setEditable(true);
+ tree.getActionMap().put("removeGenre", new AbstractAction() { //$NON-NLS-1$
+ private static final long serialVersionUID = 713L;
+
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ doRemoveGenre();
+ }
+ });
+ tree.getActionMap().put("createGenre", new AbstractAction() { //$NON-NLS-1$
+ private static final long serialVersionUID = 713L;
+
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ doCreateGenre();
+ }
+ });
+ tree.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), "removeGenre"); //$NON-NLS-1$
+ tree.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_INSERT, 0), "createGenre"); //$NON-NLS-1$
+ tree.setDropMode(DropMode.USE_SELECTION);
+ tree.setTransferHandler(new TreeSourceAndDestTransferHandler(tree, nodeCache, changes));
+ JScrollPane treeView = new JScrollPane(tree);
+
+ return treeView;
+ }
+
+
+ protected void doConfigureClient() {
+ ConfigDialog cd = new ConfigDialog(frame);
+
+ cd.showDialog(frame);
+ }
+
+
+ protected void doConnectServer() {
+ MessageBundle mb = ApplicationServiceProvider.getService(MessageBundle.class);
+ Config config = ApplicationServiceProvider.getService(Config.class);
+ Object ms = JOptionPane.showInputDialog(frame, mb.getMessage(CMPMessageBundle.MCC_12), mb
+ .getMessage(CMPMessageBundle.MCC_13), JOptionPane.PLAIN_MESSAGE, null, config.getKnownServers()
+ .toArray(), mb.getMessage(CMPMessageBundle.MCC_14));
+
+ if (ms instanceof MediaServer) {
+ System.out.println(mb.getMessage(CMPMessageBundle.MCC_15) + ((MediaServer) ms).getHostName()
+ + mb.getMessage(CMPMessageBundle.MCC_16) + ((MediaServer) ms).getPort());
+
+ clientStub = new CMPClient((MediaServer) ms);
+ ApplicationServiceProvider.registerService(ListLoader.class, clientStub);
+ DataManager dm = ApplicationServiceProvider.getService(DataManager.class);
+
+ dm.load(rootNode, mediaList, this);
+ }
+ }
+
+
+ // respond to tree action
+ protected void doCreateGenre() {
+ MessageBundle mb = ApplicationServiceProvider.getService(MessageBundle.class);
+
+ System.out.println(mb.getMessage(CMPMessageBundle.MCC_17));
+
+ //TODO: ask user for genre name and create node and cache entries
+ tree.updateUI();
+ };
+
+
+ protected void doDisconnectServer() {
+ ApplicationServiceProvider.registerService(MediaServer.class, null);
+ mediaList.getReadWriteLock().writeLock().lock();
+ mediaList.clear();
+ mediaList.getReadWriteLock().writeLock().unlock();
+ ((DefaultMutableTreeNode) tree.getModel().getRoot()).removeAllChildren();
+ tree.updateUI();
+ selectedMedia.clear();
+ updateServerActions(false);
+ clientStub = null;
+ }
+
+
+ // respond to tree action
+ protected void doRemoveGenre() {
+ MessageBundle mb = ApplicationServiceProvider.getService(MessageBundle.class);
+
+ System.out.println(mb.getMessage(CMPMessageBundle.MCC_0));
+ DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getSelectionPath().getLastPathComponent();
+ if (node == null)
+ return;
+ Genre g = (Genre) node.getUserObject();
+
+ if (g.getMediaList().size() > 0 || g.getChildren().size() > 0) {
+ //TODO: ask user and/or pop some warning
+ } else {
+ nodeCache.remove(g.getRealPath());
+ ((DefaultMutableTreeNode) node.getParent()).remove(node);
+ tree.updateUI();
+ }
+ }
+
+
+ protected void doServerRescan() {
+ clientStub.execServerRescan();
+ }
+
+
+ protected void doShowAbout() {
+ AboutDialog dlgAbout = new AboutDialog(frame);
+
+ dlgAbout.showDialog(frame);
+ }
+
+
+ protected void doShowHelp() {
+ }
+
+
+ protected void doShutdownServer() {
+ clientStub.execServerShutdown();
+ doDisconnectServer();
+ }
+
+
+ protected void doTransmitChanges() {
+ clientStub.transmitChanges(changes);
+ }
+
+
+ protected void restoreAppStatus() {
+ Config config = ApplicationServiceProvider.getService(Config.class);
+
+ try {
+ if (config != null) {
+ if (config.getMainWidth() > 0 && config.getMainHeight() > 0)
+ frame.setSize(config.getMainWidth(), config.getMainHeight());
+
+ if (config.getPosX() > 0 || config.getPosY() > 0)
+ frame.setLocation(config.getPosX(), config.getPosY());
+ }
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ }
+
+
+ protected void restorePerspective() {
+ File dockableSettings = new File(configDirectory, DOCKING_CONFIG);
+
+ try {
+ if (dockableSettings.exists() && dockableSettings.canRead())
+ control.getResources().readFile(dockableSettings);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ restoreAppStatus();
+ }
+
+
+ protected void saveAppStatus() {
+ Config config = ApplicationServiceProvider.getService(Config.class);
+ ConfigFactory cf = ApplicationServiceProvider.getService(ConfigFactory.class);
+
+ try {
+ Dimension mainDim = frame.getSize();
+ Point mainPos = frame.getLocation();
+
+ config.setMainWidth(mainDim.width);
+ config.setMainHeight(mainDim.height);
+ config.setPosX(mainPos.x);
+ config.setPosY(mainPos.y);
+
+ cf.putConfig(config);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ }
+
+
+ protected void savePerspective() {
+ File dockableSettings = new File(configDirectory, DOCKING_CONFIG);
+
+ try {
+ if (!dockableSettings.exists())
+ dockableSettings.getParentFile().mkdirs();
+ control.getResources().writeFile(dockableSettings);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ saveAppStatus();
+ }
+
+
+ protected JComponent setupPerspective(JFrame frame) {
+ MessageBundle mb = ApplicationServiceProvider.getService(MessageBundle.class);
+
+ cdGenreTree = new BasicDockable("genreTree", mb.getMessage(CMPMessageBundle.MCC_29), createTreeView()); //$NON-NLS-1$
+ cdMediaList = new BasicDockable("mediaList", mb.getMessage(CMPMessageBundle.MCC_31), createMediaTableView()); //$NON-NLS-1$
+ cdMediaTypes = new BasicDockable(
+ "mediaTypes", mb.getMessage(CMPMessageBundle.MCC_33), mediaTypeSelector.getComponent()); //$NON-NLS-1$
+ cdProperties = new BasicDockable("properties", mb.getMessage(CMPMessageBundle.MCC_35), createPropertyView()); //$NON-NLS-1$
+ CGrid grid = new CGrid(control);
+
+ grid.add(0, 0, 1, 2, cdGenreTree);
+ grid.add(1, 0, 1, 1, cdMediaList);
+ grid.add(2, 0, 1, 2, cdMediaTypes);
+ grid.add(1, 1, 1, 1, cdProperties);
+
+ cdMediaList.setStackable(false);
+ cdMediaList.setExternalizable(false);
+ cdMediaList.setMinimizable(false);
+ control.getContentArea().deploy(grid);
+
+ return control.getContentArea();
+ }
+
+
+ protected Genre setupServices(String[] args, ConfigFactory configFactory) {
+ MessageBundle mb = new CMPMessageBundle();
+ configDirectory = configFactory.getConfigDirectory();
+ ApplicationServiceProvider.registerService(Config.class, configFactory.getConfig());
+ ApplicationServiceProvider.registerService(ConfigFactory.class, configFactory);
+ ApplicationServiceProvider.registerService(MessageBundle.class, mb);
+ if (args.length > 0) {
+ File tmp = new File(args[0]);
+
+ if (tmp.exists() && tmp.canRead()) {
+ System.out.println(mb.getMessage(CMPMessageBundle.MCC_4) + " " + tmp.getAbsolutePath()
+ + mb.getMessage(CMPMessageBundle.MCC_5));
+
+ input = tmp;
+ }
+ }
+ ApplicationServiceProvider.registerService(ActionManager.class, new ActionManager<Commands>());
+ ApplicationServiceProvider.registerService(DataManager.class, new DataManager(input));
+ ApplicationServiceProvider.registerService(ImageFactory.class, new ImageFactory());
+ ApplicationServiceProvider.registerService(MedialistParser.class, new MedialistParser());
+
+ File base = new File("/"); //$NON-NLS-1$
+ Genre root = new Genre(base);
+
+ // ApplicationServiceProvider.registerService(FilesystemListLoader.class, new FilesystemListLoader(base));
+
+ return root;
+ }
+
+
+ protected void updateServerActions(boolean connected) {
+ @SuppressWarnings("unchecked")
+ ActionManager<Commands> am = ApplicationServiceProvider.getService(ActionManager.class);
+
+ am.getAction(Commands.SrvOpen).setEnabled(!connected);
+ am.getAction(Commands.SrvClose).setEnabled(connected);
+ am.getAction(Commands.SrvRefresh).setEnabled(connected);
+ am.getAction(Commands.SrvShutdown).setEnabled(connected);
+ }
+
+
+ public static void main(final String[] args) {
+ javax.swing.SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ File configDir = new File(System.getProperty(USER_HOME), ".cmp"); //$NON-NLS-1$
+ CMPCJ app = new CMPCJ(args, new ConfigFactory(configDir, "CMPCJ"));
+
+ app.createAndShow();
+ }
+ });
+ }
+
+ private DefaultMutableTreeNode rootNode;
+ private SortedList<Media> mediaList;
+ private SelectedMedia selectedMedia;
+ private EventList<AbstractMediaNode> changes;
+ private Map<File, DefaultMutableTreeNode> nodeCache;
+ private EventList<Map.Entry<String, Object>> propertyList;
+ private MediaTypeSelector mediaTypeSelector;
+ private CMPClient clientStub;
+ private CControl control;
+ private JFrame frame;
+ private BasicDockable cdMediaList;
+ private BasicDockable cdGenreTree;
+ private BasicDockable cdMediaTypes;
+ private BasicDockable cdProperties;
+ private File configDirectory;
+ private JTree tree;
+ private File input;
+}
diff --git a/cmpcj/src/de/schwarzrot/control/app/CMPMessageBundle.java b/cmpcj/src/de/schwarzrot/control/app/CMPMessageBundle.java
new file mode 100644
index 0000000..33c4854
--- /dev/null
+++ b/cmpcj/src/de/schwarzrot/control/app/CMPMessageBundle.java
@@ -0,0 +1,73 @@
+/**
+ * ======================== legal notice ======================
+ *
+ * File: MCCMessageBundle.java
+ * Created: 13. June 2012, 04:57
+ * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a>
+ * 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.control.app;
+
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import de.schwarzrot.base.util.MessageBundle;
+
+
+public class CMPMessageBundle implements MessageBundle {
+ public static final String MCC_0 = "MCC_0";
+ public static final String MCC_12 = "MCC_12";
+ public static final String MCC_13 = "MCC_13";
+ public static final String MCC_14 = "MCC_14";
+ public static final String MCC_15 = "MCC_15";
+ public static final String MCC_16 = "MCC_16";
+ public static final String MCC_17 = "MCC_17";
+ public static final String MCC_18 = "MCC_18";
+ public static final String MCC_19 = "MCC_19";
+ public static final String MCC_20 = "MCC_20";
+ public static final String MCC_21 = "MCC_21";
+ public static final String MCC_22 = "MCC_22";
+ public static final String MCC_29 = "MCC_29";
+ public static final String MCC_31 = "MCC_31";
+ public static final String MCC_33 = "MCC_33";
+ public static final String MCC_35 = "MCC_35";
+ public static final String MCC_4 = "MCC_4";
+ public static final String MCC_5 = "MCC_5";
+ public static final String MCC_6 = "MCC_6";
+ public static final String MCC_7 = "MCC_7";
+ public static final String PTF_0 = "PTF_0";
+ public static final String PTF_1 = "PTF_1";
+ public static final String MTF_0 = "MTF_0";
+ public static final String MTF_1 = "MTF_1";
+ public static final String MTF_2 = "MTF_2";
+
+
+ @Override
+ public String getMessage(String key) {
+ try {
+ return RESOURCE_BUNDLE.getString(key);
+ } catch (MissingResourceException e) {
+ return '!' + key + '!';
+ }
+ }
+
+ private final String BUNDLE_NAME = "de.schwarzrot.control.app.lang.messages"; //$NON-NLS-1$
+ private final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME);
+}
diff --git a/cmpcj/src/de/schwarzrot/control/client/CMPClient.java b/cmpcj/src/de/schwarzrot/control/client/CMPClient.java
new file mode 100644
index 0000000..38c6ccb
--- /dev/null
+++ b/cmpcj/src/de/schwarzrot/control/client/CMPClient.java
@@ -0,0 +1,171 @@
+/**
+ * ======================== legal notice ======================
+ *
+ * File: CMPClient.java
+ * Created: 13. June 2012, 04:57
+ * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a>
+ * 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.control.client;
+
+
+import java.net.ConnectException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.UnknownHostException;
+import java.util.Date;
+import ca.odell.glazedlists.EventList;
+import de.schwarzrot.base.util.ApplicationServiceProvider;
+import de.schwarzrot.media.domain.AbstractMediaNode;
+import de.schwarzrot.media.domain.Media;
+import de.schwarzrot.media.domain.MediaServer;
+import de.schwarzrot.media.domain.PlayList;
+import de.schwarzrot.media.util.ElementConsumer;
+import de.schwarzrot.media.util.ListLoader;
+import de.schwarzrot.media.util.MedialistParser;
+
+
+public class CMPClient implements ListLoader<Media> {
+ public CMPClient(MediaServer serverDefinition) {
+ server = serverDefinition;
+ }
+
+
+ public void execServerRescan() {
+ try {
+ URL request = new URL("http", server.getHostName(), server.getPort(), "/refresh");
+ URLConnection conn = request.openConnection();
+
+ conn.connect();
+ conn.getContentLength();
+ } catch (Throwable t) {
+ throw new RuntimeException(t);
+ }
+ }
+
+
+ public void execServerShutdown() {
+ try {
+ URL request = new URL("http", server.getHostName(), server.getPort(), "/stop");
+ URLConnection conn = request.openConnection();
+
+ conn.connect();
+ conn.getContentLength();
+ } catch (Throwable t) {
+ throw new RuntimeException(t);
+ }
+ }
+
+
+ public MediaServer getServerDefinition() {
+ return server;
+ }
+
+
+ @Override
+ public long[] loadFirst(ElementConsumer<Media> consumer) {
+ MedialistParser jsonParser = ApplicationServiceProvider.getService(MedialistParser.class);
+ URL request = null;
+ Date start, end;
+ long[] rv = new long[2];
+
+ try {
+ start = new Date();
+ request = new URL("http", server.getHostName(), server.getPort(), "/?format=json");
+ URLConnection conn = request.openConnection();
+ final PlayList firstPlaylist = jsonParser.parseListChunk(conn.getInputStream());
+
+ for (Media m : firstPlaylist.getResults())
+ consumer.consumeElement(m);
+
+ end = new Date();
+ rv[0] = firstPlaylist.getResults().size();
+ rv[1] = firstPlaylist.getTotal();
+ System.out.println("processing of first playlist-part took " + (end.getTime() - start.getTime()) + " ms.");
+ } catch (UnknownHostException uhe) {
+ throw new RuntimeException("failed to connect to " + server.getHostName(), uhe);
+ } catch (ConnectException ce) {
+ throw new RuntimeException("connection failure with " + server.getHostName(), ce);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ return rv;
+ }
+
+
+ @Override
+ public long loadRest(long[] listInfo, ElementConsumer<Media> consumer) {
+ MedialistParser jsonParser = ApplicationServiceProvider.getService(MedialistParser.class);
+ URL request = null;
+ Date start, end;
+ long rv = 0;
+
+ try {
+ PlayList next;
+ URLConnection conn;
+ long total = listInfo[1];
+ long n = listInfo[0];
+ long elementsRead = 0;
+ String uri;
+
+ start = new Date();
+ try {
+ while (n < total) {
+ uri = String.format("/?start=%d&limit=%d&format=json", n, 100);
+ request = new URL("http", server.getHostName(), server.getPort(), uri);
+ conn = request.openConnection();
+ next = jsonParser.parseListChunk(conn.getInputStream());
+ for (Media m : next.getResults())
+ consumer.consumeElement(m);
+ elementsRead = next.getResults().size();
+ n += elementsRead;
+ rv += elementsRead;
+ Thread.sleep(10);
+ }
+ } catch (UnknownHostException uhe) {
+ throw new RuntimeException("failed to connect to " + server.getHostName(), uhe);
+ } catch (ConnectException ce) {
+ throw new RuntimeException("connection failure with " + server.getHostName(), ce);
+ } catch (Throwable t) {
+ System.err.println("Error on chunk #" + n);
+ t.printStackTrace();
+ }
+ end = new Date();
+ System.out.println("processing of rest of playlist took " + (end.getTime() - start.getTime()) + " ms.");
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ return rv;
+ }
+
+
+ public void transmitChanges(EventList<AbstractMediaNode> changes) {
+ for (AbstractMediaNode n : changes) {
+ System.out.println("geänderter Eintrag: " + n.getClass().getSimpleName() + " - " + n.getName()); //$NON-NLS-1$
+ System.out.println("\tverschieben von " + n.getOriginalPath().getAbsolutePath() + " nach "
+ + n.getRealPath().getAbsolutePath());
+
+ //TODO: really create jobs for changes, so backend can participate on work
+
+ }
+ }
+
+ private MediaServer server;
+}
diff --git a/cmpcj/src/de/schwarzrot/control/client/MediaClientExecutor.java b/cmpcj/src/de/schwarzrot/control/client/MediaClientExecutor.java
new file mode 100644
index 0000000..4ad39f2
--- /dev/null
+++ b/cmpcj/src/de/schwarzrot/control/client/MediaClientExecutor.java
@@ -0,0 +1,34 @@
+/**
+ * ======================== legal notice ======================
+ *
+ * File: MediaClientExecutor.java
+ * Created: 13. June 2012, 04:57
+ * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a>
+ * 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.control.client;
+
+
+import de.schwarzrot.media.domain.Media;
+
+
+public interface MediaClientExecutor {
+ public void playMedia(Media m);
+}
diff --git a/cmpcj/src/de/schwarzrot/control/config/ConfigDialog.java b/cmpcj/src/de/schwarzrot/control/config/ConfigDialog.java
new file mode 100644
index 0000000..2acb026
--- /dev/null
+++ b/cmpcj/src/de/schwarzrot/control/config/ConfigDialog.java
@@ -0,0 +1,131 @@
+/**
+ * ======================== legal notice ======================
+ *
+ * File: ConfigDialog.java
+ * Created: 13. June 2012, 04:57
+ * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a>
+ * 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.control.config;
+
+
+import java.awt.Window;
+import java.util.List;
+import javax.swing.JComponent;
+import javax.swing.JScrollPane;
+import javax.swing.JTabbedPane;
+import javax.swing.JTable;
+import ca.odell.glazedlists.BasicEventList;
+import ca.odell.glazedlists.EventList;
+import ca.odell.glazedlists.GlazedLists;
+import ca.odell.glazedlists.swing.DefaultEventTableModel;
+import de.schwarzrot.base.util.AbstractDialog;
+import de.schwarzrot.base.util.ApplicationServiceProvider;
+import de.schwarzrot.control.table.PlayerDefinitionTableFormat;
+import de.schwarzrot.control.table.ServerDefinitionTableFormat;
+import de.schwarzrot.media.domain.AbstractMediaNode;
+import de.schwarzrot.media.domain.Config;
+import de.schwarzrot.media.domain.MediaServer;
+import de.schwarzrot.media.domain.PlayerDefinition;
+
+
+public class ConfigDialog extends AbstractDialog {
+ private static final long serialVersionUID = 713L;
+
+
+ public ConfigDialog(Window parent) {
+ super(parent, true, DialogMode.CANCEL_APPROVE, Orientation.Right);
+ config = ApplicationServiceProvider.getService(Config.class);
+ }
+
+
+ @Override
+ public JComponent createContentPane() {
+ JTabbedPane rv = new JTabbedPane();
+
+ rv.addTab("server", createServerTable());
+ rv.addTab("player", createPlayerTable());
+
+ return rv;
+ }
+
+
+ protected JComponent createPlayerTable() {
+ playerDefinitions = new BasicEventList<PlayerDefinition>();
+ for (AbstractMediaNode.SupportedMediaType mt : AbstractMediaNode.SupportedMediaType.values()) {
+ if (mt == AbstractMediaNode.SupportedMediaType.Unknown)
+ break;
+ PlayerDefinition pd = config.getPlayerMap().get(mt);
+
+ pd.setMediaType(mt);
+ playerDefinitions.add(pd);
+ }
+ PlayerDefinitionTableFormat ptf = new PlayerDefinitionTableFormat();
+ DefaultEventTableModel<PlayerDefinition> tm = new DefaultEventTableModel<PlayerDefinition>(playerDefinitions,
+ ptf);
+ JTable playerTable = new JTable(tm);
+ JScrollPane playerTableScrollPane = new JScrollPane(playerTable);
+ int mx = playerTable.getColumnModel().getColumnCount();
+
+ for (int i = 0; i < mx; ++i) {
+ int cw = ptf.getColumnWidth(i);
+
+ if (cw > 0) {
+ playerTable.getColumnModel().getColumn(i).setPreferredWidth(cw);
+ playerTable.getColumnModel().getColumn(i).setMaxWidth(cw);
+ }
+ }
+ return playerTableScrollPane;
+ }
+
+
+ protected JComponent createServerTable() {
+ serverDefinitions = GlazedLists.eventList(config.getKnownServers());
+ ServerDefinitionTableFormat stf = new ServerDefinitionTableFormat();
+ DefaultEventTableModel<MediaServer> tm = new DefaultEventTableModel<MediaServer>(serverDefinitions, stf);
+ JTable serverTable = new JTable(tm);
+ JScrollPane serverTableScrollPane = new JScrollPane(serverTable);
+ int mx = serverTable.getColumnModel().getColumnCount();
+
+ for (int i = 0; i < mx; ++i) {
+ int cw = stf.getColumnWidth(i);
+
+ if (cw > 0) {
+ serverTable.getColumnModel().getColumn(i).setPreferredWidth(cw);
+ serverTable.getColumnModel().getColumn(i).setMaxWidth(cw);
+ }
+ }
+ return serverTableScrollPane;
+ }
+
+
+ @Override
+ protected void performApprove() {
+ System.out.println("should save config now!?!");
+ List<MediaServer> cfgServers = config.getKnownServers();
+
+ cfgServers.clear();
+ cfgServers.addAll(serverDefinitions);
+ }
+
+ private EventList<MediaServer> serverDefinitions;
+ private EventList<PlayerDefinition> playerDefinitions;
+ private Config config;
+}
diff --git a/cmpcj/src/de/schwarzrot/control/config/ConfigFactory.java b/cmpcj/src/de/schwarzrot/control/config/ConfigFactory.java
new file mode 100644
index 0000000..5424ef5
--- /dev/null
+++ b/cmpcj/src/de/schwarzrot/control/config/ConfigFactory.java
@@ -0,0 +1,225 @@
+/**
+ * ======================== legal notice ======================
+ *
+ * File: ConfigFactory.java
+ * Created: 13. June 2012, 04:57
+ * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a>
+ * 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.control.config;
+
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import de.schwarzrot.media.domain.Config;
+import de.schwarzrot.media.domain.Media;
+import de.schwarzrot.media.domain.MediaServer;
+import de.schwarzrot.media.domain.PlayerDefinition;
+
+
+public class ConfigFactory {
+ protected static final Pattern SETUP_MASK = Pattern.compile("^\\s*(\\S+)\\s*=\\s*(.+)$");
+
+
+ public ConfigFactory(File configDirectory, String applicationID) {
+ baseDir = configDirectory;
+ appID = applicationID;
+ }
+
+
+ public Config getConfig() {
+ if (config == null) {
+ config = readConfig();
+ }
+ return config;
+ }
+
+
+ public File getConfigDirectory() {
+ return baseDir;
+ }
+
+
+ public void putConfig(Config config) {
+ if (config != null)
+ writeConfig(config);
+ }
+
+
+ protected Config readConfig() {
+ File setupFile = new File(baseDir, "srclient.conf");
+ BufferedReader br = null;
+ Config rv = new Config();
+
+ if (setupFile.exists()) {
+ try {
+ br = new BufferedReader(new FileReader(setupFile));
+ String line, trimmedLine;
+
+ while ((line = br.readLine()) != null) {
+ trimmedLine = line.trim();
+
+ if (trimmedLine.isEmpty() || trimmedLine.startsWith("#"))
+ continue;
+ Matcher m = SETUP_MASK.matcher(trimmedLine);
+
+ if (m.matches()) {
+ String key = m.group(1);
+ String value = m.group(2);
+
+ if (key.compareToIgnoreCase("server") == 0) {
+ String[] parts = value.split("\\s*\\:\\s*");
+ MediaServer ms = null;
+
+ if (parts.length > 1) {
+ ms = new MediaServer();
+ ms.setHostName(parts[0]);
+ ms.setPort(Integer.decode(parts[1]));
+
+ rv.addServer(ms);
+ }
+ } else if (key.compareToIgnoreCase("player") == 0) {
+ String[] parts = value.split("\\s*\\:\\s*");
+ PlayerDefinition pd = null;
+
+ if (parts.length > 1) {
+ pd = new PlayerDefinition();
+ String[] cmdline = parts[1].split("\\s+");
+
+ pd.setExecutable(cmdline[0]);
+
+ for (int i = 1; i < cmdline.length; ++i) {
+ pd.addParameter(cmdline[i]);
+ }
+ if (parts[0].compareTo("*") == 0) {
+ // default player
+ for (Media.SupportedMediaType cmt : Media.SupportedMediaType.values())
+ rv.putPlayer(cmt, pd);
+ } else {
+ for (Media.SupportedMediaType cmt : Media.SupportedMediaType.values()) {
+ if (parts[0].compareTo(cmt.name()) == 0)
+ rv.putPlayer(cmt, pd);
+ }
+ }
+ }
+ } else if (key.compareToIgnoreCase("size") == 0) {
+ String[] parts = value.split("\\s*x\\s*");
+
+ if (parts.length > 1) {
+ try {
+ rv.setMainWidth(Integer.decode(parts[0]));
+ } catch (Throwable t) {
+ }
+ try {
+ rv.setMainHeight(Integer.decode(parts[1]));
+ } catch (Throwable t) {
+ }
+ }
+ } else if (key.compareToIgnoreCase("pos") == 0) {
+ String[] parts = value.split("\\s*\\/\\s*");
+
+ if (parts.length > 1) {
+ try {
+ rv.setPosX(Integer.decode(parts[0]));
+ } catch (Throwable t) {
+ }
+ try {
+ rv.setPosY(Integer.decode(parts[1]));
+ } catch (Throwable t) {
+ }
+ }
+ }
+ }
+ }
+ } catch (Throwable t) {
+ t.printStackTrace();
+ } finally {
+ if (br != null) {
+ try {
+ br.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ }
+ return rv;
+ }
+
+
+ protected void writeConfig(Config config) {
+ File setupFile = new File(baseDir, "srclient.conf");
+ PrintWriter out = null;
+ StringBuilder sb = null;
+
+ if (!setupFile.exists())
+ setupFile.getParentFile().mkdirs();
+ try {
+ out = new PrintWriter(new FileWriter(setupFile));
+
+ sb = new StringBuilder("#\n# configuration for ");
+ sb.append(appID).append("\n#");
+ out.println(sb.toString());
+ for (MediaServer server : config.getKnownServers()) {
+ sb = new StringBuilder("server = ");
+ sb.append(server.getHostName()).append(":").append(server.getPort());
+ out.println(sb.toString());
+ }
+ out.println();
+ sb = new StringBuilder("#\n# currently supported media types (");
+ sb.append(Media.SupportedMediaType.LegacyVdrRecording.name());
+ sb.append(" is the old PES format):\n");
+ sb.append("# ");
+ sb.append("#");
+ out.println(sb.toString());
+ for (Media.SupportedMediaType mt : config.getPlayerMap().keySet()) {
+ PlayerDefinition player = config.getPlayerMap().get(mt);
+
+ sb = new StringBuilder("player = ");
+ sb.append(mt.name()).append(" : ").append(player.getExecutable());
+ for (String p : player.getParameters()) {
+ sb.append(" ").append(p);
+ }
+ out.println(sb.toString());
+ }
+ out.println();
+ sb = new StringBuilder("size = ");
+ sb.append(config.getMainWidth()).append(" x ").append(config.getMainHeight());
+ out.println(sb.toString());
+
+ sb = new StringBuilder("pos = ");
+ sb.append(config.getPosX()).append(" / ").append(config.getPosY());
+ out.println(sb.toString());
+ } catch (Throwable t) {
+ t.printStackTrace();
+ } finally {
+ if (out != null)
+ out.close();
+ }
+ }
+ private Config config;
+ private File baseDir;
+ private final String appID;
+}
diff --git a/cmpcj/src/de/schwarzrot/control/dnd/FilelistTransferable.java b/cmpcj/src/de/schwarzrot/control/dnd/FilelistTransferable.java
new file mode 100644
index 0000000..678bbc1
--- /dev/null
+++ b/cmpcj/src/de/schwarzrot/control/dnd/FilelistTransferable.java
@@ -0,0 +1,72 @@
+/**
+ * ======================== legal notice ======================
+ *
+ * File: FilelistTransferable.java
+ * Created: 13. June 2012, 04:57
+ * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a>
+ * 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.control.dnd;
+
+
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+
+public class FilelistTransferable implements Transferable {
+ public FilelistTransferable(List<File> fileList) {
+ files = fileList;
+ }
+
+
+ protected FilelistTransferable() {
+ }
+
+
+ @Override
+ public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
+ if (DataFlavor.javaFileListFlavor.equals(flavor))
+ return files;
+ throw new UnsupportedFlavorException(flavor);
+ }
+
+
+ @Override
+ public DataFlavor[] getTransferDataFlavors() {
+ return new DataFlavor[] { DataFlavor.javaFileListFlavor };
+ }
+
+
+ @Override
+ public boolean isDataFlavorSupported(DataFlavor flavor) {
+ return DataFlavor.javaFileListFlavor.equals(flavor);
+ }
+
+
+ protected void setFileList(List<File> list) {
+ files = list;
+ }
+
+ private List<File> files;
+}
diff --git a/cmpcj/src/de/schwarzrot/control/dnd/ListSelectionSourceTransferHandler.java b/cmpcj/src/de/schwarzrot/control/dnd/ListSelectionSourceTransferHandler.java
new file mode 100644
index 0000000..e396e17
--- /dev/null
+++ b/cmpcj/src/de/schwarzrot/control/dnd/ListSelectionSourceTransferHandler.java
@@ -0,0 +1,69 @@
+/**
+ * ======================== legal notice ======================
+ *
+ * File: ListSelectionSourceTransferHandler.java
+ * Created: 13. June 2012, 04:57
+ * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a>
+ * 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.control.dnd;
+
+
+import java.awt.datatransfer.Transferable;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import javax.swing.JComponent;
+import javax.swing.TransferHandler;
+import ca.odell.glazedlists.EventList;
+import ca.odell.glazedlists.swing.DefaultEventSelectionModel;
+import de.schwarzrot.media.domain.Media;
+
+
+public class ListSelectionSourceTransferHandler extends TransferHandler {
+ private static final long serialVersionUID = 713L;
+
+
+ public ListSelectionSourceTransferHandler(DefaultEventSelectionModel<Media> selectionModel) {
+ sm = selectionModel;
+ }
+
+
+ @Override
+ public Transferable createTransferable(JComponent c) {
+ if (sm.isSelectionEmpty())
+ return null;
+ EventList<Media> selection = sm.getSelected();
+ List<File> transferList = new ArrayList<File>();
+
+ for (Media m : selection) {
+ transferList.add(m.getRealPath());
+ }
+ return new FilelistTransferable(transferList);
+ }
+
+
+ @Override
+ public int getSourceActions(JComponent c) {
+ return TransferHandler.LINK;
+ }
+
+ private DefaultEventSelectionModel<Media> sm;
+}
diff --git a/cmpcj/src/de/schwarzrot/control/dnd/TreePathTransferable.java b/cmpcj/src/de/schwarzrot/control/dnd/TreePathTransferable.java
new file mode 100644
index 0000000..a54be35
--- /dev/null
+++ b/cmpcj/src/de/schwarzrot/control/dnd/TreePathTransferable.java
@@ -0,0 +1,74 @@
+/**
+ * ======================== legal notice ======================
+ *
+ * File: TreePathTransferable.java
+ * Created: 13. June 2012, 04:57
+ * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a>
+ * 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.control.dnd;
+
+
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.io.IOException;
+import javax.swing.tree.TreePath;
+
+
+public class TreePathTransferable implements Transferable {
+ public static final DataFlavor TreePathFlavor;
+
+
+ public TreePathTransferable(TreePath path) {
+ data = path;
+ }
+
+
+ @Override
+ public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
+ if (TreePathFlavor.equals(flavor))
+ return data;
+ throw new UnsupportedFlavorException(flavor);
+ }
+
+
+ @Override
+ public DataFlavor[] getTransferDataFlavors() {
+ return new DataFlavor[] { TreePathFlavor };
+ }
+
+
+ @Override
+ public boolean isDataFlavorSupported(DataFlavor flavor) {
+ return TreePathFlavor.equals(flavor);
+ }
+
+ private TreePath data;
+ static {
+ DataFlavor tmp = null;
+
+ try {
+ tmp = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + ";class=" + TreePath.class.getName());
+ } catch (ClassNotFoundException e) {
+ }
+ TreePathFlavor = tmp;
+ }
+}
diff --git a/cmpcj/src/de/schwarzrot/control/dnd/TreeSourceAndDestTransferHandler.java b/cmpcj/src/de/schwarzrot/control/dnd/TreeSourceAndDestTransferHandler.java
new file mode 100644
index 0000000..d9c3285
--- /dev/null
+++ b/cmpcj/src/de/schwarzrot/control/dnd/TreeSourceAndDestTransferHandler.java
@@ -0,0 +1,207 @@
+/**
+ * ======================== legal notice ======================
+ *
+ * File: TreeSourceAndDestTransferHandler.java
+ * Created: 13. June 2012, 04:57
+ * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a>
+ * 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.control.dnd;
+
+
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+import javax.swing.JComponent;
+import javax.swing.JTree;
+import javax.swing.TransferHandler;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreePath;
+import ca.odell.glazedlists.EventList;
+import de.schwarzrot.media.domain.AbstractMediaNode;
+import de.schwarzrot.media.domain.Genre;
+import de.schwarzrot.media.domain.Media;
+
+
+public class TreeSourceAndDestTransferHandler extends TransferHandler {
+ private static final long serialVersionUID = 713L;
+
+
+ public TreeSourceAndDestTransferHandler(JTree tree, Map<File, DefaultMutableTreeNode> cache,
+ EventList<AbstractMediaNode> changes) {
+ this.tree = tree;
+ nodeCache = cache;
+ this.changes = changes;
+ }
+
+
+ // dest
+ @Override
+ public boolean canImport(TransferHandler.TransferSupport support) {
+ if (!support.isDrop())
+ return false;
+ support.setShowDropLocation(true);
+
+ if (support.isDataFlavorSupported(TreePathTransferable.TreePathFlavor) && support.getDropAction() == MOVE)
+ return true;
+ if (support.isDataFlavorSupported(DataFlavor.javaFileListFlavor))
+ return true;
+
+ return false;
+ }
+
+
+ // source
+ @Override
+ public Transferable createTransferable(JComponent c) {
+ if (c != tree)
+ return null;
+ TreePath selectionPath = tree.getSelectionPath();
+
+ return new TreePathTransferable(selectionPath);
+ }
+
+
+ // source
+ @Override
+ public void exportDone(JComponent c, Transferable data, int action) {
+ tree.updateUI();
+ }
+
+
+ // source
+ @Override
+ public int getSourceActions(JComponent c) {
+ return MOVE;
+ }
+
+
+ // dest
+ @Override
+ public boolean importData(TransferHandler.TransferSupport support) {
+ if (!canImport(support))
+ return false;
+ JTree.DropLocation dl = (JTree.DropLocation) support.getDropLocation();
+ TreePath targetPath = tree.getClosestPathForLocation(dl.getDropPoint().x, dl.getDropPoint().y);
+ DefaultMutableTreeNode targetNode = (DefaultMutableTreeNode) targetPath.getLastPathComponent();
+
+ if (support.isDataFlavorSupported(TreePathTransferable.TreePathFlavor)) {
+ // move a genre in tree
+ try {
+ TreePath sourcePath = (TreePath) support.getTransferable().getTransferData(
+ TreePathTransferable.TreePathFlavor);
+ DefaultMutableTreeNode transferNode = (DefaultMutableTreeNode) sourcePath.getLastPathComponent();
+ DefaultMutableTreeNode sourceParentNode = (DefaultMutableTreeNode) transferNode.getParent();
+ Genre target = (Genre) targetNode.getUserObject();
+ Genre transfer = (Genre) transferNode.getUserObject();
+
+ // System.out.println("importData() targetPath: " + targetPath);
+ // System.out.println("importData() sourcePath: " + sourcePath);
+
+ sourceParentNode.remove(transferNode);
+ targetNode.add(transferNode);
+ nodeCache.remove(transfer.getRealPath());
+ // System.out.println("old path of genre to move: " + transfer.getRealPath().getAbsolutePath());
+ transfer.setParent(target);
+ // System.out.println("new path of moved genre: " + transfer.getRealPath().getAbsolutePath());
+ nodeCache.put(transfer.getRealPath(), transferNode);
+ transfer.update();
+ refreshNodeCache();
+ if (!changes.contains(transfer)) {
+ changes.getReadWriteLock().writeLock().lock();
+ changes.add(transfer);
+ changes.getReadWriteLock().writeLock().unlock();
+ }
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ } else if (support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
+ // move media files from one genre to another (no visible tree change)
+ try {
+ @SuppressWarnings("unchecked")
+ List<File> fileList = (List<File>) support.getTransferable().getTransferData(
+ DataFlavor.javaFileListFlavor);
+
+ for (File f : fileList)
+ move2TargetNode(targetNode, f); // each media can have different parent, so don't optimize here
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ }
+ return false;
+ }
+
+
+ protected void cacheNode(DefaultMutableTreeNode node) {
+ Genre g = (Genre) node.getUserObject();
+
+ nodeCache.put(g.getRealPath(), node);
+ for (int i = 0; i < node.getChildCount(); ++i) {
+ DefaultMutableTreeNode sub = (DefaultMutableTreeNode) node.getChildAt(i);
+
+ cacheNode(sub);
+ }
+ }
+
+
+ protected void move2TargetNode(DefaultMutableTreeNode targetNode, File mediaPath) {
+ if (targetNode == null || mediaPath == null)
+ return;
+ Genre targetGenre = (Genre) targetNode.getUserObject();
+ DefaultMutableTreeNode node = nodeCache.get(mediaPath.getParentFile());
+
+ if (targetGenre != null && node != null) {
+ Media transferMedia = null;
+ Genre sourceGenre = (Genre) node.getUserObject();
+
+ for (Media m : sourceGenre.getMediaList()) {
+ if (m.getRealPath().equals(mediaPath)) {
+ transferMedia = m;
+ break;
+ }
+ }
+
+ if (transferMedia != null) {
+ System.out.println("old path of media to transfer: " + transferMedia.getRealPath().getAbsolutePath());
+ transferMedia.setParent(targetGenre);
+ System.out.println("new path of transferred media: " + transferMedia.getRealPath().getAbsolutePath());
+ if (!changes.contains(transferMedia)) {
+ changes.getReadWriteLock().writeLock().lock();
+ changes.add(transferMedia);
+ changes.getReadWriteLock().writeLock().unlock();
+ }
+ }
+ }
+ }
+
+
+ protected void refreshNodeCache() {
+ nodeCache.clear();
+ DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getModel().getRoot();
+
+ cacheNode(node);
+ }
+
+ private JTree tree;
+ private EventList<AbstractMediaNode> changes;
+ private Map<File, DefaultMutableTreeNode> nodeCache;
+}
diff --git a/cmpcj/src/de/schwarzrot/control/support/GenreSelector.java b/cmpcj/src/de/schwarzrot/control/support/GenreSelector.java
new file mode 100644
index 0000000..9566ae8
--- /dev/null
+++ b/cmpcj/src/de/schwarzrot/control/support/GenreSelector.java
@@ -0,0 +1,46 @@
+/**
+ * ======================== legal notice ======================
+ *
+ * File: GenreSelector.java
+ * Created: 13. June 2012, 04:57
+ * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a>
+ * 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.control.support;
+
+
+import ca.odell.glazedlists.matchers.Matcher;
+import de.schwarzrot.media.domain.Genre;
+import de.schwarzrot.media.domain.Media;
+
+
+public class GenreSelector implements Matcher<Media> {
+ public GenreSelector(Genre genre) {
+ g = genre;
+ }
+
+
+ @Override
+ public boolean matches(Media m) {
+ return m.getRealPath().getAbsolutePath().startsWith(g.getRealPath().getAbsolutePath());
+ }
+
+ private Genre g;
+} \ No newline at end of file
diff --git a/cmpcj/src/de/schwarzrot/control/support/MediaList2TypeList.java b/cmpcj/src/de/schwarzrot/control/support/MediaList2TypeList.java
new file mode 100644
index 0000000..8445db8
--- /dev/null
+++ b/cmpcj/src/de/schwarzrot/control/support/MediaList2TypeList.java
@@ -0,0 +1,61 @@
+/**
+ * ======================== legal notice ======================
+ *
+ * File: MediaList2TypeList.java
+ * Created: 13. June 2012, 04:57
+ * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a>
+ * 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.control.support;
+
+
+import ca.odell.glazedlists.EventList;
+import ca.odell.glazedlists.TransformedList;
+import ca.odell.glazedlists.event.ListEvent;
+import de.schwarzrot.media.domain.AbstractMediaNode;
+import de.schwarzrot.media.domain.Media;
+
+
+public class MediaList2TypeList extends TransformedList<Media, AbstractMediaNode.SupportedMediaType> {
+ public MediaList2TypeList(EventList<Media> source) {
+ super(source);
+ source.addListEventListener(this);
+ }
+
+
+ @Override
+ public Media.SupportedMediaType get(int index) {
+ Media m = source.get(index);
+
+ return m.getType();
+ }
+
+
+ @Override
+ public void listChanged(ListEvent<Media> listChanges) {
+ updates.forwardEvent(listChanges);
+ }
+
+
+ @Override
+ protected boolean isWritable() {
+ return false;
+ }
+}
diff --git a/cmpcj/src/de/schwarzrot/control/support/MediaTextFilterator.java b/cmpcj/src/de/schwarzrot/control/support/MediaTextFilterator.java
new file mode 100644
index 0000000..b36f582
--- /dev/null
+++ b/cmpcj/src/de/schwarzrot/control/support/MediaTextFilterator.java
@@ -0,0 +1,41 @@
+/**
+ * ======================== legal notice ======================
+ *
+ * File: MediaTextFilterator.java
+ * Created: 13. June 2012, 04:57
+ * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a>
+ * 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.control.support;
+
+
+import java.util.List;
+import ca.odell.glazedlists.TextFilterator;
+import de.schwarzrot.media.domain.Media;
+
+
+public class MediaTextFilterator implements TextFilterator<Media> {
+ @Override
+ public void getFilterStrings(List<String> baseList, Media m) {
+ baseList.add(m.getName());
+ baseList.add(m.getRealPath().getAbsolutePath());
+ baseList.add(m.getSearch());
+ }
+}
diff --git a/cmpcj/src/de/schwarzrot/control/support/MediaTypeSelector.java b/cmpcj/src/de/schwarzrot/control/support/MediaTypeSelector.java
new file mode 100644
index 0000000..f60ddc4
--- /dev/null
+++ b/cmpcj/src/de/schwarzrot/control/support/MediaTypeSelector.java
@@ -0,0 +1,157 @@
+/**
+ * ======================== legal notice ======================
+ *
+ * File: MediaTypeSelector.java
+ * Created: 13. June 2012, 04:57
+ * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a>
+ * 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.control.support;
+
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import javax.swing.ImageIcon;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JScrollPane;
+import javax.swing.ListCellRenderer;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import ca.odell.glazedlists.EventList;
+import ca.odell.glazedlists.UniqueList;
+import ca.odell.glazedlists.matchers.AbstractMatcherEditor;
+import ca.odell.glazedlists.matchers.Matcher;
+import ca.odell.glazedlists.swing.DefaultEventListModel;
+import ca.odell.glazedlists.swing.DefaultEventSelectionModel;
+import de.schwarzrot.base.util.ApplicationServiceProvider;
+import de.schwarzrot.base.util.ImageFactory;
+import de.schwarzrot.media.domain.Media;
+
+
+public class MediaTypeSelector extends AbstractMatcherEditor<Media> implements ListSelectionListener {
+ public class MediaTypeCellRenderer extends JLabel implements ListCellRenderer {
+ private static final long serialVersionUID = 713L;
+
+
+ public MediaTypeCellRenderer() {
+ loadImages();
+ }
+
+
+ @Override
+ public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
+ boolean cellHasFocus) {
+ ImageIcon icon = null;
+
+ if (isSelected) {
+ setBackground(list.getSelectionBackground());
+ setForeground(list.getSelectionForeground());
+ icon = selImages[((Media.SupportedMediaType) value).ordinal()];
+ } else {
+ setBackground(list.getBackground());
+ setForeground(list.getForeground());
+ icon = stdImages[((Media.SupportedMediaType) value).ordinal()];
+ }
+ setSize(110, 110);
+ setHorizontalAlignment(JLabel.CENTER);
+
+ if (icon != null) {
+ setIcon(icon);
+ setText("");
+ } else {
+ setText(value.toString());
+ }
+ return this;
+ }
+
+
+ protected void loadImages() {
+ ImageFactory imgFak = ApplicationServiceProvider.getService(ImageFactory.class);
+ int i = 0;
+
+ stdImages = new ImageIcon[Media.SupportedMediaType.values().length];
+ for (Media.SupportedMediaType smt : Media.SupportedMediaType.values()) {
+ StringBuilder sb = new StringBuilder(smt.getClass().getSimpleName());
+
+ sb.append(".").append(smt.name()).append(".default");
+ stdImages[i++] = imgFak.getIcon(sb.toString(), 110, 110);
+ }
+
+ i = 0;
+ selImages = new ImageIcon[Media.SupportedMediaType.values().length];
+ for (Media.SupportedMediaType smt : Media.SupportedMediaType.values()) {
+ StringBuilder sb = new StringBuilder(smt.getClass().getSimpleName());
+
+ sb.append(".").append(smt.name()).append(".active");
+ selImages[i++] = imgFak.getIcon(sb.toString(), 110, 110);
+ }
+ }
+
+ ImageIcon[] stdImages;
+ ImageIcon[] selImages;
+ }
+
+
+ public MediaTypeSelector(EventList<Media> source) {
+ EventList<Media.SupportedMediaType> mediaTypeNonUnique = new MediaList2TypeList(source);
+
+ mediaTypeList = new UniqueList<Media.SupportedMediaType>(mediaTypeNonUnique);
+ DefaultEventListModel<Media.SupportedMediaType> mediaTypeListModel = new DefaultEventListModel<Media.SupportedMediaType>(
+ mediaTypeList);
+
+ mediaTypeJList = new JList(mediaTypeListModel);
+ DefaultEventSelectionModel<Media.SupportedMediaType> mediaTypeSelectionModel = new DefaultEventSelectionModel<Media.SupportedMediaType>(
+ mediaTypeList);
+
+ mediaTypeJList.setSelectionModel(mediaTypeSelectionModel);
+ selectedTypes = mediaTypeSelectionModel.getSelected();
+ mediaTypeJList.addListSelectionListener(this);
+ mediaTypeJList.setCellRenderer(new MediaTypeCellRenderer());
+ mediaTypeJList.setBackground(Color.BLACK);
+ mediaTypeJList.setMinimumSize(new Dimension(100, 100));
+ mediaTypeComponent = new JScrollPane(mediaTypeJList);
+ }
+
+
+ public JComponent getComponent() {
+ return mediaTypeComponent;
+ }
+
+
+ public JList getJList() {
+ return mediaTypeJList;
+ }
+
+
+ @Override
+ public void valueChanged(ListSelectionEvent e) {
+ Matcher<Media> newMatcher = new MediatypeMatcher(selectedTypes);
+
+ fireChanged(newMatcher);
+ }
+
+ private EventList<Media.SupportedMediaType> mediaTypeList;
+ private EventList<Media.SupportedMediaType> selectedTypes;
+ private JList mediaTypeJList;
+ private JScrollPane mediaTypeComponent;
+}
diff --git a/cmpcj/src/de/schwarzrot/control/support/MediatypeMatcher.java b/cmpcj/src/de/schwarzrot/control/support/MediatypeMatcher.java
new file mode 100644
index 0000000..a01b43a
--- /dev/null
+++ b/cmpcj/src/de/schwarzrot/control/support/MediatypeMatcher.java
@@ -0,0 +1,55 @@
+/**
+ * ======================== legal notice ======================
+ *
+ * File: MediatypeMatcher.java
+ * Created: 13. June 2012, 04:57
+ * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a>
+ * 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.control.support;
+
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+import ca.odell.glazedlists.matchers.Matcher;
+import de.schwarzrot.media.domain.AbstractMediaNode;
+import de.schwarzrot.media.domain.Media;
+
+
+public class MediatypeMatcher implements Matcher<Media> {
+ public MediatypeMatcher(Collection<AbstractMediaNode.SupportedMediaType> mediaTypes) {
+ this.mediaTypes.addAll(mediaTypes);
+ }
+
+
+ @Override
+ public boolean matches(Media m) {
+ if (m == null)
+ return false;
+ if (mediaTypes.isEmpty())
+ return true;
+ Media.SupportedMediaType mt = m.getType();
+
+ return mediaTypes.contains(mt);
+ }
+
+ private Set<AbstractMediaNode.SupportedMediaType> mediaTypes = new HashSet<Media.SupportedMediaType>();
+}
diff --git a/cmpcj/src/de/schwarzrot/control/support/SelectedMedia.java b/cmpcj/src/de/schwarzrot/control/support/SelectedMedia.java
new file mode 100644
index 0000000..efde378
--- /dev/null
+++ b/cmpcj/src/de/schwarzrot/control/support/SelectedMedia.java
@@ -0,0 +1,85 @@
+/**
+ * ======================== legal notice ======================
+ *
+ * File: SelectedMedia.java
+ * Created: 13. June 2012, 04:57
+ * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a>
+ * 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.control.support;
+
+
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import ca.odell.glazedlists.EventList;
+import ca.odell.glazedlists.swing.DefaultEventSelectionModel;
+import de.schwarzrot.media.domain.Media;
+
+
+public class SelectedMedia implements ListSelectionListener {
+ public static final String MEDIA_PROPERTY = "media";
+
+
+ public SelectedMedia(EventList<Media> source) {
+ pcs = new PropertyChangeSupport(this);
+ mediaList = source;
+ }
+
+
+ public void addPropertyChangeListener(PropertyChangeListener listener) {
+ pcs.addPropertyChangeListener(listener);
+ }
+
+
+ public void clear() {
+ pcs.firePropertyChange(MEDIA_PROPERTY, this.media, this.media = null);
+ }
+
+
+ public Media getMedia() {
+ return media;
+ }
+
+
+ public void removePropertyChangeListener(PropertyChangeListener listener) {
+ pcs.removePropertyChangeListener(listener);
+ }
+
+
+ @Override
+ public void valueChanged(ListSelectionEvent e) {
+ if (e.getValueIsAdjusting())
+ return;
+ if (e.getSource() instanceof DefaultEventSelectionModel) {
+ @SuppressWarnings("unchecked")
+ DefaultEventSelectionModel<Media> sm = (DefaultEventSelectionModel<Media>) e.getSource();
+
+ if (sm.isSelectionEmpty())
+ return;
+ pcs.firePropertyChange(MEDIA_PROPERTY, this.media, this.media = mediaList.get(sm.getLeadSelectionIndex()));
+ }
+ }
+
+ private Media media;
+ private PropertyChangeSupport pcs;
+ private EventList<Media> mediaList;
+}
diff --git a/cmpcj/src/de/schwarzrot/control/support/TreeSelectionFilter.java b/cmpcj/src/de/schwarzrot/control/support/TreeSelectionFilter.java
new file mode 100644
index 0000000..99d1646
--- /dev/null
+++ b/cmpcj/src/de/schwarzrot/control/support/TreeSelectionFilter.java
@@ -0,0 +1,59 @@
+/**
+ * ======================== legal notice ======================
+ *
+ * File: TreeSelectionFilter.java
+ * Created: 13. June 2012, 04:57
+ * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a>
+ * 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.control.support;
+
+
+import javax.swing.JTree;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.tree.DefaultMutableTreeNode;
+import ca.odell.glazedlists.matchers.AbstractMatcherEditor;
+import ca.odell.glazedlists.matchers.Matcher;
+import de.schwarzrot.media.domain.Genre;
+import de.schwarzrot.media.domain.Media;
+
+
+public class TreeSelectionFilter extends AbstractMatcherEditor<Media> implements TreeSelectionListener {
+ public TreeSelectionFilter(JTree tree) {
+ this.tree = tree;
+ tree.addTreeSelectionListener(this);
+ }
+
+
+ @Override
+ public void valueChanged(TreeSelectionEvent e) {
+ DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
+
+ if (node == null)
+ return;
+ Genre g = (Genre) node.getUserObject();
+ Matcher<Media> newMatcher = new GenreSelector(g);
+
+ fireChanged(newMatcher);
+ }
+
+ private JTree tree;
+}
diff --git a/cmpcj/src/de/schwarzrot/control/table/MediaTableFormat.java b/cmpcj/src/de/schwarzrot/control/table/MediaTableFormat.java
new file mode 100644
index 0000000..88bdea1
--- /dev/null
+++ b/cmpcj/src/de/schwarzrot/control/table/MediaTableFormat.java
@@ -0,0 +1,91 @@
+/**
+ * ======================== legal notice ======================
+ *
+ * File: MediaTableFormat.java
+ * Created: 13. June 2012, 04:57
+ * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a>
+ * 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.control.table;
+
+
+import ca.odell.glazedlists.gui.TableFormat;
+import de.schwarzrot.base.util.ApplicationServiceProvider;
+import de.schwarzrot.base.util.MessageBundle;
+import de.schwarzrot.control.app.CMPMessageBundle;
+import de.schwarzrot.media.domain.Media;
+
+
+public class MediaTableFormat implements TableFormat<Media> {
+ private static MessageBundle bundle;
+
+
+ @Override
+ public int getColumnCount() {
+ return 3;
+ }
+
+
+ @Override
+ public String getColumnName(int column) {
+ if (bundle == null)
+ bundle = ApplicationServiceProvider.getService(MessageBundle.class);
+
+ switch (column) {
+ case 0:
+ return bundle.getMessage(CMPMessageBundle.MTF_0);
+ case 1:
+ return bundle.getMessage(CMPMessageBundle.MTF_1);
+ case 2:
+ return bundle.getMessage(CMPMessageBundle.MTF_2);
+ default:
+ throw new IndexOutOfBoundsException();
+ }
+ }
+
+
+ @Override
+ public Object getColumnValue(Media m, int column) {
+ switch (column) {
+ case 0:
+ return m.getType();
+ case 1:
+ return m.getFormat();
+ case 2:
+ return m.getName();
+ default:
+ throw new IndexOutOfBoundsException();
+ }
+ }
+
+
+ public int getColumnWidth(int column) {
+ switch (column) {
+ case 0:
+ return 80;
+ case 1:
+ return 110;
+ case 2:
+ return -1;
+ default:
+ throw new IndexOutOfBoundsException();
+ }
+ }
+}
diff --git a/cmpcj/src/de/schwarzrot/control/table/PlayerDefinitionTableFormat.java b/cmpcj/src/de/schwarzrot/control/table/PlayerDefinitionTableFormat.java
new file mode 100644
index 0000000..cadc6d7
--- /dev/null
+++ b/cmpcj/src/de/schwarzrot/control/table/PlayerDefinitionTableFormat.java
@@ -0,0 +1,114 @@
+/**
+ * ======================== legal notice ======================
+ *
+ * File: PlayerDefinitionTableFormat.java
+ * Created: 13. June 2012, 04:57
+ * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a>
+ * 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.control.table;
+
+
+import ca.odell.glazedlists.gui.WritableTableFormat;
+import de.schwarzrot.base.util.ApplicationServiceProvider;
+import de.schwarzrot.base.util.MessageBundle;
+import de.schwarzrot.media.domain.PlayerDefinition;
+
+
+public class PlayerDefinitionTableFormat implements WritableTableFormat<PlayerDefinition> {
+ private static MessageBundle bundle;
+ protected static final String KEY_0 = PlayerDefinitionTableFormat.class.getSimpleName() + ".col0";
+ protected static final String KEY_1 = PlayerDefinitionTableFormat.class.getSimpleName() + ".col1";
+
+
+ @Override
+ public int getColumnCount() {
+ return 2;
+ }
+
+
+ @Override
+ public String getColumnName(int column) {
+ if (bundle == null)
+ bundle = ApplicationServiceProvider.getService(MessageBundle.class);
+
+ switch (column) {
+ case 0:
+ return bundle.getMessage(KEY_0);
+ case 1:
+ return bundle.getMessage(KEY_1);
+ default:
+ throw new IndexOutOfBoundsException();
+ }
+ }
+
+
+ @Override
+ public Object getColumnValue(PlayerDefinition pd, int column) {
+ switch (column) {
+ case 0:
+ return pd.getMediaType().name();
+ case 1:
+ return pd.getCommandLine();
+ default:
+ throw new IndexOutOfBoundsException();
+ }
+ }
+
+
+ public int getColumnWidth(int column) {
+ switch (column) {
+ case 0:
+ return 150;
+ case 1:
+ return -1;
+ default:
+ throw new IndexOutOfBoundsException();
+ }
+ }
+
+
+ @Override
+ public boolean isEditable(PlayerDefinition pd, int column) {
+ switch (column) {
+ case 0:
+ return false;
+ case 1:
+ return true;
+ default:
+ throw new IndexOutOfBoundsException();
+ }
+ }
+
+
+ @Override
+ public PlayerDefinition setColumnValue(PlayerDefinition pd, Object value, int column) {
+ switch (column) {
+ case 0:
+ break;
+ case 1:
+ pd.setCommandLine(value.toString());
+ break;
+ default:
+ throw new IndexOutOfBoundsException();
+ }
+ return pd;
+ }
+}
diff --git a/cmpcj/src/de/schwarzrot/control/table/ServerDefinitionTableFormat.java b/cmpcj/src/de/schwarzrot/control/table/ServerDefinitionTableFormat.java
new file mode 100644
index 0000000..2e4c630
--- /dev/null
+++ b/cmpcj/src/de/schwarzrot/control/table/ServerDefinitionTableFormat.java
@@ -0,0 +1,119 @@
+/**
+ * ======================== legal notice ======================
+ *
+ * File: ServerDefinitionTableFormat.java
+ * Created: 13. June 2012, 04:57
+ * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a>
+ * 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.control.table;
+
+
+import ca.odell.glazedlists.gui.WritableTableFormat;
+import de.schwarzrot.base.util.ApplicationServiceProvider;
+import de.schwarzrot.base.util.MessageBundle;
+import de.schwarzrot.media.domain.MediaServer;
+
+
+public class ServerDefinitionTableFormat implements WritableTableFormat<MediaServer> {
+ private static MessageBundle bundle;
+ protected static final String KEY_0 = ServerDefinitionTableFormat.class.getSimpleName() + ".col0";
+ protected static final String KEY_1 = ServerDefinitionTableFormat.class.getSimpleName() + ".col1";
+
+
+ @Override
+ public int getColumnCount() {
+ return 2;
+ }
+
+
+ @Override
+ public String getColumnName(int column) {
+ if (bundle == null)
+ bundle = ApplicationServiceProvider.getService(MessageBundle.class);
+
+ switch (column) {
+ case 0:
+ return bundle.getMessage(KEY_0);
+ case 1:
+ return bundle.getMessage(KEY_1);
+ default:
+ throw new IndexOutOfBoundsException();
+ }
+ }
+
+
+ @Override
+ public Object getColumnValue(MediaServer sd, int column) {
+ switch (column) {
+ case 0:
+ return sd.getHostName();
+ case 1:
+ return sd.getPort();
+ default:
+ throw new IndexOutOfBoundsException();
+ }
+ }
+
+
+ public int getColumnWidth(int column) {
+ switch (column) {
+ case 0:
+ return -1;
+ case 1:
+ return 80;
+ default:
+ throw new IndexOutOfBoundsException();
+ }
+ }
+
+
+ @Override
+ public boolean isEditable(MediaServer sd, int column) {
+ switch (column) {
+ case 0:
+ case 1:
+ return true;
+ default:
+ throw new IndexOutOfBoundsException();
+ }
+ }
+
+
+ @Override
+ public MediaServer setColumnValue(MediaServer sd, Object value, int column) {
+ switch (column) {
+ case 0:
+ sd.setHostName(value.toString());
+ break;
+
+ case 1:
+ try {
+ sd.setPort(Integer.decode(value.toString()));
+ } catch (Throwable t) {
+ }
+ break;
+
+ default:
+ throw new IndexOutOfBoundsException();
+ }
+ return sd;
+ }
+}