Package org.sleuthkit.autopsy.imageanalyzer.gui

Source Code of org.sleuthkit.autopsy.imageanalyzer.gui.MediaControl

/*
* Autopsy Forensic Browser
*
* Copyright 2013 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.imageanalyzer.gui;

import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.logging.Level;
import javafx.application.Platform;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.media.MediaException;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaPlayer.Status;
import javafx.scene.media.MediaView;
import javafx.scene.text.Text;
import javafx.util.Duration;
import javafx.util.StringConverter;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.imageanalyzer.FXMLConstructor;
import org.sleuthkit.autopsy.imageanalyzer.datamodel.VideoFile;

public class MediaControl extends BorderPane {

    private static final Image VOLUME_HIGH = new Image("/org/sleuthkit/autopsy/imageanalyzer/images/speaker-volume.png");
    private static final Image VOLUME_LOW = new Image("/org/sleuthkit/autopsy/imageanalyzer/images/speaker-volume-low.png");
    private static final Image VOLUME_ZERO = new Image("/org/sleuthkit/autopsy/imageanalyzer/images/speaker-volume-none.png");
    private static final Image VOLUME_MUTE = new Image("/org/sleuthkit/autopsy/imageanalyzer/images/speaker-volume-control-mute.png");

    private static final Image PLAY = new Image("/org/sleuthkit/autopsy/imageanalyzer/images/media_controls_play_small.png", true);
    private static final Image PAUSE = new Image("/org/sleuthkit/autopsy/imageanalyzer/images/media_controls_pause_small.png", true);

    private final MediaPlayer mp;

    private final boolean repeat = false;

    private boolean stopRequested = false;

    private boolean atEndOfMedia = false;

    private Duration duration;

    @FXML
    private MediaView mediaView;

    @FXML
    private ResourceBundle resources;

    @FXML
    private URL location;

    @FXML
    private Button controlButton;

    @FXML
    private Slider timeSlider;

    @FXML
    private Slider volumeSlider;

    @FXML
    private Label timeLabel;

    @FXML
    private ImageView controlImageView;

    @FXML
    private ImageView volumeImageView;

    @FXML
    private HBox playControlBar;

    @FXML
    private Button volumeButton;

    InvalidationListener seekListener = new InvalidationListener() {
        @Override
        public void invalidated(Observable ov) {
            mp.seek(Duration.millis(timeSlider.getValue()));
        }
    };
    private final VideoFile<?> file;

    public static Node create(VideoFile<?> file) {
        try {
            return new MediaControl(new MediaPlayer(file.getMedia()), file);
        } catch (IOException ex) {
            Logger.getLogger(VideoFile.class.getName()).log(Level.WARNING, "failed to initialize MediaControl for file " + file.getName(), ex);
            return new Text(ex.getLocalizedMessage() + "\nSee the logs for details.");
        } catch (MediaException ex) {
            Logger.getLogger(VideoFile.class.getName()).log(Level.WARNING, ex.getType() + " Failed to initialize MediaControl for file " + file.getName(), ex);
            return new Text(ex.getType() + "\nSee the logs for details.");
        } catch (OutOfMemoryError ex) {
            Logger.getLogger(VideoFile.class.getName()).log(Level.WARNING, "failed to initialize MediaControl for file " + file.getName(), ex);
            return new Text("There was a problem playing video file.\nSee the logs for details.");
        }
    }

    @FXML
    void initialize() {
        assert controlButton != null : "fx:id=\"controlButton\" was not injected: check your FXML file 'MediaControl.fxml'.";
        assert timeSlider != null : "fx:id=\"timeSlider\" was not injected: check your FXML file 'MediaControl.fxml'.";
        assert volumeSlider != null : "fx:id=\"volumeSlider\" was not injected: check your FXML file 'MediaControl.fxml'.";
        mp.errorProperty().addListener((Observable observable) -> {
            final MediaException ex = mp.getError();
            if (ex != null) {
                Platform.runLater(() -> {
                    Logger.getLogger(VideoFile.class.getName()).log(Level.WARNING, ex.getType() + " Failed to initialize MediaControl for file " + file.getName(), ex);
                    setCenter(new Text(ex.getType() + "\nSee the logs for details."));
                    setBottom(null);
                });
            }
        });
        mp.statusProperty().addListener((observableStatus, oldStatus, newStatus) -> {
            Logger.getAnonymousLogger().log(Level.INFO, "media player: {0}", newStatus);
        });
        mediaView.setMediaPlayer(mp);
        mediaView.fitHeightProperty().bind(this.heightProperty().subtract(playControlBar.heightProperty()));
        mediaView.fitWidthProperty().bind(this.widthProperty());

        controlButton.setOnAction((ActionEvent e) -> {
            Status status = mp.getStatus();
            switch (status) {
                case UNKNOWN:
                case HALTED:
                    // don't do anything in these states
                    return;
                case PAUSED:
                case READY:
                case STOPPED:
                    // rewind the movie if we're sitting at the end
                    if (atEndOfMedia) {
                        mp.seek(mp.getStartTime());
                        atEndOfMedia = false;
                    }
                    mp.play();
                    break;
                default:
                    mp.pause();
            }
        });

        mp.currentTimeProperty().addListener((Observable ov) -> {
            updateTime();
        });

        mp.setOnPlaying(() -> {
            if (stopRequested) {
                mp.pause();
                stopRequested = false;
            } else {
                controlImageView.setImage(PAUSE);
            }
        });

        mp.setOnPaused(() -> {
            controlImageView.setImage(PLAY);
        });

        mp.setOnReady(() -> {
            duration = mp.getMedia().getDuration();
            timeSlider.setMax(duration.toMillis());
            timeSlider.setMajorTickUnit(duration.toMillis());
            updateTime();
            updateVolume();
        });

        mp.setCycleCount(repeat ? MediaPlayer.INDEFINITE : 1);
        mp.setOnEndOfMedia(() -> {
            if (!repeat) {
                controlImageView.setImage(PLAY);
                stopRequested = true;
                atEndOfMedia = true;
            }
        });

        mp.volumeProperty().addListener((observable, oldVolume, newVolume) -> {
            setVolumeIcon(newVolume);
        });

        mp.muteProperty().addListener((observable, oldMute, newMute) -> {
            if (newMute) {
                volumeImageView.setImage(VOLUME_MUTE);
            } else {
                setVolumeIcon(mp.getVolume());
            }
        });

        timeSlider.valueProperty().addListener(seekListener);

        // Add time slider
        timeSlider.setLabelFormatter(new StringConverter<Double>() {
            @Override
            public String toString(Double object) {
                return formatTime(Duration.millis(object));
            }

            @Override
            public Double fromString(String string) {
                throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
            }
        });

        // Add Volume slider
        volumeSlider.valueProperty().addListener((Observable ov) -> {
            if (volumeSlider.isValueChanging()) {
                mp.setVolume(volumeSlider.getValue());
                mp.setMute(false);
            }
        });

        volumeButton.setOnAction(event -> {
            mp.setMute(!mp.isMute());
        });
    }

    private void setVolumeIcon(Number newVolume) {
        if (newVolume.doubleValue() < .1) {
            volumeImageView.setImage(VOLUME_ZERO);
        } else if (newVolume.doubleValue() <= .6) {
            volumeImageView.setImage(VOLUME_LOW);
        } else {
            volumeImageView.setImage(VOLUME_HIGH);
        }
    }

    private MediaControl(MediaPlayer mp, VideoFile<?> file) {
        this.file = file;
        this.mp = mp;
        FXMLConstructor.construct(this, "MediaControl.fxml");
    }

    protected void updateTime() {
        Platform.runLater(() -> {
            Duration currentTime = mp.getCurrentTime();
            timeSlider.setDisable(duration.isUnknown());
            timeLabel.setText(formatTime(currentTime));
            if (!timeSlider.isDisabled()
                    && duration.greaterThan(Duration.ZERO)
                    && !timeSlider.isValueChanging()) {
                timeSlider.valueProperty().removeListener(seekListener);
                timeSlider.setValue(currentTime.toMillis());
                timeSlider.valueProperty().addListener(seekListener);
            }

        });
    }

    private void updateVolume() {
        Platform.runLater(() -> {
            final double volume = mp.getVolume();

            volumeSlider.setValue(volume);

            if (mp.isMute()) {
                volumeImageView.setImage(VOLUME_MUTE);
            } else {
                setVolumeIcon(volume);
            }
        });
    }

    private static String formatTime(Duration elapsed) {
        int totalSeconds = (int) Math.floor(elapsed.toSeconds());
        int elapsedHours = totalSeconds / (60 * 60);
        totalSeconds -= elapsedHours * 60 * 60;
        int elapsedMinutes = totalSeconds / 60;
        int elapsedSeconds = totalSeconds - elapsedMinutes * 60;

        if (elapsedHours > 0) {
            return String.format("%d:%02d:%02d", elapsedHours,
                    elapsedMinutes, elapsedSeconds);
        } else {
            return String.format("%02d:%02d", elapsedMinutes,
                    elapsedSeconds);
        }
    }

    public void stopVideo() {
        mp.stop();
    }
}
TOP

Related Classes of org.sleuthkit.autopsy.imageanalyzer.gui.MediaControl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.