package ca.uvic.chisel.video.widget.internal; import java.io.IOException; import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.Path; import org.eclipse.swt.SWTException; import org.eclipse.swt.browser.Browser; import org.eclipse.swt.browser.ProgressEvent; import org.eclipse.swt.browser.ProgressListener; import org.eclipse.swt.browser.StatusTextEvent; import org.eclipse.swt.browser.StatusTextListener; import org.eclipse.swt.browser.TitleEvent; import org.eclipse.swt.browser.TitleListener; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.ControlListener; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import ca.uvic.chisel.video.VideoPlayerPlugin; import ca.uvic.chisel.video.widget.AbstractVideoPlayer; import ca.uvic.chisel.video.widget.VideoEvent; public class BrowserVideoPlayer extends AbstractVideoPlayer { private static final String VIDEO_PROGRESS = "VideoProgress"; private static final String VIDEO_LOADED = "VideoLoaded"; private static final String VIDEO_PLAY_HEAD = "VideoPlayHead"; private static final String VIDEO_READY = "VideoReady"; protected static final String VIDEO_EVENT = "VideoEvent"; protected static final String FLEX_LOADED = "FlexLoaded"; private boolean loaded; private static final int STOPPED = 0; private static final int PLAYING = 1; private static final int PAUSED = 2; private int playState = STOPPED; private String deferredLoad; private boolean deferredPlay; private long deferredLocation; public BrowserVideoPlayer(Composite parent, int style) { super(parent, style); loaded = false; } @Override protected Control createContents(Composite parent, int style) { Browser browser = new Browser(parent, style); browser.addProgressListener(new ProgressListener() { @Override public void changed(ProgressEvent event) { } @Override public void completed(ProgressEvent event) { }}); browser.addTitleListener(new TitleListener() { @Override public void changed(TitleEvent event) { String[] eventText = event.title.split("\\:"); if (eventText.length > 1 && VIDEO_EVENT.equals(eventText[0])) { handleVideoEvent(eventText); } } }); browser.addStatusTextListener(new StatusTextListener(){ @Override public void changed(StatusTextEvent event) { String[] eventText = event.text.split("\\:"); if (eventText.length > 1 && VIDEO_EVENT.equals(eventText[0])) { handleVideoEvent(eventText); } }}); browser.setJavascriptEnabled(true); browser.addControlListener(new ControlListener() { @Override public void controlResized(ControlEvent e) { synchronizeBrowserSize(); } @Override public void controlMoved(ControlEvent e) {} }); URL url = VideoPlayerPlugin.getDefault().getBundle().getResource("web/main.html"); try { URL fileURL = FileLocator.toFileURL(url); browser.setUrl(fileURL.toString()); waitForLoad(); } catch (IOException e) { } return browser; } protected void handleVideoEvent(String[] eventText) { //the second string contains the event type String type = eventText[1]; if (FLEX_LOADED.equals(type)) { loaded = true; synchronizeBrowserSize(); if (deferredLoad != null) { load(deferredLoad); deferredLoad = null; } if (deferredLocation > 0) { seek(deferredLocation); deferredLocation = 0; } if (deferredPlay) { play(); } } else if (VIDEO_READY.equals(type)) { loaded = true; asyncFireVideoEvent(new VideoEvent(VideoEvent.VIDEO_READY,this)); } else if (VIDEO_PLAY_HEAD.equals(type)) { asyncFireVideoEvent(new VideoEvent(VideoEvent.VIDEO_PLAYHEAD, this)); } else if (VIDEO_LOADED.equals(type)) { asyncFireVideoEvent(new VideoEvent(VideoEvent.VIDEO_LOADED, this)); } else if (VIDEO_PROGRESS.equals(type)) { asyncFireVideoEvent(new VideoEvent(VideoEvent.VIDEO_LOAD_PROGRESS, this)); } } protected Browser getBrowser() { return (Browser)getControl(); } protected void synchronizeBrowserSize() { try { Browser b = getBrowser(); Rectangle r = b.getClientArea(); setVideoWidth(r.width); setVideoHeight(r.height); } catch (Exception e) { e.printStackTrace(); } } protected void setVideoWidth(int width) { if (!isLoaded()) { return; } Browser b = getBrowser(); String script = "return setVideoWidth(" + width + ")"; b.evaluate(script); } protected void setVideoHeight(int height) { if (!isLoaded()) { return; } Browser b = getBrowser(); b.evaluate("return setVideoHeight('" + height + "')"); } @Override public long getTime() { if (!isLoaded()) { return -1; } Object result = getBrowser().evaluate("return getVideoPlayLocation()"); if (result instanceof Number) { return ((Number)result).longValue(); } return 0; } public long getLength() { if (!isLoaded()) { return -1; } Object result = getBrowser().evaluate("return getVideoLength()"); if (result instanceof Number) { return ((Number)result).longValue(); } return 0; } public long getLoadProgress() { if (!isLoaded()) { return -1; } Object result = getBrowser().evaluate("return getVideoProgress()"); if (result instanceof Number) { return ((Number)result).longValue(); } return 0; } @Override public void load(String location) { if (!isLoaded()) { deferredLoad = location; return; } try { location = location.replace('\\', '/'); getBrowser().evaluate("return load('" + location + "')"); Object error = getBrowser().evaluate("return getError()"); if (error != null) { System.out.println(error); } } catch (SWTException e) { e.printStackTrace(); } } @Override public void pause() { if (!isLoaded()) { deferredPlay = false; return; } Object result = getBrowser().evaluate("return pause()"); if (result != null) { System.out.println(result); } else { playState = PAUSED; fireVideoEvent(new VideoEvent(VideoEvent.VIDEO_PAUSED, this)); } } @Override public void play() { if (!isLoaded()) { deferredPlay = true; return; } Object result = getBrowser().evaluate("return play()"); if (result != null) { System.out.println(result); } else { playState = PLAYING; fireVideoEvent(new VideoEvent(VideoEvent.VIDEO_STARTED, this)); } } @Override public void seek(long offset) { if (!isLoaded()) { deferredLocation = offset; return; } Object result = getBrowser().evaluate("return setVideoPlayLocation(" + offset + ")"); if (result != null) { System.out.println(result); } } @Override public void stop() { if (!isLoaded()) { deferredPlay = false; return; } Object result = getBrowser().evaluate("return stop()"); if (result != null) { System.out.println(result); } else { fireVideoEvent(new VideoEvent(VideoEvent.VIDEO_STOPPED, this)); playState = STOPPED; } } private void waitForLoad() { // while (!isLoaded()) { // getDisplay().readAndDispatch(); // } } private boolean isLoaded() { return loaded; } @Override public boolean isPaused() { return playState == PAUSED; } @Override public boolean isPlaying() { return playState == PLAYING; } @Override public boolean isStopped() { return playState == STOPPED; } }