diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentTopComponent.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentTopComponent.java index 721928e257..49f9bc86f2 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentTopComponent.java @@ -52,6 +52,7 @@ public final class DataContentTopComponent extends TopComponent implements DataC private boolean isDefault; // Different DataContentViewers private List viewers = new ArrayList(); + // contains a list of the undocked TCs private static ArrayList newWindowList = new ArrayList(); private static final String PREFERRED_ID = "DataContentTopComponent"; @@ -291,34 +292,22 @@ 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; + for (int i = 0; i < totalTabs; ++i) { + UpdateWrapper dcv = viewers.get(i); + dcv.resetComponent(); - if (totalTabs > 0) { // make sure there are tabs to reset - for (int i = 0; i < totalTabs; i++) { - UpdateWrapper dcv = viewers.get(i); - dcv.resetComponent(); - - // disable an unsupported tab (ex: picture viewer) - boolean dcvSupported = dcv.isSupported(selectedNode); - if (! dcvSupported) { - dataContentTabbedPane.setEnabledAt(i, false); - } else { - dataContentTabbedPane.setEnabledAt(i, true); - int currentPreferred = dcv.isPreferred(selectedNode, dcvSupported); - if (currentPreferred > maxPreferred) { - indexOfPreferred = i; - maxPreferred = currentPreferred; - } - - } + // disable an unsupported tab (ex: picture viewer) + boolean dcvSupported = dcv.isSupported(selectedNode); + if (!dcvSupported) { + dataContentTabbedPane.setEnabledAt(i, false); + } else { + dataContentTabbedPane.setEnabledAt(i, true); } - // set the display of the tab - dataContentTabbedPane.setSelectedIndex(indexOfPreferred); - viewers.get(indexOfPreferred).setNode(selectedNode); } + + viewers.get(currTabIndex).setNode(selectedNode); } /** diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java index ea0a2c03a0..2857368f12 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java @@ -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 @@ -186,6 +188,12 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo if (selectedNode == null) { 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) { @@ -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; @@ -444,7 +454,7 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo progressLabel.setText("Error buffering file"); return; } - ClockTime dur = null; + ClockTime dur = null; synchronized (playbinLock) { playbin2.play(); // must play, then pause and get state to get duration. playbin2.pause(); @@ -454,73 +464,97 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo duration = dur.toString(); durationMillis = dur.toMillis(); - progressSlider.setMaximum((int) durationMillis); - progressSlider.setMinimum(0); - final String finalDuration; - 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); - } - synchronized (playbinLock) { - playbin2.play(); - } - pauseButton.setText("||"); - new Thread(new Runnable() { - private boolean isPlayBinReady() { - synchronized (playbinLock) { - return playbin2 != null && !playbin2.getState().equals(State.NULL); - } - } - + SwingUtilities.invokeLater(new Runnable() { @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); + progressSlider.setMaximum((int) durationMillis); + progressSlider.setMinimum(0); + final String finalDuration; + if (duration.length() == 8 && duration.substring(0, 3).equals("00:")) { + finalDuration = duration.substring(3); + progressLabel.setText("00:00/" + duration); } else { - progressLabel.setText("00:00:00/" + finalDuration); + finalDuration = duration; + progressLabel.setText("00:00:00/" + duration); } - // If it reached the end - if (progressSlider.getValue() == progressSlider.getMaximum()) { - restartVideo(); - } - } - - public void restartVideo() { synchronized (playbinLock) { - if (playbin2 != null) { - playbin2.stop(); - playbin2.setState(State.READY); // ready to be played again - } + playbin2.play(); } - pauseButton.setText("►"); - progressSlider.setValue(0); + pauseButton.setText("||"); + videoProgressWorker = new VideoProgressWorker(); + videoProgressWorker.execute(); } - }).start(); + }); + } + } + + private class VideoProgressWorker extends SwingWorker { + + private boolean isPlayBinReady() { + synchronized (playbinLock) { + return playbin2 != null && !playbin2.getState().equals(State.NULL); + } + } + + public void restartVideo() { + synchronized (playbinLock) { + if (playbin2 != null) { + playbin2.stop(); + playbin2.setState(State.READY); // ready to be played again + } + } + pauseButton.setText("►"); + progressSlider.setValue(0); + } + + @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; } } } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerPicture.form b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerPicture.form deleted file mode 100644 index 43f9a88aea..0000000000 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerPicture.form +++ /dev/null @@ -1,45 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerPicture.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerPicture.java deleted file mode 100644 index 5d1491b6fc..0000000000 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerPicture.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2011 Basis Technology Corp. - * Contact: carrier sleuthkit 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") - // //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) - ); - }// //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; - } -} diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerString.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerString.java index dcfd151efa..aea4116a0d 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerString.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerString.java @@ -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; }