Autopsy  3.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
FXVideoPanel.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2013 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.corecomponents;
20 
21 import java.awt.Dimension;
22 import java.io.IOException;
23 import java.nio.file.Paths;
24 import java.util.Arrays;
25 import java.util.List;
26 import java.util.concurrent.CancellationException;
27 import java.util.logging.Level;
28 import javafx.application.Platform;
29 import javafx.beans.InvalidationListener;
30 import javafx.beans.Observable;
31 import javafx.beans.value.ChangeListener;
32 import javafx.beans.value.ObservableValue;
33 import javafx.embed.swing.JFXPanel;
34 import javafx.event.ActionEvent;
35 import javafx.event.EventHandler;
36 import javafx.geometry.Insets;
37 import javafx.geometry.Pos;
38 import javafx.scene.Scene;
39 import javafx.scene.control.Button;
40 import javafx.scene.control.Label;
41 import javafx.scene.control.Slider;
42 import javafx.scene.control.Tooltip;
43 import javafx.scene.layout.BorderPane;
44 import javafx.scene.layout.HBox;
45 import javafx.scene.layout.Priority;
46 import javafx.scene.layout.VBox;
47 import javafx.scene.media.Media;
48 import javafx.scene.media.MediaException;
49 import javafx.scene.media.MediaPlayer;
50 import javafx.scene.media.MediaPlayer.Status;
51 import static javafx.scene.media.MediaPlayer.Status.PAUSED;
52 import static javafx.scene.media.MediaPlayer.Status.PLAYING;
53 import static javafx.scene.media.MediaPlayer.Status.READY;
54 import static javafx.scene.media.MediaPlayer.Status.STOPPED;
55 import javafx.scene.media.MediaView;
56 import javafx.util.Duration;
57 import javax.swing.JPanel;
58 import javax.swing.SwingUtilities;
59 import javax.swing.SwingWorker;
60 import org.netbeans.api.progress.ProgressHandle;
61 import org.netbeans.api.progress.ProgressHandleFactory;
62 import org.openide.util.Cancellable;
63 import org.openide.util.NbBundle;
64 import org.openide.util.lookup.ServiceProvider;
65 import org.openide.util.lookup.ServiceProviders;
73 
77 @ServiceProviders(value = {
78  @ServiceProvider(service = FrameCapture.class)
79 })
80 public class FXVideoPanel extends MediaViewVideoPanel {
81 
82  // Refer to https://docs.oracle.com/javafx/2/api/javafx/scene/media/package-summary.html
83  // for Javafx supported formats
84  private static final String[] EXTENSIONS = new String[]{".m4v", ".fxm", ".flv", ".m3u8", ".mp4", ".aif", ".aiff", ".mp3", "m4a", ".wav"}; //NON-NLS
85  private static final List<String> MIMETYPES = Arrays.asList("audio/x-aiff", "video/x-javafx", "video/x-flv", "application/vnd.apple.mpegurl", " audio/mpegurl", "audio/mpeg", "video/mp4", "audio/x-m4a", "video/x-m4v", "audio/x-wav"); //NON-NLS
86  private static final Logger logger = Logger.getLogger(MediaViewVideoPanel.class.getName());
87 
88  private boolean fxInited = false;
89 
90  // FX Components
92 
93  // Current media content representations
95 
96  // FX UI Components
97  private JFXPanel videoComponent;
98 
102  public FXVideoPanel() {
103  fxInited = Installer.isJavaFxInited();
104  initComponents();
105  if (fxInited) {
106  setupFx();
107  }
108  }
109 
110  public JPanel getVideoPanel() {
111  return this;
112  }
113 
114  private void setupFx() {
115  Platform.runLater(new Runnable() {
116  @Override
117  public void run() {
118  videoComponent = new JFXPanel();
119  mediaPane = new MediaPane();
120  Scene fxScene = new Scene(mediaPane);
121  videoComponent.setScene(fxScene);
122 
123  SwingUtilities.invokeLater(new Runnable() {
124  @Override
125  public void run() {
126  add(videoComponent);
127  }
128  });
129  }
130  });
131  }
132 
133  @Override
134  void setupVideo(final AbstractFile file, final Dimension dims) {
135  if (file.equals(currentFile)) {
136  return;
137  }
138  if (!Case.isCaseOpen()) {
139  //handle in-between condition when case is being closed
140  //and an image was previously selected
141  return;
142  }
143  reset();
144  currentFile = file;
145  final boolean deleted = file.isDirNameFlagSet(TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC);
146  if (deleted) {
147  mediaPane.setInfoLabelText(NbBundle.getMessage(this.getClass(), "FXVideoPanel.mediaPane.infoLabel"));
148  removeAll();
149  return;
150  }
151 
152  String path = "";
153  try {
154  path = file.getUniquePath();
155  } catch (TskCoreException ex) {
156  logger.log(Level.SEVERE, "Cannot get unique path of video file"); //NON-NLS
157  }
158  mediaPane.setInfoLabelText(path);
159  mediaPane.setInfoLabelToolTipText(path);
160 
161  ExtractMedia em = new ExtractMedia(currentFile, getJFile(currentFile));
162  em.execute();
163 
164  mediaPane.setFit(dims);
165  }
166 
167  @Override
168  void reset() {
169  Platform.runLater(new Runnable() {
170  @Override
171  public void run() {
172  if (mediaPane != null) {
173  mediaPane.reset();
174  }
175  }
176  });
177  currentFile = null;
178  }
179 
180  private java.io.File getJFile(AbstractFile file) {
181  // Get the temp folder path of the case
182  String tempPath = Case.getCurrentCase().getTempDirectory();
183  String name = file.getName();
184  int extStart = name.lastIndexOf(".");
185  String ext = "";
186  if (extStart != -1) {
187  ext = name.substring(extStart, name.length()).toLowerCase();
188  }
189  tempPath = tempPath + java.io.File.separator + file.getId() + ext;
190 
191  java.io.File tempFile = new java.io.File(tempPath);
192  return tempFile;
193  }
194 
200  @SuppressWarnings("unchecked")
201  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
202  private void initComponents() {
203 
204  setBackground(new java.awt.Color(0, 0, 0));
205  setLayout(new javax.swing.BoxLayout(this, javax.swing.BoxLayout.LINE_AXIS));
206  }// </editor-fold>//GEN-END:initComponents
207  // Variables declaration - do not modify//GEN-BEGIN:variables
208  // End of variables declaration//GEN-END:variables
209 
210  @Override
211  public boolean isInited() {
212  return fxInited;
213  }
214 
219  private class ExtractMedia extends SwingWorker<Object, Void> {
220 
221  private ProgressHandle progress;
222 
223  boolean success = false;
224 
226 
227  private java.io.File jFile;
228 
229  private long extractedBytes;
230 
231  ExtractMedia(org.sleuthkit.datamodel.AbstractFile sFile, java.io.File jFile) {
232  this.sFile = sFile;
233  this.jFile = jFile;
234  }
235 
236  public long getExtractedBytes() {
237  return extractedBytes;
238  }
239 
245  public String getMediaUri() {
246  return Paths.get(jFile.getAbsolutePath()).toUri().toString();
247  }
248 
249  @Override
250  protected Object doInBackground() throws Exception {
251  success = false;
252  progress = ProgressHandleFactory.createHandle(
253  NbBundle.getMessage(this.getClass(), "FXVideoPanel.progress.bufferingFile", sFile.getName()),
254  new Cancellable() {
255  @Override
256  public boolean cancel() {
257  return ExtractMedia.this.cancel(true);
258  }
259  });
260  mediaPane.setProgressLabelText(NbBundle.getMessage(this.getClass(), "FXVideoPanel.progressLabel.buffering"));
261  progress.start();
262  progress.switchToDeterminate(100);
263  try {
264  extractedBytes = ContentUtils.writeToFile(sFile, jFile, progress, this, true);
265  } catch (IOException ex) {
266  logger.log(Level.WARNING, "Error buffering file", ex); //NON-NLS
267  }
268  logger.log(Level.INFO, "Done buffering: " + jFile.getName()); //NON-NLS
269  success = true;
270  return null;
271  }
272 
273  /* clean up or start the worker threads */
274  @Override
275  protected void done() {
276  mediaPane.setProgressLabelText("");
277  try {
278  super.get(); //block and get all exceptions thrown while doInBackground()
279  } catch (CancellationException ex) {
280  logger.log(Level.INFO, "Media buffering was canceled."); //NON-NLS
281  mediaPane.setProgressLabelText(
282  NbBundle.getMessage(this.getClass(), "FXVideoPanel.progress.bufferingCancelled"));
283  } catch (InterruptedException ex) {
284  logger.log(Level.INFO, "Media buffering was interrupted."); //NON-NLS
285  mediaPane.setProgressLabelText(
286  NbBundle.getMessage(this.getClass(), "FXVideoPanel.progress.bufferingInterrupted"));
287  } catch (Exception ex) {
288  logger.log(Level.SEVERE, "Fatal error during media buffering.", ex); //NON-NLS
289  mediaPane.setProgressLabelText(
290  NbBundle.getMessage(this.getClass(), "FXVideoPanel.progress.errorWritingVideoToDisk"));
291  } finally {
292  progress.finish();
293  if (!this.isCancelled()) {
294  logger.log(Level.INFO, "ExtractMedia in done: " + jFile.getName()); //NON-NLS
295  try {
296  Platform.runLater(new Runnable() {
297  @Override
298  public void run() {
299  mediaPane.prepareMedia(getMediaUri());
300  }
301  });
302  } catch (MediaException e) {
303  logger.log(Level.WARNING, "something went wrong with javafx", e); //NON-NLS
304  reset();
305  mediaPane.setInfoLabelText(e.getMessage());
306  return;
307  }
308  }
309  }
310  }
311  }
312 
317  private class MediaPane extends BorderPane {
318 
319  private MediaPlayer mediaPlayer;
320 
321  private MediaView mediaView;
322 
324  private Duration duration;
325 
327  private HBox mediaTools;
328 
330  private HBox mediaViewPane;
331 
332  private VBox controlPanel;
333 
334  private Slider progressSlider;
335 
336  private Button pauseButton;
337 
338  private Button stopButton;
339 
340  private Label progressLabel;
341 
342  private Label infoLabel;
343 
344  private int totalHours;
345 
346  private int totalMinutes;
347 
348  private int totalSeconds;
349 
350  private String durationFormat = "%02d:%02d:%02d/%02d:%02d:%02d "; //NON-NLS
351 
353  private final ReadyListener READY_LISTENER = new ReadyListener();
354 
356  private final EndOfMediaListener END_LISTENER = new EndOfMediaListener();
357 
359  private final TimeListener TIME_LISTENER = new TimeListener();
360 
362  private final NotPlayListener NOT_PLAY_LISTENER = new NotPlayListener();
363 
365  private final PlayListener PLAY_LISTENER = new PlayListener();
366 
367  private static final String PLAY_TEXT = "â–º";
368 
369  private static final String PAUSE_TEXT = "||";
370 
371  private static final String STOP_TEXT = "X"; //NON-NLS
372 
373  public MediaPane() {
374  // Video Display
375  mediaViewPane = new HBox();
376  mediaViewPane.setStyle("-fx-background-color: black"); //NON-NLS
377  mediaViewPane.setAlignment(Pos.CENTER);
378  mediaView = new MediaView();
379  mediaViewPane.getChildren().add(mediaView);
380  setCenter(mediaViewPane);
381 
382  // Media Controls
383  controlPanel = new VBox();
384  mediaTools = new HBox();
385  mediaTools.setAlignment(Pos.CENTER);
386  mediaTools.setPadding(new Insets(5, 10, 5, 10));
387 
388  pauseButton = new Button(PLAY_TEXT);
389  stopButton = new Button(STOP_TEXT);
390  mediaTools.getChildren().add(pauseButton);
391  mediaTools.getChildren().add(new Label(" "));
392  mediaTools.getChildren().add(stopButton);
393  mediaTools.getChildren().add(new Label(" "));
394  progressSlider = new Slider();
395  HBox.setHgrow(progressSlider, Priority.ALWAYS);
396  progressSlider.setMinWidth(50);
397  progressSlider.setMaxWidth(Double.MAX_VALUE);
398  mediaTools.getChildren().add(progressSlider);
399  progressLabel = new Label();
400  progressLabel.setPrefWidth(135);
401  progressLabel.setMinWidth(135);
402  mediaTools.getChildren().add(progressLabel);
403 
404  controlPanel.getChildren().add(mediaTools);
405  controlPanel.setStyle("-fx-background-color: white"); //NON-NLS
406  infoLabel = new Label("");
407  controlPanel.getChildren().add(infoLabel);
408  setBottom(controlPanel);
409  setProgressActionListeners();
410  }
411 
418  public void prepareMedia(String mediaUri) {
419  try {
420  mediaPlayer = createMediaPlayer(mediaUri);
421  mediaView.setMediaPlayer(mediaPlayer);
422  } catch (MediaException ex) {
423  this.setProgressLabelText("");
424  this.setInfoLabelText(NbBundle.getMessage(this.getClass(), "FXVideoPanel.media.unsupportedFormat"));
425  }
426  }
427 
432  public void reset() {
433  if (mediaPlayer != null) {
434  setInfoLabelText("");
435  if (mediaPlayer.getStatus() == Status.PLAYING) {
436  mediaPlayer.stop();
437  }
438  mediaPlayer = null;
439  mediaView.setMediaPlayer(null);
440  }
441  resetProgress();
442  }
443 
449  public void setInfoLabelText(final String text) {
450  logger.log(Level.INFO, "Setting Info Label Text: " + text); //NON-NLS
451  Platform.runLater(new Runnable() {
452  @Override
453  public void run() {
454  infoLabel.setText(text);
455  }
456  });
457  }
458 
464  public void setFit(final Dimension dims) {
465  Platform.runLater(new Runnable() {
466  @Override
467  public void run() {
468  setPrefSize(dims.getWidth(), dims.getHeight());
469  // Set the Video output to fit the size allocated for it. give an
470  // extra few px to ensure the info label will be shown
471  mediaView.setFitHeight(dims.getHeight() - controlPanel.getHeight());
472  }
473  });
474  }
475 
479  private void setProgressActionListeners() {
480  pauseButton.setOnAction(new EventHandler<ActionEvent>() {
481  @Override
482  public void handle(ActionEvent e) {
483  if (mediaPlayer == null) {
484  return;
485  }
486 
487  Status status = mediaPlayer.getStatus();
488 
489  switch (status) {
490  // If playing, pause
491  case PLAYING:
492  mediaPlayer.pause();
493  break;
494  // If ready, paused or stopped, continue playing
495  case READY:
496  case PAUSED:
497  case STOPPED:
498  mediaPlayer.play();
499  break;
500  default:
501  logger.log(Level.INFO, "MediaPlayer in unexpected state: " + status.toString()); //NON-NLS
502  // If the MediaPlayer is in an unexpected state, stop playback.
503  mediaPlayer.stop();
504  setInfoLabelText(NbBundle.getMessage(this.getClass(),
505  "FXVideoPanel.pauseButton.infoLabel.playbackErr"));
506  break;
507  }
508  }
509  });
510 
511  stopButton.setOnAction(new EventHandler<ActionEvent>() {
512  @Override
513  public void handle(ActionEvent e) {
514  if (mediaPlayer == null) {
515  return;
516  }
517 
518  mediaPlayer.stop();
519  }
520  });
521 
522  progressSlider.valueProperty().addListener(new InvalidationListener() {
523  @Override
524  public void invalidated(Observable o) {
525  if (mediaPlayer == null) {
526  return;
527  }
528 
529  if (progressSlider.isValueChanging()) {
530  mediaPlayer.seek(duration.multiply(progressSlider.getValue() / 100.0));
531  }
532  }
533  });
534  }
535 
539  private void resetProgress() {
540  totalHours = 0;
541  totalMinutes = 0;
542  totalSeconds = 0;
543  progressSlider.setValue(0.0);
544  updateTime(Duration.ZERO);
545  }
546 
556  private MediaPlayer createMediaPlayer(String mediaUri) {
557  Media media = new Media(mediaUri);
558 
559  MediaPlayer player = new MediaPlayer(media);
560  player.setOnReady(READY_LISTENER);
561  player.setOnPaused(NOT_PLAY_LISTENER);
562  player.setOnStopped(NOT_PLAY_LISTENER);
563  player.setOnPlaying(PLAY_LISTENER);
564  player.setOnEndOfMedia(END_LISTENER);
565 
566  player.currentTimeProperty().addListener(TIME_LISTENER);
567 
568  return player;
569  }
570 
575  private void updateProgress() {
576  if (mediaPlayer == null) {
577  return;
578  }
579  Duration currentTime = mediaPlayer.getCurrentTime();
580  updateSlider(currentTime);
581  updateTime(currentTime);
582  }
583 
589  private void updateSlider(Duration currentTime) {
590  if (progressSlider != null) {
591  progressSlider.setDisable(currentTime.isUnknown());
592  if (!progressSlider.isDisabled() && duration.greaterThan(Duration.ZERO)
593  && !progressSlider.isValueChanging()) {
594  progressSlider.setValue(currentTime.divide(duration.toMillis()).toMillis() * 100.0);
595  }
596  }
597  }
598 
604  private void updateTime(Duration currentTime) {
605  long millisElapsed = (long) currentTime.toMillis();
606 
607  long elapsedHours, elapsedMinutes, elapsedSeconds;
608  // pick out the elapsed hours, minutes, seconds
609  long secondsElapsed = millisElapsed / 1000;
610  elapsedHours = (int) secondsElapsed / 3600;
611  secondsElapsed -= elapsedHours * 3600;
612  elapsedMinutes = (int) secondsElapsed / 60;
613  secondsElapsed -= elapsedMinutes * 60;
614  elapsedSeconds = (int) secondsElapsed;
615 
616  String durationStr = String.format(durationFormat,
617  elapsedHours, elapsedMinutes, elapsedSeconds,
618  totalHours, totalMinutes, totalSeconds);
619  setProgressLabelText(durationStr);
620  }
621 
627  private void setProgressLabelText(final String text) {
628  Platform.runLater(new Runnable() {
629  @Override
630  public void run() {
631  progressLabel.setText(text);
632  }
633  });
634  }
635 
636  private void setInfoLabelToolTipText(final String text) {
637  Platform.runLater(new Runnable() {
638  @Override
639  public void run() {
640  infoLabel.setTooltip(new Tooltip(text));
641  }
642  });
643  }
644 
650  private class ReadyListener implements Runnable {
651 
652  @Override
653  public void run() {
654  if (mediaPlayer == null) {
655  return;
656  }
657 
658  duration = mediaPlayer.getMedia().getDuration();
659  long durationInMillis = (long) mediaPlayer.getMedia().getDuration().toMillis();
660 
661  // pick out the total hours, minutes, seconds
662  long durationSeconds = (int) durationInMillis / 1000;
663  totalHours = (int) durationSeconds / 3600;
664  durationSeconds -= totalHours * 3600;
665  totalMinutes = (int) durationSeconds / 60;
666  durationSeconds -= totalMinutes * 60;
667  totalSeconds = (int) durationSeconds;
668  updateProgress();
669  }
670  }
671 
677  private class EndOfMediaListener implements Runnable {
678 
679  @Override
680  public void run() {
681  if (mediaPlayer == null) {
682  return;
683  }
684 
685  Duration beginning = mediaPlayer.getStartTime();
686  mediaPlayer.stop();
687  mediaPlayer.pause();
688  pauseButton.setText(PLAY_TEXT);
689  updateSlider(beginning);
690  updateTime(beginning);
691  }
692  }
693 
699  private class TimeListener implements ChangeListener<Duration> {
700 
701  @Override
702  public void changed(ObservableValue<? extends Duration> observable, Duration oldValue, Duration newValue) {
703  updateSlider(newValue);
704  updateTime(newValue);
705  }
706  }
707 
711  private class NotPlayListener implements Runnable {
712 
713  @Override
714  public void run() {
715  pauseButton.setText(PLAY_TEXT);
716  }
717  }
718 
722  private class PlayListener implements Runnable {
723 
724  @Override
725  public void run() {
726  pauseButton.setText(PAUSE_TEXT);
727  }
728  }
729  }
730 
740  @Override
741  public List<VideoFrame> captureFrames(java.io.File file, int numFrames) throws Exception {
742 //
743 // try {
744 // List<VideoFrame> frames = new ArrayList<>();
745 //
746 // FrameCapturer fc = new FrameCapturer(file);
747 // logger.log(Level.INFO, "Fc is null? " + (fc == null));
748 // frames = fc.getFrames(numFrames);
749 //
750 // return frames;
751 // }
752 // catch (NullPointerException e) {
753 // e.printStackTrace();
754 // return null;
755 // }
756  return null;
757  }
758 
759 // private class FrameCapturer {
760 //
761 // private MediaPlayer mediaPlayer;
762 // private JFXPanel panel;
763 // private boolean isReady = false;
764 //
765 // FrameCapturer(java.io.File file) {
766 // initFx(file);
767 // }
768 //
769 // boolean isReady() {
770 // return isReady;
771 // }
772 //
773 // private void initFx(final java.io.File file) {
774 // Platform.runAndWait(new Runnable() {
775 // @Override
776 // public void run() {
777 // logger.log(Level.INFO, "In initFX.");
778 // // Create Media Player with no video output
779 // Media media = new Media(Paths.get(file.getAbsolutePath()).toUri().toString());
780 // mediaPlayer = new MediaPlayer(media);
781 // MediaView mediaView = new MediaView(mediaPlayer);
782 // mediaView.setStyle("-fx-background-color: black");
783 // Pane mediaViewPane = new Pane();
784 // mediaViewPane.getChildren().add(mediaView);
785 // Scene scene = new Scene(mediaViewPane);
786 // panel = new JFXPanel();
787 // panel.setScene(scene);
788 // isReady = true;
789 // }
790 // });
791 // }
792 //
793 // List<VideoFrame> getFrames(int numFrames) {
794 // logger.log(Level.INFO, "in get frames");
795 // List<VideoFrame> frames = new ArrayList<VideoFrame>(0);
796 //
797 // if (mediaPlayer.getStatus() != Status.READY) {
798 // try {
799 // Thread.sleep(500);
800 // } catch (InterruptedException e) {
801 // return frames;
802 // }
803 // }
804 //
805 // // get the duration of the video
806 // long myDurationMillis = (long) mediaPlayer.getMedia().getDuration().toMillis();
807 // if (myDurationMillis <= 0) {
808 // return frames;
809 // }
810 //
811 // // calculate the frame interval
812 // int numFramesToGet = numFrames;
813 // long frameInterval = (myDurationMillis - INTER_FRAME_PERIOD_MS) / numFrames;
814 // if (frameInterval < MIN_FRAME_INTERVAL_MILLIS) {
815 // numFramesToGet = 1;
816 // }
817 //
818 // final Object frameLock = new Object();
819 // BufferedImage frame;
820 // final int width = (int) panel.getSize().getWidth();
821 // final int height = (int) panel.getSize().getHeight();
822 // // for each timeStamp, grap a frame
823 // for (int i = 0; i < numFramesToGet; ++i) {
824 // frame = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
825 // logger.log(Level.INFO, "Grabbing a frame...");
826 // final long timeStamp = i * frameInterval + INTER_FRAME_PERIOD_MS;
827 //
828 // // Platform.runLater(new Runnable() {
829 // // @Override
830 // // public void run() {
831 // // synchronized (frameLock) {
832 // logger.log(Level.INFO, "seeking.");
833 // mediaPlayer.seek(new Duration(timeStamp));
834 // // }
835 // // }
836 // // });
837 //
838 // synchronized (frameLock) {
839 // panel.paint(frame.createGraphics());
840 // logger.log(Level.INFO, "Adding image to frames");
841 // }
842 // frames.add(new VideoFrame(frame, timeStamp));
843 // }
844 // return frames;
845 // }
846 // }
847  @Override
848  public String[] getExtensions() {
849  return EXTENSIONS;
850  }
851 
852  @Override
853  public List<String> getMimeTypes() {
854  return MIMETYPES;
855  }
856 }
static< T, V > long writeToFile(Content content, java.io.File outputFile, ProgressHandle progress, SwingWorker< T, V > worker, boolean source)
boolean isDirNameFlagSet(TSK_FS_NAME_FLAG_ENUM flag)
List< VideoFrame > captureFrames(java.io.File file, int numFrames)
void changed(ObservableValue<?extends Duration > observable, Duration oldValue, Duration newValue)
static Logger getLogger(String name)
Definition: Logger.java:131

Copyright © 2012-2015 Basis Technology. Generated on: Mon Oct 19 2015
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.