Ticket #2241: 2241_final.patch
File 2241_final.patch, 15.6 KB (added by meddle, 15 years ago) |
---|
-
modules/org.sophie2.extra.func.browser/src/main/java/org/sophie2/extra/func/browser/view/NativeBrowserFrameView.java
### Eclipse Workspace Patch 1.0 #P sophie
65 65 return getBean().makeProp(model.class); 66 66 } 67 67 68 @Override 69 public void initAccess(ResourceAccess access) { 70 super.initAccess(access); 71 // set the first frame 72 setTime(TimePos.INTRO_START); 68 private void loadUrl() { 73 69 String url = model().get().getUrl(); 74 70 if (url.startsWith("http://") == false) { 75 71 url = "http://" + url; 76 72 } 77 73 this.bridge.load(url); 78 74 } 75 76 @Override 77 public void initAccess(ResourceAccess access) { 78 super.initAccess(access); 79 // set the first frame 80 setTime(TimePos.INTRO_START); 81 loadUrl(); 82 } 79 83 80 84 @Override 81 85 public Prop<NativeBrowserContentSceneElement> contentElement() { … … 94 98 @Override 95 99 public void setTime(TimePos time) { 96 100 super.setTime(time); 101 if (TimePos.MAIN_START.equals(time)) { 102 loadUrl(); 103 } 104 97 105 ImmImage grabbedPage = this.bridge.grabPage(); 98 106 if (grabbedPage != null) { 99 107 contentElement().get().image().set(grabbedPage); -
modules/org.sophie2.main.media.natlib/src/main/java/org/sophie2/main/media/natlib/decoder/NativeMediaHandler.java
161 161 162 162 private final AudioThread audioThread; 163 163 164 165 166 164 /** 167 165 * Constructs by the file data. 168 166 * -
modules/org.sophie2.base.natlib/src/main/java/org/sophie2/base/natlib/NativeBridgeRegistry.java
1 package org.sophie2.base.natlib; 2 3 import java.util.Comparator; 4 import java.util.Timer; 5 import java.util.TimerTask; 6 import java.util.TreeSet; 7 8 /** 9 * Registry for the {@link NativeBridge}s. All the bridges when started are 10 * registered and if they are not used for some defined time, they are cleared 11 * from the registry and stopped. 12 * 13 * The registry is singleton for now... 14 * 15 * All the constants in this class and it's sub-classes are 16 * determined through testing. 17 * 18 * @author meddle 19 */ 20 public class NativeBridgeRegistry { 21 22 /** 23 * The time period in milliseconds, the registry checks 24 * if there are native processes that are not active for too long. 25 */ 26 private final static long UPDATE_PERIOD = 5000; 27 28 /** 29 * The maximum time in milliseconds one process should be 30 * not active before it is stopped. 31 */ 32 private final static long TIME_OUT = 4000; 33 34 private static NativeBridgeRegistry instance = null; 35 36 /** 37 * Implementation of the {@link Comparator} interface to take in 38 * mind the {@link NativeBridge#getLastCalled()} when comparing. 39 * 40 * @author meddle 41 */ 42 protected static class BridgeComparator implements Comparator<NativeBridge> { 43 44 public int compare(NativeBridge bridge1, NativeBridge bridge2) { 45 if (bridge1.getLastCalled() > bridge2.getLastCalled()) { 46 return 1; 47 } else if (bridge1.getLastCalled() < bridge2.getLastCalled()) { 48 return -1; 49 } 50 51 return 0; 52 } 53 54 } 55 56 private final Timer timer; 57 58 private TreeSet<NativeBridge> bridges; 59 60 /** 61 * The {@link TimerTask} that stops the not active native processes. 62 * 63 * @author meddle 64 */ 65 protected class ActivityObserver extends TimerTask { 66 67 /** 68 * The percent of the bridges to check for activity. 69 * in decimal fraction. 70 */ 71 private final static float SUSPEND_PERCENT = 0.20f; 72 73 @Override 74 @SuppressWarnings("synthetic-access") 75 public void run() { 76 synchronized (NativeBridgeRegistry.this.bridges) { 77 TreeSet<NativeBridge> sortedBridges = new TreeSet<NativeBridge>(new BridgeComparator()); 78 sortedBridges.addAll(NativeBridgeRegistry.this.bridges); 79 80 NativeBridgeRegistry.this.bridges = sortedBridges; 81 clearSuspended(); 82 } 83 } 84 85 @SuppressWarnings("synthetic-access") 86 private void clearSuspended() { 87 int size = NativeBridgeRegistry.this.bridges.size(); 88 int index = (int) Math.ceil(size * SUSPEND_PERCENT); 89 long now = System.currentTimeMillis(); 90 91 for (int i = 0; i < index; i++) { 92 93 NativeBridge first = NativeBridgeRegistry.this.bridges.first(); 94 95 long suspend = now - first.getLastCalled(); 96 if (suspend >= TIME_OUT) { 97 NativeBridgeRegistry.this.unregisterFirst(); 98 } else { 99 break; 100 } 101 } 102 } 103 } 104 105 private NativeBridgeRegistry() { 106 this.bridges = new TreeSet<NativeBridge>(new BridgeComparator()); 107 this.timer = new Timer(true); 108 109 this.timer.schedule(new ActivityObserver(), 0, UPDATE_PERIOD); 110 } 111 112 /** 113 * Getter for the {@link NativeBridge}s registered. 114 * 115 * @return 116 * The sorted set of the bridges. 117 */ 118 protected TreeSet<NativeBridge> getBridges() { 119 return this.bridges; 120 } 121 122 /** 123 * Getter of the instance of the singleton. 124 * 125 * @return 126 * The instance. 127 */ 128 public static NativeBridgeRegistry get() { 129 if (instance == null) { 130 instance = new NativeBridgeRegistry(); 131 } 132 133 return instance; 134 } 135 136 /** 137 * Registers a {@link NativeBridge} in the registry. 138 * 139 * @param bridge 140 * The bridge to register. 141 */ 142 public void register(NativeBridge bridge) { 143 synchronized (this.bridges) { 144 if (!this.bridges.contains(bridge)) { 145 this.bridges.add(bridge); 146 } 147 } 148 } 149 150 /** 151 * Unregisters and stops a bridge from the registry. 152 * 153 * @param bridge 154 * The bridge to unregister. 155 */ 156 public void unregister(NativeBridge bridge) { 157 synchronized (this.bridges) { 158 if (this.bridges.contains(bridge)) { 159 if (bridge.isRunning()) { 160 bridge.stop(); 161 } 162 163 this.bridges.remove(bridge); 164 } 165 } 166 } 167 168 /** 169 * Unregisters and stops the first bridge in the registry. 170 */ 171 private void unregisterFirst() { 172 synchronized (this.bridges) { 173 NativeBridge first = this.bridges.first(); 174 175 if (first.isRunning()) { 176 first.stop(); 177 } 178 179 this.bridges.remove(first); 180 } 181 } 182 183 /** 184 * Unregisters all the processes from the registry. 185 */ 186 public void unregisterAll() { 187 while (!this.bridges.isEmpty()) { 188 unregisterFirst(); 189 } 190 } 191 } -
modules/org.sophie2.extra.func.browser/src/main/java/org/sophie2/extra/func/browser/nat/bridge/BrowserNativeBridge.java
11 11 import org.sophie2.base.natlib.NativeBridge; 12 12 import org.sophie2.base.natlib.OkResponse; 13 13 import org.sophie2.base.natlib.Response; 14 import org.sophie2.extra.func.browser.model.BrowserFrameR4; 14 15 import org.sophie2.extra.func.browser.nat.commands.GetInfoCommand; 15 16 import org.sophie2.extra.func.browser.nat.commands.GrabPageCommand; 16 17 import org.sophie2.extra.func.browser.nat.commands.LoadCommand; … … 33 34 */ 34 35 public class BrowserNativeBridge extends NativeBridge { 35 36 37 private int lastWidth = 0; 38 private int lastHeight = 0; 39 private String lastUrl = BrowserFrameR4.KEY_URL.getDefault(); 40 41 36 42 @Override 37 43 public void stop() { 38 44 SwingUtilities.invokeLater(new Runnable() { … … 51 57 * The URL of the page to load. 52 58 */ 53 59 public void load(final String url) { 60 this.lastUrl = url; 61 54 62 SwingUtilities.invokeLater(new Runnable() { 55 63 public void run() { 56 64 sendCommand(new LoadCommand(url), OkResponse.class); … … 61 69 /** 62 70 * Returns a capture of the current web page. 63 71 * 64 * @return A capture of the current web page. 72 * @return 73 * A capture of the current web page. 65 74 */ 66 75 public ImmImage grabPage() { 67 76 PageGrabResponse response = sendCommand(new GrabPageCommand(), PageGrabResponse.class); … … 199 208 } 200 209 }); 201 210 } 202 211 212 @Override 213 protected Process getNativeProcess() { 214 boolean wasRunning = isRunning(); 215 216 Process process = super.getNativeProcess(); 217 218 if (!wasRunning) { 219 assert isRunning(); 220 resize(this.lastWidth, this.lastHeight); 221 load(this.lastUrl); 222 } 223 224 return process; 225 } 226 203 227 /** 204 228 * Resizes the native browser. 205 229 * … … 209 233 * New height. 210 234 */ 211 235 public void resize(final int width, final int height) { 236 this.lastWidth = width; 237 this.lastHeight = height; 238 212 239 sendCommand(new ResizeCommand(width, height), OkResponse.class); 213 240 } 214 241 -
modules/org.sophie2.base.natlib/src/main/java/org/sophie2/base/natlib/NativeBridge.java
20 20 * 21 21 * This class is intended to be extended by every specific native wrapper. It 22 22 * contains common methods for sending {@link Command}s and receiving 23 * {@link Response}s 23 * {@link Response}s. 24 24 * 25 * @author nenko, sveto, milo 25 * The {@link Process}es in the bridges are killed periodically when 26 * unused so write the sub classes stateless enough... 26 27 * 28 * @author nenko, sveto, milo 29 * @author meddle 27 30 */ 28 31 public abstract class NativeBridge { 29 32 … … 50 53 try { 51 54 SophieLog.debug(getExecutableString()); 52 55 this.nativeProcess = Runtime.getRuntime().exec(new String[] { getExecutableString() }); 53 this.nativeStderr = new BufferedReader( new InputStreamReader(this.nativeProcess54 .getErrorStream()));56 this.nativeStderr = new BufferedReader( 57 new InputStreamReader(this.nativeProcess.getErrorStream())); 55 58 // SophieLog.trace("sending start-command..."); 56 59 try { 57 60 int exit = this.nativeProcess.exitValue(); … … 72 75 } 73 76 this.nativeProcess = null; 74 77 this.nativeStderr = null; 78 NativeBridgeRegistry.get().unregister(this); 75 79 } 76 80 } 77 81 SophieLog.debug("NativeBridge started = " + this.started); … … 83 87 } catch (InterruptedException e) { 84 88 throw new RuntimeException(e); 85 89 } 90 91 NativeBridgeRegistry.get().register(this); 86 92 dumpError(); 87 93 88 94 } 89 95 90 96 /** 97 * Retrieves the native process, if it is not running, 98 * <code>start()</code> is called. 99 * 100 * @return 101 * The running native process. 102 */ 103 protected Process getNativeProcess() { 104 if (!isRunning()) { 105 start(); 106 } 107 108 return this.nativeProcess; 109 } 110 111 /** 91 112 * This method sends stop command to the native process and then destroys 92 113 * it. The stop command is sent if there's any action that would be done 93 114 * before stopping the process. … … 100 121 } catch (RuntimeException e) { 101 122 SophieLog.info("Problem while stopping native process : ", e); 102 123 } 124 103 125 this.started = false; 104 this.nativeProcess.destroy(); 105 this.nativeProcess = null; 126 if (this.nativeProcess != null) { 127 this.nativeProcess.destroy(); 128 this.nativeProcess = null; 129 } 106 130 this.nativeStderr = null; 131 } 107 132 133 private long lastCalled = System.currentTimeMillis(); 134 135 /** 136 * Retrieves when the bridge was last called. In other words 137 * when a command was send for the last time. 138 * 139 * @return 140 * The time when the bridge was last called. 141 */ 142 public long getLastCalled() { 143 return this.lastCalled; 108 144 } 109 145 110 146 /** … … 113 149 * @return The native standard input 114 150 */ 115 151 protected OutputStream getNativeStdin() { 116 return this.nativeProcess.getOutputStream();152 return getNativeProcess().getOutputStream(); 117 153 } 118 154 119 155 /** … … 122 158 * @return The native standard output 123 159 */ 124 160 protected InputStream getNativeStdout() { 125 return this.nativeProcess.getInputStream();161 return getNativeProcess().getInputStream(); 126 162 } 127 163 128 164 /** … … 170 206 } 171 207 return getNativeFile(prefix + getExecutableName() + suffix).getAbsolutePath(); 172 208 } 173 209 174 210 private File getNativeFile(String path) { 175 // //TODO: development version176 // final String nativesFolder = "sophie2-native";177 // File root = new File(".").getAbsoluteFile();178 // while (!Arrays.asList(root.list()).contains(nativesFolder)) {179 // root = root.getParentFile();180 // }181 // return new File(root.getAbsolutePath() + "/sophie2-native/target/" + path);182 211 // //TODO: development version 212 // final String nativesFolder = "sophie2-native"; 213 // File root = new File(".").getAbsoluteFile(); 214 // while (!Arrays.asList(root.list()).contains(nativesFolder)) { 215 // root = root.getParentFile(); 216 // } 217 // return new File(root.getAbsolutePath() + "/sophie2-native/target/" + path); 218 183 219 //Release version: 184 220 File nativeFile = FileEntryManager.get().getWritableFileEntry("natives/" + path); 185 221 String[] commands = new String[] {"chmod", "+x", nativeFile.getAbsolutePath()}; … … 192 228 } 193 229 } 194 230 return nativeFile; 195 231 196 232 } 197 233 198 234 /** … … 299 335 * @return A {@link Response} for the sent {@link Command} 300 336 */ 301 337 public <T extends Response> T sendCommand(Command command, Class<T> expectedClass) { 302 assert isRunning(); 338 long now = System.currentTimeMillis(); 339 this.lastCalled = now; 340 303 341 writeCommand(command); 304 342 // SophieLog.trace("Sent " + command); 305 343 dumpError(); … … 316 354 * to be written to stdin of the process 317 355 */ 318 356 protected void writeCommand(Command command) { 319 assert isRunning();357 //assert isRunning(); 320 358 try { 321 359 int size = command.getData().getSize(); 322 360 // SophieLog.trace("command sending to native: ID = " … … 347 385 * @return A {@link Response} read from the stdout of the process 348 386 */ 349 387 protected <T extends Response> T readResponse(Class<T> expectedClass) { 350 assert isRunning();388 //assert isRunning(); 351 389 try { 352 390 BinData data = Message.readData(getNativeStdout()); 353 391 dumpError(); -
modules/org.sophie2.main.app.commons/src/main/java/org/sophie2/main/app/commons/app/MainWindowLogic.java
11 11 import org.sophie2.base.layout.model.MainWindowOptions; 12 12 import org.sophie2.base.layout.model.MainWindowOptions.ScreenMode; 13 13 import org.sophie2.base.layout.model.MainWindowOptions.WindowsState; 14 import org.sophie2.base. media.MediaUtil;14 import org.sophie2.base.natlib.NativeBridgeRegistry; 15 15 import org.sophie2.core.modularity.FakeModuleRegistry; 16 16 import org.sophie2.core.modularity.FileSearchUtil; 17 17 import org.sophie2.core.mvc.EventFilterBuilder; … … 117 117 } 118 118 } 119 119 if (mainWindow.documents().size() == 0) { 120 MediaUtil.getDefaultAudioOutput().stop(); 120 //MediaUtil.getDefaultAudioOutput().stop(); 121 NativeBridgeRegistry.get().unregisterAll(); 121 122 if (MainAppModule.get().getBundleContext() != null) { 122 123 // In true. 123 124 try {