better Flash player integration using JavactiveX library

Issue #701 TTF file import/replace - still needs locales, better integration
Issue #702 Fixed GFX font export size
This commit is contained in:
Jindra Petřík
2014-10-22 08:22:36 +02:00
parent af29b2b4b2
commit d841b374c2
19 changed files with 262 additions and 540 deletions

View File

@@ -41,7 +41,11 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="463" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="importTTFButton" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="387" max="32767" attributes="0"/>
</Group>
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
@@ -91,7 +95,11 @@
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="415" max="32767" attributes="0"/>
<Group type="102" alignment="1" attributes="0">
<EmptySpace pref="341" max="32767" attributes="0"/>
<Component id="importTTFButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="85" max="-2" attributes="0"/>
</Group>
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
@@ -583,6 +591,14 @@
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="buttonPreviewFontActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="importTTFButton">
<Properties>
<Property name="text" type="java.lang.String" value="Import TTF"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="importTTFButtonActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Container>
</SubComponents>

View File

@@ -23,13 +23,25 @@ import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.base.FontTag;
import com.jpexs.decompiler.flash.tags.base.TextTag;
import com.jpexs.decompiler.flash.treeitems.TreeItem;
import com.jpexs.helpers.Helper;
import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.font.FontRenderContext;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileFilter;
/**
*
@@ -86,14 +98,14 @@ public class FontPanel extends javax.swing.JPanel {
return mainPanel.translate(key);
}
private void fontAddChars(FontTag ft, Set<Integer> selChars, String selFont) {
private void fontAddChars(FontTag ft, Set<Integer> selChars, Font font) {
FontTag f = (FontTag) mainPanel.tagTree.getCurrentTreeItem();
SWF swf = ft.getSwf();
String oldchars = f.getCharacters(swf.tags);
for (int ic : selChars) {
char c = (char) ic;
if (oldchars.indexOf((int) c) == -1) {
Font font = new Font(selFont, f.getFontStyle(), 1024);
font = font.deriveFont(f.getFontStyle(), 1024);
if (!font.canDisplay(c)) {
View.showMessageDialog(null, translate("error.font.nocharacter").replace("%char%", "" + c), translate("error"), JOptionPane.ERROR_MESSAGE);
return;
@@ -129,7 +141,7 @@ public class FontPanel extends javax.swing.JPanel {
continue;
}
}
f.addCharacter(c, fontSelection.getSelectedItem().toString());
f.addCharacter(c, font);
oldchars += c;
}
@@ -233,6 +245,7 @@ public class FontPanel extends javax.swing.JPanel {
buttonSave = new javax.swing.JButton();
buttonCancel = new javax.swing.JButton();
buttonPreviewFont = new javax.swing.JButton();
importTTFButton = new javax.swing.JButton();
addComponentListener(new java.awt.event.ComponentAdapter() {
public void componentResized(java.awt.event.ComponentEvent evt) {
@@ -494,11 +507,21 @@ public class FontPanel extends javax.swing.JPanel {
}
});
importTTFButton.setText("Import TTF");
importTTFButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
importTTFButtonActionPerformed(evt);
}
});
javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
jPanel2.setLayout(jPanel2Layout);
jPanel2Layout.setHorizontalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 463, Short.MAX_VALUE)
.addGroup(jPanel2Layout.createSequentialGroup()
.addContainerGap()
.addComponent(importTTFButton)
.addContainerGap(387, Short.MAX_VALUE))
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createSequentialGroup()
.addContainerGap()
@@ -536,7 +559,10 @@ public class FontPanel extends javax.swing.JPanel {
);
jPanel2Layout.setVerticalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 415, Short.MAX_VALUE)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup()
.addContainerGap(341, Short.MAX_VALUE)
.addComponent(importTTFButton)
.addGap(85, 85, 85))
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createSequentialGroup()
.addContainerGap()
@@ -588,25 +614,26 @@ public class FontPanel extends javax.swing.JPanel {
for (int c = 0; c < newchars.length(); c++) {
selChars.add(newchars.codePointAt(c));
}
fontAddChars((FontTag) item, selChars, fontSelection.getSelectedItem().toString());
fontAddChars((FontTag) item, selChars, new Font(fontSelection.getSelectedItem().toString(),Font.PLAIN,12));
fontAddCharactersField.setText("");
mainPanel.reload(true);
}
}//GEN-LAST:event_fontAddCharsButtonActionPerformed
private void fontEmbedButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fontEmbedButtonActionPerformed
TreeItem item = mainPanel.tagTree.getCurrentTreeItem();
if (item instanceof FontTag) {
FontTag fontTag = (FontTag) item;
FontEmbedDialog fed = new FontEmbedDialog(fontSelection.getSelectedItem().toString(), fontAddCharactersField.getText(), fontTag.getFontStyle());
if (fed.display()) {
FontTag ft = (FontTag) item;
FontEmbedDialog fed = new FontEmbedDialog(fontSelection.getSelectedItem().toString(), fontAddCharactersField.getText(), ft.getFontStyle());
if (fed.display()) {
Set<Integer> selChars = fed.getSelectedChars();
if (!selChars.isEmpty()) {
String selFont = fed.getSelectedFont();
fontSelection.setSelectedItem(selFont);
fontAddChars(fontTag, selChars, selFont);
fontAddCharactersField.setText("");
mainPanel.reload(true);
String selFont = fed.getSelectedFont();
fontSelection.setSelectedItem(selFont);
fontAddChars(ft, selChars, new Font(selFont,Font.PLAIN,10));
fontAddCharactersField.setText("");
mainPanel.reload(true);
}
}
}
@@ -651,6 +678,59 @@ public class FontPanel extends javax.swing.JPanel {
jPanel1.updateUI();
}//GEN-LAST:event_formComponentResized
private void importTTFButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_importTTFButtonActionPerformed
TreeItem item = mainPanel.tagTree.getCurrentTreeItem();
if (item instanceof FontTag) {
FontTag ft = (FontTag) item;
JFileChooser fc = new JFileChooser();
fc.setCurrentDirectory(new File(Configuration.lastOpenDir.get()));
FileFilter ttfFilter = new FileFilter() {
@Override
public boolean accept(File f) {
return (f.getName().toLowerCase().endsWith(".ttf")) || (f.isDirectory());
}
@Override
public String getDescription() {
return "TTF files";
}
};
fc.setFileFilter(ttfFilter);
fc.setAcceptAllFileFilterUsed(false);
JFrame fr = new JFrame();
View.setWindowIcon(fr);
int returnVal = fc.showOpenDialog(fr);
if (returnVal == JFileChooser.APPROVE_OPTION) {
Configuration.lastOpenDir.set(Helper.fixDialogFile(fc.getSelectedFile()).getParentFile().getAbsolutePath());
File selfile = Helper.fixDialogFile(fc.getSelectedFile());
Set<Integer> selChars = new HashSet<>();
try {
Font f = Font.createFont(Font.TRUETYPE_FONT, selfile);
int required[] = new int[]{0x0001, 0x0000, 0x000D, 0x0020};
loopi:for(char i=0;i<Character.MAX_VALUE;i++){
for(int r:required){
if(r==i){
continue loopi;
}
}
if(f.canDisplay((int)i)){
selChars.add((int)i);
}
}
fontAddChars(ft,selChars, f);
mainPanel.reload(true);
} catch (FontFormatException ex) {
JOptionPane.showMessageDialog(mainPanel, "Invalid TTF font");
} catch (IOException ex) {
Logger.getLogger(FontPanel.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}//GEN-LAST:event_importTTFButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton buttonCancel;
private javax.swing.JButton buttonEdit;
@@ -670,6 +750,7 @@ public class FontPanel extends javax.swing.JPanel {
private javax.swing.JLabel fontLeadingLabel;
private javax.swing.JLabel fontNameLabel;
private javax.swing.JComboBox fontSelection;
private javax.swing.JButton importTTFButton;
private javax.swing.JLabel jLabel11;
private javax.swing.JPanel jPanel1;
private javax.swing.JPanel jPanel2;

View File

@@ -1916,7 +1916,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
View.showMessageDialog(null, translate("error.font.nocharacter").replace("%char%", "" + character), translate("error"), JOptionPane.ERROR_MESSAGE);
return false;
}
font.addCharacter(character, fontName);
font.addCharacter(character, f);
return true;
}
@@ -2269,7 +2269,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
TreeItem tagObj = treeNode.getItem();
if (flashPanel != null) {
flashPanel.specialPlayback = false;
//flashPanel.specialPlayback = false;
}
previewPanel.clear();
if (soundThread != null) {

View File

@@ -781,7 +781,7 @@ public class PreviewPanel extends JSplitPane implements ActionListener {
new ShowFrameTag(swf).writeTag(sos2);
if (flashPanel != null) {
flashPanel.specialPlayback = true;
//flashPanel.specialPlayback = true;
}
} else if (tagObj instanceof DefineVideoStreamTag) {

View File

@@ -17,43 +17,19 @@
package com.jpexs.decompiler.flash.gui.player;
import com.jpexs.decompiler.flash.gui.FlashUnsupportedException;
import com.jpexs.decompiler.flash.gui.View;
import com.jpexs.helpers.CancellableWorker;
import com.jpexs.helpers.utf8.Utf8Helper;
import com.sun.jna.Native;
import com.jpexs.javactivex.ActiveX;
import com.jpexs.javactivex.example.controls.flash.ShockwaveFlash;
import com.sun.jna.Platform;
import com.sun.jna.WString;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.SHELLEXECUTEINFO;
import com.sun.jna.platform.win32.Shell32;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.platform.win32.WinUser;
import com.sun.jna.ptr.IntByReference;
import java.awt.AWTException;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Panel;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.image.BufferedImage;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JPopupMenu;
import org.pushingpixels.substance.internal.contrib.jgoodies.looks.common.ShadowPopupFactory;
/**
*
@@ -61,37 +37,10 @@ import org.pushingpixels.substance.internal.contrib.jgoodies.looks.common.Shadow
*/
public class FlashPlayerPanel extends Panel implements Closeable, MediaDisplay {
private boolean executed = false;
private String flash;
private HANDLE pipe;
private HANDLE process;
private WinDef.HWND hwnd;
private WinDef.HWND hwndFrame;
private Component frame;
private ShockwaveFlash flash;
private boolean stopped = true;
private static final int CMD_PLAY = 1;
private static final int CMD_RESIZE = 2;
private static final int CMD_BGCOLOR = 3;
private static final int CMD_CURRENT_FRAME = 4;
private static final int CMD_TOTAL_FRAMES = 5;
private static final int CMD_PAUSE = 6;
private static final int CMD_RESUME = 7;
private static final int CMD_PLAYING = 8;
private static final int CMD_REWIND = 9;
private static final int CMD_GOTO = 10;
private static final int CMD_CALL = 11;
private static final int CMD_GETVARIABLE = 12;
private static final int CMD_SETVARIABLE = 13;
private static final int CMD_CHECKCLICK = 14;
private static final int CMD_ZOOM = 15;
private static final int PIPE_TIMEOUT_MS = 1000;
private int frameRate;
public boolean specialPlayback = false;
private boolean specialPlaying = false;
private JPopupMenu rightClickMenu = null;
private Timer rightClickTimer;
@Override
public boolean screenAvailable() {
@@ -113,238 +62,54 @@ public class FlashPlayerPanel extends Panel implements Closeable, MediaDisplay {
return 0;
}
private synchronized int checkClick(Point ret) throws IOException {
if (pipe != null) {
writeToPipe(new byte[]{CMD_CHECKCLICK});
byte res[] = new byte[1];
readFromPipe(res);
int button = res[0];
if (button > 0) {
res = new byte[4];
readFromPipe(res);
ret.x = ((res[0] & 0xff) << 8) + (res[1] & 0xff);
ret.y = ((res[2] & 0xff) << 8) + (res[3] & 0xff);
}
return button;
}
return 0;
}
private double zoom = 1.0;
@Override
public synchronized void zoom(double zoom) {
if (pipe != null) {
try {
long zoomint = Math.round(100 / (zoom / this.zoom));
if (zoom == 1.0) {
zoomint = 0;
}
this.zoom = zoom;
writeToPipe(new byte[]{CMD_ZOOM});
writeToPipe(new byte[]{(byte) ((zoomint >> 8) & 0xff), (byte) (zoomint & 0xff)});
} catch (IOException ex) {
//ignore
}
int zoomint = (int) Math.round(100 / (zoom / this.zoom));
if (zoom == 1.0) {
zoomint = 0;
}
flash.Zoom(zoomint);
}
public synchronized String getVariable(String name) throws IOException {
if (pipe != null) {
writeToPipe(new byte[]{CMD_GETVARIABLE});
int nameLen = name.getBytes().length;
writeToPipe(new byte[]{(byte) ((nameLen >> 8) & 0xff), (byte) (nameLen & 0xff)});
writeToPipe(name.getBytes());
byte res[] = new byte[2];
readFromPipe(res);
int retLen = ((res[0] & 0xff) << 8) + (res[1] & 0xff);
res = new byte[retLen];
readFromPipe(res);
String ret = new String(res, 0, retLen);
return ret;
}
return null;
return flash.GetVariable(name);
}
public synchronized void setVariable(String name, String value) throws IOException {
if (pipe != null) {
writeToPipe(new byte[]{CMD_SETVARIABLE});
int nameLen = name.getBytes().length;
writeToPipe(new byte[]{(byte) ((nameLen >> 8) & 0xff), (byte) (nameLen & 0xff)});
writeToPipe(name.getBytes());
int valLen = value.getBytes().length;
writeToPipe(new byte[]{(byte) ((valLen >> 8) & 0xff), (byte) (valLen & 0xff)});
writeToPipe(value.getBytes());
}
flash.SetVariable(name, value);
}
public synchronized String call(String callString) throws IOException {
if (pipe != null) {
writeToPipe(new byte[]{CMD_CALL});
int callLen = callString.getBytes().length;
writeToPipe(new byte[]{(byte) ((callLen >> 8) & 0xff), (byte) (callLen & 0xff)});
writeToPipe(callString.getBytes());
byte res[] = new byte[2];
readFromPipe(res);
int retLen = ((res[0] & 0xff) << 8) + (res[1] & 0xff);
res = new byte[retLen];
readFromPipe(res);
String ret = new String(res, 0, retLen);
return ret;
}
return null;
}
private synchronized void resize() throws IOException {
if (pipe != null) {
writeToPipe(new byte[]{CMD_RESIZE});
writeToPipe(new byte[]{
(byte) (getWidth() / 256), (byte) (getWidth() % 256),
(byte) (getHeight() / 256), (byte) (getHeight() % 256),});
}
}
private int __getCurrentFrame() throws IOException {
byte[] res = new byte[2];
writeToPipe(new byte[]{CMD_CURRENT_FRAME});
readFromPipe(res);
return ((res[0] & 0xff) << 8) + (res[1] & 0xff);
return flash.CallFunction(callString);
}
@Override
public synchronized int getCurrentFrame() {
try {
if (specialPlayback) {
if (!specialPlaying) {
return specialPosition;
}
String posStr = getVariable("_root.my_sound.position");
if (posStr != null) {
return Integer.parseInt(posStr);
}
}
return __getCurrentFrame();
} catch (IOException ex) {
return 0;
}
return flash.getFrameNum();
}
@Override
public synchronized int getTotalFrames() {
try {
if (specialPlayback) {
String durStr = getVariable("_root.my_sound.duration");
if (durStr != null) {
return Integer.parseInt(durStr);
}
}
byte[] res = new byte[2];
writeToPipe(new byte[]{CMD_TOTAL_FRAMES});
readFromPipe(res);
return ((res[0] & 0xff) << 8) + (res[1] & 0xff);
} catch (IOException ex) {
return 0;
}
return flash.getTotalFrames();
}
@Override
public synchronized void setBackground(Color color) {
try {
writeToPipe(new byte[]{CMD_BGCOLOR});
writeToPipe(new byte[]{(byte) color.getRed(), (byte) color.getGreen(), (byte) color.getBlue()});
} catch (IOException ex) {
}
}
public void setRightClickMenu(JPopupMenu menu) {
rightClickMenu = menu;
flash.setBackgroundColor((color.getRed() << 16) + (color.getGreen() << 8) + color.getBlue());
}
public FlashPlayerPanel(Component frame) {
if (!Platform.isWindows()) {
throw new FlashUnsupportedException();
}
this.frame = frame;
//this.add(rightClickMenu);
addComponentListener(new ComponentListener() {
@Override
public void componentResized(ComponentEvent e) {
try {
resize();
} catch (IOException ex) {
}
}
@Override
public void componentMoved(ComponentEvent e) {
}
@Override
public void componentShown(ComponentEvent e) {
componentResized(e);
}
@Override
public void componentHidden(ComponentEvent e) {
}
});
}
private synchronized void execute() {
if (!executed) {
hwnd = new WinDef.HWND();
hwnd.setPointer(Native.getComponentPointer(this));
hwndFrame = new WinDef.HWND();
hwndFrame.setPointer(Native.getComponentPointer(frame));
startFlashPlayer();
executed = true;
}
}
private void restartFlashPlayer() {
Kernel32.INSTANCE.TerminateProcess(process, 0);
Kernel32.INSTANCE.CloseHandle(pipe);
startFlashPlayer();
}
private void startFlashPlayer() {
String path = Utf8Helper.urlDecode(FlashPlayerPanel.class.getProtectionDomain().getCodeSource().getLocation().getPath());
String appDir = new File(path).getParentFile().getAbsolutePath();
if (!appDir.endsWith("\\")) {
appDir += "\\";
}
String exePath = appDir + "lib\\FlashPlayer.exe";
File f = new File(exePath);
if (!f.exists()) {
Logger.getLogger(FlashPlayerPanel.class.getName()).log(Level.SEVERE, "FlashPlayer.exe not found: " + f.getPath());
return;
}
String pipeName = "\\\\.\\pipe\\ffdec_flashplayer_" + hwnd.getPointer().hashCode();
pipe = Kernel32.INSTANCE.CreateNamedPipe(pipeName, Kernel32.PIPE_ACCESS_DUPLEX, Kernel32.PIPE_TYPE_BYTE, 1, 4096, 4096, 0, null);
SHELLEXECUTEINFO sei = new SHELLEXECUTEINFO();
sei.fMask = 0x00000040;
sei.lpFile = new WString(exePath);
sei.lpParameters = new WString(hwnd.getPointer().hashCode() + " " + hwndFrame.getPointer().hashCode());
sei.nShow = WinUser.SW_NORMAL;
Shell32.INSTANCE.ShellExecuteEx(sei);
process = sei.hProcess;
Kernel32.INSTANCE.ConnectNamedPipe(pipe, null);
flash = ActiveX.createObject(ShockwaveFlash.class, this);
}
public synchronized void stopSWF() {
if (rightClickTimer != null) {
rightClickTimer.cancel();
rightClickTimer = null;
}
displaySWF("-", null, 1);
stopped = true;
}
@@ -363,183 +128,51 @@ public class FlashPlayerPanel extends Panel implements Closeable, MediaDisplay {
}
}
public synchronized void displaySWF(String flash, Color bgColor, int frameRate) {
try {
zoom = 1.0;
this.flash = flash;
repaint();
this.frameRate = frameRate;
execute();
if (bgColor != null) {
setBackground(bgColor);
}
resize();
if (pipe != null) {
writeToPipe(new byte[]{CMD_PLAY});
writeToPipe(new byte[]{(byte) flash.getBytes().length});
writeToPipe(flash.getBytes());
}
stopped = false;
specialPlaying = false;
specialPosition = 0;
if (specialPlayback) {
play();
}
if (rightClickTimer != null) {
rightClickTimer.cancel();
}
rightClickTimer = new Timer();
rightClickTimer.schedule(new TimerTask() {
public synchronized void displaySWF(String flashName, Color bgColor, int frameRate) {
@Override
public void run() {
try {
final Point pt = new Point();
final int button = checkClick(pt);
View.execInEventDispatch(new Runnable() {
@Override
public void run() {
if (rightClickMenu != null) {
if (button == 2) {
ShadowPopupFactory.uninstall();
rightClickMenu.show(FlashPlayerPanel.this, pt.x, pt.y);
ShadowPopupFactory.install();
}
if (button == 1) {
rightClickMenu.setVisible(false);
}
}
}
});
} catch (IOException ex) {
//ignore
}
}
}, 100, 100);
} catch (IOException ex) {
zoom = 1.0;
//this.frameRate = frameRate;
if (bgColor != null) {
setBackground(bgColor);
}
flash.setMovie(flashName);
//play
stopped = false;
}
@Override
public void close() throws IOException {
if (rightClickTimer != null) {
rightClickTimer.cancel();
rightClickTimer = null;
}
Kernel32.INSTANCE.CloseHandle(pipe);
Kernel32.INSTANCE.TerminateProcess(process, 0);
}
@Override
public void paint(Graphics g) {
if (flash != null) {
execute();
}
super.paint(g);
}
private int specialPosition = 0;
private synchronized void __pause() throws IOException {
writeToPipe(new byte[]{CMD_PAUSE});
}
@Override
public void pause() {
try {
if (specialPlayback) {
specialPosition = getCurrentFrame();
__gotoFrame(3);
__play();
specialPlaying = false;
return;
}
__pause();
} catch (IOException ex) {
}
flash.Stop();
}
@Override
public void rewind() {
try {
if (specialPlayback) {
boolean plays = specialPlaying;
pause();
specialPosition = 0;
if (plays) {
play();
}
return;
}
writeToPipe(new byte[]{CMD_REWIND});
} catch (IOException ex) {
}
}
private synchronized void __play() throws IOException {
writeToPipe(new byte[]{CMD_RESUME});
flash.Rewind();
}
@Override
public void play() {
try {
if (specialPlayback) {
double p = (((double) specialPosition) / 1000.0);
setVariable("_root.execParam", "" + p);
__gotoFrame(1);
__play();
specialPlaying = true;
return;
}
__play();
} catch (IOException ex) {
}
flash.Play();
}
@Override
public boolean isPlaying() {
try {
if (specialPlayback) {
return specialPlaying;
}
writeToPipe(new byte[]{CMD_PLAYING});
byte[] res = new byte[1];
readFromPipe(res);
return res[0] == 1;
} catch (IOException ex) {
return false;
}
}
private synchronized void __gotoFrame(int frame) throws IOException {
writeToPipe(new byte[]{CMD_GOTO});
writeToPipe(new byte[]{(byte) ((frame >> 8) & 0xff), (byte) (frame & 0xff)});
return flash.IsPlaying();
}
@Override
public void gotoFrame(int frame) {
try {
if (specialPlayback) {
if (specialPlaying) {
pause();
specialPosition = frame;
play();
} else {
specialPosition = frame;
}
return;
}
__gotoFrame(frame);
} catch (IOException ex) {
}
flash.GotoFrame(frame);
}
@Override
public int getFrameRate() {
if (specialPlayback) {
return 1000;
}
return frameRate;
}
@@ -548,69 +181,4 @@ public class FlashPlayerPanel extends Panel implements Closeable, MediaDisplay {
return !isStopped();
}
private synchronized boolean writeToPipe(final byte[] data) throws IOException {
final IntByReference ibr = new IntByReference();
int result = -1;
try {
result = CancellableWorker.call(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
boolean result = Kernel32.INSTANCE.WriteFile(pipe, data, data.length, ibr, null);
if (!result) {
return Kernel32.INSTANCE.GetLastError();
}
if (ibr.getValue() != data.length) {
return -1;
}
return 0;
}
}, PIPE_TIMEOUT_MS, TimeUnit.MILLISECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException ex) {
// ignore
}
if (result != 0) {
if (result == Kernel32.ERROR_NO_DATA || result == -1) {
restartFlashPlayer();
throw new IOException("Pipe write error.");
} else {
// System.out.println("pipe write failed. datalength: " + data.length + " error:" + result);
}
}
return result == 0;
}
private synchronized boolean readFromPipe(final byte[] res) throws IOException {
final IntByReference ibr = new IntByReference();
int result = -1;
try {
result = CancellableWorker.call(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
int read = 0;
while (read < res.length) {
byte[] data = new byte[res.length - read];
boolean result = Kernel32.INSTANCE.ReadFile(pipe, data, data.length, ibr, null);
if (!result) {
return Kernel32.INSTANCE.GetLastError();
}
int readNow = ibr.getValue();
System.arraycopy(data, 0, res, read, readNow);
read += readNow;
}
return 0;
}
}, PIPE_TIMEOUT_MS, TimeUnit.MILLISECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException ex) {
// ignore
}
if (result != 0) {
if (result == Kernel32.ERROR_BROKEN_PIPE || result == -1) {
restartFlashPlayer();
throw new IOException("Pipe read error.");
} else {
// System.out.println("pipe read failed. result: " + result + " datalength: " + res.length + " received: " + ibr.getValue() + " error: " + result);
}
}
return result == 0;
}
}