Audio and Video cleanup.
Add a MediaBase widget backing Audio and Video, and clean up tests. Also,
address comments by reviewer and re-encode test media files for a smaller size
and to fix an h264 video issue.
Review at http://gwt-code-reviews.appspot.com/1415801
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10001 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/tools/api-checker/config/gwt22_23userApi.conf b/tools/api-checker/config/gwt22_23userApi.conf
index 7041d0b..e1c2e38 100644
--- a/tools/api-checker/config/gwt22_23userApi.conf
+++ b/tools/api-checker/config/gwt22_23userApi.conf
@@ -123,3 +123,6 @@
# Renamed CellBasedWidgetImplSafari to CellBasedWidgetImplStandardBase.
com.google.gwt.user.cellview.client.CellBasedWidgetImplSafari MISSING
+
+# Adding protected Video(Element) that conflicts with existing (now deprecated) public Video(String)
+com.google.gwt.media.client.Video::Video(Ljava/lang/String;) OVERLOADED_METHOD_CALL
diff --git a/user/src/com/google/gwt/dom/client/DOMImplMozilla.java b/user/src/com/google/gwt/dom/client/DOMImplMozilla.java
index fc68ef6..bced2ef 100644
--- a/user/src/com/google/gwt/dom/client/DOMImplMozilla.java
+++ b/user/src/com/google/gwt/dom/client/DOMImplMozilla.java
@@ -250,14 +250,8 @@
* @return true if using Gecko 1.9 (Firefox 3) or later
*/
private native boolean isGecko19() /*-{
- var result = /rv:([0-9]+)\.([0-9]+)/.exec(navigator.userAgent.toLowerCase());
- if (result && result.length == 3) {
- var version = (parseInt(result[1]) * 1000) + parseInt(result[2]);
- if (version >= 1009) {
- return true;
- }
- }
- return false;
+ var geckoVersion = @com.google.gwt.dom.client.DOMImplMozilla::getGeckoVersion()();
+ return (geckoVersion != -1) && (geckoVersion >= 1009000);
}-*/;
private native boolean isRTL(Element elem) /*-{
diff --git a/user/src/com/google/gwt/media/client/Audio.java b/user/src/com/google/gwt/media/client/Audio.java
index 4152298..f5100f7 100644
--- a/user/src/com/google/gwt/media/client/Audio.java
+++ b/user/src/com/google/gwt/media/client/Audio.java
@@ -1,12 +1,12 @@
/*
* Copyright 2011 Google Inc.
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -19,126 +19,20 @@
import com.google.gwt.dom.client.AudioElement;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.PartialSupport;
-import com.google.gwt.event.dom.client.CanPlayThroughEvent;
-import com.google.gwt.event.dom.client.CanPlayThroughHandler;
-import com.google.gwt.event.dom.client.EndedEvent;
-import com.google.gwt.event.dom.client.EndedHandler;
-import com.google.gwt.event.dom.client.HasAllMediaHandlers;
-import com.google.gwt.event.dom.client.ProgressEvent;
-import com.google.gwt.event.dom.client.ProgressHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.user.client.ui.FocusWidget;
/**
* <p>
* A widget representing an <audio> element.
- *
+ *
* <p>
* <span style="color:red">Experimental API: This API is still under development
- * and is subject to change.
- * </span>
+ * and is subject to change. </span>
* </p>
- *
+ *
* This widget may not be supported on all browsers.
*/
@PartialSupport
-public class Audio extends FocusWidget implements HasAllMediaHandlers {
- private static AudioElementSupportDetector detector;
-
- /**
- * Return a new {@link Audio} if supported, and null otherwise.
- *
- * @return a new {@link Audio} if supported, and null otherwise
- */
- public static Audio createIfSupported() {
- if (detector == null) {
- detector = GWT.create(AudioElementSupportDetector.class);
- }
- if (!detector.isSupportedCompileTime()) {
- return null;
- }
- AudioElement element = Document.get().createAudioElement();
- if (!detector.isSupportedRunTime(element)) {
- return null;
- }
- return new Audio(element);
- }
-
- /**
- * Runtime check for whether the audio element is supported in this browser.
- *
- * @return whether the audio element is supported
- */
- public static boolean isSupported() {
- if (detector == null) {
- detector = GWT.create(AudioElementSupportDetector.class);
- }
- if (!detector.isSupportedCompileTime()) {
- return false;
- }
- AudioElement element = Document.get().createAudioElement();
- if (!detector.isSupportedRunTime(element)) {
- return false;
- }
- return true;
- }
-
- /**
- * Protected constructor. Use {@link #createIfSupported()} to create
- * an Audio element.
- */
- private Audio(AudioElement element) {
- setElement(element);
- }
-
- public HandlerRegistration addCanPlayThroughHandler(CanPlayThroughHandler handler) {
- return addDomHandler(handler, CanPlayThroughEvent.getType());
- }
-
- public HandlerRegistration addEndedHandler(EndedHandler handler) {
- return addDomHandler(handler, EndedEvent.getType());
- }
-
- public HandlerRegistration addProgressHandler(ProgressHandler handler) {
- return addDomHandler(handler, ProgressEvent.getType());
- }
-
- /**
- * Returns the attached AudioElement.
- *
- * @return the AudioElement
- */
- public AudioElement getAudioElement() {
- return this.getElement().cast();
- }
-
- /**
- * Detector for browser support of {@link AudioElement}.
- */
- private static class AudioElementSupportDetector {
- /**
- * Using a run-time check, return true if the {@link AudioElement} is
- * supported.
- *
- * @return true if supported, false otherwise.
- */
- static native boolean isSupportedRunTime(AudioElement element) /*-{
- return !!element.play;
- }-*/;
-
- /**
- * Using a compile-time check, return true if {@link AudioElement} might
- * be supported.
- *
- * @return true if might be supported, false otherwise.
- */
- boolean isSupportedCompileTime() {
- // will be true in AudioElementSupportDetectedMaybe
- // will be false in AudioElementSupportDetectedNo
- return false;
- }
- }
-
+public class Audio extends MediaBase {
/**
* Detector for permutations that might support {@link AudioElement}.
*/
@@ -172,6 +66,89 @@
@Override
boolean isSupportedCompileTime() {
return false;
- }
+ }
+ }
+
+ /**
+ * Detector for browser support of {@link AudioElement}.
+ */
+ private static class AudioElementSupportDetector {
+ /**
+ * Using a run-time check, return true if the {@link AudioElement} is
+ * supported.
+ *
+ * @return true if supported, false otherwise.
+ */
+ static native boolean isSupportedRunTime(AudioElement element) /*-{
+ return !!element.play;
+ }-*/;
+
+ /**
+ * Using a compile-time check, return true if {@link AudioElement} might be
+ * supported.
+ *
+ * @return true if might be supported, false otherwise.
+ */
+ boolean isSupportedCompileTime() {
+ // will be true in AudioElementSupportDetectedMaybe
+ // will be false in AudioElementSupportDetectedNo
+ return false;
+ }
+ }
+
+ private static AudioElementSupportDetector detector;
+
+ /**
+ * Return a new {@link Audio} if supported, and null otherwise.
+ *
+ * @return a new {@link Audio} if supported, and null otherwise
+ */
+ public static Audio createIfSupported() {
+ if (detector == null) {
+ detector = GWT.create(AudioElementSupportDetector.class);
+ }
+ if (!detector.isSupportedCompileTime()) {
+ return null;
+ }
+ AudioElement element = Document.get().createAudioElement();
+ if (!detector.isSupportedRunTime(element)) {
+ return null;
+ }
+ return new Audio(element);
+ }
+
+ /**
+ * Runtime check for whether the audio element is supported in this browser.
+ *
+ * @return whether the audio element is supported
+ */
+ public static boolean isSupported() {
+ if (detector == null) {
+ detector = GWT.create(AudioElementSupportDetector.class);
+ }
+ if (!detector.isSupportedCompileTime()) {
+ return false;
+ }
+ AudioElement element = Document.get().createAudioElement();
+ if (!detector.isSupportedRunTime(element)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Protected constructor. Use {@link #createIfSupported()} to create an Audio.
+ */
+ protected Audio(AudioElement element) {
+ super(element);
+ }
+
+ /**
+ * Returns the attached AudioElement.
+ *
+ * @return the AudioElement
+ */
+ public AudioElement getAudioElement() {
+ return getMediaElement().cast();
}
}
diff --git a/user/src/com/google/gwt/media/client/MediaBase.java b/user/src/com/google/gwt/media/client/MediaBase.java
new file mode 100644
index 0000000..3d0a1cb
--- /dev/null
+++ b/user/src/com/google/gwt/media/client/MediaBase.java
@@ -0,0 +1,501 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.media.client;
+
+import com.google.gwt.dom.client.MediaElement;
+import com.google.gwt.event.dom.client.CanPlayThroughEvent;
+import com.google.gwt.event.dom.client.CanPlayThroughHandler;
+import com.google.gwt.event.dom.client.EndedEvent;
+import com.google.gwt.event.dom.client.EndedHandler;
+import com.google.gwt.event.dom.client.HasAllMediaHandlers;
+import com.google.gwt.event.dom.client.ProgressEvent;
+import com.google.gwt.event.dom.client.ProgressHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.media.dom.client.MediaError;
+import com.google.gwt.media.dom.client.TimeRanges;
+import com.google.gwt.user.client.ui.FocusWidget;
+
+/**
+ * <p>
+ * A widget representing a media element.
+ *
+ * <p>
+ * <span style="color:red">Experimental API: This API is still under development
+ * and is subject to change. </span>
+ * </p>
+ */
+public abstract class MediaBase extends FocusWidget
+ implements HasAllMediaHandlers {
+
+ /**
+ * Protected constructor.
+ */
+ protected MediaBase(MediaElement element) {
+ setElement(element);
+ }
+
+ public HandlerRegistration addCanPlayThroughHandler(
+ CanPlayThroughHandler handler) {
+ return addDomHandler(handler, CanPlayThroughEvent.getType());
+ }
+
+ public HandlerRegistration addEndedHandler(EndedHandler handler) {
+ return addDomHandler(handler, EndedEvent.getType());
+ }
+
+ public HandlerRegistration addProgressHandler(ProgressHandler handler) {
+ return addDomHandler(handler, ProgressEvent.getType());
+ }
+
+ /**
+ * Returns {@code true} if the native player is capable of playing content of
+ * the given MIME type.
+ *
+ * @param type a String representing a MIME type
+ * @return one of {@link MediaElement#CAN_PLAY_PROBABLY},
+ * {@link MediaElement#CAN_PLAY_MAYBE}, or
+ * {@link MediaElement#CANNOT_PLAY}
+ */
+ public String canPlayType(String type) {
+ return getMediaElement().canPlayType(type);
+ }
+
+ /**
+ * Returns a {@link TimeRanges} object indicating which portions of the source
+ * have been buffered locally.
+ *
+ * @return a {@link TimeRanges} instance, or {@code null}.
+ */
+ public TimeRanges getBuffered() {
+ return getMediaElement().getBuffered();
+ }
+
+ /**
+ * Returns the URL of the current media source, or the empty String if no
+ * source is set.
+ *
+ * @return a String URL
+ */
+ public String getCurrentSrc() {
+ return getMediaElement().getCurrentSrc();
+ }
+
+ /**
+ * Returns the current time within the source media stream.
+ *
+ * @return the time, in seconds, as a double
+ *
+ * @see #setCurrentTime(double)
+ */
+ public double getCurrentTime() {
+ return getMediaElement().getCurrentTime();
+ }
+
+ /**
+ * Returns the default playback rate, where 1.0 corresponds to normal
+ * playback. If no rate has been set, 1.0 is returned.
+ *
+ * @return the current default playback rate, or 1.0 if it has not been set
+ *
+ * @see #setDefaultPlaybackRate(double)
+ */
+ public double getDefaultPlaybackRate() {
+ return getMediaElement().getDefaultPlaybackRate();
+ }
+
+ /**
+ * Returns the duration of the source media stream, in seconds. If the
+ * duration is unknown, {@link Double#NaN} is returned. For unbounded media
+ * streams, {@link Double#POSITIVE_INFINITY} is returned.
+ *
+ * @return a positive duration in seconds, NaN, or Infinity
+ */
+ public double getDuration() {
+ return getMediaElement().getDuration();
+ }
+
+ /**
+ * Returns the type of error that has occurred while attempting to load and
+ * play the media. If no error has occurred, {@code null} is returned.
+ *
+ * @return a {@link MediaError} instance, or {@code null}
+ */
+ public MediaError getError() {
+ return getMediaElement().getError();
+ }
+
+ /**
+ * Returns the time to which the media stream was seeked at the time it was
+ * loaded, in seconds, or 0.0 if the position is unknown.
+ *
+ * @return the initial time, or 0.0 if unknown
+ */
+ public double getInitialTime() {
+ return getMediaElement().getInitialTime();
+ }
+
+ /**
+ * Returns the attached Media Element.
+ *
+ * @return the Media Element
+ */
+ public MediaElement getMediaElement() {
+ return this.getElement().cast();
+ }
+
+ /**
+ * Returns the network state, one of {@link MediaElement#NETWORK_EMPTY},
+ * {@link MediaElement#NETWORK_IDLE}, {@link MediaElement#NETWORK_LOADING}, or
+ * {@link MediaElement#NETWORK_NO_SOURCE}.
+ *
+ * @return an integer constant indicating the network state
+ *
+ * @see MediaElement#NETWORK_EMPTY
+ * @see MediaElement#NETWORK_IDLE
+ * @see MediaElement#NETWORK_LOADING
+ * @see MediaElement#NETWORK_NO_SOURCE
+ */
+ public int getNetworkState() {
+ return getMediaElement().getNetworkState();
+ }
+
+ /**
+ * Returns the playback rate, where 1.0 corresponds to normal playback. If the
+ * rate has not been set, 1.0 is returned.
+ *
+ * @return the playback rate, if known, otherwise 1.0
+ *
+ * @see #setPlaybackRate(double)
+ */
+ public double getPlaybackRate() {
+ return getMediaElement().getPlaybackRate();
+ }
+
+ /**
+ * Returns a {@link TimeRanges} object indicating which portions of the source
+ * have been played.
+ *
+ * @return a {@link TimeRanges} instance, or {@code null}.
+ */
+ public TimeRanges getPlayed() {
+ return getMediaElement().getPlayed();
+ }
+
+ /**
+ * Returns the preload setting, one of {@link MediaElement#PRELOAD_AUTO},
+ * {@link MediaElement#PRELOAD_METADATA}, or
+ * {@link MediaElement#PRELOAD_NONE}.
+ *
+ * @return the preload setting
+ *
+ * @see #setPreload(String)
+ * @see MediaElement#PRELOAD_AUTO
+ * @see MediaElement#PRELOAD_METADATA
+ * @see MediaElement#PRELOAD_NONE
+ */
+ public String getPreload() {
+ return getMediaElement().getPreload();
+ }
+
+ /**
+ * Returns the current state of the media with respect to rendering the
+ * current playback position, as one of the constants
+ * {@link MediaElement#HAVE_CURRENT_DATA},
+ * {@link MediaElement#HAVE_ENOUGH_DATA},
+ * {@link MediaElement#HAVE_FUTURE_DATA}, {@link MediaElement#HAVE_METADATA},
+ * or {@link MediaElement#HAVE_NOTHING} .
+ *
+ * @return an integer constant indicating the ready state
+ *
+ * @see MediaElement#HAVE_CURRENT_DATA
+ * @see MediaElement#HAVE_ENOUGH_DATA
+ * @see MediaElement#HAVE_FUTURE_DATA
+ * @see MediaElement#HAVE_METADATA
+ * @see MediaElement#HAVE_NOTHING
+ */
+ public int getReadyState() {
+ return getMediaElement().getReadyState();
+ }
+
+ /**
+ * Returns a {@link TimeRanges} object indicating which portions of the source
+ * are seekable.
+ *
+ * @return a {@link TimeRanges} instance, or {@code null}.
+ */
+ public TimeRanges getSeekable() {
+ return getMediaElement().getSeekable();
+ }
+
+ /**
+ * Returns the source URL for the media, or {@code null} if none is set.
+ *
+ * @return a String URL or {@code null}
+ *
+ * @see #setSrc(String)
+ */
+ public String getSrc() {
+ return getMediaElement().getSrc();
+ }
+
+ /**
+ * Returns the time corresponding to the zero time in the media timeline,
+ * measured in seconds since midnight, January 1 1970 UTC, or
+ * {@link Double#NaN} if none is specified.
+ *
+ * @return the start time
+ */
+ public double getStartOffsetTime() {
+ return getMediaElement().getStartOffsetTime();
+ }
+
+ /**
+ * Returns the current audio volume setting for the media, as a number between
+ * 0.0 and 1.0.
+ *
+ * @return a number between 0.0 (silent) and 1.0 (loudest)
+ *
+ * @see #setVolume(double)
+ */
+ public double getVolume() {
+ return getMediaElement().getVolume();
+ }
+
+ /**
+ * Returns {@code true} if the media player should display interactive
+ * controls (for example, to control play/pause, seek position, and volume),
+ * {@code false} otherwise.
+ *
+ * @return whether controls should be displayed
+ *
+ * @see #setControls(boolean)
+ */
+ public boolean hasControls() {
+ return getMediaElement().hasControls();
+ }
+
+ /**
+ * Returns {@code true} if playback has reached the end of the media, {@code
+ * false} otherwise.
+ *
+ * @return whether playback has ended
+ */
+ public boolean hasEnded() {
+ return getMediaElement().hasEnded();
+ }
+
+ /**
+ * Returns {@code true} if autoplay is enabled, {@code false} otherwise. When
+ * autoplay is enabled, the user agent will begin playback automatically as
+ * soon as it can do so without stopping.
+ *
+ * @return the autoplay setting
+ *
+ * @see #setAutoplay(boolean)
+ */
+ public boolean isAutoplay() {
+ return getMediaElement().isAutoplay();
+ }
+
+ /**
+ * Returns {@code true} if the user agent is to seek back to the start of the
+ * media once playing has ended, {@code false} otherwise.
+ *
+ * @return the loop setting
+ *
+ * @see #setLoop(boolean)
+ */
+ public boolean isLoop() {
+ return getMediaElement().isLoop();
+ }
+
+ /**
+ * Returns {@code true} if the volume is to be muted (overriding the normal
+ * volume setting), {@code false} otherwise.
+ *
+ * @return the muting setting
+ *
+ * @see #setMuted(boolean)
+ * @see #getVolume()
+ * @see #setVolume(double)
+ */
+ public boolean isMuted() {
+ return getMediaElement().isMuted();
+ }
+
+ /**
+ * Returns {@code true} if playback is paused, {@code false} otherwise.
+ *
+ * @return the paused setting
+ *
+ * @see #pause()
+ * @see #play()
+ */
+ public boolean isPaused() {
+ return getMediaElement().isPaused();
+ }
+
+ /**
+ * Returns {@code true} if the playback position is in the process of changing
+ * discontinuously, e.g., by use of the interactive controls, {@code false}
+ * otherwise.
+ *
+ * @return the seeking status
+ *
+ * @see #setControls(boolean)
+ * @see #hasControls()
+ */
+ public boolean isSeeking() {
+ return getMediaElement().isSeeking();
+ }
+
+ /**
+ * Causes the resource to be loaded.
+ */
+ public void load() {
+ getMediaElement().load();
+ }
+
+ /**
+ * Causes playback of the resource to be paused.
+ */
+ public void pause() {
+ getMediaElement().pause();
+ }
+
+ /**
+ * Causes playback of the resource to be started or resumed.
+ */
+ public void play() {
+ getMediaElement().play();
+ }
+
+ /**
+ * Enables or disables autoplay of the resource.
+ *
+ * @param autoplay if {@code true}, enable autoplay
+ *
+ * @see #isAutoplay()
+ */
+ public void setAutoplay(boolean autoplay) {
+ getMediaElement().setAutoplay(autoplay);
+ }
+
+ /**
+ * Enables or disables interactive controls.
+ *
+ * @param controls if {@code true}, enable controls
+ *
+ * @see #hasControls()
+ */
+ public void setControls(boolean controls) {
+ getMediaElement().setControls(controls);
+ }
+
+ /**
+ * Sets the current playback time within the media stream, in seconds.
+ *
+ * @param time a number within the ranges given by {@link #getSeekable()}
+ *
+ * @see #getCurrentTime()
+ */
+ public void setCurrentTime(double time) {
+ getMediaElement().setCurrentTime(time);
+ }
+
+ /**
+ * Sets the default playback rate.
+ *
+ * @param rate a double value
+ *
+ * @see #getDefaultPlaybackRate()
+ */
+ public void setDefaultPlaybackRate(double rate) {
+ getMediaElement().setDefaultPlaybackRate(rate);
+ }
+
+ /**
+ * Enables or disables looping.
+ *
+ * @param loop if {@code true}, enable looping
+ *
+ * @see #isLoop()
+ */
+ public final void setLoop(boolean loop) {
+ getMediaElement().setLoop(loop);
+ }
+
+ /**
+ * Enables or disables muting.
+ *
+ * @param muted if {@code true}, enable muting
+ *
+ * @see #isMuted()
+ */
+ public void setMuted(boolean muted) {
+ getMediaElement().setMuted(muted);
+ }
+
+ /**
+ * Sets the playback rate.
+ *
+ * @param rate a double value
+ *
+ * @see #getPlaybackRate()
+ */
+ public void setPlaybackRate(double rate) {
+ getMediaElement().setPlaybackRate(rate);
+ }
+
+ /**
+ * Changes the preload setting to one of {@link MediaElement#PRELOAD_AUTO},
+ * {@link MediaElement#PRELOAD_METADATA}, or
+ * {@link MediaElement#PRELOAD_NONE}.
+ *
+ * @param preload a String constants
+ *
+ * @see #getPreload()
+ * @see #setPreload(String)
+ * @see MediaElement#PRELOAD_AUTO
+ * @see MediaElement#PRELOAD_METADATA
+ * @see MediaElement#PRELOAD_NONE
+ */
+ public void setPreload(String preload) {
+ getMediaElement().setPreload(preload);
+ }
+
+ /**
+ * Sets the source URL for the media.
+ *
+ * @param url a String URL
+ *
+ * @see #getSrc()
+ */
+ public void setSrc(String url) {
+ getMediaElement().setSrc(url);
+ }
+
+ /**
+ * Sets the playback volume.
+ *
+ * @param volume a value between 0.0 (silent) and 1.0 (loudest)
+ *
+ * @see #getVolume()
+ */
+ public void setVolume(double volume) {
+ getMediaElement().setVolume(volume);
+ }
+}
diff --git a/user/src/com/google/gwt/media/client/Video.java b/user/src/com/google/gwt/media/client/Video.java
index 74eb17d..f3dcd8a 100644
--- a/user/src/com/google/gwt/media/client/Video.java
+++ b/user/src/com/google/gwt/media/client/Video.java
@@ -1,12 +1,12 @@
/*
* Copyright 2011 Google Inc.
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -18,134 +18,19 @@
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.VideoElement;
-import com.google.gwt.event.dom.client.CanPlayThroughEvent;
-import com.google.gwt.event.dom.client.CanPlayThroughHandler;
-import com.google.gwt.event.dom.client.EndedEvent;
-import com.google.gwt.event.dom.client.EndedHandler;
-import com.google.gwt.event.dom.client.HasAllMediaHandlers;
-import com.google.gwt.event.dom.client.ProgressEvent;
-import com.google.gwt.event.dom.client.ProgressHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.user.client.ui.FocusWidget;
/**
* <p>
* A widget representing a <video> element.
- *
+ *
* <p>
* <span style="color:red">Experimental API: This API is still under development
- * and is subject to change.
- * </span>
+ * and is subject to change. </span>
* </p>
- *
+ *
* This widget may not be supported on all browsers.
*/
-public class Video extends FocusWidget implements HasAllMediaHandlers {
- private static VideoElementSupportDetector detector;
-
- /**
- * Return a new {@link Video} if supported, and null otherwise.
- *
- * @return a new {@link Video} if supported, and null otherwise
- */
- public static Video createIfSupported() {
- if (detector == null) {
- detector = GWT.create(VideoElementSupportDetector.class);
- }
- if (!detector.isSupportedCompileTime()) {
- return null;
- }
- VideoElement element = Document.get().createVideoElement();
- if (!detector.isSupportedRunTime(element)) {
- return null;
- }
- return new Video(element);
- }
-
- /**
- * Runtime check for whether the video element is supported in this browser.
- *
- * @return whether the video element is supported
- */
- public static boolean isSupported() {
- if (detector == null) {
- detector = GWT.create(VideoElementSupportDetector.class);
- }
- if (!detector.isSupportedCompileTime()) {
- return false;
- }
- VideoElement element = Document.get().createVideoElement();
- if (!detector.isSupportedRunTime(element)) {
- return false;
- }
- return true;
- }
-
- /**
- * Protected constructor. Use {@link #createIfSupported()} to create a Video.
- */
- private Video(VideoElement element) {
- setElement(element);
- }
-
- /**
- * Creates a Video widget with a given source URL.
- *
- * @param src a String URL
- */
- public Video(String src) {
- setElement(Document.get().createVideoElement());
- getVideoElement().setSrc(src);
- }
-
- public HandlerRegistration addCanPlayThroughHandler(CanPlayThroughHandler handler) {
- return addDomHandler(handler, CanPlayThroughEvent.getType());
- }
-
- public HandlerRegistration addEndedHandler(EndedHandler handler) {
- return addDomHandler(handler, EndedEvent.getType());
- }
-
- public HandlerRegistration addProgressHandler(ProgressHandler handler) {
- return addDomHandler(handler, ProgressEvent.getType());
- }
-
- /**
- * Returns the attached VideoElement.
- *
- * @return the VideoElement
- */
- public VideoElement getVideoElement() {
- return this.getElement().cast();
- }
-
- /**
- * Detector for browser support of {@link VideoElement}.
- */
- private static class VideoElementSupportDetector {
- /**
- * Using a run-time check, return true if the {@link VideoElement} is
- * supported.
- *
- * @return true if supported, false otherwise.
- */
- static native boolean isSupportedRunTime(VideoElement element) /*-{
- return !!element.play;
- }-*/;
-
- /**
- * Using a compile-time check, return true if {@link VideoElement} might
- * be supported.
- *
- * @return true if might be supported, false otherwise.
- */
- boolean isSupportedCompileTime() {
- // will be true in VideoElementSupportDetectedMaybe
- // will be false in VideoElementSupportDetectedNo
- return false;
- }
- }
-
+public class Video extends MediaBase {
/**
* Detector for permutations that might support {@link VideoElement}.
*/
@@ -179,6 +64,144 @@
@Override
boolean isSupportedCompileTime() {
return false;
- }
+ }
+ }
+
+ /**
+ * Detector for browser support of {@link VideoElement}.
+ */
+ private static class VideoElementSupportDetector {
+ /**
+ * Using a run-time check, return true if the {@link VideoElement} is
+ * supported.
+ *
+ * @return true if supported, false otherwise.
+ */
+ static native boolean isSupportedRunTime(VideoElement element) /*-{
+ return !!element.play;
+ }-*/;
+
+ /**
+ * Using a compile-time check, return true if {@link VideoElement} might be
+ * supported.
+ *
+ * @return true if might be supported, false otherwise.
+ */
+ boolean isSupportedCompileTime() {
+ // will be true in VideoElementSupportDetectedMaybe
+ // will be false in VideoElementSupportDetectedNo
+ return false;
+ }
+ }
+
+ private static VideoElementSupportDetector detector;
+
+ /**
+ * Return a new {@link Video} if supported, and null otherwise.
+ *
+ * @return a new {@link Video} if supported, and null otherwise
+ */
+ public static Video createIfSupported() {
+ if (detector == null) {
+ detector = GWT.create(VideoElementSupportDetector.class);
+ }
+ if (!detector.isSupportedCompileTime()) {
+ return null;
+ }
+ VideoElement element = Document.get().createVideoElement();
+ if (!detector.isSupportedRunTime(element)) {
+ return null;
+ }
+ return new Video(element);
+ }
+
+ /**
+ * Runtime check for whether the video element is supported in this browser.
+ *
+ * @return whether the video element is supported
+ */
+ public static boolean isSupported() {
+ if (detector == null) {
+ detector = GWT.create(VideoElementSupportDetector.class);
+ }
+ if (!detector.isSupportedCompileTime()) {
+ return false;
+ }
+ VideoElement element = Document.get().createVideoElement();
+ if (!detector.isSupportedRunTime(element)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Protected constructor. Use {@link #createIfSupported()} to create a Video.
+ */
+ protected Video(VideoElement element) {
+ super(element);
+ }
+
+ /**
+ * Creates a Video widget with a given source URL.
+ *
+ * @param src a String URL.
+ * @deprecated use {@link #createIfSupported()}.
+ */
+ @Deprecated
+ public Video(String src) {
+ super(Document.get().createVideoElement());
+ getMediaElement().setSrc(src);
+ }
+
+ /**
+ * Returns a poster URL.
+ *
+ * @return a URL containing a poster image
+ *
+ * @see #setPoster(String)
+ */
+ public String getPoster() {
+ return getVideoElement().getPoster();
+ }
+
+ /**
+ * Returns the attached VideoElement.
+ *
+ * @return the VideoElement
+ */
+ public VideoElement getVideoElement() {
+ return getMediaElement().cast();
+ }
+
+ /**
+ * Gets the intrinsic height of video within the element.
+ *
+ * To get the element height, use {@link VideoElement#getOffsetHeight()}
+ *
+ * @return the height, in pixels
+ */
+ public int getVideoHeight() {
+ return getVideoElement().getVideoHeight();
+ }
+
+ /**
+ * Gets the instrinsic width of the video within the element.
+ *
+ * To get the element width, use {@link VideoElement#getOffsetWidth()}
+ *
+ * @return the width, in pixels
+ */
+ public int getVideoWidth() {
+ return getVideoElement().getVideoWidth();
+ }
+
+ /**
+ * Sets the poster URL.
+ *
+ * @param url the poster image URL
+ * @see #getPoster
+ */
+ public void setPoster(String url) {
+ getVideoElement().setPoster(url);
}
}
diff --git a/user/test/com/google/gwt/canvas/client/CanvasTest.java b/user/test/com/google/gwt/canvas/client/CanvasTest.java
index 8b3958a..d8b38d7 100644
--- a/user/test/com/google/gwt/canvas/client/CanvasTest.java
+++ b/user/test/com/google/gwt/canvas/client/CanvasTest.java
@@ -23,49 +23,36 @@
/**
* Tests {@link Canvas}.
- *
- * Because HtmlUnit does not support HTML5, you will need to run these tests manually in order to
- * have them run. To do that, go to "run configurations" or "debug configurations", select the test
- * you would like to run, and put this line in the VM args under the arguments tab:
- * -Dgwt.args="-runStyle Manual:1"
+ *
+ * Because HtmlUnit does not support HTML5, you will need to run these tests
+ * manually in order to have them run. To do that, go to "run configurations" or
+ * "debug configurations", select the test you would like to run, and put this
+ * line in the VM args under the arguments tab: -Dgwt.args="-runStyle Manual:1"
*/
@DoNotRunWith(Platform.HtmlUnitUnknown)
public class CanvasTest extends GWTTestCase {
- protected Canvas canvas1;
- protected Canvas canvas2;
+ private static native boolean isFirefox35OrLater() /*-{
+ var geckoVersion = @com.google.gwt.dom.client.DOMImplMozilla::getGeckoVersion()();
+ return (geckoVersion != -1) && (geckoVersion >= 1009001);
+ }-*/;
- native boolean isWebkit525OrBefore() /*-{
+ private static native boolean isIE6() /*-{
+ return @com.google.gwt.dom.client.DOMImplIE6::isIE6()();
+ }-*/;
+
+ private static native boolean isWebkit525OrBefore() /*-{
return @com.google.gwt.dom.client.DOMImplWebkit::isWebkit525OrBefore()();
}-*/;
+ protected Canvas canvas1;
+
+ protected Canvas canvas2;
+
@Override
public String getModuleName() {
return "com.google.gwt.canvas.Canvas";
}
- @Override
- protected void gwtSetUp() throws Exception {
- canvas1 = Canvas.createIfSupported();
- canvas2 = Canvas.createIfSupported();
-
- if (canvas1 == null) {
- return; // don't continue if not supported
- }
-
- RootPanel.get().add(canvas1);
- RootPanel.get().add(canvas2);
- }
-
- @Override
- protected void gwtTearDown() throws Exception {
- if (canvas1 == null) {
- return; // don't continue if not supported
- }
-
- RootPanel.get().remove(canvas1);
- RootPanel.get().remove(canvas2);
- }
-
/*
* If the canvas has no pixels (i.e. either its horizontal dimension or its
* vertical dimension is zero) then the method must return the string
@@ -91,7 +78,7 @@
assertEquals(0, canvas1.getOffsetWidth());
canvas1.setCoordinateSpaceHeight(0);
canvas1.setCoordinateSpaceWidth(0);
-
+
String dataUrl = canvas1.toDataUrl();
assertTrue("toDataURL() should return data:something",
dataUrl.startsWith("data:"));
@@ -112,9 +99,9 @@
canvas1.setWidth("10px");
canvas1.setCoordinateSpaceHeight(10);
canvas1.setCoordinateSpaceWidth(10);
-
+
String dataUrl = canvas1.toDataUrl("image/png");
- assertTrue("toDataURL(image/png) should return data:image/png[data]",
+ assertTrue("toDataURL(image/png) should return data:image/png[data]",
dataUrl.startsWith("data:image/png"));
}
@@ -139,7 +126,7 @@
canvas1.setCoordinateSpaceHeight(140);
canvas1.setCoordinateSpaceWidth(160);
context.fillRect(2, 2, 300, 300);
-
+
assertEquals(41, canvas1.getOffsetHeight());
assertEquals(61, canvas1.getOffsetWidth());
}
@@ -167,7 +154,7 @@
assertEquals(60, canvas1.getOffsetWidth());
assertEquals(140, canvas1.getCoordinateSpaceHeight());
assertEquals(160, canvas1.getCoordinateSpaceWidth());
-
+
// resize internal
canvas1.setCoordinateSpaceHeight(141);
canvas1.setCoordinateSpaceWidth(161);
@@ -184,5 +171,38 @@
assertTrue(
"isSupported() should be true when createIfSupported() returns non-null", Canvas.isSupported());
}
+ // test the isxxxSupported() call if running known-sup or known-not-sup
+ // browsers
+ if (isFirefox35OrLater()) {
+ assertTrue(Canvas.isSupported());
+ assertTrue(Canvas.isSupported());
+ }
+ if (isIE6()) {
+ assertFalse(Canvas.isSupported());
+ assertFalse(Canvas.isSupported());
+ }
+ }
+
+ @Override
+ protected void gwtSetUp() throws Exception {
+ canvas1 = Canvas.createIfSupported();
+ canvas2 = Canvas.createIfSupported();
+
+ if (canvas1 == null) {
+ return; // don't continue if not supported
+ }
+
+ RootPanel.get().add(canvas1);
+ RootPanel.get().add(canvas2);
+ }
+
+ @Override
+ protected void gwtTearDown() throws Exception {
+ if (canvas1 == null) {
+ return; // don't continue if not supported
+ }
+
+ RootPanel.get().remove(canvas1);
+ RootPanel.get().remove(canvas2);
}
}
diff --git a/user/test/com/google/gwt/media/MediaSuite.java b/user/test/com/google/gwt/media/MediaSuite.java
index 1ecc7e4..de3542f 100644
--- a/user/test/com/google/gwt/media/MediaSuite.java
+++ b/user/test/com/google/gwt/media/MediaSuite.java
@@ -18,6 +18,8 @@
import com.google.gwt.junit.tools.GWTTestSuite;
import com.google.gwt.user.client.MediaEventsSinkTest;
+import com.google.gwt.media.client.AudioTest;
+import com.google.gwt.media.client.VideoTest;
import junit.framework.Test;
@@ -29,13 +31,9 @@
GWTTestSuite suite = new GWTTestSuite("Test suite for Media GWTTestCases");
suite.addTestSuite(MediaEventsSinkTest.class);
+ suite.addTestSuite(AudioTest.class);
+ suite.addTestSuite(VideoTest.class);
- /*
- * Tests disabled temporarily
- * suite.addTestSuite(AudioTest.class);
- * suite.addTestSuite(VideoTest.class);
- */
-
return suite;
}
diff --git a/user/test/com/google/gwt/media/client/AudioTest.java b/user/test/com/google/gwt/media/client/AudioTest.java
index 29b8b87..212c495 100644
--- a/user/test/com/google/gwt/media/client/AudioTest.java
+++ b/user/test/com/google/gwt/media/client/AudioTest.java
@@ -15,23 +15,22 @@
*/
package com.google.gwt.media.client;
-import com.google.gwt.dom.client.AudioElement;
import com.google.gwt.dom.client.MediaElement;
import com.google.gwt.junit.DoNotRunWith;
import com.google.gwt.junit.Platform;
import com.google.gwt.user.client.ui.RootPanel;
/**
- * Tests {@link AudioElement}.
+ * Tests {@link Audio}.
*
- * Because HtmlUnit does not support HTML5, you will need to run these tests
+ * Because HtmlUnit does not support HTML5, you will need to run these tests
* manually in order to have them run. To do that, go to "run configurations" or
* "debug configurations", select the test you would like to run, and put this
* line in the VM args under the arguments tab: -Dgwt.args="-runStyle Manual:1"
*/
@DoNotRunWith(Platform.HtmlUnitUnknown)
public class AudioTest extends MediaTest {
- Audio audio;
+ protected Audio audio;
final static String audioUrlMp3 = "smallmp3.mp3";
final static String audioFormatMp3 = "audio/mpeg";
@@ -39,46 +38,8 @@
final static String audioFormatOgg = "audio/ogg";
@Override
- public MediaElement getElement() {
- if (audio == null) {
- return null;
- }
- return audio.getAudioElement();
- }
-
- @Override
- public String getElementState() {
- StringBuilder sb = new StringBuilder();
- AudioElement e = audio.getAudioElement();
- sb.append("AudioElement[");
- sb.append("currentSrc=");
- sb.append(e.getCurrentSrc());
- sb.append(",currentTime=");
- sb.append(e.getCurrentTime());
- sb.append(",defaultPlaybackRate=");
- sb.append(e.getDefaultPlaybackRate());
- sb.append(",duration=");
- sb.append(e.getDuration());
- sb.append(",initialTime=");
- sb.append(e.getInitialTime());
- sb.append(",networkState=");
- sb.append(e.getNetworkState());
- sb.append(",playbackRate=");
- sb.append(e.getPlaybackRate());
- sb.append(",preload=");
- sb.append(e.getPreload());
- sb.append(",readyState=");
- sb.append(e.getReadyState());
- sb.append(",src=");
- sb.append(e.getSrc());
- sb.append(",startOffsetTime=");
- sb.append(e.getStartOffsetTime());
- sb.append(",seekable=");
- sb.append(e.getSeekable());
- sb.append(",volume=");
- sb.append(e.getVolume());
- sb.append("]");
- return sb.toString();
+ public MediaBase getMedia() {
+ return audio;
}
@Override
@@ -89,21 +50,25 @@
@Override
protected void gwtSetUp() throws Exception {
audio = Audio.createIfSupported();
-
+
if (audio == null) {
return; // don't continue if not supported
}
- AudioElement element = audio.getAudioElement();
- String canPlayMp3 = element.canPlayType(audioFormatMp3);
- String canPlayOgg = element.canPlayType(audioFormatOgg);
- if (!canPlayMp3.equalsIgnoreCase(MediaElement.CANNOT_PLAY)) {
- element.setSrc(audioUrlMp3);
- } else if (!canPlayOgg.equalsIgnoreCase(MediaElement.CANNOT_PLAY)) {
- element.setSrc(audioUrlOgg);
+ String canPlayMp3 = audio.canPlayType(audioFormatMp3);
+ String canPlayOgg = audio.canPlayType(audioFormatOgg);
+ if (canPlayMp3.equals(MediaElement.CAN_PLAY_PROBABLY)) {
+ audio.setSrc(audioUrlMp3);
+ } else if (canPlayOgg.equals(MediaElement.CAN_PLAY_PROBABLY)) {
+ audio.setSrc(audioUrlOgg);
+ } else if (canPlayMp3.equals(MediaElement.CAN_PLAY_MAYBE)) {
+ audio.setSrc(audioUrlMp3);
+ } else if (canPlayOgg.equals(MediaElement.CAN_PLAY_MAYBE)) {
+ audio.setSrc(audioUrlOgg);
} else {
throw new Exception("Could not find suitable audio format");
}
+
RootPanel.get().add(audio);
}
@@ -112,8 +77,11 @@
if (audio == null) {
return; // don't continue if not supported
}
-
- audio.getAudioElement().pause();
+
+ // clean up
+ audio.pause();
+ audio.setSrc("");
+ audio.load();
RootPanel.get().remove(audio);
}
}
diff --git a/user/test/com/google/gwt/media/client/MediaTest.java b/user/test/com/google/gwt/media/client/MediaTest.java
index 9eda220..d288211 100644
--- a/user/test/com/google/gwt/media/client/MediaTest.java
+++ b/user/test/com/google/gwt/media/client/MediaTest.java
@@ -1,12 +1,12 @@
/*
* Copyright 2011 Google Inc.
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -19,17 +19,18 @@
import com.google.gwt.junit.DoNotRunWith;
import com.google.gwt.junit.Platform;
import com.google.gwt.junit.client.GWTTestCase;
+import com.google.gwt.media.dom.client.MediaError;
import com.google.gwt.user.client.Timer;
import junit.framework.Assert;
/**
- * Base test for {@link MediaElement}.
- *
- * Do not call this class directly. To use, extend this class and override the
+ * Base test for {@link MediaBase}.
+ *
+ * Do not call this class directly. To use, extend this class and override the
* getElement and isSupported methods.
- *
- * Because HtmlUnit does not support HTML5, you will need to run these tests
+ *
+ * Because HtmlUnit does not support HTML5, you will need to run these tests
* manually in order to have them run. To do that, go to "run configurations" or
* "debug configurations", select the test you would like to run, and put this
* line in the VM args under the arguments tab: -Dgwt.args="-runStyle Manual:1"
@@ -37,39 +38,50 @@
@DoNotRunWith(Platform.HtmlUnitUnknown)
public abstract class MediaTest extends GWTTestCase {
- native boolean isOldFirefox() /*-{
- return @com.google.gwt.dom.client.DOMImplMozilla::isGecko191OrBefore()();
+ static native boolean isFirefox35OrLater() /*-{
+ var geckoVersion = @com.google.gwt.dom.client.DOMImplMozilla::getGeckoVersion()();
+ return (geckoVersion != -1) && (geckoVersion >= 1009001);
}-*/;
- native boolean isFirefox40OrEarlier() /*-{
+ static native boolean isFirefox40OrEarlier() /*-{
return @com.google.gwt.dom.client.DOMImplMozilla::isGecko2OrBefore()();
}-*/;
- public void disabled_testCurrentTime() {
- MediaElement element = getElement();
- if (element == null) {
+ static native boolean isIE6() /*-{
+ return @com.google.gwt.dom.client.DOMImplIE6::isIE6()();
+ }-*/;
+
+ static native boolean isOldFirefox() /*-{
+ return @com.google.gwt.dom.client.DOMImplMozilla::isGecko191OrBefore()();
+ }-*/;
+
+ public void disabled_testPreload() {
+ final MediaBase media = getMedia();
+ if (media == null) {
return; // don't continue if not supported
}
- Assert.assertTrue("currentTime must be positive.",
- element.getCurrentTime() >= 0.0);
+ if (isFirefox40OrEarlier()) {
+ return; // don't continue on older versions of Firefox.
+ }
- double seekTime = 2.0; // seconds
- element.setCurrentTime(seekTime);
- Assert.assertEquals("currentTime must be able to be set.", seekTime,
- element.getCurrentTime());
+ String state = media.getPreload();
+ assertNotNull(state);
+ assertTrue("Illegal preload state", state.equals(MediaElement.PRELOAD_AUTO)
+ || state.equals(MediaElement.PRELOAD_METADATA)
+ || state.equals(MediaElement.PRELOAD_NONE));
+
+ media.setPreload(MediaElement.PRELOAD_METADATA);
+ assertEquals("Preload should be able to be set.",
+ MediaElement.PRELOAD_METADATA, media.getPreload());
}
/**
- * Return the MediaElement associated with the test.
- *
- * @return the MediaElement associated with the test.
+ * Return the Media associated with the test.
+ *
+ * @return the Media associated with the test.
*/
- public MediaElement getElement() {
- return null;
- }
-
- public abstract String getElementState();
+ public abstract MediaBase getMedia();
@Override
public String getModuleName() {
@@ -77,70 +89,141 @@
}
public void testAutoPlay() {
- MediaElement element = getElement();
- if (element == null) {
+ final MediaBase media = getMedia();
+ if (media == null) {
return; // don't continue if not supported
}
- element.setAutoplay(false);
- assertFalse("Autoplay should be off.", element.isAutoplay());
- element.setAutoplay(true);
- assertTrue("Autoplay should be on.", element.isAutoplay());
+ media.setAutoplay(false);
+ assertFalse("Autoplay should be off.", media.isAutoplay());
+ media.setAutoplay(true);
+ assertTrue("Autoplay should be on.", media.isAutoplay());
}
public void testControls() {
- MediaElement element = getElement();
- if (element == null) {
+ final MediaBase media = getMedia();
+ if (media == null) {
return; // don't continue if not supported
}
- element.setControls(false);
- assertFalse("Controls should be off.", element.hasControls());
- element.setControls(true);
- assertTrue("Controls should be on.", element.hasControls());
+ media.setControls(false);
+ assertFalse("Controls should be off.", media.hasControls());
+ media.setControls(true);
+ assertTrue("Controls should be on.", media.hasControls());
}
public void testCurrentSrc() {
- MediaElement element = getElement();
- if (element == null) {
+ final MediaBase media = getMedia();
+ if (media == null) {
return; // don't continue if not supported
}
- element.load();
- Assert.assertNotNull("currentSrc should be set in these tests.",
- element.getCurrentSrc());
+ media.load();
+ Assert.assertNotNull(
+ "currentSrc should be set in these tests.", media.getCurrentSrc());
+ }
+
+ public void testCurrentTime() {
+ final MediaBase media = getMedia();
+ if (media == null) {
+ return; // don't continue if not supported
+ }
+
+ delayTestFinish(25 * 1000);
+
+ // wait a little, then make sure it played and seek to a previous time
+ new Timer() {
+ @Override
+ public void run() {
+ MediaError error = media.getError();
+ if (error != null) {
+ fail("Media error (" + error.getCode() + ")");
+ }
+
+ // make sure it's playing
+ assertTrue("Media should have played", media.getCurrentTime() > 0);
+
+ // make sure it played enough
+ assertTrue(
+ "Did not play enough", 1000 * media.getCurrentTime() >= 6 * 1000);
+
+ // seek to a previous time
+ media.setCurrentTime(0.0);
+ }
+ }.schedule(15 * 1000);
+
+ // wait an additional 5000ms, then check that the seek was successful
+ new Timer() {
+ @Override
+ public void run() {
+ MediaError error = media.getError();
+ if (error != null) {
+ fail("Media error (" + error.getCode() + ")");
+ }
+
+ assertTrue(1000 * media.getCurrentTime() < 6 * 1000);
+ finishTest();
+ }
+ }.schedule(20 * 1000);
+
+ media.play();
+ }
+
+ public void testLoad() {
+ final MediaBase media = getMedia();
+ if (media == null) {
+ return; // don't continue if not supported
+ }
+
+ // the media resource needs time to load
+ delayTestFinish(20 * 1000);
+
+ // wait a little, then make sure it loaded
+ new Timer() {
+ @Override
+ public void run() {
+ MediaError error = media.getError();
+ if (error != null) {
+ fail("Media error (" + error.getCode() + ")");
+ }
+ finishTest();
+ }
+ }.schedule(15 * 1000);
+
+ media.load();
}
public void testLoop() {
- MediaElement element = getElement();
- if (element == null) {
+ final MediaBase media = getMedia();
+ if (media == null) {
return; // don't continue if not supported
}
- element.setLoop(false);
- assertFalse("Loop should be off.", element.isLoop());
- element.setLoop(true);
- assertTrue("Loop should be on.", element.isLoop());
+ media.setLoop(false);
+ assertFalse("Loop should be off.", media.isLoop());
+ media.setLoop(true);
+ assertTrue("Loop should be on.", media.isLoop());
}
public void testMuted() {
- MediaElement element = getElement();
- if (element == null) {
+ final MediaBase media = getMedia();
+ if (media == null) {
return; // don't continue if not supported
}
- element.setMuted(true);
- assertTrue("Muted should be true.", element.isMuted());
- element.setMuted(false);
- assertFalse("Muted should be false.", element.isMuted());
+ media.setMuted(true);
+ assertTrue("Muted should be true.", media.isMuted());
+ media.setMuted(false);
+ assertFalse("Muted should be false.", media.isMuted());
}
public void testNetworkState() {
- MediaElement element = getElement();
- if (element == null) {
+ final MediaBase media = getMedia();
+ if (media == null) {
return; // don't continue if not supported
}
- int state = element.getNetworkState();
+
+ int state = media.getNetworkState();
assertTrue("Illegal network state", state == MediaElement.NETWORK_EMPTY
|| state == MediaElement.NETWORK_IDLE
|| state == MediaElement.NETWORK_LOADING
@@ -148,88 +231,78 @@
}
public void testPlay() {
- MediaElement element = getElement();
- if (element == null) {
+ final MediaBase media = getMedia();
+ if (media == null) {
return; // don't continue if not supported
}
- int waitMillis = 10000;
- delayTestFinish(3 * waitMillis);
-
- element.setPlaybackRate(1.0);
- element.play();
+ // the media resource needs time to play
+ delayTestFinish(20 * 1000);
// wait a little, then make sure it played
new Timer() {
@Override
public void run() {
+ MediaError error = media.getError();
+ if (error != null) {
+ fail("Media error (" + error.getCode() + ")");
+ }
+
+ assertTrue(media.getCurrentTime() > 0);
finishTest();
}
- }.schedule(waitMillis);
+ }.schedule(15 * 1000);
+
+ media.play();
}
public void testPlaybackRate() {
- final MediaElement element = getElement();
- if (element == null) {
+ final MediaBase media = getMedia();
+ if (media == null) {
return; // don't continue if not supported
}
- int waitMillis = 5000;
- delayTestFinish(3 * waitMillis);
-
assertEquals("Default playback rate should be 1.0", 1.0,
- element.getDefaultPlaybackRate());
+ media.getDefaultPlaybackRate());
- element.play();
+ // the media resource needs time to play
+ delayTestFinish(20 * 1000);
- // wait a little, then make sure it played
+ // wait a little, then change the playback rate
new Timer() {
@Override
public void run() {
+ MediaError error = media.getError();
+ if (error != null) {
+ fail("Media error (" + error.getCode() + ")");
+ }
+
// set rate to 2.0
double rate = 2.0;
- element.setPlaybackRate(rate);
+ media.setPlaybackRate(rate);
assertEquals("Should be able to change playback rate", rate,
- element.getPlaybackRate());
+ media.getPlaybackRate());
// return to 1.0
rate = 1.0;
- element.setPlaybackRate(rate);
+ media.setPlaybackRate(rate);
assertEquals("Should be able to change playback rate", rate,
- element.getPlaybackRate());
+ media.getPlaybackRate());
finishTest();
}
- }.schedule(waitMillis);
- }
+ }.schedule(15 * 1000);
- public void disabled_testPreload() {
- MediaElement element = getElement();
- if (element == null) {
- return; // don't continue if not supported
- }
- if (isFirefox40OrEarlier()) {
- return; // don't continue on older versions of Firefox.
- }
-
- String state = element.getPreload();
- assertNotNull(state);
- assertTrue("Illegal preload state", state.equals(MediaElement.PRELOAD_AUTO)
- || state.equals(MediaElement.PRELOAD_METADATA)
- || state.equals(MediaElement.PRELOAD_NONE));
-
- element.setPreload(MediaElement.PRELOAD_METADATA);
- assertEquals("Preload should be able to be set.",
- MediaElement.PRELOAD_METADATA, element.getPreload());
+ media.play();
}
public void testReadyState() {
- MediaElement element = getElement();
- if (element == null) {
+ final MediaBase media = getMedia();
+ if (media == null) {
return; // don't continue if not supported
}
- int state = element.getReadyState();
+ int state = media.getReadyState();
assertTrue("Illegal ready state", state == MediaElement.HAVE_CURRENT_DATA
|| state == MediaElement.HAVE_ENOUGH_DATA
|| state == MediaElement.HAVE_FUTURE_DATA
@@ -237,17 +310,29 @@
|| state == MediaElement.HAVE_NOTHING);
}
+ public void testSupported() {
+ // test the isxxxSupported() call if running known sup or not sup browsers.
+ if (isIE6()) {
+ assertFalse(Audio.isSupported());
+ assertFalse(Video.isSupported());
+ }
+ if (isFirefox35OrLater()) {
+ assertTrue(Audio.isSupported());
+ assertTrue(Video.isSupported());
+ }
+ }
+
public void testVolume() {
- MediaElement element = getElement();
- if (element == null) {
+ final MediaBase media = getMedia();
+ if (media == null) {
return; // don't continue if not supported
}
- element.setVolume(0.5);
- assertEquals("Volume should be at one-half loudness.", 0.5,
- element.getVolume());
- element.setVolume(0.75);
+ media.setVolume(0.5);
+ assertEquals(
+ "Volume should be at one-half loudness.", 0.5, media.getVolume());
+ media.setVolume(0.75);
assertEquals("Volume should be at three-quarters loudness.", 0.75,
- element.getVolume());
+ media.getVolume());
}
}
diff --git a/user/test/com/google/gwt/media/client/VideoTest.java b/user/test/com/google/gwt/media/client/VideoTest.java
index 05cecfe..115c107 100644
--- a/user/test/com/google/gwt/media/client/VideoTest.java
+++ b/user/test/com/google/gwt/media/client/VideoTest.java
@@ -1,12 +1,12 @@
/*
* Copyright 2011 Google Inc.
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -16,23 +16,23 @@
package com.google.gwt.media.client;
import com.google.gwt.dom.client.MediaElement;
-import com.google.gwt.dom.client.VideoElement;
import com.google.gwt.junit.DoNotRunWith;
import com.google.gwt.junit.Platform;
+import com.google.gwt.media.dom.client.MediaError;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.RootPanel;
/**
- * Tests {@link VideoElement}.
- *
- * Because HtmlUnit does not support HTML5, you will need to run these tests
+ * Tests {@link Video}.
+ *
+ * Because HtmlUnit does not support HTML5, you will need to run these tests
* manually in order to have them run. To do that, go to "run configurations" or
* "debug configurations", select the test you would like to run, and put this
* line in the VM args under the arguments tab: -Dgwt.args="-runStyle Manual:1"
*/
@DoNotRunWith(Platform.HtmlUnitUnknown)
public class VideoTest extends MediaTest {
- Video video;
+ protected Video video;
final static String posterUrl = "poster.jpg";
final static String videoUrlH264 = "smallh264.mp4";
@@ -40,61 +40,12 @@
final static String videoUrlOgv = "smalltheora.ogv";
final static String videoFormatOgv = "video/ogg; codecs=\"theora, vorbis\"";
- final static int videoWidth = 32;
- final static int videoHeight = 18;
+ final static int videoWidth = 64;
+ final static int videoHeight = 36;
@Override
- public MediaElement getElement() {
- if (video == null) {
- return null;
- }
- return video.getVideoElement();
- }
-
- @Override
- public String getElementState() {
- StringBuilder sb = new StringBuilder();
- VideoElement e = video.getVideoElement();
-
- sb.append("VideoElement[");
- sb.append("currentSrc=");
- sb.append(e.getCurrentSrc());
- sb.append(",currentTime=");
- sb.append(e.getCurrentTime());
- sb.append(",defaultPlaybackRate=");
- sb.append(e.getDefaultPlaybackRate());
- sb.append(",duration=");
- sb.append(e.getDuration());
- sb.append(",height=");
- sb.append(e.getHeight());
- sb.append(",initialTime=");
- sb.append(e.getInitialTime());
- sb.append(",networkState=");
- sb.append(e.getNetworkState());
- sb.append(",playbackRate=");
- sb.append(e.getPlaybackRate());
- sb.append(",poster=");
- sb.append(e.getPoster());
- sb.append(",preload=");
- sb.append(e.getPreload());
- sb.append(",readyState=");
- sb.append(e.getReadyState());
- sb.append(",src=");
- sb.append(e.getSrc());
- sb.append(",startOffsetTime=");
- sb.append(e.getStartOffsetTime());
- sb.append(",seekable=");
- sb.append(e.getSeekable());
- sb.append(",videoHeight=");
- sb.append(e.getVideoHeight());
- sb.append(",videoWidth=");
- sb.append(e.getVideoWidth());
- sb.append(",volume=");
- sb.append(e.getVolume());
- sb.append(",width=");
- sb.append(e.getWidth());
- sb.append("]");
- return sb.toString();
+ public MediaBase getMedia() {
+ return video;
}
@Override
@@ -107,9 +58,8 @@
return; // don't continue if not supported
}
- VideoElement element = video.getVideoElement();
- element.setPoster(posterUrl);
- String poster = element.getPoster();
+ video.setPoster(posterUrl);
+ String poster = video.getPoster();
assertEquals(posterUrl, poster.substring(poster.lastIndexOf('/') + 1));
}
@@ -120,11 +70,24 @@
int width = 100;
int height = 200;
- VideoElement element = video.getVideoElement();
- element.setWidth(width);
- element.setHeight(height);
- assertEquals(width, element.getWidth());
- assertEquals(height, element.getHeight());
+ video.setWidth(width + "px");
+ video.setHeight(height + "px");
+ assertEquals(width, video.getOffsetWidth());
+ assertEquals(height, video.getOffsetHeight());
+ }
+
+ // test that the deprecated src constructor works
+ public void testSrcConstructor() {
+ if (video == null) {
+ return; // don't continue if not supported
+ }
+
+ Video video = new Video("http://google.com/video");
+ assertNotNull(video);
+ assertEquals("http://google.com/video", video.getSrc());
+ video.setSrc("");
+ video.load();
+ RootPanel.get().remove(video);
}
public void testVideoSize() {
@@ -132,43 +95,48 @@
return; // don't continue if not supported
}
- int waitMillis = 5000;
- delayTestFinish(3 * waitMillis);
+ // the media resource needs time to load
+ delayTestFinish(20 * 1000);
- final VideoElement element = video.getVideoElement();
- element.play();
-
- // wait a little, then make sure it played
+ // wait a little, then make sure it loaded
new Timer() {
@Override
public void run() {
- assertEquals("Element = " + getElementState() + ", expected width "
- + videoWidth, videoWidth, element.getVideoWidth());
- assertEquals("Element = " + getElementState() + ", expected height "
- + videoHeight, videoHeight, element.getVideoHeight());
+ MediaError error = video.getError();
+ if (error != null) {
+ fail("Media error (" + error.getCode() + ")");
+ }
+ assertEquals(videoWidth, video.getVideoWidth());
+ assertEquals(videoHeight, video.getVideoHeight());
finishTest();
}
- }.schedule(waitMillis);
+ }.schedule(15 * 1000);
+
+ video.play();
}
@Override
protected void gwtSetUp() throws Exception {
video = Video.createIfSupported();
-
+
if (video == null) {
return; // don't continue if not supported
}
- VideoElement element = video.getVideoElement();
- if (!element.canPlayType(videoFormatH264).equalsIgnoreCase(
- MediaElement.CANNOT_PLAY)) {
- element.setSrc(videoUrlH264);
- } else if (!element.canPlayType(videoFormatOgv).equalsIgnoreCase(
- MediaElement.CANNOT_PLAY)) {
- element.setSrc(videoUrlOgv);
+ String canPlayH264 = video.canPlayType(videoFormatH264);
+ String canPlayOgv = video.canPlayType(videoFormatOgv);
+ if (canPlayH264.equals(MediaElement.CAN_PLAY_PROBABLY)) {
+ video.setSrc(videoUrlH264);
+ } else if (canPlayOgv.equals(MediaElement.CAN_PLAY_PROBABLY)) {
+ video.setSrc(videoUrlOgv);
+ } else if (canPlayH264.equals(MediaElement.CAN_PLAY_MAYBE)) {
+ video.setSrc(videoUrlH264);
+ } else if (canPlayOgv.equals(MediaElement.CAN_PLAY_MAYBE)) {
+ video.setSrc(videoUrlOgv);
} else {
throw new Exception("Could not find suitable video format");
}
+
RootPanel.get().add(video);
}
@@ -177,8 +145,11 @@
if (video == null) {
return; // don't continue if not supported
}
-
- video.getVideoElement().pause();
+
+ // clean up
+ video.pause();
+ video.setSrc("");
+ video.load();
RootPanel.get().remove(video);
}
}
diff --git a/user/test/com/google/gwt/media/public-test/poster.jpg b/user/test/com/google/gwt/media/public-test/poster.jpg
index 980ed41..3ad24d8 100644
--- a/user/test/com/google/gwt/media/public-test/poster.jpg
+++ b/user/test/com/google/gwt/media/public-test/poster.jpg
Binary files differ
diff --git a/user/test/com/google/gwt/media/public-test/smallh264.mp4 b/user/test/com/google/gwt/media/public-test/smallh264.mp4
index 1ec0fea..b9b1bff 100644
--- a/user/test/com/google/gwt/media/public-test/smallh264.mp4
+++ b/user/test/com/google/gwt/media/public-test/smallh264.mp4
Binary files differ
diff --git a/user/test/com/google/gwt/media/public-test/smalltheora.ogv b/user/test/com/google/gwt/media/public-test/smalltheora.ogv
index c0950be..48c3df9 100644
--- a/user/test/com/google/gwt/media/public-test/smalltheora.ogv
+++ b/user/test/com/google/gwt/media/public-test/smalltheora.ogv
Binary files differ