Autopsy  4.12.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
MediaPlayerPanel.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2013-2019 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.contentviewers;
20 
21 import com.google.common.io.Files;
22 import java.awt.event.ActionEvent;
23 import java.awt.event.ActionListener;
24 import java.io.File;
25 import java.io.IOException;
26 import java.util.Arrays;
27 import java.util.List;
28 import java.util.SortedSet;
29 import java.util.TreeSet;
30 import java.util.concurrent.CancellationException;
31 import java.util.concurrent.ExecutionException;
32 import java.util.concurrent.TimeUnit;
33 import java.util.logging.Level;
34 import javax.swing.BoxLayout;
35 import javax.swing.JPanel;
36 import javax.swing.SwingWorker;
37 import javax.swing.Timer;
38 import javax.swing.event.ChangeEvent;
39 import org.freedesktop.gstreamer.Bus;
40 import org.freedesktop.gstreamer.ClockTime;
41 import org.freedesktop.gstreamer.Gst;
42 import org.freedesktop.gstreamer.GstObject;
43 import org.freedesktop.gstreamer.State;
44 import org.freedesktop.gstreamer.elements.PlayBin;
45 import org.netbeans.api.progress.ProgressHandle;
46 import org.openide.util.NbBundle;
52 import org.sleuthkit.datamodel.AbstractFile;
53 import org.sleuthkit.datamodel.TskData;
54 import javafx.embed.swing.JFXPanel;
55 import javax.swing.event.ChangeListener;
56 import org.freedesktop.gstreamer.GstException;
57 
62 @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
63 public class MediaPlayerPanel extends JPanel implements MediaFileViewer.MediaViewPanel {
64 
65  //Enumerate the accepted file extensions and mimetypes
66  private static final String[] FILE_EXTENSIONS = new String[]{
67  ".3g2",
68  ".3gp",
69  ".3gpp",
70  ".aac",
71  ".aif",
72  ".aiff",
73  ".amr",
74  ".asf",
75  ".au",
76  ".avi",
77  ".flac",
78  ".flv",
79  ".m4a",
80  ".m4v",
81  ".mka",
82  ".mkv",
83  ".mov",
84  ".mp2",
85  ".mp3",
86  ".mp4",
87  ".mpeg",
88  ".mpg",
89  ".mxf",
90  ".ogg",
91  ".wav",
92  ".webm",
93  ".wma",
94  ".wmv",}; //NON-NLS
95  private static final List<String> MIME_TYPES = Arrays.asList(
96  "video/3gpp",
97  "video/3gpp2",
98  "audio/aiff",
99  "audio/amr-wb",
100  "audio/basic",
101  "audio/mp4",
102  "video/mp4",
103  "audio/mpeg",
104  "video/mpeg",
105  "audio/mpeg3",
106  "application/mxf",
107  "application/ogg",
108  "video/quicktime",
109  "audio/vorbis",
110  "audio/vnd.wave",
111  "video/webm",
112  "video/x-3ivx",
113  "audio/x-aac",
114  "audio/x-adpcm",
115  "audio/x-alaw",
116  "audio/x-cinepak",
117  "video/x-divx",
118  "audio/x-dv",
119  "video/x-dv",
120  "video/x-ffv",
121  "audio/x-flac",
122  "video/x-flv",
123  "audio/x-gsm",
124  "video/x-h263",
125  "video/x-h264",
126  "video/x-huffyuv",
127  "video/x-indeo",
128  "video/x-intel-h263",
129  "audio/x-ircam",
130  "video/x-jpeg",
131  "audio/x-m4a",
132  "video/x-m4v",
133  "audio/x-mace",
134  "audio/x-matroska",
135  "video/x-matroska",
136  "audio/x-mpeg",
137  "video/x-mpeg",
138  "audio/x-mpeg-3",
139  "video/x-ms-asf",
140  "audio/x-ms-wma",
141  "video/x-ms-wmv",
142  "video/x-msmpeg",
143  "video/x-msvideo",
144  "video/x-msvideocodec",
145  "audio/x-mulaw",
146  "audio/x-nist",
147  "audio/x-oggflac",
148  "audio/x-paris",
149  "audio/x-qdm2",
150  "audio/x-raw",
151  "video/x-raw",
152  "video/x-rle",
153  "audio/x-speex",
154  "video/x-svq",
155  "audio/x-svx",
156  "video/x-tarkin",
157  "video/x-theora",
158  "audio/x-voc",
159  "audio/x-vorbis",
160  "video/x-vp3",
161  "audio/x-w64",
162  "audio/x-wav",
163  "audio/x-wma",
164  "video/x-wmv",
165  "video/x-xvid"
166  ); //NON-NLS
167 
168  private static final Logger logger = Logger.getLogger(MediaPlayerPanel.class.getName());
169  private static final String MEDIA_PLAYER_ERROR_STRING = NbBundle.getMessage(MediaPlayerPanel.class,
170  "GstVideoPanel.cannotProcFile.err");
171 
172  //Video playback components
173  private volatile PlayBin gstPlayBin;
174  private JavaFxAppSink fxAppSink;
175  private Bus.ERROR errorListener;
176  private Bus.STATE_CHANGED stateChangeListener;
177  private Bus.EOS endOfStreamListener;
178 
179  //Update progress bar and time label during video playback
180  private final Timer timer = new Timer(75, new VideoPanelUpdater());
181  private static final int PROGRESS_SLIDER_SIZE = 2000;
182 
184 
188  public MediaPlayerPanel() throws GstException, UnsatisfiedLinkError {
189  initComponents();
190  initGst();
191  customizeComponents();
192  }
193 
194  private void customizeComponents() {
195  progressSlider.setEnabled(false); // disable slider; enable after user plays vid
196  progressSlider.setMinimum(0);
197  progressSlider.setMaximum(PROGRESS_SLIDER_SIZE);
198  progressSlider.setValue(0);
199  //Manage the gstreamer video position when a user is dragging the slider in the panel.
200  progressSlider.addChangeListener(new ChangeListener() {
201  @Override
202  public void stateChanged(ChangeEvent e) {
203  if (progressSlider.getValueIsAdjusting()) {
204  long duration = gstPlayBin.queryDuration(TimeUnit.NANOSECONDS);
205  double relativePosition = progressSlider.getValue() * 1.0 / PROGRESS_SLIDER_SIZE;
206  long newPos = (long) (relativePosition * duration);
207  gstPlayBin.seek(newPos, TimeUnit.NANOSECONDS);
208  //Keep constantly updating the time label so users have a sense of
209  //where the slider they are dragging is in relation to the video time
210  updateTimeLabel(newPos, duration);
211  }
212  }
213  });
214  //Manage the audio level when the user is adjusting the volumn slider
215  audioSlider.addChangeListener((ChangeEvent event) -> {
216  if (audioSlider.getValueIsAdjusting()) {
217  double audioPercent = (audioSlider.getValue() * 2.0) / 100.0;
218  gstPlayBin.setVolume(audioPercent);
219  }
220  });
221  errorListener = new Bus.ERROR() {
222  @Override
223  public void errorMessage(GstObject go, int i, String string) {
224  enableComponents(false);
225  infoLabel.setText(String.format(
226  "<html><font color='red'>%s</font></html>",
227  MEDIA_PLAYER_ERROR_STRING));
228  timer.stop();
229  }
230  };
231  stateChangeListener = new Bus.STATE_CHANGED() {
232  @Override
233  public void stateChanged(GstObject go, State oldState, State currentState, State pendingState) {
234  if (State.PLAYING.equals(currentState)) {
235  playButton.setText("||");
236  } else {
237  playButton.setText("►");
238  }
239  }
240  };
241  endOfStreamListener = new Bus.EOS() {
242  @Override
243  public void endOfStream(GstObject go) {
244  gstPlayBin.seek(ClockTime.ZERO);
245  progressSlider.setValue(0);
249  Gst.getExecutor().submit(() -> gstPlayBin.pause());
250  }
251  };
252  }
253 
254  private void initGst() throws GstException, UnsatisfiedLinkError {
255  logger.log(Level.INFO, "Attempting initializing of gstreamer for video/audio viewing"); //NON-NLS
256  Gst.init();
257  }
258 
265  @NbBundle.Messages({"GstVideoPanel.noOpenCase.errMsg=No open case available."})
266  void loadFile(final AbstractFile file) {
267  //Ensure everything is back in the initial state
268  infoLabel.setText("");
269  if (file.isDirNameFlagSet(TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC)) {
270  infoLabel.setText(NbBundle.getMessage(this.getClass(), "GstVideoPanel.setupVideo.infoLabel.text"));
271  return;
272  }
273 
274  try {
275  //Pushing off initialization to the background
276  extractMediaWorker = new ExtractMedia(file, VideoUtils.getVideoFileInTempDir(file));
277  extractMediaWorker.execute();
278  } catch (NoCurrentCaseException ex) {
279  logger.log(Level.SEVERE, "Exception while getting open case.", ex); //NON-NLS
280  infoLabel.setText(String.format("<html><font color='red'>%s</font></html>", Bundle.GstVideoPanel_noOpenCase_errMsg()));
281  enableComponents(false);
282  }
283  }
284 
289  @NbBundle.Messages({
290  "MediaPlayerPanel.noSupport=File not supported."
291  })
292  void resetComponents() {
293  progressLabel.setText(String.format("%s/%s", Bundle.MediaPlayerPanel_unknownTime(),
294  Bundle.MediaPlayerPanel_unknownTime()));
295  infoLabel.setText(Bundle.MediaPlayerPanel_noSupport());
296  progressSlider.setValue(0);
297  }
298 
302  void reset() {
303  if (extractMediaWorker != null) {
304  extractMediaWorker.cancel(true);
305  }
306  timer.stop();
307  if (gstPlayBin != null) {
308  gstPlayBin.stop();
309  gstPlayBin.getBus().disconnect(endOfStreamListener);
310  gstPlayBin.getBus().disconnect(endOfStreamListener);
311  gstPlayBin.getBus().disconnect(endOfStreamListener);
312  gstPlayBin.dispose();
313  fxAppSink.clear();
314  gstPlayBin = null;
315  }
316  videoPanel.removeAll();
317  resetComponents();
318  enableComponents(false);
319  }
320 
321  private void enableComponents(boolean isEnabled) {
322  playButton.setEnabled(isEnabled);
323  progressSlider.setEnabled(isEnabled);
324  videoPanel.setEnabled(isEnabled);
325  audioSlider.setEnabled(isEnabled);
326  }
327 
328  @Override
329  public List<String> getSupportedExtensions() {
330  return Arrays.asList(FILE_EXTENSIONS.clone());
331  }
332 
333  @Override
334  public List<String> getSupportedMimeTypes() {
335  return MIME_TYPES;
336  }
337 
338  @Override
339  public boolean isSupported(AbstractFile file) {
340  String extension = file.getNameExtension();
357  if (getSupportedExtensions().contains("." + extension)) {
358  SortedSet<String> mimeTypes = new TreeSet<>(getSupportedMimeTypes());
359  try {
360  String mimeType = new FileTypeDetector().getMIMEType(file);
361  return mimeTypes.contains(mimeType);
363  logger.log(Level.WARNING, "Failed to look up mimetype for " + file.getName() + " using FileTypeDetector. Fallingback on AbstractFile.isMimeType", ex);
364  if (!mimeTypes.isEmpty() && file.isMimeType(mimeTypes) == AbstractFile.MimeMatchEnum.TRUE) {
365  return true;
366  }
367  }
368 
369  return getSupportedExtensions().contains("." + extension);
370  }
371  return false;
372  }
373 
381  private void updateTimeLabel(long start, long total) {
382  progressLabel.setText(formatTime(start, false) + "/" + formatTime(total, true));
383  }
384 
388  @NbBundle.Messages({
389  "MediaPlayerPanel.unknownTime=Unknown",
390  "MediaPlayerPanel.timeFormat=%02d:%02d:%02d"
391  })
392  private String formatTime(long ns, boolean ceiling) {
393  if (ns == -1) {
394  return Bundle.MediaPlayerPanel_unknownTime();
395  }
396 
397  double millis = ns / 1000000.0;
398  double seconds;
399  if (ceiling) {
400  seconds = Math.ceil(millis / 1000);
401  } else {
402  seconds = millis / 1000;
403  }
404  double hours = seconds / 3600;
405  seconds -= (int) hours * 3600;
406  double minutes = seconds / 60;
407  seconds -= (int) minutes * 60;
408 
409  return String.format(Bundle.MediaPlayerPanel_timeFormat(), (int) hours, (int) minutes, (int) seconds);
410  }
411 
416  private class ExtractMedia extends SwingWorker<Void, Void> {
417 
418  private ProgressHandle progress;
419  private final AbstractFile sourceFile;
420  private final java.io.File tempFile;
421 
422  ExtractMedia(AbstractFile sFile, File jFile) {
423  this.sourceFile = sFile;
424  this.tempFile = jFile;
425  }
426 
427  @Override
428  protected Void doInBackground() throws Exception {
429  if (!tempFile.exists() || tempFile.length() < sourceFile.getSize()) {
430  progress = ProgressHandle.createHandle(NbBundle.getMessage(MediaPlayerPanel.class, "GstVideoPanel.ExtractMedia.progress.buffering", sourceFile.getName()), () -> this.cancel(true));
431  progressLabel.setText(NbBundle.getMessage(this.getClass(), "GstVideoPanel.progress.buffering"));
432  progress.start(100);
433  try {
434  Files.createParentDirs(tempFile);
435  ContentUtils.writeToFile(sourceFile, tempFile, progress, this, true);
436  } catch (IOException ex) {
437  logger.log(Level.WARNING, "Error creating parent directory for copying video/audio in temp directory", ex); //NON-NLS
438  } finally {
439  progress.finish();
440  }
441  }
442  return null;
443  }
444 
445  /*
446  * Initialize the playback components if the extraction was successful.
447  */
448  @Override
449  protected void done() {
450  try {
451  super.get();
452 
453  if(this.isCancelled()) {
454  return;
455  }
456  //Video is ready for playback. Create new components
457  gstPlayBin = new PlayBin("VideoPlayer", tempFile.toURI());
458  //Configure event handling
459  Bus playBinBus = gstPlayBin.getBus();
460  playBinBus.connect(endOfStreamListener);
461  playBinBus.connect(stateChangeListener);
462  playBinBus.connect(errorListener);
463 
464  if(this.isCancelled()) {
465  return;
466  }
467 
468  JFXPanel fxPanel = new JFXPanel();
469  videoPanel.removeAll();
470  videoPanel.setLayout(new BoxLayout(videoPanel, BoxLayout.Y_AXIS));
471  videoPanel.add(fxPanel);
472  fxAppSink = new JavaFxAppSink("JavaFxAppSink", fxPanel);
473  gstPlayBin.setVideoSink(fxAppSink);
474 
475  if(this.isCancelled()) {
476  return;
477  }
478 
479  gstPlayBin.setVolume((audioSlider.getValue() * 2.0) / 100.0);
480  gstPlayBin.pause();
481 
482  timer.start();
483  enableComponents(true);
484  } catch (CancellationException ex) {
485  logger.log(Level.INFO, "Media buffering was canceled."); //NON-NLS
486  } catch (InterruptedException ex) {
487  logger.log(Level.INFO, "Media buffering was interrupted."); //NON-NLS
488  } catch (ExecutionException ex) {
489  logger.log(Level.SEVERE, "Fatal error during media buffering.", ex); //NON-NLS
490  }
491  }
492  }
493 
497  private class VideoPanelUpdater implements ActionListener {
498 
499  @Override
500  public void actionPerformed(ActionEvent e) {
501  if (!progressSlider.getValueIsAdjusting()) {
502  long position = gstPlayBin.queryPosition(TimeUnit.NANOSECONDS);
503  long duration = gstPlayBin.queryDuration(TimeUnit.NANOSECONDS);
509  if (duration != -1) {
510  double relativePosition = (double) position / duration;
511  progressSlider.setValue((int) (relativePosition * PROGRESS_SLIDER_SIZE));
512  }
513 
514  updateTimeLabel(position, duration);
515  }
516  }
517  }
518 
524  @SuppressWarnings("unchecked")
525  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
526  private void initComponents() {
527 
528  videoPanel = new javax.swing.JPanel();
529  controlPanel = new javax.swing.JPanel();
530  progressSlider = new javax.swing.JSlider();
531  infoLabel = new javax.swing.JLabel();
532  playButton = new javax.swing.JButton();
533  progressLabel = new javax.swing.JLabel();
534  VolumeIcon = new javax.swing.JLabel();
535  audioSlider = new javax.swing.JSlider();
536 
537  javax.swing.GroupLayout videoPanelLayout = new javax.swing.GroupLayout(videoPanel);
538  videoPanel.setLayout(videoPanelLayout);
539  videoPanelLayout.setHorizontalGroup(
540  videoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
541  .addGap(0, 0, Short.MAX_VALUE)
542  );
543  videoPanelLayout.setVerticalGroup(
544  videoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
545  .addGap(0, 259, Short.MAX_VALUE)
546  );
547 
548  progressSlider.setValue(0);
549  progressSlider.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
550  progressSlider.setDoubleBuffered(true);
551  progressSlider.setMinimumSize(new java.awt.Dimension(36, 21));
552  progressSlider.setPreferredSize(new java.awt.Dimension(200, 21));
553 
554  org.openide.awt.Mnemonics.setLocalizedText(infoLabel, org.openide.util.NbBundle.getMessage(MediaPlayerPanel.class, "MediaPlayerPanel.infoLabel.text")); // NOI18N
555  infoLabel.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
556 
557  org.openide.awt.Mnemonics.setLocalizedText(playButton, org.openide.util.NbBundle.getMessage(MediaPlayerPanel.class, "MediaPlayerPanel.playButton.text")); // NOI18N
558  playButton.addActionListener(new java.awt.event.ActionListener() {
559  public void actionPerformed(java.awt.event.ActionEvent evt) {
560  playButtonActionPerformed(evt);
561  }
562  });
563 
564  org.openide.awt.Mnemonics.setLocalizedText(progressLabel, org.openide.util.NbBundle.getMessage(MediaPlayerPanel.class, "MediaPlayerPanel.progressLabel.text")); // NOI18N
565 
566  org.openide.awt.Mnemonics.setLocalizedText(VolumeIcon, org.openide.util.NbBundle.getMessage(MediaPlayerPanel.class, "MediaPlayerPanel.VolumeIcon.text")); // NOI18N
567 
568  audioSlider.setMajorTickSpacing(10);
569  audioSlider.setMaximum(50);
570  audioSlider.setMinorTickSpacing(5);
571  audioSlider.setPaintTicks(true);
572  audioSlider.setToolTipText(org.openide.util.NbBundle.getMessage(MediaPlayerPanel.class, "MediaPlayerPanel.audioSlider.toolTipText")); // NOI18N
573  audioSlider.setValue(25);
574  audioSlider.setMinimumSize(new java.awt.Dimension(200, 21));
575  audioSlider.setPreferredSize(new java.awt.Dimension(200, 21));
576 
577  javax.swing.GroupLayout controlPanelLayout = new javax.swing.GroupLayout(controlPanel);
578  controlPanel.setLayout(controlPanelLayout);
579  controlPanelLayout.setHorizontalGroup(
580  controlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
581  .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, controlPanelLayout.createSequentialGroup()
582  .addContainerGap()
583  .addGroup(controlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
584  .addGroup(controlPanelLayout.createSequentialGroup()
585  .addComponent(playButton, javax.swing.GroupLayout.PREFERRED_SIZE, 64, javax.swing.GroupLayout.PREFERRED_SIZE)
586  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
587  .addComponent(progressSlider, javax.swing.GroupLayout.DEFAULT_SIZE, 680, Short.MAX_VALUE)
588  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
589  .addComponent(progressLabel))
590  .addGroup(controlPanelLayout.createSequentialGroup()
591  .addComponent(infoLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
592  .addGap(18, 18, 18)
593  .addComponent(VolumeIcon, javax.swing.GroupLayout.PREFERRED_SIZE, 64, javax.swing.GroupLayout.PREFERRED_SIZE)
594  .addGap(2, 2, 2)
595  .addComponent(audioSlider, javax.swing.GroupLayout.PREFERRED_SIZE, 229, javax.swing.GroupLayout.PREFERRED_SIZE)))
596  .addContainerGap())
597  );
598  controlPanelLayout.setVerticalGroup(
599  controlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
600  .addGroup(controlPanelLayout.createSequentialGroup()
601  .addGroup(controlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
602  .addGroup(controlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
603  .addComponent(progressLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
604  .addComponent(progressSlider, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
605  .addComponent(playButton))
606  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
607  .addGroup(controlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
608  .addComponent(audioSlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
609  .addGroup(controlPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
610  .addComponent(VolumeIcon, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
611  .addComponent(infoLabel)))
612  .addGap(13, 13, 13))
613  );
614 
615  javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
616  this.setLayout(layout);
617  layout.setHorizontalGroup(
618  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
619  .addComponent(videoPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
620  .addComponent(controlPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
621  );
622  layout.setVerticalGroup(
623  layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
624  .addGroup(layout.createSequentialGroup()
625  .addComponent(videoPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
626  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
627  .addComponent(controlPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
628  );
629  }// </editor-fold>//GEN-END:initComponents
630 
631  private void playButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_playButtonActionPerformed
632  if (gstPlayBin.isPlaying()) {
633  gstPlayBin.pause();
634  } else {
635  gstPlayBin.play();
636  }
637  }//GEN-LAST:event_playButtonActionPerformed
638 
639 
640  // Variables declaration - do not modify//GEN-BEGIN:variables
641  private javax.swing.JLabel VolumeIcon;
642  private javax.swing.JSlider audioSlider;
643  private javax.swing.JPanel controlPanel;
644  private javax.swing.JLabel infoLabel;
645  private javax.swing.JButton playButton;
646  private javax.swing.JLabel progressLabel;
647  private javax.swing.JSlider progressSlider;
648  private javax.swing.JPanel videoPanel;
649  // End of variables declaration//GEN-END:variables
650 }
void playButtonActionPerformed(java.awt.event.ActionEvent evt)
static< T > long writeToFile(Content content, java.io.File outputFile, ProgressHandle progress, Future< T > worker, boolean source)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124

Copyright © 2012-2018 Basis Technology. Generated on: Wed Sep 18 2019
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.