Cherry picking r9652 into releases/2.2
git-svn-id: https://google-web-toolkit.googlecode.com/svn/releases/2.2@9654 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/dom/client/AudioElement.java b/user/src/com/google/gwt/dom/client/AudioElement.java
new file mode 100644
index 0000000..2cf92e1
--- /dev/null
+++ b/user/src/com/google/gwt/dom/client/AudioElement.java
@@ -0,0 +1,39 @@
+/*
+ * 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.dom.client;
+
+/**
+ * Audio element.
+ *
+ * <p>
+ * <span style="color:red">Experimental API: This API is still under development
+ * and is subject to change.
+ * </span>
+ * </p>
+ *
+ * @see <a href="http://www.w3.org/TR/html5/video.html#audio">W3C HTML 5 Specification</a>
+ */
+@TagName(AudioElement.TAG)
+public class AudioElement extends MediaElement {
+
+ /**
+ * The tag for this element.
+ */
+ public static final String TAG = "audio";
+
+ protected AudioElement() {
+ }
+}
diff --git a/user/src/com/google/gwt/dom/client/DOMImplMozilla.java b/user/src/com/google/gwt/dom/client/DOMImplMozilla.java
index 900fcf9..d892460 100644
--- a/user/src/com/google/gwt/dom/client/DOMImplMozilla.java
+++ b/user/src/com/google/gwt/dom/client/DOMImplMozilla.java
@@ -19,25 +19,50 @@
* Mozilla implementation of StandardBrowser.
*/
class DOMImplMozilla extends DOMImplStandard {
-
- /**
- * Return true if using Gecko 1.9.0 (Firefox 3) or earlier.
- *
- * @return true if using Gecko 1.9.0 (Firefox 3) or earlier.
- */
- @SuppressWarnings("unused")
- private static native boolean isGecko190OrBefore() /*-{
+
+ private static native int getGeckoVersion() /*-{
var result = /rv:([0-9]+)\.([0-9]+)\.([0-9]+)?/.exec(navigator.userAgent.toLowerCase());
if (result && result.length >= 3) {
var version = (parseInt(result[1]) * 1000000) + (parseInt(result[2]) * 1000) +
parseInt(result.length == 4 ? result[3] : 0);
- if (version <= 1009000) {
- return true;
- }
+ return version;
}
- return false;
+ return -1; // not gecko
}-*/;
+ /**
+ * Return true if using Gecko 1.9.0 (Firefox 3) or earlier.
+ *
+ * @return true if using Gecko 1.9.0 (Firefox 3) or earlier
+ */
+ @SuppressWarnings("unused")
+ private static boolean isGecko190OrBefore() {
+ int geckoVersion = getGeckoVersion();
+ return (geckoVersion != -1) && (geckoVersion <= 1009000);
+ }
+
+ /**
+ * Return true if using Gecko 1.9.1 (Firefox 3.5) or earlier.
+ *
+ * @return true if using Gecko 1.9.1 (Firefox 3.5) or earlier
+ */
+ @SuppressWarnings("unused")
+ private static boolean isGecko191OrBefore() {
+ int geckoVersion = getGeckoVersion();
+ return (geckoVersion != -1) && (geckoVersion <= 1009001);
+ }
+
+ /**
+ * Return true if using Gecko 2.0.0 (Firefox 4.0) or earlier.
+ *
+ * @return true if using Gecko 2.0.0 (Firefox 4.0) or earlier
+ */
+ @SuppressWarnings("unused")
+ private static boolean isGecko2OrBefore() {
+ int geckoVersion = getGeckoVersion();
+ return (geckoVersion != -1) && (geckoVersion < 2000000);
+ }
+
@Override
public native void buttonClick(ButtonElement button) /*-{
var doc = button.ownerDocument;
diff --git a/user/src/com/google/gwt/dom/client/Document.java b/user/src/com/google/gwt/dom/client/Document.java
index 256f88a..8981878 100644
--- a/user/src/com/google/gwt/dom/client/Document.java
+++ b/user/src/com/google/gwt/dom/client/Document.java
@@ -54,6 +54,15 @@
}
/**
+ * Creates an <audio> element.
+ *
+ * @return the newly created element
+ */
+ public final AudioElement createAudioElement() {
+ return (AudioElement) DOMImpl.impl.createElement(this, AudioElement.TAG);
+ }
+
+ /**
* Creates a <base> element.
*
* @return the newly created element
@@ -1190,6 +1199,15 @@
}-*/;
/**
+ * Creates a <video> element.
+ *
+ * @return the newly created element
+ */
+ public final VideoElement createVideoElement() {
+ return (VideoElement) DOMImpl.impl.createElement(this, VideoElement.TAG);
+ }
+
+ /**
* Enables or disables scrolling of the document.
*
* @param enable whether scrolling should be enabled or disabled
diff --git a/user/src/com/google/gwt/dom/client/MediaElement.java b/user/src/com/google/gwt/dom/client/MediaElement.java
new file mode 100644
index 0000000..16e24c3
--- /dev/null
+++ b/user/src/com/google/gwt/dom/client/MediaElement.java
@@ -0,0 +1,551 @@
+/*
+ * 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.dom.client;
+
+import com.google.gwt.media.dom.client.MediaError;
+import com.google.gwt.media.dom.client.TimeRanges;
+
+/**
+ * Common superclass for Audio and Video elements.
+ *
+ * See {@link <a href="http://www.w3.org/TR/html5/video.html">W3C HTML5 Video and Audio</a>}
+ */
+public class MediaElement extends Element {
+
+ /**
+ * Constant returned from {@link #canPlayType(String)}.
+ */
+ public static final String CAN_PLAY_PROBABLY = "probably";
+
+ /**
+ * Constant returned from {@link #canPlayType(String)}.
+ */
+ public static final String CAN_PLAY_MAYBE = "maybe";
+
+ /**
+ * Constant returned from {@link #canPlayType(String)}.
+ */
+ public static final String CANNOT_PLAY = "";
+
+ /**
+ * Constant returned from {@link #getReadyState()}.
+ */
+ public static final int HAVE_NOTHING = 0;
+
+ /**
+ * Constant returned from {@link #getReadyState()}.
+ */
+ public static final int HAVE_METADATA = 1;
+
+ /**
+ * Constant returned from {@link #getReadyState()}.
+ */
+ public static final int HAVE_CURRENT_DATA = 2;
+
+ /**
+ * Constant returned from {@link #getReadyState()}.
+ */
+ public static final int HAVE_FUTURE_DATA = 3;
+
+ /**
+ * Constant returned from {@link #getReadyState()}.
+ */
+ public static final int HAVE_ENOUGH_DATA = 4;
+
+ /**
+ * Constant returned from {@link #getNetworkState}.
+ */
+ public static final int NETWORK_EMPTY = 0;
+
+ /**
+ * Constant returned from {@link #getNetworkState}.
+ */
+ public static final int NETWORK_IDLE = 1;
+
+ /**
+ * Constant returned from {@link #getNetworkState}.
+ */
+ public static final int NETWORK_LOADING = 2;
+
+ /**
+ * Constant returned from {@link #getNetworkState}.
+ */
+ public static final int NETWORK_NO_SOURCE = 3;
+
+ /**
+ * Constant used by {@link #getPreload()} and {@link #setPreload(String)}.
+ */
+ public static final String PRELOAD_AUTO = "auto";
+
+ /**
+ * Constant used by {@link #getPreload()} and {@link #setPreload(String)}.
+ */
+ public static final String PRELOAD_METADATA = "metadata";
+
+ /**
+ * Constant used by {@link #getPreload()} and {@link #setPreload(String)}.
+ */
+ public static final String PRELOAD_NONE = "none";
+
+ protected MediaElement() {
+ }
+
+ /**
+ * 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 #CAN_PLAY_PROBABLY}, {@link #CAN_PLAY_MAYBE}, or
+ * {@link #CANNOT_PLAY}
+ */
+ public final native String canPlayType(String type) /*-{
+ return this.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 final native TimeRanges getBuffered() /*-{
+ return this.buffered;
+ }-*/;
+
+ /**
+ * Returns the URL of the current media source, or the empty String
+ * if no source is set.
+ *
+ * @return a String URL
+ */
+ public final native String getCurrentSrc() /*-{
+ return this.currentSrc;
+ }-*/;
+
+ /**
+ * Returns the current time within the source media stream.
+ *
+ * @return the time, in seconds, as a double
+ *
+ * @see #setCurrentTime(double)
+ */
+ public final native double getCurrentTime() /*-{
+ return this.currentTime;
+ }-*/;
+
+ /**
+ * 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 final double getDefaultPlaybackRate() {
+ return getDoubleAttr("defaultPlaybackRate", 1.0);
+ }
+
+ /**
+ * 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 final native double getDuration() /*-{
+ return this.duration;
+ }-*/;
+
+ /**
+ * 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 final native MediaError getError() /*-{
+ return this.error || null;
+ }-*/;
+
+ /**
+ * 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 final double getInitialTime() {
+ return getDoubleAttr("initialTime", 0.0);
+ }
+
+ /**
+ * Returns the network state, one of {@link #NETWORK_EMPTY},
+ * {@link #NETWORK_IDLE}, {@link #NETWORK_LOADING}, or
+ * {@link #NETWORK_NO_SOURCE}.
+ *
+ * @return an integer constant indicating the network state
+ *
+ * @see #NETWORK_EMPTY
+ * @see #NETWORK_IDLE
+ * @see #NETWORK_LOADING
+ * @see #NETWORK_NO_SOURCE
+ */
+ public final native int getNetworkState() /*-{
+ return this.networkState;
+ }-*/;
+
+ /**
+ * 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 final native double getPlaybackRate() /*-{
+ var rate = this.playbackRate;
+ if (rate != null && typeof(rate) == 'number') {
+ return rate;
+ }
+ return 1.0;
+ }-*/;
+
+ /**
+ * Returns a {@link TimeRanges} object indicating which portions of the
+ * source have been played.
+ *
+ * @return a {@link TimeRanges} instance, or {@code null}.
+ */
+ public final native TimeRanges getPlayed() /*-{
+ return this.played;
+ }-*/;
+
+ /**
+ * Returns the preload setting, one of {@link #PRELOAD_AUTO},
+ * {@link #PRELOAD_METADATA}, or {@link #PRELOAD_NONE}.
+ *
+ * @return the preload setting
+ *
+ * @see #setPreload(String)
+ * @see #PRELOAD_AUTO
+ * @see #PRELOAD_METADATA
+ * @see #PRELOAD_NONE
+ */
+ public final native String getPreload() /*-{
+ return this.preload;
+ }-*/;
+
+ /**
+ * Returns the current state of the media with respect to rendering the
+ * current playback position, as one of the constants
+ * {@link #HAVE_CURRENT_DATA}, {@link #HAVE_ENOUGH_DATA},
+ * {@link #HAVE_FUTURE_DATA}, {@link #HAVE_METADATA}, or {@link #HAVE_NOTHING}
+ * .
+ *
+ * @return an integer constant indicating the ready state
+ *
+ * @see #HAVE_CURRENT_DATA
+ * @see #HAVE_ENOUGH_DATA
+ * @see #HAVE_FUTURE_DATA
+ * @see #HAVE_METADATA
+ * @see #HAVE_NOTHING
+ */
+ public final native int getReadyState() /*-{
+ return this.readyState;
+ }-*/;
+
+ /**
+ * Returns a {@link TimeRanges} object indicating which portions of the
+ * source are seekable.
+ *
+ * @return a {@link TimeRanges} instance, or {@code null}.
+ */
+ public final native TimeRanges getSeekable() /*-{
+ return this.seekable;
+ }-*/;
+
+ /**
+ * 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 final native String getSrc() /*-{
+ return this.getAttribute('src');
+ }-*/;
+
+ /**
+ * 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 final double getStartOffsetTime() {
+ return getDoubleAttr("startOffsetTime", Double.NaN);
+ }
+
+ /**
+ * 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 final native double getVolume() /*-{
+ return this.volume;
+ }-*/;
+
+ /**
+ * 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 final native boolean hasControls() /*-{
+ return this.hasAttribute('controls');
+ }-*/;
+
+ /**
+ * Returns {@code true} if playback has reached the end of the media, {@code
+ * false} otherwise.
+ *
+ * @return whether playback has ended
+ */
+ public final native boolean hasEnded() /*-{
+ return this.ended;
+ }-*/;
+
+ /**
+ * 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 final native boolean isAutoplay() /*-{
+ return this.hasAttribute('autoplay');
+ }-*/;
+
+ /**
+ * 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 final native boolean isLoop() /*-{
+ return this.hasAttribute('loop');
+ }-*/;
+
+ /**
+ * 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 final native boolean isMuted() /*-{
+ return !!this.muted;
+ }-*/;
+
+ /**
+ * Returns {@code true} if playback is paused, {@code false} otherwise.
+ *
+ * @return the paused setting
+ *
+ * @see #pause()
+ * @see #play()
+ */
+ public final native boolean isPaused() /*-{
+ return !!this.paused;
+ }-*/;
+
+ /**
+ * 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 final native boolean isSeeking() /*-{
+ return !!this.seeking;
+ }-*/;
+
+ /**
+ * Causes the resource to be loaded.
+ */
+ public final native void load() /*-{
+ this.load();
+ }-*/;
+
+ /**
+ * Causes playback of the resource to be paused.
+ */
+ public final native void pause() /*-{
+ this.pause();
+ }-*/;
+
+ /**
+ * Causes playback of the resource to be started or resumed.
+ */
+ public final native void play() /*-{
+ this.play();
+ }-*/;
+
+ /**
+ * Enables or disables autoplay of the resource.
+ *
+ * @param autoplay if {@code true}, enable autoplay
+ *
+ * @see #isAutoplay()
+ */
+ public final void setAutoplay(boolean autoplay) {
+ setBooleanAttr("autoplay", autoplay);
+ }
+
+ /**
+ * Enables or disables interactive controls.
+ *
+ * @param controls if {@code true}, enable controls
+ *
+ * @see #hasControls()
+ */
+ public final void setControls(boolean controls) {
+ setBooleanAttr("controls", 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 final native void setCurrentTime(double time) /*-{
+ this.currentTime = time;
+ }-*/;
+
+ /**
+ * Sets the default playback rate.
+ *
+ * @param rate a double value
+ *
+ * @see #getDefaultPlaybackRate()
+ */
+ public final native void setDefaultPlaybackRate(double rate) /*-{
+ this.defaultPlaybackRate = rate;
+ }-*/;
+
+ /**
+ * Enables or disables looping.
+ *
+ * @param loop if {@code true}, enable looping
+ *
+ * @see #isLoop()
+ */
+ public final void setLoop(boolean loop) {
+ setBooleanAttr("loop", loop);
+ }
+
+ /**
+ * Enables or disables muting.
+ *
+ * @param muted if {@code true}, enable muting
+ *
+ * @see #isMuted()
+ */
+ public final native void setMuted(boolean muted) /*-{
+ this.muted = muted;
+ }-*/;
+
+ /**
+ * Sets the playback rate.
+ *
+ * @param rate a double value
+ *
+ * @see #getPlaybackRate()
+ */
+ public final native void setPlaybackRate(double rate) /*-{
+ this.playbackRate = rate;
+ }-*/;
+
+ /**
+ * Changes the preload setting to one of {@link #PRELOAD_AUTO},
+ * {@link #PRELOAD_METADATA}, or {@link #PRELOAD_NONE}.
+ *
+ * @param preload a String constants
+ *
+ * @see #getPreload()
+ * @see #setPreload(String)
+ * @see #PRELOAD_AUTO
+ * @see #PRELOAD_METADATA
+ * @see #PRELOAD_NONE
+ */
+ public final native void setPreload(String preload) /*-{
+ this.preload = preload;
+ }-*/;
+
+ /**
+ * Sets the source URL for the media.
+ *
+ * @param url a String URL
+ *
+ * @see #getSrc()
+ */
+ public final native void setSrc(String url) /*-{
+ this.src = url;
+ }-*/;
+
+ /**
+ * Sets the playback volume.
+ *
+ * @param volume a value between 0.0 (silent) and 1.0 (loudest)
+ *
+ * @see #getVolume()
+ */
+ public final native void setVolume(double volume) /*-{
+ this.volume = volume
+ }-*/;
+
+ private native double getDoubleAttr(String name, double def) /*-{
+ var value = this.getAttribute(name);
+ if (value == null || typeof(value) == 'undefined') {
+ return def;
+ }
+ return value;
+ }-*/;
+
+ private void setBooleanAttr(String name, boolean value) {
+ if (value) {
+ setAttribute(name, "");
+ } else {
+ removeAttribute(name);
+ }
+ }
+}
diff --git a/user/src/com/google/gwt/dom/client/VideoElement.java b/user/src/com/google/gwt/dom/client/VideoElement.java
new file mode 100644
index 0000000..3fecf60
--- /dev/null
+++ b/user/src/com/google/gwt/dom/client/VideoElement.java
@@ -0,0 +1,120 @@
+/*
+ * 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.dom.client;
+
+/**
+ * Video element.
+ *
+ * <p>
+ * <span style="color:red">Experimental API: This API is still under development
+ * and is subject to change.
+ * </span>
+ * </p>
+ *
+ * @see <a href="http://www.w3.org/TR/html5/video.html#video">W3C HTML 5 Specification</a>
+ */
+@TagName(VideoElement.TAG)
+public class VideoElement extends MediaElement {
+
+ /**
+ * The tag for this element.
+ */
+ public static final String TAG = "video";
+
+ protected VideoElement() {
+ }
+
+ /**
+ * Gets the height of the element.
+ *
+ * @return the height, in pixels
+ * @see #setHeight(int)
+ */
+ public final native int getHeight() /*-{
+ return this.height;
+ }-*/;
+
+ /**
+ * Returns a poster URL.
+ *
+ * @return a URL containing a poster image
+ *
+ * @see #setPoster(String)
+ */
+ public final native String getPoster() /*-{
+ return this.poster;
+ }-*/;
+
+ /**
+ * Gets the intrinsic height of video within the element.
+ *
+ * @return the height, in pixels
+ * @see #setHeight(int)
+ */
+ public final native int getVideoHeight() /*-{
+ return this.videoHeight;
+ }-*/;
+
+ /**
+ * Gets the instrinsic width of the video within the element.
+ *
+ * @return the width, in pixels
+ * @see #setWidth(int)
+ */
+ public final native int getVideoWidth() /*-{
+ return this.videoWidth;
+ }-*/;
+
+ /**
+ * Gets the width of the element.
+ *
+ * @return the width, in pixels
+ * @see #setWidth(int)
+ */
+ public final native int getWidth() /*-{
+ return this.width;
+ }-*/;
+
+ /**
+ * Sets the height of the element.
+ *
+ * @param height the height, in pixels
+ * @see #getHeight()
+ */
+ public final native void setHeight(int height) /*-{
+ this.height = height;
+ }-*/;
+
+ /**
+ * Sets the poster URL.
+ *
+ * @param url the poster image URL
+ * @see #getPoster
+ */
+ public final native void setPoster(String url) /*-{
+ this.poster = url;
+ }-*/;
+
+ /**
+ * Sets the width of the element.
+ *
+ * @param width the width, in pixels
+ * @see #getWidth()
+ */
+ public final native void setWidth(int width) /*-{
+ this.width = width;
+ }-*/;
+}
diff --git a/user/src/com/google/gwt/media/Media.gwt.xml b/user/src/com/google/gwt/media/Media.gwt.xml
new file mode 100644
index 0000000..4588b70
--- /dev/null
+++ b/user/src/com/google/gwt/media/Media.gwt.xml
@@ -0,0 +1,20 @@
+<!--
+ 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.
+-->
+<module>
+ <inherits name="com.google.gwt.user.User"/>
+ <inherits name="com.google.gwt.media.dom.DOM"/>
+ <source path="client"/>
+</module>
diff --git a/user/src/com/google/gwt/media/client/Audio.java b/user/src/com/google/gwt/media/client/Audio.java
new file mode 100644
index 0000000..210c90a
--- /dev/null
+++ b/user/src/com/google/gwt/media/client/Audio.java
@@ -0,0 +1,166 @@
+/*
+ * 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.core.client.GWT;
+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.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>
+ * </p>
+ *
+ * This widget may not be supported on all browsers.
+ */
+@PartialSupport
+public class Audio extends FocusWidget {
+ 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.
+ */
+ private Audio(AudioElement element) {
+ setElement(element);
+ }
+
+ /**
+ * Creates an Audio widget with a given source URL.
+ *
+ * @param src a String URL
+ */
+ public Audio(String src) {
+ setElement(Document.get().createAudioElement());
+ getAudioElement().setSrc(src);
+ }
+
+ /**
+ * 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.getContext;
+ }-*/;
+
+ /**
+ * 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;
+ }
+ }
+
+ /**
+ * Detector for permutations that might support {@link AudioElement}.
+ */
+ @SuppressWarnings("unused")
+ private static class AudioElementSupportDetectedMaybe
+ extends AudioElementSupportDetector {
+ /**
+ * Using a compile-time check, return true if {@link AudioElement} might be
+ * supported.
+ *
+ * @return true if might be supported, false otherwise.
+ */
+ @Override
+ boolean isSupportedCompileTime() {
+ return true;
+ }
+ }
+
+ /**
+ * Detector for permutations that do not support {@link AudioElement}.
+ */
+ @SuppressWarnings("unused")
+ private static class AudioElementSupportDetectedNo
+ extends AudioElementSupportDetector {
+ /**
+ * Using a compile-time check, return true if {@link AudioElement} might be
+ * supported.
+ *
+ * @return true if might be supported, false otherwise.
+ */
+ @Override
+ boolean isSupportedCompileTime() {
+ return false;
+ }
+ }
+}
diff --git a/user/src/com/google/gwt/media/client/Video.java b/user/src/com/google/gwt/media/client/Video.java
new file mode 100644
index 0000000..bd1eac7
--- /dev/null
+++ b/user/src/com/google/gwt/media/client/Video.java
@@ -0,0 +1,171 @@
+/*
+ * 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.core.client.GWT;
+import com.google.gwt.dom.client.Document;
+import com.google.gwt.dom.client.VideoElement;
+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>
+ * </p>
+ *
+ * This widget may not be supported on all browsers.
+ */
+public class Video extends FocusWidget {
+ 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.
+ */
+ public Video() {
+ setElement(Document.get().createVideoElement());
+ }
+
+ /**
+ * 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);
+ }
+
+ /**
+ * 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.getContext;
+ }-*/;
+
+ /**
+ * 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;
+ }
+ }
+
+ /**
+ * Detector for permutations that might support {@link VideoElement}.
+ */
+ @SuppressWarnings("unused")
+ private static class VideoElementSupportDetectedMaybe
+ extends VideoElementSupportDetector {
+ /**
+ * Using a compile-time check, return true if {@link VideoElement} might be
+ * supported.
+ *
+ * @return true if might be supported, false otherwise.
+ */
+ @Override
+ boolean isSupportedCompileTime() {
+ return true;
+ }
+ }
+
+ /**
+ * Detector for permutations that do not support {@link VideoElement}.
+ */
+ @SuppressWarnings("unused")
+ private static class VideoElementSupportDetectedNo
+ extends VideoElementSupportDetector {
+ /**
+ * Using a compile-time check, return true if {@link VideoElement} might be
+ * supported.
+ *
+ * @return true if might be supported, false otherwise.
+ */
+ @Override
+ boolean isSupportedCompileTime() {
+ return false;
+ }
+ }
+}
diff --git a/user/src/com/google/gwt/media/client/package-info.java b/user/src/com/google/gwt/media/client/package-info.java
new file mode 100644
index 0000000..ae09cd7
--- /dev/null
+++ b/user/src/com/google/gwt/media/client/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+/**
+ * <p>
+ * Widgets for HTML Audio and Video support.
+ */
+@com.google.gwt.util.PreventSpuriousRebuilds
+package com.google.gwt.media.client;
diff --git a/user/src/com/google/gwt/media/dom/DOM.gwt.xml b/user/src/com/google/gwt/media/dom/DOM.gwt.xml
new file mode 100644
index 0000000..961e68d
--- /dev/null
+++ b/user/src/com/google/gwt/media/dom/DOM.gwt.xml
@@ -0,0 +1,18 @@
+<!--
+ 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.
+-->
+<module>
+ <source path="client"/>
+</module>
diff --git a/user/src/com/google/gwt/media/dom/client/MediaError.java b/user/src/com/google/gwt/media/dom/client/MediaError.java
new file mode 100644
index 0000000..1d0aea6
--- /dev/null
+++ b/user/src/com/google/gwt/media/dom/client/MediaError.java
@@ -0,0 +1,72 @@
+/*
+ * 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.dom.client;
+
+import com.google.gwt.core.client.JavaScriptObject;
+
+/**
+ * <p>
+ * A {@link JavaScriptObject} indicating the type of error encountered by a
+ * {@link com.google.gwt.dom.client.MediaElement MediaElement}.
+ *
+ * <p>
+ * <span style="color:red">Experimental API: This API is still under development
+ * and is subject to change.
+ * </span>
+ * </p>
+ *
+ * @see com.google.gwt.dom.client.MediaElement#getError()
+ */
+public final class MediaError extends JavaScriptObject {
+
+ /**
+ * A constant returned by {@link #getCode} indicating that playback
+ * was aborted at the user's request.
+ */
+ public static final int MEDIA_ERR_ABORTED = 1;
+
+ /**
+ * A constant returned by {@link #getCode} indicating that playback
+ * was aborted due to a network error.
+ */
+ public static final int MEDIA_ERR_NETWORK = 2;
+
+ /**
+ * A constant returned by {@link #getCode} indicating that playback
+ * was aborted due to an error in decoding.
+ */
+ public static final int MEDIA_ERR_DECODE = 3;
+
+ /**
+ * A constant returned by {@link #getCode} indicating that the format
+ * of the source stream was unsuitable for playback.
+ */
+ public static final int MEDIA_ERR_SRC_NOT_SUPPORTED = 4;
+
+ protected MediaError() {
+ }
+
+ /**
+ * Returns an error code indicating the reason for the error.
+ *
+ * @return one of {@link MediaError#MEDIA_ERR_ABORTED},
+ * {@link MediaError#MEDIA_ERR_NETWORK}, {@link MediaError#MEDIA_ERR_DECODE},
+ * or {@link MediaError#MEDIA_ERR_SRC_NOT_SUPPORTED}
+ */
+ public native int getCode() /*-{
+ return this.code;
+ }-*/;
+}
diff --git a/user/src/com/google/gwt/media/dom/client/TimeRanges.java b/user/src/com/google/gwt/media/dom/client/TimeRanges.java
new file mode 100644
index 0000000..a11bf89
--- /dev/null
+++ b/user/src/com/google/gwt/media/dom/client/TimeRanges.java
@@ -0,0 +1,74 @@
+/*
+ * 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.dom.client;
+
+import com.google.gwt.core.client.JavaScriptObject;
+
+/**
+ * <p>
+ * A {@link JavaScriptObject} representing a time range returned from a
+ * {@link com.google.gwt.dom.client.MediaElement MediaElement}.
+ *
+ * <p>
+ * <span style="color:red">Experimental API: This API is still under development
+ * and is subject to change.
+ * </span>
+ * </p>
+ *
+ * @see com.google.gwt.dom.client.MediaElement#getBuffered()
+ * @see com.google.gwt.dom.client.MediaElement#getPlayed()
+ * @see com.google.gwt.dom.client.MediaElement#getSeekable()
+ */
+public final class TimeRanges extends JavaScriptObject {
+
+ protected TimeRanges() {
+ }
+
+ /**
+ * Returns the end time of the range indexed by {@code index}.
+ *
+ * @param index the range index, between 0 (inclusive) and {@link #length()}
+ * (exclusive)
+ * @return a double indicating the end time in seconds
+ *
+ * @see #start(int)
+ */
+ public native double end(int index) /*-{
+ return this.end(index);
+ }-*/;
+
+ /**
+ * Returns the number of distinct ranges contained in this object.
+ *
+ * @return an integer number of ranges
+ */
+ public native int length() /*-{
+ return this.length;
+ }-*/;
+
+ /**
+ * Returns the start time of the range indexed by {@code index}.
+ *
+ * @param index the range index, between 0 (inclusive) and {@link #length()}
+ * (exclusive)
+ * @return a double indicating the start time in seconds
+ *
+ * @see #end(int)
+ */
+ public native double start(int index) /*-{
+ return this.start(index);
+ }-*/;
+}
diff --git a/user/src/com/google/gwt/media/dom/client/package-info.java b/user/src/com/google/gwt/media/dom/client/package-info.java
new file mode 100644
index 0000000..88e740d
--- /dev/null
+++ b/user/src/com/google/gwt/media/dom/client/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+/**
+ * <p>
+ * DOM classes for HTML Audio and Video support.
+ */
+@com.google.gwt.util.PreventSpuriousRebuilds
+package com.google.gwt.media.dom.client;
diff --git a/user/src/com/google/gwt/user/User.gwt.xml b/user/src/com/google/gwt/user/User.gwt.xml
index 905c37e..f6277dc 100644
--- a/user/src/com/google/gwt/user/User.gwt.xml
+++ b/user/src/com/google/gwt/user/User.gwt.xml
@@ -26,6 +26,7 @@
<inherits name="com.google.gwt.editor.Editor" />
<inherits name="com.google.gwt.resources.Resources"/>
<inherits name="com.google.gwt.layout.Layout"/>
+ <inherits name="com.google.gwt.media.Media"/>
<inherits name="com.google.gwt.uibinder.UiBinder"/>
<inherits name="com.google.gwt.user.AsyncProxy"/>
<inherits name="com.google.gwt.user.RemoteService"/>
diff --git a/user/test/com/google/gwt/media/MediaSuite.java b/user/test/com/google/gwt/media/MediaSuite.java
new file mode 100644
index 0000000..3174327
--- /dev/null
+++ b/user/test/com/google/gwt/media/MediaSuite.java
@@ -0,0 +1,41 @@
+/*
+ * 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;
+
+import com.google.gwt.junit.tools.GWTTestSuite;
+
+import junit.framework.Test;
+
+/**
+ * Tests of Media.
+ */
+public class MediaSuite {
+ public static Test suite() {
+ GWTTestSuite suite = new GWTTestSuite("Test suite for Media GWTTestCases");
+
+ /*
+ * Tests disabled temporarily
+ * suite.addTestSuite(AudioTest.class);
+ * suite.addTestSuite(VideoTest.class);
+ */
+
+ return suite;
+ }
+
+ private MediaSuite() {
+ }
+}
diff --git a/user/test/com/google/gwt/media/MediaTest.gwt.xml b/user/test/com/google/gwt/media/MediaTest.gwt.xml
new file mode 100644
index 0000000..11f6d65
--- /dev/null
+++ b/user/test/com/google/gwt/media/MediaTest.gwt.xml
@@ -0,0 +1,26 @@
+<!-- -->
+<!-- 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 -->
+<!-- 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. License for the specific language governing permissions and -->
+<!-- limitations under the License. -->
+
+<module>
+ <!-- Inherit the JUnit support -->
+ <inherits name='com.google.gwt.junit.JUnit'/>
+
+ <!-- Make media files available on the server by abusing the 'script' tag -->
+ <source path="client"/>
+ <script src="jabberwocky.ogg"></script>
+ <script src="jabberwocky.mp3"></script>
+ <script src="testogg.ogv"></script>
+ <script src="testh264.mp4"></script>
+ <script src="poster.jpg"></script>
+</module>
diff --git a/user/test/com/google/gwt/media/client/AudioTest.java b/user/test/com/google/gwt/media/client/AudioTest.java
new file mode 100644
index 0000000..e491cd4
--- /dev/null
+++ b/user/test/com/google/gwt/media/client/AudioTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.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}.
+ *
+ * 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;
+
+ final static String audioUrlMp3 = "jabberwocky.mp3";
+ final static String audioFormatMp3 = "audio/mpeg";
+ final static String audioUrlOgg = "jabberwocky.ogg";
+ 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();
+ }
+
+ @Override
+ public String getModuleName() {
+ return "com.google.gwt.media.MediaTest";
+ }
+
+ @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);
+ } else {
+ throw new Exception("Could not find suitable audio format");
+ }
+ RootPanel.get().add(audio);
+ }
+
+ @Override
+ protected void gwtTearDown() throws Exception {
+ if (audio == null) {
+ return; // don't continue if not supported
+ }
+
+ audio.getAudioElement().pause();
+ 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
new file mode 100644
index 0000000..9eda220
--- /dev/null
+++ b/user/test/com/google/gwt/media/client/MediaTest.java
@@ -0,0 +1,253 @@
+/*
+ * 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.junit.DoNotRunWith;
+import com.google.gwt.junit.Platform;
+import com.google.gwt.junit.client.GWTTestCase;
+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
+ * getElement and isSupported methods.
+ *
+ * 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 abstract class MediaTest extends GWTTestCase {
+
+ native boolean isOldFirefox() /*-{
+ return @com.google.gwt.dom.client.DOMImplMozilla::isGecko191OrBefore()();
+ }-*/;
+
+ native boolean isFirefox40OrEarlier() /*-{
+ return @com.google.gwt.dom.client.DOMImplMozilla::isGecko2OrBefore()();
+ }-*/;
+
+ public void disabled_testCurrentTime() {
+ MediaElement element = getElement();
+ if (element == null) {
+ return; // don't continue if not supported
+ }
+
+ Assert.assertTrue("currentTime must be positive.",
+ element.getCurrentTime() >= 0.0);
+
+ double seekTime = 2.0; // seconds
+ element.setCurrentTime(seekTime);
+ Assert.assertEquals("currentTime must be able to be set.", seekTime,
+ element.getCurrentTime());
+ }
+
+ /**
+ * Return the MediaElement associated with the test.
+ *
+ * @return the MediaElement associated with the test.
+ */
+ public MediaElement getElement() {
+ return null;
+ }
+
+ public abstract String getElementState();
+
+ @Override
+ public String getModuleName() {
+ return "com.google.gwt.media.MediaTest";
+ }
+
+ public void testAutoPlay() {
+ MediaElement element = getElement();
+ if (element == 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());
+ }
+
+ public void testControls() {
+ MediaElement element = getElement();
+ if (element == 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());
+ }
+
+ public void testCurrentSrc() {
+ MediaElement element = getElement();
+ if (element == null) {
+ return; // don't continue if not supported
+ }
+
+ element.load();
+ Assert.assertNotNull("currentSrc should be set in these tests.",
+ element.getCurrentSrc());
+ }
+
+ public void testLoop() {
+ MediaElement element = getElement();
+ if (element == 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());
+ }
+
+ public void testMuted() {
+ MediaElement element = getElement();
+ if (element == 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());
+ }
+
+ public void testNetworkState() {
+ MediaElement element = getElement();
+ if (element == null) {
+ return; // don't continue if not supported
+ }
+ int state = element.getNetworkState();
+ assertTrue("Illegal network state", state == MediaElement.NETWORK_EMPTY
+ || state == MediaElement.NETWORK_IDLE
+ || state == MediaElement.NETWORK_LOADING
+ || state == MediaElement.NETWORK_NO_SOURCE);
+ }
+
+ public void testPlay() {
+ MediaElement element = getElement();
+ if (element == null) {
+ return; // don't continue if not supported
+ }
+
+ int waitMillis = 10000;
+ delayTestFinish(3 * waitMillis);
+
+ element.setPlaybackRate(1.0);
+ element.play();
+
+ // wait a little, then make sure it played
+ new Timer() {
+ @Override
+ public void run() {
+ finishTest();
+ }
+ }.schedule(waitMillis);
+ }
+
+ public void testPlaybackRate() {
+ final MediaElement element = getElement();
+ if (element == 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());
+
+ element.play();
+
+ // wait a little, then make sure it played
+ new Timer() {
+ @Override
+ public void run() {
+ // set rate to 2.0
+ double rate = 2.0;
+ element.setPlaybackRate(rate);
+ assertEquals("Should be able to change playback rate", rate,
+ element.getPlaybackRate());
+
+ // return to 1.0
+ rate = 1.0;
+ element.setPlaybackRate(rate);
+ assertEquals("Should be able to change playback rate", rate,
+ element.getPlaybackRate());
+
+ finishTest();
+ }
+ }.schedule(waitMillis);
+ }
+
+ 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());
+ }
+
+ public void testReadyState() {
+ MediaElement element = getElement();
+ if (element == null) {
+ return; // don't continue if not supported
+ }
+
+ int state = element.getReadyState();
+ assertTrue("Illegal ready state", state == MediaElement.HAVE_CURRENT_DATA
+ || state == MediaElement.HAVE_ENOUGH_DATA
+ || state == MediaElement.HAVE_FUTURE_DATA
+ || state == MediaElement.HAVE_METADATA
+ || state == MediaElement.HAVE_NOTHING);
+ }
+
+ public void testVolume() {
+ MediaElement element = getElement();
+ if (element == 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);
+ assertEquals("Volume should be at three-quarters loudness.", 0.75,
+ element.getVolume());
+ }
+}
diff --git a/user/test/com/google/gwt/media/client/VideoTest.java b/user/test/com/google/gwt/media/client/VideoTest.java
new file mode 100644
index 0000000..069ef0f
--- /dev/null
+++ b/user/test/com/google/gwt/media/client/VideoTest.java
@@ -0,0 +1,184 @@
+/*
+ * 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.dom.client.VideoElement;
+import com.google.gwt.junit.DoNotRunWith;
+import com.google.gwt.junit.Platform;
+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
+ * 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;
+
+ final static String posterUrl = "poster.jpg";
+ final static String videoUrlH264 = "testh264.mp4";
+ final static String videoFormatH264 = "video/mp4; codecs=\"avc1.42E01E, mp4a.40.2\"";
+ final static String videoUrlOgg = "testogg.ogv";
+ final static String videoFormatOgg = "video/ogg; codecs=\"theora, vorbis\"";
+
+ final static int videoWidth = 480;
+ final static int videoHeight = 270;
+
+ @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("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(",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();
+ }
+
+ @Override
+ public String getModuleName() {
+ return "com.google.gwt.media.MediaTest";
+ }
+
+ public void testPoster() {
+ if (video == null) {
+ return; // don't continue if not supported
+ }
+
+ VideoElement element = video.getVideoElement();
+ element.setPoster(posterUrl);
+ String poster = element.getPoster();
+ assertEquals(posterUrl, poster.substring(poster.lastIndexOf('/') + 1));
+ }
+
+ public void testSize() {
+ if (video == null) {
+ return; // don't continue if not supported
+ }
+
+ int width = 100;
+ int height = 200;
+ VideoElement element = video.getVideoElement();
+ element.setWidth(width);
+ element.setHeight(height);
+ assertEquals(width, element.getWidth());
+ assertEquals(height, element.getHeight());
+ }
+
+ public void testVideoSize() {
+ if (video == null) {
+ return; // don't continue if not supported
+ }
+
+ int waitMillis = 5000;
+ delayTestFinish(3 * waitMillis);
+
+ final VideoElement element = video.getVideoElement();
+ element.play();
+
+ // wait a little, then make sure it played
+ new Timer() {
+ @Override
+ public void run() {
+ assertEquals("Element = " + getElementState() + ", expected width "
+ + videoWidth, videoWidth, element.getVideoWidth());
+ assertEquals("Element = " + getElementState() + ", expected height "
+ + videoHeight, videoHeight, element.getVideoHeight());
+ finishTest();
+ }
+ }.schedule(waitMillis);
+ }
+
+ @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(videoFormatOgg).equalsIgnoreCase(
+ MediaElement.CANNOT_PLAY)) {
+ element.setSrc(videoUrlOgg);
+ } else {
+ throw new Exception("Could not find suitable video format");
+ }
+ RootPanel.get().add(video);
+ }
+
+ @Override
+ protected void gwtTearDown() throws Exception {
+ if (video == null) {
+ return; // don't continue if not supported
+ }
+
+ video.getVideoElement().pause();
+ RootPanel.get().remove(video);
+ }
+}
diff --git a/user/test/com/google/gwt/media/public/jabberwocky.mp3 b/user/test/com/google/gwt/media/public/jabberwocky.mp3
new file mode 100644
index 0000000..ead8687
--- /dev/null
+++ b/user/test/com/google/gwt/media/public/jabberwocky.mp3
Binary files differ
diff --git a/user/test/com/google/gwt/media/public/jabberwocky.ogg b/user/test/com/google/gwt/media/public/jabberwocky.ogg
new file mode 100644
index 0000000..d9a6b0f
--- /dev/null
+++ b/user/test/com/google/gwt/media/public/jabberwocky.ogg
Binary files differ
diff --git a/user/test/com/google/gwt/media/public/poster.jpg b/user/test/com/google/gwt/media/public/poster.jpg
new file mode 100644
index 0000000..980ed41
--- /dev/null
+++ b/user/test/com/google/gwt/media/public/poster.jpg
Binary files differ
diff --git a/user/test/com/google/gwt/media/public/testh264.mp4 b/user/test/com/google/gwt/media/public/testh264.mp4
new file mode 100644
index 0000000..df28ab1
--- /dev/null
+++ b/user/test/com/google/gwt/media/public/testh264.mp4
Binary files differ
diff --git a/user/test/com/google/gwt/media/public/testogg.ogv b/user/test/com/google/gwt/media/public/testogg.ogv
new file mode 100644
index 0000000..f428074
--- /dev/null
+++ b/user/test/com/google/gwt/media/public/testogg.ogv
Binary files differ