Merge pull request #119 from tmciver-basis/master

Changes to DataContentViewerMedia for thread issues
This commit is contained in:
adam 2012-12-20 11:27:55 -08:00
commit f5e6ec64f4
5 changed files with 114 additions and 329 deletions

View File

@ -52,6 +52,7 @@ public final class DataContentTopComponent extends TopComponent implements DataC
private boolean isDefault;
// Different DataContentViewers
private List<UpdateWrapper> viewers = new ArrayList<UpdateWrapper>();
// contains a list of the undocked TCs
private static ArrayList<DataContentTopComponent> newWindowList = new ArrayList<DataContentTopComponent>();
private static final String PREFERRED_ID = "DataContentTopComponent";
@ -291,13 +292,9 @@ public final class DataContentTopComponent extends TopComponent implements DataC
*/
public void setupTabs(Node selectedNode) {
int currTabIndex = dataContentTabbedPane.getSelectedIndex();
int totalTabs = dataContentTabbedPane.getTabCount();
int maxPreferred = 0;
int indexOfPreferred = 0;
if (totalTabs > 0) { // make sure there are tabs to reset
for (int i = 0; i < totalTabs; i++) {
for (int i = 0; i < totalTabs; ++i) {
UpdateWrapper dcv = viewers.get(i);
dcv.resetComponent();
@ -307,18 +304,10 @@ public final class DataContentTopComponent extends TopComponent implements DataC
dataContentTabbedPane.setEnabledAt(i, false);
} else {
dataContentTabbedPane.setEnabledAt(i, true);
int currentPreferred = dcv.isPreferred(selectedNode, dcvSupported);
if (currentPreferred > maxPreferred) {
indexOfPreferred = i;
maxPreferred = currentPreferred;
}
}
}
}
// set the display of the tab
dataContentTabbedPane.setSelectedIndex(indexOfPreferred);
viewers.get(indexOfPreferred).setNode(selectedNode);
}
viewers.get(currTabIndex).setNode(selectedNode);
}
/**

View File

@ -25,6 +25,7 @@ import java.util.concurrent.CancellationException;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.BoxLayout;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
@ -59,6 +60,7 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
private long durationMillis = 0;
private boolean autoTracking = false; // true if the slider is moving automatically
private final Object playbinLock = new Object(); // lock for synchronization of playbin2 player
private VideoProgressWorker videoProgressWorker;
/**
* Creates new form DataContentViewerVideo
@ -187,6 +189,12 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
return;
}
// get rid of any existing videoProgressWorker thread
if (videoProgressWorker != null) {
videoProgressWorker.cancel(true);
videoProgressWorker = null;
}
File file = selectedNode.getLookup().lookup(File.class);
if (file == null) {
return;
@ -303,15 +311,19 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
}
private void reset() {
// reset the progress label text on the event dispatch thread
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
progressLabel.setText(" ");
}
});
synchronized (playbinLock) {
if (playbin2 != null) {
if (playbin2.isPlaying()) {
playbin2.stop();
}
playbin2.setState(State.NULL);
// try {
// Thread.sleep(20); // gstreamer needs to catch up
// } catch (InterruptedException ex) { }
if (playbin2.getState().equals(State.NULL)) {
playbin2.dispose();
}
@ -397,8 +409,6 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
this.jFile = jFile;
}
;
@Override
protected Object doInBackground() throws Exception {
success = false;
@ -454,6 +464,9 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
duration = dur.toString();
durationMillis = dur.toMillis();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
progressSlider.setMaximum((int) durationMillis);
progressSlider.setMinimum(0);
final String finalDuration;
@ -468,48 +481,21 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
playbin2.play();
}
pauseButton.setText("||");
new Thread(new Runnable() {
videoProgressWorker = new VideoProgressWorker();
videoProgressWorker.execute();
}
});
}
}
private class VideoProgressWorker extends SwingWorker<Object, Object> {
private boolean isPlayBinReady() {
synchronized (playbinLock) {
return playbin2 != null && !playbin2.getState().equals(State.NULL);
}
}
@Override
public void run() {
long positionMillis = 0;
while (positionMillis < durationMillis
&& isPlayBinReady() ) {
ClockTime pos = null;
synchronized (playbinLock) {
pos = playbin2.queryPosition();
}
position = pos.toString();
positionMillis = pos.toMillis();
if (position.length() == 8) {
position = position.substring(3);
}
progressLabel.setText(position + "/" + finalDuration);
autoTracking = true;
progressSlider.setValue((int) positionMillis);
autoTracking = false;
try {
Thread.sleep(20);
} catch (InterruptedException ex) {
}
}
if (finalDuration.length() == 5) {
progressLabel.setText("00:00/" + finalDuration);
} else {
progressLabel.setText("00:00:00/" + finalDuration);
}
// If it reached the end
if (progressSlider.getValue() == progressSlider.getMaximum()) {
restartVideo();
}
}
public void restartVideo() {
synchronized (playbinLock) {
if (playbin2 != null) {
@ -520,7 +506,55 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
pauseButton.setText("");
progressSlider.setValue(0);
}
}).start();
@Override
protected Object doInBackground() throws Exception {
long positionMillis = 0;
String finalDuration = "";
while (positionMillis < durationMillis
&& isPlayBinReady() && !isCancelled()) {
ClockTime pos = null;
synchronized (playbinLock) {
pos = playbin2.queryPosition();
}
String position = pos.toString();
positionMillis = pos.toMillis();
if (position.length() == 8) {
position = position.substring(3);
}
String duration = playbin2.queryDuration().toString();
if (duration.length() == 8 && duration.substring(0, 3).equals("00:")) {
finalDuration = duration.substring(3);
progressLabel.setText("00:00/" + duration);
} else {
finalDuration = duration;
progressLabel.setText("00:00:00/" + duration);
}
progressLabel.setText(position + "/" + finalDuration);
autoTracking = true;
progressSlider.setValue((int) positionMillis);
autoTracking = false;
try {
Thread.sleep(20);
} catch (InterruptedException ex) {
throw ex;
}
}
if (finalDuration.length() == 5) {
progressLabel.setText("00:00/" + finalDuration);
} else {
progressLabel.setText("00:00:00/" + finalDuration);
}
// If it reached the end
if (progressSlider.getValue() == progressSlider.getMaximum()) {
restartVideo();
}
return null;
}
}
}

View File

@ -1,45 +0,0 @@
<?xml version="1.1" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="picViewerScrollPanel" alignment="0" pref="589" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="picViewerScrollPanel" alignment="0" pref="382" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="picViewerScrollPanel">
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JLabel" name="picLabel">
<Properties>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataContentViewerPicture.picLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="horizontalTextPosition" type="int" value="0"/>
</Properties>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Form>

View File

@ -1,193 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* 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.apache.org/licenses/LICENSE-2.0
*
* 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 org.sleuthkit.autopsy.corecomponents;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Image;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
import org.openide.nodes.Node;
import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.File;
import org.sleuthkit.datamodel.FsContent;
import org.sleuthkit.datamodel.TskException;
/**
* File content viewer capable of displaying some image formats.
*/
//@ServiceProvider(service = DataContentViewer.class)
public class DataContentViewerPicture extends javax.swing.JPanel implements DataContentViewer {
// for error handling
private JPanel caller;
private String className = this.getClass().toString();
/** Creates new form DataContentViewerPicture */
public DataContentViewerPicture() {
initComponents();
this.resetComponent();
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
picViewerScrollPanel = new javax.swing.JScrollPane();
picLabel = new javax.swing.JLabel();
picLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
picLabel.setText(org.openide.util.NbBundle.getMessage(DataContentViewerPicture.class, "DataContentViewerPicture.picLabel.text")); // NOI18N
picLabel.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
picViewerScrollPanel.setViewportView(picLabel);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(picViewerScrollPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 589, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(picViewerScrollPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 382, Short.MAX_VALUE)
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel picLabel;
private javax.swing.JScrollPane picViewerScrollPanel;
// End of variables declaration//GEN-END:variables
@Override
public void setNode(Node selectedNode) {
// change the cursor to "waiting cursor" for this operation
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
try {
if (selectedNode != null) {
try {
// read the byte of the image file
Content content = selectedNode.getLookup().lookup(Content.class);
byte[] dataSource = new byte[(int) content.getSize()];
int bytesRead = content.read(dataSource, 0, content.getSize());
// create the input stream for the content
if (bytesRead > 0) {
InputStream is = new ByteArrayInputStream(dataSource);
Image image = ImageIO.read(is); // create the image
if (image!= null)
this.picLabel.setIcon(new javax.swing.ImageIcon(image)); // show the file
}
} catch (TskException ex) {
// TODO: maybe make errors bubble
Logger.getLogger(this.className).log(Level.WARNING, "Error while trying to display the picture content.", ex);
} catch (Exception ex) {
Logger.getLogger(this.className).log(Level.WARNING, "Error while trying to display the picture content.", ex);
}
}
} finally {
this.setCursor(null);
}
}
@Override
public String getTitle() {
return "Picture View";
}
@Override
public String getToolTip() {
return "Displays supported image files.";
}
@Override
public DataContentViewer getInstance() {
return new DataContentViewerPicture();
}
@Override
public void resetComponent() {
this.picLabel.setText("");
//this.picLabel.setIcon(null);
}
@Override
public boolean isSupported(Node node) {
if (node != null) {
// Note: only supports JPG, GIF, and PNG for now
/*return node.getDisplayName().toLowerCase().endsWith(".jpg")
|| node.getDisplayName().toLowerCase().endsWith(".jpeg")
|| node.getDisplayName().toLowerCase().endsWith(".jpe")
|| node.getDisplayName().toLowerCase().endsWith(".jfif")
|| node.getDisplayName().toLowerCase().endsWith(".gif")
|| node.getDisplayName().toLowerCase().endsWith(".bmp")
|| //node.getDisplayName().toLowerCase().endsWith(".tif") ||
//node.getDisplayName().toLowerCase().endsWith(".tiff") ||
//node.getDisplayName().toLowerCase().endsWith(".tga") ||
node.getDisplayName().toLowerCase().endsWith(".png");*/
File file = node.getLookup().lookup(File.class);
if (file != null) {
return file.getSize() > 0
&& (file.getName().toLowerCase().endsWith(".jpg")
|| file.getName().toLowerCase().endsWith(".jpeg")
|| file.getName().toLowerCase().endsWith(".jpe")
|| file.getName().toLowerCase().endsWith(".jfif")
|| file.getName().toLowerCase().endsWith(".gif")
|| file.getName().toLowerCase().endsWith(".bmp")
|| //node.getName().toLowerCase().endsWith(".tif") ||
//node.getName().toLowerCase().endsWith(".tiff") ||
//node.getName().toLowerCase().endsWith(".tga") ||
file.getName().toLowerCase().endsWith(".png"));
} else {
return false;
}
} else {
return false;
}
}
@Override
public int isPreferred(Node node, boolean isSupported) {
if(isSupported) {
return 1;
} else {
return 0;
}
}
@Override
public Component getComponent() {
return this;
}
}

View File

@ -482,7 +482,7 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
@Override
public int isPreferred(Node node, boolean isSupported) {
if(node != null && isSupported){
return 2;
return 1;
} else {
return 0;
}