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