From 53714b0450bfab0f77e9dbd02060ab9e0045321d Mon Sep 17 00:00:00 2001 From: honfika Date: Sat, 28 Jun 2014 22:09:14 +0200 Subject: [PATCH] stream reading improvements, collecting dump infos can be disabled --- src/com/jpexs/decompiler/flash/SWF.java | 6 +- .../decompiler/flash/SWFInputStream.java | 34 +- .../flash/configuration/Configuration.java | 4 + .../jpexs/decompiler/flash/gui/DumpTree.java | 86 ---- .../decompiler/flash/gui/DumpTreeModel.java | 84 ---- .../decompiler/flash/gui/DumpViewPanel.java | 98 ----- .../decompiler/flash/gui/LoadingPanel.java | 14 +- .../flash/gui/player/PlayerControls.java | 379 +++++++++--------- src/com/jpexs/helpers/MemoryInputStream.java | 25 +- 9 files changed, 239 insertions(+), 491 deletions(-) delete mode 100644 src/com/jpexs/decompiler/flash/gui/DumpTree.java delete mode 100644 src/com/jpexs/decompiler/flash/gui/DumpTreeModel.java delete mode 100644 src/com/jpexs/decompiler/flash/gui/DumpViewPanel.java diff --git a/src/com/jpexs/decompiler/flash/SWF.java b/src/com/jpexs/decompiler/flash/SWF.java index ba48adb9d..fdf8af9e5 100644 --- a/src/com/jpexs/decompiler/flash/SWF.java +++ b/src/com/jpexs/decompiler/flash/SWF.java @@ -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); } diff --git a/src/com/jpexs/decompiler/flash/SWFInputStream.java b/src/com/jpexs/decompiler/flash/SWFInputStream.java index 0219a9174..2441d76ea 100644 --- a/src/com/jpexs/decompiler/flash/SWFInputStream.java +++ b/src/com/jpexs/decompiler/flash/SWFInputStream.java @@ -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()); diff --git a/src/com/jpexs/decompiler/flash/configuration/Configuration.java b/src/com/jpexs/decompiler/flash/configuration/Configuration.java index 71c80c5c7..ce5397bf4 100644 --- a/src/com/jpexs/decompiler/flash/configuration/Configuration.java +++ b/src/com/jpexs/decompiler/flash/configuration/Configuration.java @@ -94,6 +94,10 @@ public class Configuration { @ConfigurationCategory("display") public static final ConfigurationItem dumpView = null; + @ConfigurationDefaultBoolean(true) + @ConfigurationCategory("display") + public static final ConfigurationItem dumpInfoCollecting = null; + @ConfigurationDefaultBoolean(false) @ConfigurationCategory("ui") public static final ConfigurationItem gotoMainClassOnStartup = null; diff --git a/src/com/jpexs/decompiler/flash/gui/DumpTree.java b/src/com/jpexs/decompiler/flash/gui/DumpTree.java deleted file mode 100644 index 21e335ca5..000000000 --- a/src/com/jpexs/decompiler/flash/gui/DumpTree.java +++ /dev/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 . - */ -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); - } - } - } - -} diff --git a/src/com/jpexs/decompiler/flash/gui/DumpTreeModel.java b/src/com/jpexs/decompiler/flash/gui/DumpTreeModel.java deleted file mode 100644 index 877998a98..000000000 --- a/src/com/jpexs/decompiler/flash/gui/DumpTreeModel.java +++ /dev/null @@ -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 . - */ -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 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) { - } - -} diff --git a/src/com/jpexs/decompiler/flash/gui/DumpViewPanel.java b/src/com/jpexs/decompiler/flash/gui/DumpViewPanel.java deleted file mode 100644 index 8ebf563a7..000000000 --- a/src/com/jpexs/decompiler/flash/gui/DumpViewPanel.java +++ /dev/null @@ -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 . - */ -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 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); - } -} diff --git a/src/com/jpexs/decompiler/flash/gui/LoadingPanel.java b/src/com/jpexs/decompiler/flash/gui/LoadingPanel.java index 84a19f988..db2cece80 100644 --- a/src/com/jpexs/decompiler/flash/gui/LoadingPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/LoadingPanel.java @@ -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); } diff --git a/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java b/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java index a5ac833d1..9a75252a0 100644 --- a/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java +++ b/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java @@ -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 . - */ -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 . + */ +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; + } + } +} diff --git a/src/com/jpexs/helpers/MemoryInputStream.java b/src/com/jpexs/helpers/MemoryInputStream.java index abc28118b..c30d2ca26 100644 --- a/src/com/jpexs/helpers/MemoryInputStream.java +++ b/src/com/jpexs/helpers/MemoryInputStream.java @@ -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;