mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-07-17 22:48:21 +00:00
stream reading improvements, collecting dump infos can be disabled
This commit is contained in:
@@ -512,11 +512,13 @@ public final class SWF implements TreeItem, Timelined {
|
||||
|
||||
SWFInputStream sis = new SWFInputStream(this, uncompressedData);
|
||||
dumpInfo = new DumpInfoSwfNode(this, "rootswf", "", null, 0, 0);
|
||||
sis.dumpInfo = dumpInfo;
|
||||
if (Configuration.dumpInfoCollecting.get()) {
|
||||
sis.dumpInfo = dumpInfo;
|
||||
}
|
||||
sis.readBytesEx(3, "signature"); // skip siganture
|
||||
version = sis.readUI8("version");
|
||||
fileSize = sis.readUI32("fileSize");
|
||||
sis.dumpInfo.lengthBytes = fileSize;
|
||||
dumpInfo.lengthBytes = fileSize;
|
||||
if (listener != null) {
|
||||
sis.addPercentListener(listener);
|
||||
}
|
||||
|
||||
@@ -310,6 +310,18 @@ public class SWFInputStream implements AutoCloseable {
|
||||
}
|
||||
}
|
||||
|
||||
private void informListeners() {
|
||||
if (listeners.size() > 0 && percentMax > 0) {
|
||||
int percent = (int) (getPos() * 100 / percentMax);
|
||||
if (lastPercent != percent) {
|
||||
for (ProgressListener pl : listeners) {
|
||||
pl.progress(percent);
|
||||
}
|
||||
lastPercent = percent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setPercentMax(long percentMax) {
|
||||
this.percentMax = percentMax;
|
||||
}
|
||||
@@ -410,15 +422,7 @@ public class SWFInputStream implements AutoCloseable {
|
||||
private int lastPercent = -1;
|
||||
|
||||
private int readNoBitReset() throws IOException, EndOfStreamException {
|
||||
if (listeners.size() > 0 && percentMax > 0) {
|
||||
int percent = (int) (getPos() * 100 / percentMax);
|
||||
if (lastPercent != percent) {
|
||||
for (ProgressListener pl : listeners) {
|
||||
pl.progress(percent);
|
||||
}
|
||||
lastPercent = percent;
|
||||
}
|
||||
}
|
||||
informListeners();
|
||||
int r = is.read();
|
||||
if (r == -1) {
|
||||
throw new EndOfStreamException();
|
||||
@@ -694,10 +698,14 @@ public class SWFInputStream implements AutoCloseable {
|
||||
if (count <= 0) {
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
informListeners();
|
||||
bitPos = 0;
|
||||
byte[] ret = new byte[(int) count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
ret[i] = (byte) readEx();
|
||||
if (is.read(ret) != count) {
|
||||
throw new EndOfStreamException();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -960,7 +968,7 @@ public class SWFInputStream implements AutoCloseable {
|
||||
public Tag call() throws Exception {
|
||||
try {
|
||||
Tag t = resolveTag(tag, level, parallel, skipUnusualTags, gfx);
|
||||
if (t != null) {
|
||||
if (dumpInfo!= null && t != null) {
|
||||
dumpInfo.name = t.getName();
|
||||
}
|
||||
return t;
|
||||
@@ -1004,7 +1012,7 @@ public class SWFInputStream implements AutoCloseable {
|
||||
tag = null;
|
||||
}
|
||||
DumpInfo di = dumpInfo;
|
||||
if (tag != null) {
|
||||
if (di != null && tag != null) {
|
||||
di.name = tag.getName();
|
||||
}
|
||||
endDumpLevel(tag == null ? null : tag.getId());
|
||||
|
||||
@@ -94,6 +94,10 @@ public class Configuration {
|
||||
@ConfigurationCategory("display")
|
||||
public static final ConfigurationItem<Boolean> dumpView = null;
|
||||
|
||||
@ConfigurationDefaultBoolean(true)
|
||||
@ConfigurationCategory("display")
|
||||
public static final ConfigurationItem<Boolean> dumpInfoCollecting = null;
|
||||
|
||||
@ConfigurationDefaultBoolean(false)
|
||||
@ConfigurationCategory("ui")
|
||||
public static final ConfigurationItem<Boolean> gotoMainClassOnStartup = null;
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2014 JPEXS
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.gui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.plaf.basic.BasicLabelUI;
|
||||
import javax.swing.plaf.basic.BasicTreeUI;
|
||||
import javax.swing.tree.DefaultTreeCellRenderer;
|
||||
import javax.swing.tree.TreeModel;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class DumpTree extends JTree {
|
||||
|
||||
public class DumpTreeCellRenderer extends DefaultTreeCellRenderer {
|
||||
|
||||
@Override
|
||||
public Component getTreeCellRendererComponent(
|
||||
JTree tree,
|
||||
Object value,
|
||||
boolean sel,
|
||||
boolean expanded,
|
||||
boolean leaf,
|
||||
int row,
|
||||
boolean hasFocus) {
|
||||
|
||||
super.getTreeCellRendererComponent(
|
||||
tree, value, sel,
|
||||
expanded, leaf, row,
|
||||
hasFocus);
|
||||
|
||||
//DumpInfo dumpInfo = (DumpInfo) value;
|
||||
setUI(new BasicLabelUI());
|
||||
setOpaque(false);
|
||||
setBackgroundNonSelectionColor(Color.white);
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
DumpTree(DumpTreeModel treeModel) {
|
||||
super(treeModel);
|
||||
setCellRenderer(new DumpTreeCellRenderer());
|
||||
setRootVisible(false);
|
||||
setBackground(Color.white);
|
||||
setUI(new BasicTreeUI() {
|
||||
@Override
|
||||
public void paint(Graphics g, JComponent c) {
|
||||
setHashColor(Color.gray);
|
||||
super.paint(g, c);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModel(TreeModel tm) {
|
||||
super.setModel(tm);
|
||||
if (tm != null) {
|
||||
int rowCount = tm.getChildCount(tm.getRoot());
|
||||
for (int i = rowCount - 1; i >= 0; i--) {
|
||||
expandRow(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2014 JPEXS
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.gui;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.dumpview.DumpInfo;
|
||||
import com.jpexs.decompiler.flash.treeitems.SWFList;
|
||||
import java.util.List;
|
||||
import javax.swing.event.TreeModelListener;
|
||||
import javax.swing.tree.TreeModel;
|
||||
import javax.swing.tree.TreePath;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class DumpTreeModel implements TreeModel {
|
||||
|
||||
private final DumpInfo root;
|
||||
|
||||
public DumpTreeModel(List<SWFList> swfs) {
|
||||
DumpInfo root = new DumpInfo("root", "", null, 0, 0);
|
||||
for (SWFList swfList : swfs) {
|
||||
for (SWF swf : swfList) {
|
||||
swf.dumpInfo.name = swf.getFileTitle();
|
||||
root.childInfos.add(swf.dumpInfo);
|
||||
}
|
||||
}
|
||||
this.root = root;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getRoot() {
|
||||
return root;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getChild(Object o, int i) {
|
||||
return ((DumpInfo) o).childInfos.get(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChildCount(Object o) {
|
||||
return ((DumpInfo) o).childInfos.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLeaf(Object o) {
|
||||
return ((DumpInfo) o).childInfos.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void valueForPathChanged(TreePath tp, Object o) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIndexOfChild(Object o, Object o1) {
|
||||
return ((DumpInfo) o).childInfos.indexOf(o1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTreeModelListener(TreeModelListener tl) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeTreeModelListener(TreeModelListener tl) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2014 JPEXS
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.gui;
|
||||
|
||||
import com.jpexs.decompiler.flash.dumpview.DumpInfo;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class DumpViewPanel extends JPanel {
|
||||
|
||||
private final JLabel dumpViewLabel;
|
||||
private final HexView dumpViewHexTable;
|
||||
|
||||
public DumpViewPanel() {
|
||||
super(new BorderLayout());
|
||||
|
||||
dumpViewLabel = new JLabel();
|
||||
dumpViewLabel.setMinimumSize(new Dimension(100, 20));
|
||||
add(dumpViewLabel, BorderLayout.SOUTH);
|
||||
|
||||
dumpViewHexTable = new HexView();
|
||||
add(new JScrollPane(dumpViewHexTable), BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
private int getEndIndex(DumpInfo dumpInfo) {
|
||||
int end = (int) dumpInfo.startByte;
|
||||
if (dumpInfo.lengthBytes != 0) {
|
||||
end += dumpInfo.lengthBytes;
|
||||
} else {
|
||||
int bits = dumpInfo.startBit + dumpInfo.lengthBits;
|
||||
end += bits / 8;
|
||||
if (bits % 8 != 0) {
|
||||
end++;
|
||||
}
|
||||
}
|
||||
return end - 1;
|
||||
}
|
||||
|
||||
public void setData(byte[] data, DumpInfo dumpInfo) {
|
||||
List<DumpInfo> dumpInfos = new ArrayList<>();
|
||||
DumpInfo di = dumpInfo;
|
||||
while (di.parent != null) {
|
||||
dumpInfos.add(di);
|
||||
di = di.parent;
|
||||
}
|
||||
long[] highlightStarts = new long[dumpInfos.size()];
|
||||
long[] highlightEnds = new long[dumpInfos.size()];
|
||||
for (int i = 0; i < dumpInfos.size(); i++) {
|
||||
DumpInfo di2 = dumpInfos.get(highlightStarts.length - i - 1);
|
||||
highlightStarts[i] = di2.startByte;
|
||||
highlightEnds[i] = getEndIndex(di2);
|
||||
}
|
||||
dumpViewHexTable.setData(data, highlightStarts, highlightEnds);
|
||||
|
||||
if (dumpInfo.lengthBytes != 0 || dumpInfo.lengthBits != 0) {
|
||||
int selectionStart = (int) dumpInfo.startByte;
|
||||
int selectionEnd = getEndIndex(dumpInfo);
|
||||
|
||||
dumpViewHexTable.scrollToByte(dumpInfo.startByte);
|
||||
|
||||
setLabelText("startByte: " + dumpInfo.startByte
|
||||
+ " startBit: " + dumpInfo.startBit
|
||||
+ " lengthBytes: " + dumpInfo.lengthBytes
|
||||
+ " lengthBits: " + dumpInfo.lengthBits
|
||||
+ " selectionStart: " + selectionStart
|
||||
+ " selectionEnd: " + selectionEnd);
|
||||
}
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
public void setLabelText(String text) {
|
||||
dumpViewLabel.setText(text);
|
||||
}
|
||||
}
|
||||
@@ -61,7 +61,7 @@ public class LoadingPanel extends JPanel {
|
||||
|
||||
private synchronized void redrawImage(int size) {
|
||||
if (drawTimer != null) {
|
||||
drawTimer.cancel();;
|
||||
drawTimer.cancel();
|
||||
drawTimer = null;
|
||||
}
|
||||
BufferedImage bi = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
|
||||
@@ -105,12 +105,14 @@ public class LoadingPanel extends JPanel {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
double rot2 = rotation - Math.PI * 2 / segments;
|
||||
if (rot2 < 0) {
|
||||
rot2 += Math.PI * 2;
|
||||
if (isVisible()) {
|
||||
double rot2 = rotation - Math.PI * 2 / segments;
|
||||
if (rot2 < 0) {
|
||||
rot2 += Math.PI * 2;
|
||||
}
|
||||
setRotation(rot2);
|
||||
repaint();
|
||||
}
|
||||
setRotation(rot2);
|
||||
repaint();
|
||||
}
|
||||
}, idelay, idelay);
|
||||
}
|
||||
|
||||
@@ -1,189 +1,190 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2014 JPEXS
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.gui.player;
|
||||
|
||||
import com.jpexs.decompiler.flash.AppStrings;
|
||||
import com.jpexs.decompiler.flash.gui.View;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.Insets;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JProgressBar;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class PlayerControls extends JPanel implements ActionListener {
|
||||
|
||||
static final String ACTION_PAUSE = "PAUSE";
|
||||
static final String ACTION_STOP = "STOP";
|
||||
|
||||
private final JButton pauseButton;
|
||||
private boolean paused = false;
|
||||
private MediaDisplay display;
|
||||
private JProgressBar progress;
|
||||
private final Timer timer;
|
||||
private final JLabel timeLabel;
|
||||
private final JLabel totalTimeLabel;
|
||||
private static final Icon pauseIcon = View.getIcon("pause16");
|
||||
private static final Icon playIcon = View.getIcon("play16");
|
||||
|
||||
public PlayerControls(MediaDisplay display) {
|
||||
this.display = display;
|
||||
JPanel controlPanel = new JPanel(new BorderLayout());
|
||||
timeLabel = new JLabel("00:00.00");
|
||||
totalTimeLabel = new JLabel("00:00.00");
|
||||
controlPanel.add(timeLabel, BorderLayout.WEST);
|
||||
controlPanel.add(totalTimeLabel, BorderLayout.EAST);
|
||||
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
|
||||
JPanel buttonsPanel = new JPanel();
|
||||
buttonsPanel.setLayout(new FlowLayout());
|
||||
|
||||
pauseButton = new JButton(AppStrings.translate("preview.pause"), pauseIcon);
|
||||
pauseButton.setMargin(new Insets(0, 0, 0, 0));
|
||||
pauseButton.setActionCommand(ACTION_PAUSE);
|
||||
pauseButton.addActionListener(this);
|
||||
JButton stopButton = new JButton(AppStrings.translate("preview.stop"), View.getIcon("stop16"));
|
||||
stopButton.setMargin(new Insets(0, 0, 0, 0));
|
||||
stopButton.setActionCommand(ACTION_STOP);
|
||||
stopButton.addActionListener(this);
|
||||
buttonsPanel.add(pauseButton);
|
||||
buttonsPanel.add(stopButton);
|
||||
controlPanel.add(buttonsPanel, BorderLayout.CENTER);
|
||||
|
||||
progress = new JProgressBar();
|
||||
Dimension pref = progress.getPreferredSize();
|
||||
pref.height = 20;
|
||||
progress.setPreferredSize(pref);
|
||||
final PlayerControls t = this;
|
||||
progress.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
int frame = (int) Math.floor(e.getX() * t.display.getTotalFrames() / (double) progress.getWidth());
|
||||
boolean p = t.display.isPlaying();
|
||||
t.display.gotoFrame(frame);
|
||||
if (p) {
|
||||
t.display.play();
|
||||
}
|
||||
}
|
||||
});
|
||||
add(progress);
|
||||
add(controlPanel);
|
||||
timer = new Timer();
|
||||
timer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
update();
|
||||
}
|
||||
}, 100, 100);
|
||||
}
|
||||
|
||||
private String formatMs(long ms) {
|
||||
long s = ms / 1000;
|
||||
ms %= 1000;
|
||||
long m = s / 60;
|
||||
s %= 60;
|
||||
long h = m / 60;
|
||||
m %= 60;
|
||||
return "" + (h > 0 ? h + ":" : "") + pad(m) + ":" + pad(s) + "." + pad(ms / 10);
|
||||
}
|
||||
|
||||
private String pad(long t) {
|
||||
String ret = "" + t;
|
||||
while (ret.length() < 2) {
|
||||
ret = "0" + ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void setMedia(MediaDisplay media) {
|
||||
this.display = media;
|
||||
}
|
||||
|
||||
private void update() {
|
||||
View.execInEventDispatch(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!display.isLoaded()) {
|
||||
return;
|
||||
}
|
||||
int totalFrames = display.getTotalFrames();
|
||||
int currentFrame = display.getCurrentFrame();
|
||||
int frameRate = display.getFrameRate();
|
||||
if (totalFrames == 0) {
|
||||
progress.setIndeterminate(true);
|
||||
} else {
|
||||
progress.setMaximum(totalFrames - 1);
|
||||
progress.setMinimum(0);
|
||||
progress.setValue(currentFrame);
|
||||
progress.setIndeterminate(false);
|
||||
}
|
||||
if (frameRate != 0) {
|
||||
timeLabel.setText(formatMs((currentFrame * 1000) / frameRate));
|
||||
totalTimeLabel.setText(formatMs(((totalFrames - 1) * 1000) / frameRate));
|
||||
}
|
||||
if (totalFrames <= 1 && isVisible()) {
|
||||
setVisible(false);
|
||||
}
|
||||
if (totalFrames > 1 && !isVisible()) {
|
||||
setVisible(true);
|
||||
}
|
||||
if (display.isPlaying() == paused) {
|
||||
paused = !paused;
|
||||
|
||||
if (paused) {
|
||||
pauseButton.setText(AppStrings.translate("preview.play"));
|
||||
pauseButton.setIcon(playIcon);
|
||||
} else {
|
||||
pauseButton.setText(AppStrings.translate("preview.pause"));
|
||||
pauseButton.setIcon(pauseIcon);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
switch (e.getActionCommand()) {
|
||||
case ACTION_PAUSE:
|
||||
if (paused) {
|
||||
display.play();
|
||||
} else {
|
||||
display.pause();
|
||||
}
|
||||
break;
|
||||
case ACTION_STOP:
|
||||
display.pause();
|
||||
display.rewind();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2010-2014 JPEXS
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.gui.player;
|
||||
|
||||
import com.jpexs.decompiler.flash.AppStrings;
|
||||
import com.jpexs.decompiler.flash.gui.View;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.Insets;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JProgressBar;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class PlayerControls extends JPanel implements ActionListener {
|
||||
|
||||
static final String ACTION_PAUSE = "PAUSE";
|
||||
static final String ACTION_STOP = "STOP";
|
||||
|
||||
private final JButton pauseButton;
|
||||
private boolean paused = false;
|
||||
private MediaDisplay display;
|
||||
private JProgressBar progress;
|
||||
private final Timer timer;
|
||||
private final JLabel timeLabel;
|
||||
private final JLabel totalTimeLabel;
|
||||
private static final Icon pauseIcon = View.getIcon("pause16");
|
||||
private static final Icon playIcon = View.getIcon("play16");
|
||||
|
||||
public PlayerControls(MediaDisplay display) {
|
||||
this.display = display;
|
||||
JPanel controlPanel = new JPanel(new BorderLayout());
|
||||
timeLabel = new JLabel("00:00.00");
|
||||
totalTimeLabel = new JLabel("00:00.00");
|
||||
controlPanel.add(timeLabel, BorderLayout.WEST);
|
||||
controlPanel.add(totalTimeLabel, BorderLayout.EAST);
|
||||
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
|
||||
JPanel buttonsPanel = new JPanel();
|
||||
buttonsPanel.setLayout(new FlowLayout());
|
||||
|
||||
pauseButton = new JButton(AppStrings.translate("preview.pause"), pauseIcon);
|
||||
pauseButton.setMargin(new Insets(0, 0, 0, 0));
|
||||
pauseButton.setActionCommand(ACTION_PAUSE);
|
||||
pauseButton.addActionListener(this);
|
||||
JButton stopButton = new JButton(AppStrings.translate("preview.stop"), View.getIcon("stop16"));
|
||||
stopButton.setMargin(new Insets(0, 0, 0, 0));
|
||||
stopButton.setActionCommand(ACTION_STOP);
|
||||
stopButton.addActionListener(this);
|
||||
buttonsPanel.add(pauseButton);
|
||||
buttonsPanel.add(stopButton);
|
||||
controlPanel.add(buttonsPanel, BorderLayout.CENTER);
|
||||
|
||||
progress = new JProgressBar();
|
||||
Dimension pref = progress.getPreferredSize();
|
||||
pref.height = 20;
|
||||
progress.setPreferredSize(pref);
|
||||
final PlayerControls t = this;
|
||||
progress.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
int frame = (int) Math.floor(e.getX() * t.display.getTotalFrames() / (double) progress.getWidth());
|
||||
boolean p = t.display.isPlaying();
|
||||
t.display.gotoFrame(frame);
|
||||
if (p) {
|
||||
t.display.play();
|
||||
}
|
||||
}
|
||||
});
|
||||
add(progress);
|
||||
add(controlPanel);
|
||||
timer = new Timer();
|
||||
timer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
update();
|
||||
}
|
||||
}, 100, 100);
|
||||
}
|
||||
|
||||
private String formatMs(long ms) {
|
||||
long s = ms / 1000;
|
||||
ms %= 1000;
|
||||
long m = s / 60;
|
||||
s %= 60;
|
||||
long h = m / 60;
|
||||
m %= 60;
|
||||
return "" + (h > 0 ? h + ":" : "") + pad(m) + ":" + pad(s) + "." + pad(ms / 10);
|
||||
}
|
||||
|
||||
private String pad(long t) {
|
||||
String ret = "" + t;
|
||||
while (ret.length() < 2) {
|
||||
ret = "0" + ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void setMedia(MediaDisplay media) {
|
||||
this.display = media;
|
||||
}
|
||||
|
||||
private void update() {
|
||||
if (!display.isLoaded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
View.execInEventDispatch(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int totalFrames = display.getTotalFrames();
|
||||
int currentFrame = display.getCurrentFrame();
|
||||
int frameRate = display.getFrameRate();
|
||||
if (totalFrames == 0) {
|
||||
progress.setIndeterminate(true);
|
||||
} else {
|
||||
progress.setMaximum(totalFrames - 1);
|
||||
progress.setMinimum(0);
|
||||
progress.setValue(currentFrame);
|
||||
progress.setIndeterminate(false);
|
||||
}
|
||||
if (frameRate != 0) {
|
||||
timeLabel.setText(formatMs((currentFrame * 1000) / frameRate));
|
||||
totalTimeLabel.setText(formatMs(((totalFrames - 1) * 1000) / frameRate));
|
||||
}
|
||||
if (totalFrames <= 1 && isVisible()) {
|
||||
setVisible(false);
|
||||
}
|
||||
if (totalFrames > 1 && !isVisible()) {
|
||||
setVisible(true);
|
||||
}
|
||||
if (display.isPlaying() == paused) {
|
||||
paused = !paused;
|
||||
|
||||
if (paused) {
|
||||
pauseButton.setText(AppStrings.translate("preview.play"));
|
||||
pauseButton.setIcon(playIcon);
|
||||
} else {
|
||||
pauseButton.setText(AppStrings.translate("preview.pause"));
|
||||
pauseButton.setIcon(pauseIcon);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
switch (e.getActionCommand()) {
|
||||
case ACTION_PAUSE:
|
||||
if (paused) {
|
||||
display.play();
|
||||
} else {
|
||||
display.pause();
|
||||
}
|
||||
break;
|
||||
case ACTION_STOP:
|
||||
display.pause();
|
||||
display.rewind();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ public class MemoryInputStream extends SeekableInputStream {
|
||||
|
||||
private final byte[] buffer;
|
||||
private long pos;
|
||||
private int count;
|
||||
private int startPos;
|
||||
private int maxLength;
|
||||
|
||||
@@ -51,10 +50,6 @@ public class MemoryInputStream extends SeekableInputStream {
|
||||
}
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public byte[] getAllRead() {
|
||||
return buffer;
|
||||
}
|
||||
@@ -75,11 +70,7 @@ public class MemoryInputStream extends SeekableInputStream {
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
if (pos > count) {
|
||||
count = (int) pos;
|
||||
}
|
||||
|
||||
if (pos < length()) {
|
||||
if (pos < maxLength) {
|
||||
int ret = buffer[(int) pos + startPos] & 0xff;
|
||||
pos++;
|
||||
return ret;
|
||||
@@ -88,10 +79,18 @@ public class MemoryInputStream extends SeekableInputStream {
|
||||
return -1;
|
||||
}
|
||||
|
||||
private int length() {
|
||||
return maxLength;
|
||||
@Override
|
||||
public int read(byte[] bytes) throws IOException {
|
||||
if (pos < maxLength) {
|
||||
int toRead = Math.min(available(), bytes.length);
|
||||
System.arraycopy(buffer, (int) pos + startPos, bytes, 0, toRead);
|
||||
pos += toRead;
|
||||
return toRead;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int available() throws IOException {
|
||||
return maxLength - (int) pos;
|
||||
|
||||
Reference in New Issue
Block a user