/*
* Copyright 2004-2010 Information & Software Engineering Group (188/1)
* Institute of Software Technology and Interactive Systems
* Vienna University of Technology, Austria
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.ifs.tuwien.ac.at/dm/somtoolbox/license.html
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package at.tuwien.ifs.somtoolbox.apps.viewer.controls.player;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import org.jdesktop.swingx.JXBusyLabel;
import cern.colt.matrix.DoubleMatrix1D;
import edu.umd.cs.piccolo.nodes.PPath;
import at.tuwien.ifs.commons.gui.controls.TitledCollapsiblePanel;
import at.tuwien.ifs.somtoolbox.SOMToolboxException;
import at.tuwien.ifs.somtoolbox.apps.viewer.CommonSOMViewerStateData;
import at.tuwien.ifs.somtoolbox.apps.viewer.GeneralUnitPNode;
import at.tuwien.ifs.somtoolbox.apps.viewer.MapPNode;
import at.tuwien.ifs.somtoolbox.apps.viewer.RhythmPattern;
import at.tuwien.ifs.somtoolbox.apps.viewer.RhythmPatternsVisWindow;
import at.tuwien.ifs.somtoolbox.apps.viewer.SOMViewer;
import at.tuwien.ifs.somtoolbox.apps.viewer.controls.AbstractSelectionPanel;
import at.tuwien.ifs.somtoolbox.apps.viewer.controls.AbstractViewerControl;
import at.tuwien.ifs.somtoolbox.apps.viewer.controls.PlaySOMPanel;
import at.tuwien.ifs.somtoolbox.data.DataDimensionException;
import at.tuwien.ifs.somtoolbox.data.InputData;
import at.tuwien.ifs.somtoolbox.data.InputDatum;
import at.tuwien.ifs.somtoolbox.data.SOMVisualisationData;
import at.tuwien.ifs.somtoolbox.data.metadata.AbstractVectorMetaData;
import at.tuwien.ifs.somtoolbox.data.metadata.AudioVectorMetaData;
import at.tuwien.ifs.somtoolbox.layers.Unit;
import at.tuwien.ifs.somtoolbox.summarisation.SummariserGUI;
import at.tuwien.ifs.somtoolbox.util.GridBagConstraintsIFS;
/**
* @author Jakob Frank
* @version $Id: PlaySOMPlayer.java 3752 2010-08-10 15:37:18Z frank $
*/
public class PlaySOMPlayer extends AbstractSelectionPanel implements PlayerListener {
/**
* @author Jakbo Frank
* @version $Id: PlaySOMPlayer.java 3752 2010-08-10 15:37:18Z frank $
*/
private final class SearchThread extends Thread {
/**
*
*/
private final String q;
private boolean isCancelled;
/**
* @param q The search string
*/
private SearchThread(String q) {
this.q = q;
this.isCancelled = false;
}
public void cancel() {
isCancelled = true;
}
@Override
public void run() {
btnSearch.setText("Cancel");
txtSearch.setEditable(false);
lblFindBusy.setBusy(true);
lblFindBusy.setVisible(true);
lblFindLabel.setText("Searching...");
setName("SearchThread (\"" + q + "\")");
state.mapPNode.clearHistogramOverlayVisualization();
if (searchList == null) {
// init searchList
searchList = new LinkedList<AbstractVectorMetaData>();
String[] dNames = state.growingLayer.getAllMappedDataNames();
for (String name : dNames) {
searchList.add(AbstractVectorMetaData.createMetaData(name));
if (isCancelled) {
searchList = null;
return;
}
}
}
// System.err.println("Searching for \"" + q + "\"");
clearList();
hitHist = new int[state.growingLayer.getXSize()][state.growingLayer.getYSize()];
for (int x = 0; x < hitHist.length; x++) {
for (int y = 0; y < hitHist[x].length; y++) {
hitHist[x][y] = 0;
if (isCancelled) {
return;
}
}
}
int c = 0;
for (AbstractVectorMetaData vec : searchList) {
// try {
// Thread.sleep(25);
// } catch (InterruptedException e) {
// }
if (vec.matches(q)) {
Unit u = state.growingLayer.getUnitForDatum(vec.getID());
hitHist[u.getXPos()][u.getYPos()] = 1;
addToList(vec.getID(), u);
playList.addSong(vec.getID());
c++;
if (isCancelled) {
break;
}
}
}
btnSearch.setText("Find");
txtSearch.setEditable(true);
chkShowHH.setEnabled(true);
lblFindBusy.setBusy(false);
lblFindBusy.setVisible(false);
lblFindLabel.setText(c + " items found.");
}
}
private static final long serialVersionUID = 1L;
private static final Color CIRCLE_COLOR = Color.BLUE;
private static final int CIRCLE_STROKE_WIDTH = 15;
private static final float CIRCLE_TRANSPARENCY = .4f;
public static final String TITLE = "PlaySOMPlayer";
/**
* 0 == none, 1 == highlight, 2 == circle;
*/
public static final int DEFAULT_PLAYING_MARKER = 2;
private int playing_marker = DEFAULT_PLAYING_MARKER;
private PlayList playList;
private PPath circle;
// private Hashtable<File, double[]> filePos;
private Hashtable<File, GeneralUnitPNode> nodePos;
private JTextField txtSearch;
private JButton btnSearch;
private Vector<GeneralUnitPNode> foundUnits = null;
private GeneralUnitPNode playingNode;
private JLabel lblFindLabel;
private static Logger log = Logger.getLogger("at.tuwien.ifs.somtoolbox.apps.viewer.controls.player.PlaySOMPlayer");
// private JList lstPlayList;
public PlaySOMPlayer(CommonSOMViewerStateData state) {
super(new BorderLayout(), state, TITLE);
// filePos = new Hashtable<File, double[]>();
nodePos = new Hashtable<File, GeneralUnitPNode>();
circle = createCircle();
state.mapPNode.addChild(circle);
// circle.repaint();
// init gui
initialize();
// this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
}
private PPath createCircle() {
MapPNode mp = state.mapPNode;
PPath c = PPath.createEllipse(0, 0, mp.getUnitWidth(), mp.getUnitHeight());
c.setPickable(false);
c.setStrokePaint(CIRCLE_COLOR);
c.setStroke(new BasicStroke(CIRCLE_STROKE_WIDTH));
c.setTransparency(CIRCLE_TRANSPARENCY);
c.setVisible(false);
return c;
}
@Override
synchronized public void clearList() {
super.clearList();
playList.clearPlaylist();
}
synchronized public List<String> getPlayList() {
return playList.getDataItems();
}
synchronized public void startPlaying() {
playList.play();
}
synchronized public void startPlaying(String dataItem) {
playList.play(playList.getIndexOf(dataItem));
}
synchronized public void stopPlaying() {
playList.stop();
}
synchronized public void skipPlayer(int count) {
playList.skip(count);
}
private void initialize() {
JPanel main = new JPanel();
main.setLayout(new GridBagLayout());
GridBagConstraints gc = new GridBagConstraints();
gc.gridx = 0;
gc.gridy = 0;
gc.gridwidth = GridBagConstraints.REMAINDER;
gc.weightx = 2;
gc.fill = GridBagConstraints.BOTH;
this.setContentPane(main);
playList = new PlayList();
playList.addPlayerListener(this);
JList liste = playList.createMatchingJList(true);
JScrollPane scpPlayList = new JScrollPane(liste);
/*
* Would be nice to display the current Rhythm-Patterns Matrix while playing. Wouldn't it?
*/
// Rhythm pattern
final JPanel visPanel = createVisualisationPanel(liste);
playList.addPlayerListener(new PlayerListener() {
@Override
public void playStarted(int mode, AudioVectorMetaData song) {
visPanel.repaint();
}
@Override
public void playStopped(int reason, AudioVectorMetaData song) {
visPanel.repaint();
}
});
final TitledCollapsiblePanel vP = new TitledCollapsiblePanel("Rhythm Pattern", new BorderLayout());
vP.setCollapsed(true);
vP.setContentBorder(BorderFactory.createEmptyBorder());
vP.add(visPanel, BorderLayout.CENTER);
main.add(vP, gc);
gc.gridy += 1;
PlayerControl pc = new PlayerControl(playList);
TitledCollapsiblePanel pP = new TitledCollapsiblePanel("Player", new BorderLayout());
pP.add(pc, BorderLayout.CENTER);
main.add(pP, gc);
gc.gridy += 1;
gc.weighty = 1;
main.add(scpPlayList, gc);
gc.weighty = 0;
gc.gridy += 1;
/* Core-Functionality done, now some extras */
// Search
gc.insets.top = 2;
main.add(createSearchPanel(), gc);
// // RhythmPattern
// gc.gridy += 1;
// gc.gridwidth = 1;
// gc.insets.top = 0;
// main.add(createRhythmPatternButton(liste), gc);
//
// // Export Playlist
// gc.gridx += 1;
// main.add(createExportPlaylistButton(liste), gc);
gc.gridx = 0;
gc.gridwidth = 2;
gc.gridy++;
main.add(createExtraFuncPanel(liste), gc);
// this.pack();
this.setVisible(true);
}
private JPanel createExtraFuncPanel(JList liste) {
TitledCollapsiblePanel extra = new TitledCollapsiblePanel("Extras", new GridBagLayout());
GridBagConstraintsIFS gc = new GridBagConstraintsIFS(GridBagConstraints.CENTER, 0);
extra.setCollapsed(true);
// RhythmPattern
extra.add(createRhythmPatternButton(liste), gc);
// Export Playlist
extra.add(createExportPlaylistButton(liste), gc.nextCol());
// Summarise button - new Code from Julius Penaranda
JButton buttonSummarise = new JButton("Summarise");
buttonSummarise.setMargin(SMALL_INSETS);
buttonSummarise.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// require input vector file
if (state.inputDataObjects.getInputData() == null) { // not loaded
SOMVisualisationData inputObject = state.inputDataObjects.getObject(SOMVisualisationData.INPUT_VECTOR);
try { // try to load it
inputObject.loadFromFile(state.fileChooser, state.parentFrame);
} catch (SOMToolboxException exception) {
Logger.getLogger("at.tuwien.ifs.somtoolbox").severe(exception.getMessage());
}
if (state.inputDataObjects.getInputData() == null) { // not loaded
Logger.getLogger("at.tuwien.ifs.somtoolbox").severe(
"Input vector file needed for summarisation!");
return;
}
}
Object[] items;
if (PlaySOMPlayer.this.playlists[0].isSelectionEmpty()) {
items = new Object[PlaySOMPlayer.this.playlists[0].getModel().getSize()];
for (int i = 0; i < PlaySOMPlayer.this.playlists[0].getModel().getSize(); i++) {
items[i] = PlaySOMPlayer.this.playlists[0].getModel().getElementAt(i);
}
} else {
items = PlaySOMPlayer.this.playlists[0].getSelectedValues();
}
JFrame parent = (SOMViewer) PlaySOMPlayer.this.getParent().getParent().getParent().getParent().getParent().getParent();
new SummariserGUI(parent, state, items);
}
});
extra.add(buttonSummarise, gc.nextRow());
// END: Summarise
// BEGIN: Andreas Senfter: add evalPanel Button
JButton btEvalSOM = new JButton("Acoustic Evaluation");
btEvalSOM.setMargin(SMALL_INSETS);
btEvalSOM.addActionListener(new ActionListener() {
private AbstractViewerControl evalPanel = null;
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
try {
@SuppressWarnings("unchecked")
Class<? extends AbstractViewerControl> c = (Class<? extends AbstractViewerControl>) Class.forName("at.tuwien.ifs.somtoolbox.apps.viewer.controls.EvalSOMPanel");
if (evalPanel == null) {
Constructor<? extends AbstractViewerControl> constr = c.getConstructor(
CommonSOMViewerStateData.class, PlaySOMPanel.class);
// evalPanel = new EvalSOMPanel(state, this);
evalPanel = constr.newInstance(new Object[] { state, this });
// PlaySOMPlayer.super.getDesktopPane().add(evalPanel);
}
if (evalPanel != null) {
evalPanel.setVisible(true);
evalPanel.setSelected(true);
}
} catch (InvocationTargetException e2) {
e2.getCause().printStackTrace();
} catch (Exception e2) {
}
}
});
extra.add(btEvalSOM, gc.nextCol());
// END: Andreas Senfter
return extra;
}
private JButton createExportPlaylistButton(final JList liste) {
JButton b = new JButton("Export Playlist");
b.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JFileChooser fc = state.fileChooser;
if (fc.showSaveDialog(PlaySOMPlayer.this) != JFileChooser.APPROVE_OPTION) {
// Canceled
return;
}
File f = fc.getSelectedFile();
if (!f.getName().endsWith(".m3u")) {
f = new File(f.getParentFile(), f.getName() + ".m3u");
}
try {
PrintStream ps = new PrintStream(f);
// Header
ps.println("#EXTM3U");
Iterator<File> iF = playList.getSongs().iterator();
Iterator<String> iD = playList.getDataItems().iterator();
while (iF.hasNext() && iD.hasNext()) {
File song = iF.next();
String title = iD.next();
ps.printf("%n#EXTINF:-1,%s%n%s%n", title, song);
}
ps.close();
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
b.setMargin(SMALL_INSETS);
return b;
}
private JButton createRhythmPatternButton(final JList liste) {
JButton b = new JButton();
b.setText("Show RP");
b.setToolTipText("Show the Rhythm Pattern of the current song.");
b.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int selectedIndices[] = liste.getSelectedIndices();
if (selectedIndices.length == 0) {
String label;
Unit unit;
Collection<GeneralUnitPNode> c = nodePos.values();
List<Unit> tmp = new ArrayList<Unit>();
for (GeneralUnitPNode node : c) {
unit = node.getUnit();
if (!tmp.contains(unit)) {
tmp.add(unit);
label = "Weight vector of map unit (" + unit.getXPos() + "/" + unit.getYPos() + ")";
showRhythmPattern(unit.getWeightVector(), label);
}
}
} else {
ArrayList<String> vecNames;
vecNames = new ArrayList<String>();
for (int selectedIndice : selectedIndices) {
try {
// vecNames[i] = (String) this.playlists[0].getModel().getElementAt(selectedIndices[i]);
vecNames.add(playList.getPlayListItem(selectedIndice).getID());
// System.out.println(selectedIndices[i]+ ": " + vecNames[i]);
} catch (NullPointerException npe) {
// This happens sometimes with an empty playlist. No need to worry!
}
}
showRhythmPattern(vecNames.toArray(new String[] {}));
}
}
});
b.setMargin(SMALL_INSETS);
return b;
}
private JPanel createVisualisationPanel(JList list) {
JPanel rpVis = new JPanel();
// JPanel visualisation = new JPanel();
rpVis.setLayout(new GridBagLayout());
rpVis.setBackground(Color.black);
rpVis.setBorder(BorderFactory.createLineBorder(Color.black, 2));
JPanel draw = new JPanel() {
private static final long serialVersionUID = 1L;
@Override
protected void paintComponent(Graphics g) {
g.setColor(Color.black);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
try {
String di = playList.getPlayListItem(playList.getCurrentSongIndex()).getID();
if (di.equals("")) {
return;
}
;
InputData iv = state.inputDataObjects.getInputData();
InputDatum id = iv.getInputDatum(di);
RhythmPattern rp = new RhythmPattern(id.getVector().toArray(), iv.getFeatureMatrixColumns(),
iv.getFeatureMatrixRows());
rp.bx = 3;
rp.by = 3;
rp.paint(g);
} catch (DataDimensionException e) {
log.info(e.getMessage());
// e.printStackTrace();
} catch (Exception e) {
// No song playing right now. TODO: Handle this issue better.
}
// super.paintComponent(g);
}
};
// draw.setMinimumSize(new Dimension(60 * 3, 24 * 3));
// draw.setPreferredSize(new Dimension(60 * 3, 24 * 3));
GridBagConstraints gc = new GridBagConstraints();
gc.fill = GridBagConstraints.BOTH;
rpVis.add(draw, gc);
return rpVis;
}
/**
* show RhythmPattern(s) of selected vector(s)
*/
public void showRhythmPattern(String[] vecNames) {
if (vecNames == null) {
return;
}
if (vecNames.length == 0) {
return;
}
String dispname; // name for pattern to display in window
// String content_subtype;
DoubleMatrix1D vec = null;
InputDatum iv = null;
InputData inputVectors = state.inputDataObjects.getInputData();
if (inputVectors == null) {
Logger.getLogger("at.tuwien.ifs.somtoolbox").severe(
"Input vectors not found! Please load input vector file first!");
return;
}
// by omitting this, RP vis is also possible for non-RP data
// if (!inputVectors.getContentType().equals("audio")) {
// Logger.getLogger("at.tuwien.ifs.somtoolbox").severe("Content type of input vectors is not 'audio'!");
// return;
// }
//
// content_subtype = inputVectors.getContentSubType();
// if (!content_subtype.startsWith("rp")) {
// Logger.getLogger("at.tuwien.ifs.somtoolbox").severe("Content subtype of input vectors is not 'rp'!");
// return;
// }
int xdim = inputVectors.getFeatureMatrixColumns();
int ydim = inputVectors.getFeatureMatrixRows();
if (xdim == -1 || ydim == -1) {
Logger.getLogger("at.tuwien.ifs.somtoolbox").warning(
"Could not get dimensions of Rhythm Patterns!" + " - Defaulting to 24x60 Rhythm Pattern.");
xdim = 60;
ydim = 24;
}
if (vecNames.length == 1) {// show single Rhythm Pattern
if (vecNames[0] == null) {
return;
}
iv = inputVectors.getInputDatum(vecNames[0]);
if (iv == null) {
Logger.getLogger("at.tuwien.ifs.somtoolbox").severe(
"Could not get input vector data for " + vecNames[0]);
return;
}
vec = iv.getVector();
dispname = vecNames[0];
} else { // compute average of multiple vectors
vec = inputVectors.getMeanVector(vecNames);
dispname = Integer.toString(vecNames.length) + " selected vectors";
}
if (vec == null) {
Logger.getLogger("at.tuwien.ifs.somtoolbox").severe(
"Could not get (mean) input vector data for selected vectors!");
return;
}
RhythmPatternsVisWindow rpwin;
try {
rpwin = new RhythmPatternsVisWindow(state.parentFrame, vec, xdim, ydim, dispname);
rpwin.pack();
rpwin.setLocation(300, 100);
rpwin.setVisible(true);
} catch (DataDimensionException e) {
Logger.getLogger("at.tuwien.ifs.somtoolbox").severe(e.getMessage());
}
}
/**
* show RhythmPattern(s) of weight vector(s) of currently selected unit(s)
*/
public void showRhythmPattern(double[] vector, String dispname) {
// TODO solve this: xdim and ydim again have to be guessed without inputvector file or $DATA_TYPE
InputData inputVectors = state.inputDataObjects.getInputData();
int xdim = -1;
int ydim = -1;
if (inputVectors == null) {
Logger.getLogger("at.tuwien.ifs.somtoolbox").warning(
"Input vectors not found! Please load input vector file first!");
} else {
xdim = inputVectors.getFeatureMatrixColumns();
ydim = inputVectors.getFeatureMatrixRows();
}
if (xdim == -1 || ydim == -1) {
Logger.getLogger("at.tuwien.ifs.somtoolbox").warning(
"Could not get dimensions of Rhythm Patterns!" + " - Defaulting to 24x60 Rhythm Pattern.");
xdim = 60;
ydim = 24;
}
RhythmPatternsVisWindow rpwin;
try {
rpwin = new RhythmPatternsVisWindow(state.parentFrame, vector, xdim, ydim, dispname);
rpwin.pack();
rpwin.setLocation(300, 100);
rpwin.setVisible(true);
} catch (DataDimensionException e) {
Logger.getLogger("at.tuwien.ifs.somtoolbox").severe(e.getMessage());
}
}
private JPanel createSearchPanel() {
TitledCollapsiblePanel search = new TitledCollapsiblePanel("Search/Find");
search.setLayout(new GridBagLayout());
GridBagConstraints l = new GridBagConstraints();
GridBagConstraints t = new GridBagConstraints();
GridBagConstraints b = new GridBagConstraints();
l.gridx = 0;
l.gridy = 0;
l.weightx = 0;
l.anchor = GridBagConstraints.EAST;
l.insets.right = 2;
t.fill = GridBagConstraints.BOTH;
t.gridx = 1;
t.gridy = 0;
t.weightx = 1;
b.gridx = 2;
b.gridy = 0;
b.gridwidth = GridBagConstraints.REMAINDER;
b.weightx = 0;
txtSearch = new JTextField();
txtSearch.setToolTipText("Search for items, using (java) regular expressions");
final String SEARCH_BUTTON_TEXT = "Find";
btnSearch = new JButton(SEARCH_BUTTON_TEXT);
btnSearch.setMargin(SMALL_INSETS);
lblFindBusy = new JXBusyLabel(new Dimension(12, 12));
lblFindBusy.setVisible(false);
lblFindLabel = new JLabel("");
// TODO: Use BusyButton
chkShowHH = new JCheckBox("Show ResultHistogram");
chkShowHH.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (chkShowHH.isSelected()) {
state.mapPNode.showHistogramOverlayVisualization(hitHist, 0);
} else {
state.mapPNode.clearHistogramOverlayVisualization();
}
}
});
chkShowHH.setEnabled(false);
JLabel find = new JLabel("Find:");
find.setLabelFor(txtSearch);
search.add(find, l);
search.add(txtSearch, t);
search.add(btnSearch, b);
JPanel p = new JPanel();
p.setLayout(new FlowLayout(FlowLayout.CENTER, 2, 0));
GridBagConstraints x = new GridBagConstraints();
x.gridx = 0;
x.gridwidth = 3;
x.gridx = GridBagConstraints.REMAINDER;
p.add(lblFindBusy);
p.add(lblFindLabel);
search.add(p, x);
search.add(chkShowHH, x);
ActionListener searchAC = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (searchThread != null && searchThread.isAlive()) {
searchThread.cancel();
} else {
searchThread = new SearchThread(txtSearch.getText().trim());
searchThread.start();
}
}
};
txtSearch.addActionListener(searchAC);
btnSearch.addActionListener(searchAC);
return search;
}
private List<AbstractVectorMetaData> searchList = null;
private JXBusyLabel lblFindBusy;
int[][] hitHist = new int[state.growingLayer.getXSize()][state.growingLayer.getYSize()];
private JCheckBox chkShowHH;
private SearchThread searchThread = null;
@SuppressWarnings("unused")
private void oldSearchFor(String query) {
if (foundUnits != null) {
for (GeneralUnitPNode u : foundUnits) {
u.removeQueryHit();
}
}
foundUnits = null;
if (query == "") {
// empty search, disable
playing_marker = DEFAULT_PLAYING_MARKER;
return;
} else {
playing_marker = 2;
}
Pattern searchPattern;
try {
searchPattern = Pattern.compile(query);
} catch (PatternSyntaxException pse) {
Logger.getLogger("PlaySOMPlayer").warning("Could not compile search string: \"" + query + "\"");
return;
}
Unit[] units = state.growingLayer.getAllUnits();
foundUnits = new Vector<GeneralUnitPNode>();
for (Unit unit : units) {
String[] data = unit.getMappedInputNames();
if (data == null) {
continue;
}
boolean firstHitOnThisUnit = true;
for (String element : data) {
Matcher m = searchPattern.matcher(element);
if (m.matches()) {
System.out.println("Found " + element);
if (firstHitOnThisUnit) {
GeneralUnitPNode gup = state.mapPNode.getUnit(unit);
foundUnits.add(gup);
gup.setQueryHit();
// firstHitOnThisUnit = false;
}
addToList(element, unit);
}
}
}
}
/* (non-Javadoc)
* @see at.tuwien.ifs.somtoolbox.apps.viewer.controls.AbstractSelectionPanel#addToList(java.lang.String, at.tuwien.ifs.somtoolbox.layers.Unit)
*/
@Override
public void addToList(String elementName, Unit u) {
addToList(elementName, CommonSOMViewerStateData.fileNamePrefix, u);
}
@Override
public void addToList(String elementName, String fileNamePrefix, Unit u) {
super.addToList(elementName, fileNamePrefix, u);
File candidate = new File(fileNamePrefix, elementName);
if (candidate.exists()) {
playList.addSong(elementName, candidate);
nodePos.put(candidate, state.mapPNode.getUnit(u));
}
}
@Override
public void unitSelectionChanged(Object[] selection, boolean newSelection) {
// super.unitSelectionChanged(selection, newSelection);
// System.out.println("SELECT: " + selection.length + " (" + newSelection + ")");
// newUnit++;
playList.clearPlaylist();
// unitsInPlaylist.clear();
new Thread() {
@Override
public void run() {
setName("PlayerStopper");
playList.stop();
}
}.start();
Vector<Unit> list2 = new Vector<Unit>();
for (Object element : selection) {
if (element instanceof GeneralUnitPNode) {
GeneralUnitPNode node = (GeneralUnitPNode) element;
list2.add(node.getUnit());
if (!unitsInPlaylist.contains(node.getUnit())) {
unitsInPlaylist.add(node.getUnit());
}
String[] items = node.getMappedDataNames();
if (items != null) {
for (String item : items) {
// for (int j = 0; j < 1; j++) {
File song = new File(CommonSOMViewerStateData.fileNamePrefix + item
+ CommonSOMViewerStateData.fileNameSuffix);
playList.addSong(item, song);
// filePos.put(song, new double[] {node.getX(), node.getY()});
nodePos.put(song, node);
}
}
}
}
unitsInPlaylist.retainAll(list2);
}
@Override
public void playStarted(int mode, AudioVectorMetaData song) {
playingNode = nodePos.get(song.getAudioFile());
// System.out.println("Moving circle to " + node.getX() + "/" + node.getY());
if (playingNode == null) {
return;
}
switch (playing_marker) {
case 0:
break;
case 1:
playingNode.setSelected(true);
break;
case 2:
double x = playingNode.getX();// - (CIRCLE_STROKE_WIDTH / 2);
double y = playingNode.getY();// - (CIRCLE_STROKE_WIDTH / 2);
// if (circle.getVisible()) {
circle.setVisible(true);
circle.animateToPositionScaleRotation(x, y, 1, 0, 750);
// } else {
// circle.setX(x);
// circle.setY(y);
// }
state.mapPNode.repaint();
break;
}
}
@Override
public void playStopped(int reason, AudioVectorMetaData song) {
// System.out.println("Hiding circle");
if (playingNode != null) {
if (playing_marker == 1) {
playingNode.setSelected(false);
}
}
circle.setVisible(false);
state.mapPNode.repaint();
}
@Override
public Dimension getMinimumSize() {
return new Dimension(state.controlElementsWidth, 350);
}
public String getCurrentSongID() {
try {
return playList.getPlayListItem(playList.getCurrentSongIndex()).getID();
} catch (Exception e) {
return "";
}
}
public AudioVectorMetaData getCurrentSong() {
try {
return playList.getPlayListItem(playList.getCurrentSongIndex());
} catch (Exception e) {
return null;
}
}
public double[] getCurrentPos() {
try {
double x, y;
x = playingNode.getX() / state.mapPNode.getWidth() + playingNode.getWidth();
y = playingNode.getY() / state.mapPNode.getHeight() + playingNode.getHeight();
return new double[] { x, y };
} catch (Exception e) {
return new double[] { 0.0, 0.0 };
}
}
public void addPlayerListener(PlayerListener l) {
playList.addPlayerListener(l);
}
public void removePlayerListener(PlayerListener l) {
playList.removePlayerListener(l);
}
public void addPlayListListener(PlayListListener pll) {
playList.addPlayListListener(pll);
}
public void removePlayListListener(PlayListListener pll) {
playList.removePlayListListener(pll);
}
public boolean isPlaying() {
return playList.isPlaying();
}
}