Revert "Revert merging for WICKET-5819"

This reverts commit 37116aff50ba0d4382c4b3371eb537bad29fa48d.


Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/95e9eaa2
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/95e9eaa2
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/95e9eaa2

Branch: refs/heads/pr-86-media_tags
Commit: 95e9eaa23b97b4b29d3cd80217126cfe3b4da67e
Parents: 478f1be
Author: Andrea Del Bene <[email protected]>
Authored: Fri Mar 13 21:40:20 2015 +0100
Committer: Andrea Del Bene <[email protected]>
Committed: Fri Mar 13 21:40:20 2015 +0100

----------------------------------------------------------------------
 .../util/resource/PackageResourceStream.java    |  27 +-
 .../markup/html/media/MediaComponent.java       | 500 +++++++++++++++++++
 .../media/MediaStreamingResourceReference.java  | 182 +++++++
 .../markup/html/media/PartWriterCallback.java   | 185 +++++++
 .../apache/wicket/markup/html/media/Source.java | 240 +++++++++
 .../apache/wicket/markup/html/media/Track.java  | 274 ++++++++++
 .../wicket/markup/html/media/audio/Audio.java   |  95 ++++
 .../wicket/markup/html/media/video/Video.java   | 210 ++++++++
 .../html/media/MediaComponentsApplication.java  |  52 ++
 .../html/media/MediaTagsExtendedTestPage.html   |  12 +
 .../html/media/MediaTagsExtendedTestPage.java   |  53 ++
 .../wicket/markup/html/media/MediaTagsTest.java |  92 ++++
 .../markup/html/media/MediaTagsTestPage.html    |  10 +
 .../markup/html/media/MediaTagsTestPage.java    |  56 +++
 .../wicket/markup/html/media/dummyAudio.mp3     |   0
 .../wicket/markup/html/media/dummyPoster.jpg    |   0
 .../wicket/markup/html/media/dummySubtitles.vtt |   0
 .../wicket/markup/html/media/dummyVideo.m4a     |   0
 wicket-examples/pom.xml                         |   2 +
 .../org/apache/wicket/examples/media/Home.css   |  32 ++
 .../org/apache/wicket/examples/media/Home.html  |  29 ++
 .../org/apache/wicket/examples/media/Home.java  | 116 +++++
 .../examples/media/VideosApplication.java       |  63 +++
 .../apache/wicket/examples/media/novideo.gif    | Bin 0 -> 25903 bytes
 .../org/apache/wicket/examples/media/video.mp4  | Bin 0 -> 2757913 bytes
 .../wicket/examples/homepage/HomePage.html      |   1 +
 wicket-examples/src/main/webapp/WEB-INF/web.xml |  22 +-
 27 files changed, 2248 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/95e9eaa2/wicket-core/src/main/java/org/apache/wicket/core/util/resource/PackageResourceStream.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/core/util/resource/PackageResourceStream.java
 
b/wicket-core/src/main/java/org/apache/wicket/core/util/resource/PackageResourceStream.java
index e76926d..4a1a4e6 100644
--- 
a/wicket-core/src/main/java/org/apache/wicket/core/util/resource/PackageResourceStream.java
+++ 
b/wicket-core/src/main/java/org/apache/wicket/core/util/resource/PackageResourceStream.java
@@ -18,6 +18,7 @@ package org.apache.wicket.core.util.resource;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.Locale;
 
 import org.apache.wicket.Application;
 import org.apache.wicket.WicketRuntimeException;
@@ -36,10 +37,10 @@ import org.apache.wicket.util.time.Time;
  * {@link IResourceStreamLocator}.
  *
  * @author <a href="mailto:[email protected]";>Jean-Baptiste Quenot</a>
+ * @author Tobias Soloschenko
  */
 public class PackageResourceStream extends AbstractResourceStream
 {
-       /** */
        private static final long serialVersionUID = 1L;
 
        private final IResourceStream resourceStream;
@@ -56,11 +57,33 @@ public class PackageResourceStream extends 
AbstractResourceStream
         */
        public PackageResourceStream(Class<?> scope, String path)
        {
+               this(scope, path, null, null, null);
+       }
+
+       /**
+        * Obtains an {@link IResourceStream} from the application's
+        * {@link IResourceStreamLocator#locate(Class, String)}
+        *
+        * @param scope
+        *            This argument will be used to get the class loader for 
loading the package
+        *            resource, and to determine what package it is in.
+        * @param path
+        *            The path to the resource
+        * @param locale
+        *            the locale of the resource to get
+        * @param style
+        *            the style of the resource to get
+        * @param variation
+        *            the variation of the resource to get
+        */
+       public PackageResourceStream(Class<?> scope, String path, Locale 
locale, String style,
+               String variation)
+       {
                String absolutePath = Packages.absolutePath(scope, path);
                resourceStream = Application.get()
                        .getResourceSettings()
                        .getResourceStreamLocator()
-                       .locate(scope, absolutePath, null, null, null, null, 
false);
+                       .locate(scope, absolutePath, style, variation, locale, 
null, false);
 
                if (resourceStream == null)
                {

http://git-wip-us.apache.org/repos/asf/wicket/blob/95e9eaa2/wicket-core/src/main/java/org/apache/wicket/markup/html/media/MediaComponent.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/markup/html/media/MediaComponent.java
 
b/wicket-core/src/main/java/org/apache/wicket/markup/html/media/MediaComponent.java
new file mode 100755
index 0000000..d8f6d49
--- /dev/null
+++ 
b/wicket-core/src/main/java/org/apache/wicket/markup/html/media/MediaComponent.java
@@ -0,0 +1,500 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.wicket.markup.html.media;
+
+import org.apache.wicket.markup.ComponentTag;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.request.Url;
+import org.apache.wicket.request.cycle.RequestCycle;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.apache.wicket.request.mapper.parameter.PageParametersEncoder;
+
+/**
+ * The media component is used to provide basic functionality to the video and 
audio component. The
+ * given media streaming resource reference supports Content-Ranges and other 
stuff to make the
+ * audio and video playback smooth.
+ * 
+ * @author Tobias Soloschenko
+ * @author Andrew Lombardi
+ */
+public abstract class MediaComponent extends WebMarkupContainer
+{
+       private static final long serialVersionUID = 1L;
+
+       /**
+        * To be used for the <em>crossorigin</em> attribute
+        * 
+        * @see {@link #setCrossOrigin(Cors)}
+        */
+       public enum Cors
+       {
+               ANONYMOUS("anonymous"), USER_CREDENTIALS("user-credentials"), 
NO_CORS("");
+
+               private final String realName;
+
+               private Cors(String realName)
+               {
+                       this.realName = realName;
+               }
+
+               public String getRealName()
+               {
+                       return realName;
+               }
+       }
+
+       /**
+        * To be used for the <em>preload</em> attribute
+        * 
+        * @see {@link #setPreload(Preload)}
+        */
+       public enum Preload
+       {
+               NONE("none"), METADATA("metadata"), AUTO("auto");
+
+               public final String realName;
+
+               private Preload(String realname)
+               {
+                       realName = realname;
+               }
+
+               public String getRealName()
+               {
+                       return realName;
+               }
+       }
+
+       private boolean autoplay;
+
+       private boolean loop;
+
+       private boolean muted;
+
+       private boolean controls = true;
+
+       private Preload preload;
+
+       private String startTime;
+
+       private String endTime;
+
+       private String mediaGroup;
+
+       private Cors crossOrigin;
+
+       private final PageParameters pageParameters;
+
+       private final MediaStreamingResourceReference 
mediaStreamingResourceReference;
+
+       private final String url;
+
+       /**
+        * Constructor.
+        *
+        * @param id
+        *            The component id
+        */
+       public MediaComponent(String id)
+       {
+               this(id, null, null, null, null);
+       }
+
+       /**
+        * Constructor.
+        *
+        * @param id
+        *            The component id
+        * @param model
+        *            The component model
+        */
+       public MediaComponent(String id, IModel<?> model)
+       {
+               this(id, model, null, null, null);
+       }
+
+       /**
+        * Constructor.
+        *
+        * @param id
+        *            The component id
+        * @param mediaStreamingResourceReference
+        */
+       public MediaComponent(String id, MediaStreamingResourceReference 
mediaStreamingResourceReference)
+       {
+               this(id, null, null, null, mediaStreamingResourceReference);
+       }
+
+       public MediaComponent(String id, IModel<?> model,
+               MediaStreamingResourceReference mediaStreamingResourceReference)
+       {
+               this(id, model, null, null, mediaStreamingResourceReference);
+       }
+
+       public MediaComponent(String id,
+               MediaStreamingResourceReference mediaStreamingResourceReference,
+               PageParameters pageParameters)
+       {
+               this(id, null, null, pageParameters, 
mediaStreamingResourceReference);
+       }
+
+       public MediaComponent(String id, IModel<?> model,
+               MediaStreamingResourceReference mediaStreamingResourceReference,
+               PageParameters pageParameters)
+       {
+               this(id, model, null, pageParameters, 
mediaStreamingResourceReference);
+       }
+
+       public MediaComponent(String id, String url)
+       {
+               this(id, null, url, null, null);
+       }
+
+       public MediaComponent(String id, IModel<?> model, String url)
+       {
+               this(id, model, url, null, null);
+       }
+
+       public MediaComponent(String id, IModel<?> model, String url, 
PageParameters pageParameters)
+       {
+               this(id, model, url, pageParameters, null);
+       }
+
+       private MediaComponent(String id, IModel<?> model, String url, 
PageParameters pageParameters,
+               MediaStreamingResourceReference mediaStreamingResourceReference)
+       {
+               super(id, model);
+               this.url = url;
+               this.pageParameters = pageParameters;
+               this.mediaStreamingResourceReference = 
mediaStreamingResourceReference;
+       }
+
+       @Override
+       protected void onComponentTag(ComponentTag tag)
+       {
+               super.onComponentTag(tag);
+
+               // The time management is used to set the start / stop
+               // time in seconds of the movie to be played back
+               String timeManagement = "";
+               if (startTime != null)
+               {
+                       timeManagement += "#t=" + startTime + (endTime != null 
? "," + endTime : "");
+               }
+
+               if (mediaStreamingResourceReference != null)
+               {
+                       CharSequence urlToMediaReference = 
RequestCycle.get().urlFor(
+                               mediaStreamingResourceReference, 
pageParameters);
+                       tag.put("src", urlToMediaReference + timeManagement);
+               }
+               else if (url != null)
+               {
+                       Url encoded = new 
PageParametersEncoder().encodePageParameters(pageParameters);
+                       String queryString = encoded.getQueryString();
+                       tag.put("src", url + (queryString != null ? "?" + 
queryString : "") + timeManagement);
+               }
+
+               String mg = getMediaGroup();
+               if (mg != null)
+               {
+                       tag.put("mediagroup", mg);
+               }
+
+               if (isAutoplay())
+               {
+                       tag.put("autoplay", "autoplay");
+               }
+
+               if (isLooping())
+               {
+                       tag.put("loop", "loop");
+               }
+
+               if (isMuted())
+               {
+                       tag.put("muted", "muted");
+               }
+
+               if (hasControls())
+               {
+                       tag.put("controls", "controls");
+               }
+
+               Preload _preload = getPreload();
+               if (_preload != null)
+               {
+                       tag.put("preload", _preload.getRealName());
+               }
+
+               Cors cors = getCrossOrigin();
+               if (cors != null)
+               {
+                       tag.put("crossorigin", cors.getRealName());
+               }
+       }
+
+       /**
+        * If the playback is autoplayed on load
+        * 
+        * @return If the playback is autoplayed on load
+        */
+       public boolean isAutoplay()
+       {
+               return autoplay;
+       }
+
+       /**
+        * Sets the playback to be autoplayed on load
+        * 
+        * @param autoplay
+        *            If the playback is autoplayed on load
+        */
+       public void setAutoplay(boolean autoplay)
+       {
+               this.autoplay = autoplay;
+       }
+
+       /**
+        * If the playback is looped
+        * 
+        * @return If the playback is looped
+        */
+       public boolean isLooping()
+       {
+               return loop;
+       }
+
+       /**
+        * Sets the playback to be looped
+        * 
+        * @param loop
+        *            If the playback is looped
+        */
+       public void setLooping(boolean loop)
+       {
+               this.loop = loop;
+       }
+
+       /**
+        * If the playback is muted initially
+        * 
+        * @return If the playback is muted initially
+        */
+       public boolean isMuted()
+       {
+               return muted;
+       }
+
+       /**
+        * Sets the playback muted initially
+        * 
+        * @param muted
+        *            If the playback is muted initially
+        */
+       public void setMuted(boolean muted)
+       {
+               this.muted = muted;
+       }
+
+       /**
+        * If the controls are going to be displayed
+        * 
+        * @return if the controls are going to displayed
+        */
+       public boolean hasControls()
+       {
+               return controls;
+       }
+
+       /**
+        * Sets if the controls are going to be displayed
+        * 
+        * @param controls
+        *            if the controls are going to displayed
+        */
+       public void setControls(Boolean controls)
+       {
+               this.controls = controls;
+       }
+
+       /**
+        * The type of preload
+        * 
+        * @see {@link #setPreload(Preload)}
+        * 
+        * @return the preload
+        */
+       public Preload getPreload()
+       {
+               return preload;
+       }
+
+       /**
+        * Sets the type of preload.
+        * <ul>
+        * <li><b>none</b>: Hints to the user agent that either the author does 
not expect the user to
+        * need the media resource, or that the server wants to minimise 
unnecessary traffic.</li>
+        *
+        * <li><b>metadata</b>: Hints to the user agent that the author does 
not expect the user to need
+        * the media resource, but that fetching the resource metadata 
(dimensions, first frame, track
+        * list, duration, etc) is reasonable.</li>
+        *
+        * <li><b>auto</b>: Hints to the user agent that the user agent can put 
the user's needs first
+        * without risk to the server, up to and including optimistically 
downloading the entire
+        * resource.</li>
+        * </ul>
+        * </p>
+        * 
+        * @param preload
+        *            the type of the preload
+        */
+       public void setPreload(Preload preload)
+       {
+               this.preload = preload;
+       }
+
+       /**
+        * Gets the position at which the media component starts the playback
+        * 
+        * @see {@link #setStartTime(String)}
+        * 
+        * @return the time at which position the media component starts the 
playback
+        */
+       public String getStartTime()
+       {
+               return startTime;
+       }
+
+       /**
+        * Sets the position at which the media component starts the 
playback<br>
+        * <br>
+        * t=<b>10</b>,20<br>
+        * t=<b>npt:10</b>,20<br>
+        * <br>
+        * 
+        * t=<b>120s</b>,121.5s<br>
+        * t=<b>npt:120</b>,0:02:01.5<br>
+        * <br>
+        * 
+        * t=<b>smpte-30:0:02:00</b>,0:02:01:15<br>
+        * t=<b>smpte-25:0:02:00:00</b>,0:02:01:12.1<br>
+        * <br>
+        * 
+        * t=<b>clock:20090726T111901Z</b>,20090726T121901Z
+        * 
+        * @param startTime
+        *            the time at which position the media component starts the 
playback
+        */
+       public void setStartTime(String startTime)
+       {
+               this.startTime = startTime;
+       }
+
+       /**
+        * Gets the position at which the media component stops the playback
+        * 
+        * @see {@link #setEndTime(String)}
+        * 
+        * @return the time at which position the media component stops the 
playback
+        */
+       public String getEndTime()
+       {
+               return endTime;
+       }
+
+       /**
+        * Sets the position at which the media component stops the playback<br>
+        * <br>
+        * t=10,<b>20</b><br>
+        * t=npt:10,<b>20</b><br>
+        * <br>
+        * 
+        * t=120s,<b>121.5s</b><br>
+        * t=npt:120,<b>0:02:01.5</b><br>
+        * <br>
+        * 
+        * t=smpte-30:0:02:00,<b>0:02:01:15</b><br>
+        * t=smpte-25:0:02:00:00,<b>0:02:01:12.1</b><br>
+        * <br>
+        * 
+        * t=clock:20090726T111901Z,<b>20090726T121901Z</b>
+        * 
+        * @param endTime
+        *            the time at which position the media component stops the 
playback
+        */
+       public void setEndTime(String endTime)
+       {
+               this.endTime = endTime;
+       }
+
+       /**
+        * Gets the media group.
+        * 
+        * @return the media group
+        */
+       public String getMediaGroup()
+       {
+               return mediaGroup;
+       }
+
+       /**
+        * Sets the media group
+        * 
+        * @param mediaGroup
+        *            to be set
+        */
+       public void setMediaGroup(String mediaGroup)
+       {
+               this.mediaGroup = mediaGroup;
+       }
+
+       /**
+        * Gets the cross origin settings
+        * 
+        * @see {@link #setCrossOrigin(Cors)}
+        * 
+        * @return the cross origins settings
+        */
+       public Cors getCrossOrigin()
+       {
+               return crossOrigin;
+       }
+
+       /**
+        * Sets the cross origin settings<br>
+        * <br>
+        * 
+        * <b>ANONYMOUS</b>: Cross-origin CORS requests for the element will 
not have the credentials
+        * flag set.<br>
+        * <br>
+        * <b>USER_CREDENTIALS</b>: Cross-origin CORS requests for the element 
will have the credentials
+        * flag set.<br>
+        * <br>
+        * <b>NO_CORS</b>: The empty string is also a valid keyword, and maps 
to the Anonymous state.
+        * The attribute's invalid value default is the Anonymous state. The 
missing value default, used
+        * when the attribute is omitted, is the No CORS state
+        * 
+        * @param crossOrigin
+        *            the cross origins settings to set
+        */
+       public void setCrossOrigin(Cors crossOrigin)
+       {
+               this.crossOrigin = crossOrigin;
+       }
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/95e9eaa2/wicket-core/src/main/java/org/apache/wicket/markup/html/media/MediaStreamingResourceReference.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/markup/html/media/MediaStreamingResourceReference.java
 
b/wicket-core/src/main/java/org/apache/wicket/markup/html/media/MediaStreamingResourceReference.java
new file mode 100755
index 0000000..03903df
--- /dev/null
+++ 
b/wicket-core/src/main/java/org/apache/wicket/markup/html/media/MediaStreamingResourceReference.java
@@ -0,0 +1,182 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.wicket.markup.html.media;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import org.apache.wicket.Application;
+import org.apache.wicket.WicketRuntimeException;
+import org.apache.wicket.request.Request;
+import org.apache.wicket.request.Response;
+import org.apache.wicket.request.http.WebRequest;
+import org.apache.wicket.request.http.WebResponse;
+import org.apache.wicket.request.resource.ContentDisposition;
+import org.apache.wicket.request.resource.PackageResource;
+import org.apache.wicket.request.resource.PackageResourceReference;
+import org.apache.wicket.util.resource.IResourceStream;
+import org.apache.wicket.util.string.Strings;
+
+/**
+ * The media streaming resource reference is used to provided streamed data 
based on bytes requested
+ * by the client for video and audio files
+ * 
+ * @author Tobias Soloschenko
+ */
+public class MediaStreamingResourceReference extends PackageResourceReference
+{
+       private static final long serialVersionUID = 1L;
+
+       public MediaStreamingResourceReference(Class<?> scope, String name, 
Locale locale,
+               String style, String variation)
+       {
+               super(scope, name, locale, style, variation);
+       }
+
+       public MediaStreamingResourceReference(Class<?> scope, String name)
+       {
+               this(scope, name, null, null, null);
+       }
+
+       public MediaStreamingResourceReference(Key key)
+       {
+               super(key);
+       }
+
+       public MediaStreamingResourceReference(String name)
+       {
+               super(name);
+       }
+
+       @Override
+       public PackageResource getResource()
+       {
+               return new PackageResource(getScope(), getName(), getLocale(), 
getStyle(), getVariation())
+               {
+                       private static final long serialVersionUID = 1L;
+
+                       @Override
+                       protected ResourceResponse 
newResourceResponse(Attributes attributes)
+                       {
+                               IResourceStream resourceStream = 
getResourceStream();
+                               if (resourceStream == null)
+                               {
+                                       throw new 
WicketRuntimeException("Cannot find resource: " + toString());
+                               }
+                               try
+                               {
+                                       Request request = 
attributes.getRequest();
+                                       Response response = 
attributes.getResponse();
+
+                                       if (!(request instanceof WebRequest) || 
!(response instanceof WebResponse))
+                                       {
+                                               throw new IllegalStateException(
+                                                       "Web request/response 
are required! Request: " + request +
+                                                               ", response: " 
+ response);
+                                       }
+
+                                       WebRequest webRequest = 
(WebRequest)request;
+                                       WebResponse webResponse = 
(WebResponse)response;
+
+                                       long length = 
resourceStream.length().bytes();
+
+                                       ResourceResponse resourceResponse = new 
ResourceResponse();
+                                       
resourceResponse.setContentType(resourceStream.getContentType());
+                                       
resourceResponse.setFileName(MediaStreamingResourceReference.this.getName());
+                                       
resourceResponse.setContentDisposition(ContentDisposition.ATTACHMENT);
+                                       
resourceResponse.setLastModified(resourceStream.lastModifiedTime());
+
+                                       // accept ranges, so that the player can
+                                       // load and play content from a 
specific byte position
+                                       webResponse.setHeader("Accept-Range", 
"bytes");
+
+                                       Long startbyte = null;
+                                       Long endbyte = null;
+
+                                       // Calculating the response code and 
the byte range to be played
+                                       String rangeHeader = 
webRequest.getHeader("range");
+                                       if (Strings.isEmpty(rangeHeader))
+                                       {
+                                               
resourceResponse.setStatusCode(200);
+                                               
resourceResponse.setContentLength(length);
+                                       }
+                                       else
+                                       {
+                                               rangeHeader = 
rangeHeader.replaceAll(" ", "");
+                                               // partial content has to be 
returned
+                                               
resourceResponse.setStatusCode(206);
+
+                                               // And now the calculation of 
the range to be read
+                                               // and to be given as response 
within the Content-Range header
+                                               // for more information take a 
look here:
+                                               // 
http://stackoverflow.com/questions/8293687/sample-http-range-request-session
+                                               String range = 
rangeHeader.substring(rangeHeader.indexOf('=') + 1,
+                                                       rangeHeader.length());
+                                               String[] rangeParts = 
Strings.split(range, '-');
+
+                                               String startByteString = 
rangeParts[0];
+                                               String endByteString = 
rangeParts[1];
+
+                                               startbyte = startByteString != 
null && !startByteString.trim().equals("")
+                                                       ? 
Long.parseLong(startByteString) : 0;
+                                               endbyte = endByteString != null 
&& !endByteString.trim().equals("")
+                                                       ? 
Long.parseLong(endByteString) : length - 1;
+
+                                               
webResponse.setHeader("Content-Range", "bytes " + startbyte + '-' +
+                                                       endbyte + '/' + length);
+                                               
resourceResponse.setContentLength((endbyte - startbyte) + 1);
+                                       }
+
+                                       // Apply the writer callback to send 
the requested part to the client
+                                       resourceResponse.setWriteCallback(new 
PartWriterCallback(resourceStream,
+                                               startbyte, endbyte));
+
+                                       return resourceResponse;
+                               }
+                               catch (Exception e)
+                               {
+                                       throw new WicketRuntimeException(
+                                               "A problem occurred while 
creating the video response.", e);
+                               }
+                               finally
+                               {
+                                       try
+                                       {
+                                               resourceStream.close();
+                                       }
+                                       catch (IOException e)
+                                       {
+                                               throw new 
WicketRuntimeException(
+                                                       "A problem occurred 
while closing the video response stream.", e);
+                                       }
+                               }
+                       }
+               };
+
+       }
+
+       /**
+        * Returns the mime type of the media this resource reference belongs to
+        * 
+        * @return the mime type of this media
+        */
+       public String getType()
+       {
+               final String resourceName = 
MediaStreamingResourceReference.this.getName();
+               return Application.get().getMimeType(resourceName);
+       }
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/95e9eaa2/wicket-core/src/main/java/org/apache/wicket/markup/html/media/PartWriterCallback.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/markup/html/media/PartWriterCallback.java
 
b/wicket-core/src/main/java/org/apache/wicket/markup/html/media/PartWriterCallback.java
new file mode 100644
index 0000000..cb6dd64
--- /dev/null
+++ 
b/wicket-core/src/main/java/org/apache/wicket/markup/html/media/PartWriterCallback.java
@@ -0,0 +1,185 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.wicket.markup.html.media;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.wicket.WicketRuntimeException;
+import org.apache.wicket.protocol.http.servlet.ResponseIOException;
+import org.apache.wicket.request.resource.AbstractResource.WriteCallback;
+import org.apache.wicket.request.resource.IResource.Attributes;
+import org.apache.wicket.util.io.Streams;
+import org.apache.wicket.util.resource.IResourceStream;
+
+/**
+ * Used to read a part of the package resource stream and write it to the 
output stream of the
+ * response.
+ * 
+ * @author Tobias Soloschenko
+ *
+ */
+public class PartWriterCallback extends WriteCallback
+{
+       private final IResourceStream resourceStream;
+
+       private final Long startbyte;
+
+       private Long endbyte;
+
+       private int bufferSize;
+
+       /**
+        * Creates a part writer callback.<br>
+        * <br>
+        * Reads a part of the given resource stream. If the startbyte 
parameter is not null the
+        * number of bytes are skipped till the stream is read. If the endbyte 
is not null the stream is
+        * read till endbyte, else to the end of the whole stream. If startbyte 
and endbyte is null the
+        * whole stream is read.
+        * 
+        * @param resourceStream
+        *            the resource stream to read
+        * @param startbyte
+        *            the start position to read from (if not null the number 
of bytes are skipped till
+        *            the stream is read)
+        * @param endbyte
+        *            the end position to read to (if not null the stream is 
going to be read till
+        *            endbyte, else to the end of the whole stream)
+        */
+       public PartWriterCallback(IResourceStream resourceStream, Long 
startbyte,
+               Long endbyte)
+       {
+               this.resourceStream = resourceStream;
+               this.startbyte = startbyte;
+               this.endbyte = endbyte;
+       }
+
+       /**
+        * Writes the data
+        * 
+        * @param attributes
+        *            the attributes to get the output stream of the response
+        */
+       @Override
+       public void writeData(Attributes attributes) throws IOException
+       {
+               try
+               {
+                       InputStream inputStream = 
resourceStream.getInputStream();
+                       OutputStream outputStream = 
attributes.getResponse().getOutputStream();
+                       byte[] buffer = new byte[getBufferSize()];
+
+                       if (startbyte != null || endbyte != null)
+                       {
+                               // skipping the first bytes which are
+                               // requested to be skipped by the client
+                               if (startbyte != null)
+                               {
+                                       inputStream.skip(startbyte);
+                               }
+
+                               // If there are no end bytes given read the 
whole stream till the end
+                               if (endbyte == null)
+                               {
+                                       endbyte = 
resourceStream.length().bytes();
+                               }
+
+                               long totalBytes = 0;
+                               int actualReadBytes;
+
+                               while ((actualReadBytes = 
inputStream.read(buffer)) != -1)
+                               {
+                                       totalBytes = totalBytes + buffer.length;
+                                       long lowerBuffer = endbyte - totalBytes;
+                                       if (lowerBuffer <= 0)
+                                       {
+                                               buffer = resizeArray(buffer, 
actualReadBytes);
+                                               outputStream.write(buffer);
+                                               break;
+                                       }
+                                       else
+                                       {
+                                               outputStream.write(buffer);
+                                       }
+                               }
+                       }
+                       else
+                       {
+                               Streams.copy(inputStream, outputStream, 
getBufferSize());
+                       }
+               }
+               catch (ResponseIOException e)
+               {
+                       // the client has closed the connection and
+                       // doesn't read the stream further on
+                       // (in tomcats
+                       // org.apache.catalina.connector.ClientAbortException)
+                       // we ignore this case
+               }
+               catch (Exception e)
+               {
+                       throw new WicketRuntimeException(
+                               "A problem occurred while writing the buffer to 
the output stream.", e);
+               }
+       }
+
+       /**
+        * Reallocates an array with a new size, and copies the contents of the 
old array to the new
+        * array.
+        * 
+        * @param oldArray
+        *            the old array, to be reallocated.
+        * @param newSize
+        *            the new array size.
+        * @return A new array with the same contents.
+        */
+       @SuppressWarnings("rawtypes")
+       private static byte[] resizeArray(byte[] oldArray, int newSize)
+       {
+               int oldSize = oldArray.length;
+               byte[] newArray = new byte[newSize];
+               int minLength = Math.min(oldSize, newSize);
+               if (minLength > 0)
+               {
+                       System.arraycopy(oldArray, 0, newArray, 0, minLength);
+               }
+               return newArray;
+       }
+
+       /**
+        * Sets the buffer size used to send the data to the client
+        * 
+        * @return the buffer size used to send the data to the client (default 
is 4096)
+        */
+       public int getBufferSize()
+       {
+               return bufferSize > 0 ? bufferSize : 4096;
+       }
+
+       /**
+        * Sets the buffer size used to send the data to the client
+        * 
+        * @param bufferSize
+        *            the buffer size used to send the data to the client
+        */
+       public void setBufferSize(int bufferSize)
+       {
+               this.bufferSize = bufferSize;
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/95e9eaa2/wicket-core/src/main/java/org/apache/wicket/markup/html/media/Source.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/markup/html/media/Source.java 
b/wicket-core/src/main/java/org/apache/wicket/markup/html/media/Source.java
new file mode 100755
index 0000000..c3fc50f
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/markup/html/media/Source.java
@@ -0,0 +1,240 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.wicket.markup.html.media;
+
+import org.apache.wicket.markup.ComponentTag;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.request.cycle.RequestCycle;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+
+/**
+ * The source of an audio or a video media component
+ * 
+ * @author Tobias Soloschenko
+ * @author Andrew Lombardi
+ */
+public class Source extends WebMarkupContainer
+{
+       private static final long serialVersionUID = 1L;
+
+       private boolean displayType;
+
+       private String type;
+
+       private String media;
+
+       private final MediaStreamingResourceReference 
mediaStreamingResourceReference;
+
+       private final PageParameters pageParameters;
+
+       private final String url;
+
+       public Source(String id)
+       {
+               this(id, null, null, null, null);
+       }
+
+       public Source(String id, IModel<?> model)
+       {
+               this(id, model, null, null, null);
+       }
+
+       public Source(String id, MediaStreamingResourceReference 
mediaStreamingResourceReference)
+       {
+               this(id, null, null, null, mediaStreamingResourceReference);
+       }
+
+       public Source(String id, IModel<?> model,
+               MediaStreamingResourceReference mediaStreamingResourceReference)
+       {
+               this(id, model, null, null, mediaStreamingResourceReference);
+       }
+
+       public Source(String id, MediaStreamingResourceReference 
mediaStreamingResourceReference,
+               PageParameters pageParameters)
+       {
+               this(id, null, null, pageParameters, 
mediaStreamingResourceReference);
+       }
+
+       public Source(String id, IModel<?> model,
+               MediaStreamingResourceReference mediaStreamingResourceReference,
+               PageParameters pageParameters)
+       {
+               this(id, model, null, pageParameters, 
mediaStreamingResourceReference);
+       }
+
+       public Source(String id, String url)
+       {
+               this(id, null, url, null, null);
+       }
+
+       public Source(String id, IModel<?> model, String url)
+       {
+               this(id, model, url, null, null);
+       }
+
+       private Source(String id, IModel<?> model, String url, PageParameters 
pageParameters,
+                      MediaStreamingResourceReference 
mediaStreamingResourceReference)
+       {
+               super(id, model);
+               this.url = url;
+               this.pageParameters = pageParameters;
+               this.mediaStreamingResourceReference = 
mediaStreamingResourceReference;
+       }
+
+       @Override
+       protected void onComponentTag(ComponentTag tag)
+       {
+               checkComponentTag(tag, "source");
+               super.onComponentTag(tag);
+
+               if (mediaStreamingResourceReference != null)
+               {
+                       CharSequence url = 
RequestCycle.get().urlFor(mediaStreamingResourceReference, pageParameters);
+                       tag.put("src", url);
+               } else if (url != null)
+               {
+                       tag.put("src", url);
+               }
+
+               if (getDisplayType())
+               {
+                       if (type != null)
+                       {
+                               tag.put("type", type);
+                       }
+                       else if (mediaStreamingResourceReference != null)
+                       {
+                               tag.put("type", 
mediaStreamingResourceReference.getType());
+                       }
+               }
+
+               String _media = getMedia();
+               if (_media != null)
+               {
+                       tag.put("media", _media);
+               }
+
+       }
+
+       /**
+        * If the type is going to be displayed
+        * 
+        * @return If the type is going to be displayed
+        */
+       public boolean getDisplayType()
+       {
+               return displayType;
+       }
+
+       /**
+        * Sets if the type is going to be displayed
+        * 
+        * @param displayType
+        *            if the type is going to be displayed
+        */
+       public void setDisplayType(boolean displayType)
+       {
+               this.displayType = displayType;
+       }
+
+       /**
+        * Gets the type
+        * 
+        * @see {@link #setType(String)}
+        * 
+        * @return the type of this media element
+        */
+       public String getType()
+       {
+               return type;
+       }
+
+       /**
+        * Sets the type<br>
+        * <br>
+        * 
+        * * The following list shows some examples of how to use the codecs= 
MIME parameter in the type
+        * attribute.<br>
+        * <br>
+        * 
+        * H.264 Constrained baseline profile video (main and extended video 
compatible) level 3 and
+        * Low-Complexity AAC audio in MP4 container<br>
+        * &lt;source src='video.mp4' <b>type='video/mp4; codecs="avc1.42E01E, 
mp4a.40.2"'</b>&gt;<br>
+        * H.264 Extended profile video (baseline-compatible) level 3 and 
Low-Complexity AAC audio in
+        * MP4 container<br>
+        * &lt;source src='video.mp4' <b>type='video/mp4; codecs="avc1.58A01E, 
mp4a.40.2"'</b>&gt;<br>
+        * H.264 Main profile video level 3 and Low-Complexity AAC audio in MP4 
container<br>
+        * &lt;source src='video.mp4' <b>type='video/mp4; codecs="avc1.4D401E, 
mp4a.40.2"'</b>&gt;<br>
+        * H.264 'High' profile video (incompatible with main, baseline, or 
extended profiles) level 3
+        * and Low-Complexity AAC audio in MP4 container<br>
+        * &lt;source src='video.mp4' <b>type='video/mp4; codecs="avc1.64001E, 
mp4a.40.2"'</b>&gt;<br>
+        * MPEG-4 Visual Simple Profile Level 0 video and Low-Complexity AAC 
audio in MP4 container<br>
+        * &lt;source src='video.mp4' <b>type='video/mp4; codecs="mp4v.20.8, 
mp4a.40.2"'</b>&gt;<br>
+        * MPEG-4 Advanced Simple Profile Level 0 video and Low-Complexity AAC 
audio in MP4 container<br>
+        * &lt;source src='video.mp4' <b>type='video/mp4; codecs="mp4v.20.240, 
mp4a.40.2"'</b>&gt;<br>
+        * MPEG-4 Visual Simple Profile Level 0 video and AMR audio in 3GPP 
container<br>
+        * &lt;source src='video.3gp' <b>type='video/3gpp; codecs="mp4v.20.8, 
samr"'</b>&gt;<br>
+        * Theora video and Vorbis audio in Ogg container<br>
+        * &lt;source src='video.ogv' <b>type='video/ogg; codecs="theora, 
vorbis"'</b>&gt;<br>
+        * Theora video and Speex audio in Ogg container<br>
+        * &lt;source src='video.ogv' <b>type='video/ogg; codecs="theora, 
speex"'</b>&gt;<br>
+        * Vorbis audio alone in Ogg container<br>
+        * &lt;source src='audio.ogg' <b>type='audio/ogg; 
codecs=vorbis'</b>&gt;<br>
+        * Speex audio alone in Ogg container<br>
+        * &lt;source src='audio.spx' <b>type='audio/ogg; 
codecs=speex'</b>&gt;<br>
+        * FLAC audio alone in Ogg container<br>
+        * &lt;source src='audio.oga' <b>type='audio/ogg; 
codecs=flac'</b>&gt;<br>
+        * Dirac video and Vorbis audio in Ogg container<br>
+        * &lt;source src='video.ogv' <b>type='video/ogg; codecs="dirac, 
vorbis"'</b>&gt;<br>
+        * Theora video and Vorbis audio in Matroska container<br>
+        * &lt;source src='video.mkv' <b>type='video/x-matroska; 
codecs="theora, vorbis"'</b>&gt;<br>
+        * 
+        * @param type
+        *            the type of this media element
+        */
+       public void setType(String type)
+       {
+               this.type = type;
+       }
+
+       /**
+        * The media for which the content of this source should be shown
+        * 
+        * @See {@link #setMedia(String)}
+        * @return The media for which the content of this source should be 
shown
+        */
+       public String getMedia()
+       {
+               return media;
+       }
+
+       /**
+        * Sets the media for which the content of this source should be 
shown<br>
+        * <br>
+        * 
+        * &lt;source src="movie.ogg" type="video/ogg" <b>media="screen and 
(min-width:320px)"&gt;<br>
+        * 
+        * @param media
+        *            the media for which to content of this source should be 
shown
+        */
+       public void setMedia(String media)
+       {
+               this.media = media;
+       }
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/95e9eaa2/wicket-core/src/main/java/org/apache/wicket/markup/html/media/Track.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/markup/html/media/Track.java 
b/wicket-core/src/main/java/org/apache/wicket/markup/html/media/Track.java
new file mode 100755
index 0000000..cef3914
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/markup/html/media/Track.java
@@ -0,0 +1,274 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.wicket.markup.html.media;
+
+import java.util.Locale;
+
+import org.apache.wicket.markup.ComponentTag;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.request.cycle.RequestCycle;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.apache.wicket.request.resource.ResourceReference;
+
+/**
+ * The track tag is used to provide subtitles, captions, descriptions, 
chapters, metadata to a video
+ * media component
+ * 
+ * @author Tobias Soloschenko
+ */
+public class Track extends WebMarkupContainer
+{
+       private static final long serialVersionUID = 1L;
+
+       /**
+        * To be used for the kind attribute
+        */
+       public enum Kind
+       {
+               SUBTITLES("subtitles"), CAPTIONS("captions"), 
DESCRIPTIONS("descriptions"), CHAPTERS(
+                       "chapters"), METADATA("metadata");
+
+               private String realName;
+
+               Kind(String realName)
+               {
+                       this.realName = realName;
+               }
+
+               public String getRealName()
+               {
+                       return realName;
+               }
+       }
+
+       private Kind kind;
+
+       private String label;
+
+       private boolean defaultTrack;
+
+       private Locale srclang;
+
+       private final ResourceReference resourceReference;
+
+       private final String url;
+
+       private final PageParameters pageParameters;
+
+       public Track(String id)
+       {
+               this(id, null, null, null, null);
+       }
+
+       public Track(String id, IModel<?> model)
+       {
+               this(id, model, null, null, null);
+       }
+
+       public Track(String id, ResourceReference resourceReference)
+       {
+               this(id, null, null, null, resourceReference);
+       }
+
+       public Track(String id, IModel<?> model, ResourceReference 
resourceReference)
+       {
+               this(id, model, null, null, resourceReference);
+       }
+
+       public Track(String id, ResourceReference resourceReference, 
PageParameters pageParameters)
+       {
+               this(id, null, null, pageParameters, resourceReference);
+       }
+
+       public Track(String id, IModel<?> model, ResourceReference 
resourceReference,
+               PageParameters pageParameters)
+       {
+               this(id, model, null, pageParameters, resourceReference);
+       }
+
+       public Track(String id, String url)
+       {
+               this(id, null, url, null, null);
+       }
+
+       public Track(String id, IModel<?> model, String url)
+       {
+               this(id, model, url, null, null);
+       }
+
+       private Track(String id, IModel<?> model, String url, PageParameters 
pageParameters,
+               ResourceReference resourceReference)
+       {
+               super(id, model);
+               this.url = url;
+               this.pageParameters = pageParameters;
+               this.resourceReference = resourceReference;
+       }
+
+       @Override
+       protected void onComponentTag(ComponentTag tag)
+       {
+               checkComponentTag(tag, "track");
+               super.onComponentTag(tag);
+
+               if (resourceReference != null)
+               {
+                       tag.put("src", 
RequestCycle.get().urlFor(resourceReference, pageParameters));
+               }
+               else if (url != null)
+               {
+                       tag.put("src", url);
+               }
+
+               Kind _kind = getKind();
+               if (_kind != null)
+               {
+                       tag.put("kind", _kind.getRealName());
+               }
+
+               String _label = getLabel();
+               if (_label != null)
+               {
+                       tag.put("label", _label);
+               }
+
+               if (defaultTrack)
+               {
+                       tag.put("default", "default");
+               }
+
+               // if the srclang field is set use this, else if the
+               // resource reference provides a locale use the language
+               // of the resource reference
+               Locale _srclang = getSrclang();
+               if (_srclang != null)
+               {
+                       tag.put("srclang", _srclang.getLanguage());
+               }
+               else if (resourceReference != null && 
resourceReference.getLocale() != null)
+               {
+                       tag.put("srclang", 
resourceReference.getLocale().getLanguage());
+               }
+       }
+
+       /**
+        * Gets the kind of the track belongs to the media component
+        * 
+        * @see {@link #setKind(Kind)}
+        * 
+        * @return the kind
+        */
+       public Kind getKind()
+       {
+               return kind;
+       }
+
+       /**
+        * Sets the kind of the track belongs to the media component<br>
+        * <br>
+        * <b>SUBTITLES</b>: Transcription or translation of the dialogue, 
suitable for when the sound
+        * is available but not understood (e.g. because the user does not 
understand the language of
+        * the media resource's soundtrack). Displayed over the video.<br>
+        * <br>
+        * <b>CAPTIONS</b>: Transcription or translation of the dialogue, sound 
effects, relevant
+        * musical cues, and other relevant audio information, suitable for 
when the soundtrack is
+        * unavailable (e.g. because it is muted or because the user is deaf). 
Displayed over the video;
+        * labeled as appropriate for the hard-of-hearing.<br>
+        * <br>
+        * <b>DESCRIPTIONS</b>: Textual descriptions of the video component of 
the media resource,
+        * intended for audio synthesis when the visual component is 
unavailable (e.g. because the user
+        * is interacting with the application without a screen while driving, 
or because the user is
+        * blind). Synthesized as separate audio track.<br>
+        * <br>
+        * <b>CHAPTERS</b>: Chapter titles, intended to be used for navigating 
the media resource.
+        * Displayed as an interactive list in the user agent's interface.<br>
+        * <br>
+        * <b>METADATA</b>: Tracks intended for use from script. Not displayed 
by the user agent.<br>
+        * <br>
+        * 
+        * @param kind
+        *            the kind
+        */
+       public void setKind(Kind kind)
+       {
+               this.kind = kind;
+       }
+
+       /**
+        * The label for this track
+        * 
+        * @return the label
+        */
+       public String getLabel()
+       {
+               return label;
+       }
+
+       /**
+        * Sets the label for this track
+        * 
+        * @param label
+        *            the label to be set
+        */
+       public void setLabel(String label)
+       {
+               this.label = label;
+       }
+
+       /**
+        * If the track is the default track
+        * 
+        * @return if the track is the default track
+        */
+       public boolean isDefaultTrack()
+       {
+               return defaultTrack;
+       }
+
+       /**
+        * Sets if this track is the default track
+        * 
+        * @param defaultTrack
+        *            if the track is the default track
+        */
+       public void setDefaultTrack(Boolean defaultTrack)
+       {
+               this.defaultTrack = defaultTrack;
+       }
+
+       /**
+        * Gets the src lang
+        * 
+        * @return the src lang
+        */
+       public Locale getSrclang()
+       {
+               return srclang;
+       }
+
+       /**
+        * Sets the src lang
+        * 
+        * @param srclang
+        *            the src lang to set
+        */
+       public void setSrclang(Locale srclang)
+       {
+               this.srclang = srclang;
+       }
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/95e9eaa2/wicket-core/src/main/java/org/apache/wicket/markup/html/media/audio/Audio.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/markup/html/media/audio/Audio.java
 
b/wicket-core/src/main/java/org/apache/wicket/markup/html/media/audio/Audio.java
new file mode 100755
index 0000000..c29d98c
--- /dev/null
+++ 
b/wicket-core/src/main/java/org/apache/wicket/markup/html/media/audio/Audio.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.wicket.markup.html.media.audio;
+
+import org.apache.wicket.markup.ComponentTag;
+import org.apache.wicket.markup.html.media.MediaComponent;
+import org.apache.wicket.markup.html.media.MediaStreamingResourceReference;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+
+/**
+ * An audio media component to playback audio files.
+ * 
+ * @author Tobias Soloschenko
+ * @author Andrew Lombardi
+ */
+public class Audio extends MediaComponent
+{
+       private static final long serialVersionUID = 1L;
+
+       public Audio(String id)
+       {
+               super(id);
+       }
+
+       public Audio(String id, IModel<?> model)
+       {
+               super(id, model);
+       }
+
+       public Audio(String id, MediaStreamingResourceReference 
mediaStreamingResourceReference)
+       {
+               super(id, mediaStreamingResourceReference);
+       }
+
+       public Audio(String id, IModel<?> model,
+               MediaStreamingResourceReference mediaStreamingResourceReference)
+       {
+               super(id, model, mediaStreamingResourceReference);
+       }
+
+       public Audio(String id, MediaStreamingResourceReference 
mediaStreamingResourceReference,
+               PageParameters pageParameters)
+       {
+               super(id, mediaStreamingResourceReference, pageParameters);
+       }
+
+       public Audio(String id, IModel<?> model,
+               MediaStreamingResourceReference mediaStreamingResourceReference,
+               PageParameters pageParameters)
+       {
+               super(id, model, mediaStreamingResourceReference, 
pageParameters);
+       }
+
+       public Audio(String id, String url)
+       {
+               super(id, url);
+       }
+
+       public Audio(String id, IModel<?> model, String url)
+       {
+               super(id, model, url);
+       }
+
+       public Audio(String id, String url, PageParameters pageParameters)
+       {
+               super(id, null, url, pageParameters);
+       }
+
+       public Audio(String id, IModel<?> model, String url, PageParameters 
pageParameters)
+       {
+               super(id, model, url, pageParameters);
+       }
+
+       @Override
+       protected void onComponentTag(ComponentTag tag)
+       {
+               checkComponentTag(tag, "audio");
+               super.onComponentTag(tag);
+       }
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/95e9eaa2/wicket-core/src/main/java/org/apache/wicket/markup/html/media/video/Video.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/main/java/org/apache/wicket/markup/html/media/video/Video.java
 
b/wicket-core/src/main/java/org/apache/wicket/markup/html/media/video/Video.java
new file mode 100755
index 0000000..a608a4b
--- /dev/null
+++ 
b/wicket-core/src/main/java/org/apache/wicket/markup/html/media/video/Video.java
@@ -0,0 +1,210 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.wicket.markup.html.media.video;
+
+import org.apache.wicket.markup.ComponentTag;
+import org.apache.wicket.markup.html.media.MediaComponent;
+import org.apache.wicket.markup.html.media.MediaStreamingResourceReference;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.request.cycle.RequestCycle;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.apache.wicket.request.resource.ResourceReference;
+
+/**
+ * A video media component to display videos.
+ * 
+ * @author Tobias Soloschenko
+ * @author Andrew Lombardi
+ */
+public class Video extends MediaComponent
+{
+       private static final long serialVersionUID = 1L;
+
+       private Integer width;
+
+       private Integer height;
+
+       private ResourceReference poster;
+
+       private PageParameters posterPageParameters;
+
+       public Video(String id)
+       {
+               super(id);
+       }
+
+       public Video(String id, IModel<?> model)
+       {
+               super(id, model);
+       }
+
+       public Video(String id, MediaStreamingResourceReference 
mediaStreamingResourceReference)
+       {
+               super(id, mediaStreamingResourceReference);
+       }
+
+       public Video(String id, IModel<?> model,
+               MediaStreamingResourceReference mediaStreamingResourceReference)
+       {
+               super(id, model, mediaStreamingResourceReference);
+       }
+
+       public Video(String id, MediaStreamingResourceReference 
mediaStreamingResourceReference,
+               PageParameters pageParameters)
+       {
+               super(id, mediaStreamingResourceReference, pageParameters);
+       }
+
+       public Video(String id, IModel<?> model,
+               MediaStreamingResourceReference mediaStreamingResourceReference,
+               PageParameters pageParameters)
+       {
+               super(id, model, mediaStreamingResourceReference, 
pageParameters);
+       }
+
+       public Video(String id, String url)
+       {
+               super(id, url);
+       }
+
+       public Video(String id, IModel<?> model, String url)
+       {
+               super(id, model, url);
+       }
+
+       public Video(String id, String url, PageParameters pageParameters)
+       {
+               super(id, null, url, pageParameters);
+       }
+
+       public Video(String id, IModel<?> model, String url, PageParameters 
pageParameters)
+       {
+               super(id, model, url, pageParameters);
+       }
+
+       @Override
+       protected void onComponentTag(ComponentTag tag)
+       {
+               checkComponentTag(tag, "video");
+               super.onComponentTag(tag);
+
+               Integer _width = getWidth();
+               if (_width != null)
+               {
+                       tag.put("width", _width);
+               }
+
+               Integer _height = getHeight();
+               if (_height != null)
+               {
+                       tag.put("height", _height);
+               }
+
+               ResourceReference _poster = getPoster();
+               if (_poster != null)
+               {
+                       tag.put("poster", RequestCycle.get().urlFor(_poster, 
getPosterPageParameters()));
+               }
+       }
+
+       /**
+        * The image to be displayed if the video isn't available
+        * 
+        * @return the resource reference of the image
+        */
+       public ResourceReference getPoster()
+       {
+               return poster;
+       }
+
+       /**
+        * Gets the posters page parameters
+        * 
+        * @return the page parameters for the poster
+        */
+       public PageParameters getPosterPageParameters()
+       {
+               return posterPageParameters;
+       }
+
+       /**
+        * Sets the image to be displayed if the video isn't available
+        * 
+        * @param poster
+        *            the resource reference of the image used if the video 
isn't available
+        */
+       public void setPoster(ResourceReference poster)
+       {
+               this.poster = poster;
+       }
+
+       /**
+        * Sets the image to be displayed if the video isn't available
+        * 
+        * @param poster
+        *            the resource reference of the image used if the video 
isn't available
+        * @param posterPageParameters
+        *            the page parameters for the poster
+        */
+       public void setPoster(ResourceReference poster, PageParameters 
posterPageParameters)
+       {
+               this.poster = poster;
+               this.posterPageParameters = posterPageParameters;
+       }
+
+       /**
+        * Gets the width of the video area
+        * 
+        * @return the width of the video area
+        */
+       public Integer getWidth()
+       {
+               return width;
+       }
+
+       /**
+        * Sets the width of the video area
+        * 
+        * @param width
+        *            the width of the video area
+        */
+       public void setWidth(Integer width)
+       {
+               this.width = width;
+       }
+
+       /**
+        * Gets the height of the video area
+        * 
+        * @return the height of the video area
+        */
+       public Integer getHeight()
+       {
+               return height;
+       }
+
+       /**
+        * Sets the height of the video area
+        * 
+        * @param height
+        *            the height of the video area
+        */
+       public void setHeight(Integer height)
+       {
+               this.height = height;
+       }
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/95e9eaa2/wicket-core/src/test/java/org/apache/wicket/markup/html/media/MediaComponentsApplication.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/test/java/org/apache/wicket/markup/html/media/MediaComponentsApplication.java
 
b/wicket-core/src/test/java/org/apache/wicket/markup/html/media/MediaComponentsApplication.java
new file mode 100755
index 0000000..0fb54c6
--- /dev/null
+++ 
b/wicket-core/src/test/java/org/apache/wicket/markup/html/media/MediaComponentsApplication.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.wicket.markup.html.media;
+
+import org.apache.wicket.Page;
+import org.apache.wicket.markup.html.IPackageResourceGuard;
+import org.apache.wicket.markup.html.SecurePackageResourceGuard;
+import org.apache.wicket.protocol.http.WebApplication;
+import org.apache.wicket.request.resource.caching.NoOpResourceCachingStrategy;
+
+public class MediaComponentsApplication extends WebApplication
+{
+       @Override
+       public Class<? extends Page> getHomePage()
+       {
+               return MediaTagsTestPage.class;
+       }
+       
+       @Override
+       protected void init()
+       {
+               super.init();
+
+               
getResourceSettings().setCachingStrategy(NoOpResourceCachingStrategy.INSTANCE);
+
+               IPackageResourceGuard packageResourceGuard = 
org.apache.wicket.Application.get()
+                               .getResourceSettings()
+                               .getPackageResourceGuard();
+               if (packageResourceGuard instanceof SecurePackageResourceGuard)
+               {
+                       SecurePackageResourceGuard securePackageResourceGuard = 
(SecurePackageResourceGuard)packageResourceGuard;
+                       securePackageResourceGuard.addPattern("+*.vtt");
+                       securePackageResourceGuard.addPattern("+*.srt");
+                       securePackageResourceGuard.addPattern("+*.mp3");
+                       securePackageResourceGuard.addPattern("+*.m4a");
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/95e9eaa2/wicket-core/src/test/java/org/apache/wicket/markup/html/media/MediaTagsExtendedTestPage.html
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/test/java/org/apache/wicket/markup/html/media/MediaTagsExtendedTestPage.html
 
b/wicket-core/src/test/java/org/apache/wicket/markup/html/media/MediaTagsExtendedTestPage.html
new file mode 100755
index 0000000..1f7d793
--- /dev/null
+++ 
b/wicket-core/src/test/java/org/apache/wicket/markup/html/media/MediaTagsExtendedTestPage.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+       <head>
+               <title>de.test.mediatags</title>
+       </head>
+       <body>
+               <video wicket:id="video">
+                       <source wicket:id="source" />
+                       <track wicket:id="track" />
+               </video>
+       </body>
+</html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/wicket/blob/95e9eaa2/wicket-core/src/test/java/org/apache/wicket/markup/html/media/MediaTagsExtendedTestPage.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/test/java/org/apache/wicket/markup/html/media/MediaTagsExtendedTestPage.java
 
b/wicket-core/src/test/java/org/apache/wicket/markup/html/media/MediaTagsExtendedTestPage.java
new file mode 100644
index 0000000..d530894
--- /dev/null
+++ 
b/wicket-core/src/test/java/org/apache/wicket/markup/html/media/MediaTagsExtendedTestPage.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.wicket.markup.html.media;
+
+import java.util.Locale;
+
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.media.Track.Kind;
+import org.apache.wicket.markup.html.media.video.Video;
+import org.apache.wicket.request.resource.PackageResourceReference;
+
+public class MediaTagsExtendedTestPage extends WebPage
+{
+       private static final long serialVersionUID = 1L;
+
+       public MediaTagsExtendedTestPage()
+       {
+               Video video = new Video("video", new 
MediaStreamingResourceReference(
+                       MediaTagsTestPage.class, "dummyVideo.m4a"));
+               
+               // source tag
+               Source source = new 
Source("source","http://www.mytestpage.xc/video.m4a";);
+               source.setMedia("screen and (device-width:500px)");
+               source.setType("video/mp4");
+               source.setDisplayType(true);
+               video.add(source);
+               
+               // tack tag
+               Track track = new Track("track", new 
PackageResourceReference(MediaTagsTestPage.class,"dummySubtitles.vtt"));
+               track.setKind(Kind.SUBTITLES);
+               track.setLabel("Subtitles of video");
+               track.setSrclang(Locale.GERMANY);
+               track.setDefaultTrack(true);
+               video.add(track);
+               
+               add(video);
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/95e9eaa2/wicket-core/src/test/java/org/apache/wicket/markup/html/media/MediaTagsTest.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/test/java/org/apache/wicket/markup/html/media/MediaTagsTest.java
 
b/wicket-core/src/test/java/org/apache/wicket/markup/html/media/MediaTagsTest.java
new file mode 100644
index 0000000..7c50031
--- /dev/null
+++ 
b/wicket-core/src/test/java/org/apache/wicket/markup/html/media/MediaTagsTest.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.wicket.markup.html.media;
+
+import org.apache.wicket.WicketTestCase;
+import org.apache.wicket.protocol.http.WebApplication;
+import org.apache.wicket.util.tester.TagTester;
+import org.junit.Test;
+
+public class MediaTagsTest extends WicketTestCase
+{
+       @Override
+       protected WebApplication newApplication()
+       {
+               return new MediaComponentsApplication();
+       }
+
+       @Test
+       public void audioTagIsRenderedRight()
+       {
+               tester.startPage(MediaTagsTestPage.class);
+               String lastResponseAsString = 
tester.getLastResponse().getDocument();
+               TagTester createTagByAttribute = 
TagTester.createTagByAttribute(lastResponseAsString,
+                       "audio");
+               assertTrue(createTagByAttribute.hasAttribute("autoplay"));
+               assertTrue(createTagByAttribute.hasAttribute("controls"));
+               assertTrue(createTagByAttribute.hasAttribute("loop"));
+               assertTrue(createTagByAttribute.hasAttribute("muted"));
+               assertEquals("user-credentials", 
createTagByAttribute.getAttribute("crossorigin"));
+               String attribute = createTagByAttribute.getAttribute("src");
+               assertTrue("The time period is set right in the src attribute",
+                       attribute.contains("#t=5,10"));
+               assertTrue("page parameter is in the url of the src attribute",
+                       attribute.contains("test=test"));
+       }
+
+       @Test
+       public void videoTagIsRenderedRight()
+       {
+               tester.startPage(MediaTagsTestPage.class);
+               String lastResponseAsString = 
tester.getLastResponse().getDocument();
+               TagTester createTagByAttribute = 
TagTester.createTagByAttribute(lastResponseAsString,
+                       "video");
+               String attribute = createTagByAttribute.getAttribute("poster");
+               assertTrue("page parameter is in the url of the poster",
+                       attribute.contains("test2=test2"));
+               String attributesrc = createTagByAttribute.getAttribute("src");
+               assertTrue("video url is in the src attribute",
+                       attributesrc.contains("dummyVideo.m4a"));
+               assertEquals("500", createTagByAttribute.getAttribute("width"));
+               assertEquals("400", 
createTagByAttribute.getAttribute("height"));
+       }
+
+       @Test
+       public void extendedVideoTagIsRenderedRight()
+       {
+               tester.startPage(MediaTagsExtendedTestPage.class);
+               String lastResponseAsString = 
tester.getLastResponse().getDocument();
+               TagTester createTagByAttribute = 
TagTester.createTagByAttribute(lastResponseAsString,
+                       "video");
+               assertTrue(createTagByAttribute.hasChildTag("source"));
+               assertTrue(createTagByAttribute.hasChildTag("track"));
+               
+               
+               TagTester sourceTag = 
TagTester.createTagByAttribute(lastResponseAsString, "source");
+               assertEquals("video/mp4", sourceTag.getAttribute("type")); 
+               assertEquals("screen and (device-width:500px)", 
sourceTag.getAttribute("media")); 
+               assertEquals("http://www.mytestpage.xc/video.m4a";, 
sourceTag.getAttribute("src")); 
+               
+               TagTester trackTag = 
TagTester.createTagByAttribute(lastResponseAsString, "track");
+               
+               
assertTrue(trackTag.getAttribute("src").contains("dummySubtitles")); 
+               assertEquals("subtitles", trackTag.getAttribute("kind")); 
+               assertEquals("Subtitles of video", 
trackTag.getAttribute("label")); 
+               assertEquals("default", trackTag.getAttribute("default")); 
+               assertEquals("de", trackTag.getAttribute("srclang")); 
+       }
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/95e9eaa2/wicket-core/src/test/java/org/apache/wicket/markup/html/media/MediaTagsTestPage.html
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/test/java/org/apache/wicket/markup/html/media/MediaTagsTestPage.html
 
b/wicket-core/src/test/java/org/apache/wicket/markup/html/media/MediaTagsTestPage.html
new file mode 100755
index 0000000..e68360d
--- /dev/null
+++ 
b/wicket-core/src/test/java/org/apache/wicket/markup/html/media/MediaTagsTestPage.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+       <head>
+               <title>de.test.mediatags</title>
+       </head>
+       <body>
+               <audio wicket:id="audio" />
+               <video wicket:id="video"/>
+       </body>
+</html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/wicket/blob/95e9eaa2/wicket-core/src/test/java/org/apache/wicket/markup/html/media/MediaTagsTestPage.java
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/test/java/org/apache/wicket/markup/html/media/MediaTagsTestPage.java
 
b/wicket-core/src/test/java/org/apache/wicket/markup/html/media/MediaTagsTestPage.java
new file mode 100644
index 0000000..e8dbdd8
--- /dev/null
+++ 
b/wicket-core/src/test/java/org/apache/wicket/markup/html/media/MediaTagsTestPage.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.wicket.markup.html.media;
+
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.media.MediaComponent.Cors;
+import org.apache.wicket.markup.html.media.audio.Audio;
+import org.apache.wicket.markup.html.media.video.Video;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.apache.wicket.request.resource.PackageResourceReference;
+
+public class MediaTagsTestPage extends WebPage
+{
+       private static final long serialVersionUID = 1L;
+
+       public MediaTagsTestPage()
+       {
+               PageParameters pageParameters = new PageParameters();
+               pageParameters.set("test", "test");
+               Audio audio = new Audio("audio", new 
MediaStreamingResourceReference(
+                       MediaTagsTestPage.class, "dummyAudio.mp3"), 
pageParameters);
+               audio.setAutoplay(true);
+               audio.setControls(true);
+               audio.setCrossOrigin(Cors.USER_CREDENTIALS);
+               audio.setLooping(true);
+               audio.setMuted(true);
+               audio.setStartTime("5");
+               audio.setEndTime("10");
+               add(audio);
+
+               Video video = new Video("video", new 
MediaStreamingResourceReference(
+                       MediaTagsTestPage.class, "dummyVideo.m4a"));
+               PageParameters pageParameters2 = new PageParameters();
+               pageParameters2.add("test2", "test2");
+               video.setPoster(new 
PackageResourceReference(MediaTagsTestPage.class, "dummyPoster.jpg"),
+                       pageParameters2);
+               video.setWidth(500);
+               video.setHeight(400);
+               add(video);
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/95e9eaa2/wicket-core/src/test/java/org/apache/wicket/markup/html/media/dummyAudio.mp3
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/test/java/org/apache/wicket/markup/html/media/dummyAudio.mp3 
b/wicket-core/src/test/java/org/apache/wicket/markup/html/media/dummyAudio.mp3
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/wicket/blob/95e9eaa2/wicket-core/src/test/java/org/apache/wicket/markup/html/media/dummyPoster.jpg
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/test/java/org/apache/wicket/markup/html/media/dummyPoster.jpg 
b/wicket-core/src/test/java/org/apache/wicket/markup/html/media/dummyPoster.jpg
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/wicket/blob/95e9eaa2/wicket-core/src/test/java/org/apache/wicket/markup/html/media/dummySubtitles.vtt
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/test/java/org/apache/wicket/markup/html/media/dummySubtitles.vtt
 
b/wicket-core/src/test/java/org/apache/wicket/markup/html/media/dummySubtitles.vtt
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/wicket/blob/95e9eaa2/wicket-core/src/test/java/org/apache/wicket/markup/html/media/dummyVideo.m4a
----------------------------------------------------------------------
diff --git 
a/wicket-core/src/test/java/org/apache/wicket/markup/html/media/dummyVideo.m4a 
b/wicket-core/src/test/java/org/apache/wicket/markup/html/media/dummyVideo.m4a
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/wicket/blob/95e9eaa2/wicket-examples/pom.xml
----------------------------------------------------------------------
diff --git a/wicket-examples/pom.xml b/wicket-examples/pom.xml
index d03ffad..c184b27 100644
--- a/wicket-examples/pom.xml
+++ b/wicket-examples/pom.xml
@@ -204,6 +204,7 @@
                                        <include>**/*.txt</include>
                                        <include>**/*.xml</include>
                                        <include>**/*.properties</include>
+                                       <include>**/*.mp4</include>
                                </includes>
                        </resource>
                        <resource>
@@ -221,6 +222,7 @@
                                        <include>**/*.properties</include>
                                        <include>**/*.vm</include>
                                        <include>**/*.tmpl</include>
+                                       <include>**/*.mp4</include>
                                </includes>
                        </resource>
                </resources>

http://git-wip-us.apache.org/repos/asf/wicket/blob/95e9eaa2/wicket-examples/src/main/java/org/apache/wicket/examples/media/Home.css
----------------------------------------------------------------------
diff --git 
a/wicket-examples/src/main/java/org/apache/wicket/examples/media/Home.css 
b/wicket-examples/src/main/java/org/apache/wicket/examples/media/Home.css
new file mode 100644
index 0000000..45dee80
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/media/Home.css
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+video{
+       float:left;
+       height:240px;
+       width:320px;
+       margin-bottom:10px;
+       margin-right:10px;
+}
+.videoDescription{
+       float:left;
+       height:240px;
+       width:300px;
+       margin-bottom:10px;
+}
+.clearer{
+       clear:both;
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/95e9eaa2/wicket-examples/src/main/java/org/apache/wicket/examples/media/Home.html
----------------------------------------------------------------------
diff --git 
a/wicket-examples/src/main/java/org/apache/wicket/examples/media/Home.html 
b/wicket-examples/src/main/java/org/apache/wicket/examples/media/Home.html
new file mode 100644
index 0000000..7388a03
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/media/Home.html
@@ -0,0 +1,29 @@
+<html xmlns:wicket="http://wicket.apache.org";>
+<head>
+    <title>Wicket Examples - videos</title>
+    <link rel="stylesheet" type="text/css" href="style.css"/>
+</head>
+<body>
+       <div wicket:id="mainNavigation"></div>
+       <h2>Below there are three types of videos to show the basic 
functionality of Wicket's media implementation</h2>
+       <h3>The implementation features full support of video / audio / source 
/ track tags.</h3>
+       <div>
+               <!-- Video 1 -->
+               <video wicket:id="video1" ></video>
+               <div class="videoDescription"><b>Video1</b><br/>Demonstrate the 
basic set of methods to configure a video (setAutoplay(false); 
setControls(true); setLooping(false); setWidth(320); setHeight(240);) The width 
and height are null by default which means that the video is going to be 
rendered in size of the media file.</div>
+               <div class="clearer"></div>
+               
+               <!-- Video 2 -->
+               <video wicket:id="video2" >
+                       <source wicket:id="source2" />
+               </video>
+               <div class="videoDescription"><b>Video2</b><br/>This video is 
rendered with a source tag. You can add many source tags and apply a media 
query (setMedia(query);) so that based on the resolution different videos are 
going to be displayed.</div>
+               <div class="clearer"></div>
+               
+               <!-- Video 3 -->
+               <video wicket:id="video3" ></video>
+               <div class="videoDescription"><b>Video3</b><br/>The last sample 
shows a remote video located here: 
http://media.w3.org/2010/05/video/movie_300.mp4. It can be added by set the url 
as String instead of adding a ResourceReference.</div>
+               <div class="clearer"></div>
+       </div>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/wicket/blob/95e9eaa2/wicket-examples/src/main/java/org/apache/wicket/examples/media/Home.java
----------------------------------------------------------------------
diff --git 
a/wicket-examples/src/main/java/org/apache/wicket/examples/media/Home.java 
b/wicket-examples/src/main/java/org/apache/wicket/examples/media/Home.java
new file mode 100644
index 0000000..03b1e8f
--- /dev/null
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/media/Home.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.wicket.examples.media;
+
+import java.util.UUID;
+
+import org.apache.wicket.examples.WicketExamplePage;
+import org.apache.wicket.markup.head.CssHeaderItem;
+import org.apache.wicket.markup.head.IHeaderResponse;
+import org.apache.wicket.markup.html.media.MediaStreamingResourceReference;
+import org.apache.wicket.markup.html.media.Source;
+import org.apache.wicket.markup.html.media.video.Video;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.apache.wicket.request.resource.PackageResourceReference;
+
+
+/**
+ * Demonstrates different flavors of org.apache.wicket.examples.videos.<br>
+ * <br>
+ * 
+ * Videos are from: http://media.w3.org/2010/05/video/<br>
+ * <br>
+ * Images are from: http://search.creativecommons.org/ with check on 
commercial use and modify...
+ * 
+ * @author Tobias Soloschenko
+ */
+public final class Home extends WicketExamplePage
+{
+
+       private static final long serialVersionUID = 1L;
+
+       /**
+        * Constructor
+        */
+       public Home()
+       {
+               // Internal video with several options
+
+               Video video1 = new Video("video1", new 
MediaStreamingResourceReference(Home.class,
+                       "video.mp4"));
+               video1.setAutoplay(false);
+               video1.setControls(true);
+               video1.setLooping(false);
+               video1.setWidth(320);
+               video1.setHeight(240);
+               video1.setPoster(new PackageResourceReference(Home.class, 
"novideo.gif"));
+               add(video1);
+
+               // video with source
+
+               Video video2 = new Video("video2");
+               video2.setPoster(new PackageResourceReference(Home.class, 
"novideo.gif"));
+
+               Source source2 = new Source("source2", new 
MediaStreamingResourceReference(Home.class,
+                       "video.mp4"));
+               // Need to be set to true to show the type
+               source2.setDisplayType(true);
+               // the default type is the mime type of the image with no codec 
information
+               source2.setType("video/mp4; codecs=\"avc1.42E01E, mp4a.40.2\"");
+               video2.add(source2);
+
+               add(video2);
+
+               // External video
+               PageParameters pageParameters = new PageParameters();
+               pageParameters.add("random", UUID.randomUUID().toString());
+               pageParameters.add("test", "test");
+               Video video3 = new Video("video3", 
"http://media.w3.org/2010/05/video/movie_300.mp4";,
+                       pageParameters);
+               video3.setPoster(new PackageResourceReference(Home.class, 
"novideo.gif"));
+               add(video3);
+
+               /*
+                * // video with track
+                * Video video4 = new Video("video4", new 
MediaStreamingResourceReference(Home.class, "dummyVideo.m4a"));
+                * 
+                * // source tag 
+                * Source source4 = new Source("source4", 
"http://www.mytestpage.xc/video.m4a";);
+                * source4.setMedia("screen and (device-width:500px)"); 
+                * source4.setType("video/mp4");
+                * source4.setDisplayType(true); video4.add(source4);
+                * 
+                * // tack tag 
+                * Track track4 = new Track("track4", new 
PackageResourceReference(Home.class, "dummySubtitles.vtt")); 
+                * track4.setKind(Kind.subtitles);
+                * track4.setLabel("Subtitles of video"); 
+                * track4.setSrclang(Locale.GERMANY);
+                * track4.setDefaultTrack(true); 
+                * video4.add(track4);
+                * 
+                * add(video4);
+                */
+       }
+
+       @Override
+       public void renderHead(IHeaderResponse response)
+       {
+               super.renderHead(response);
+               response.render(CssHeaderItem.forReference(new 
PackageResourceReference(Home.class,
+                       "Home.css")));
+       }
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/95e9eaa2/wicket-examples/src/main/java/org/apache/wicket/examples/media/VideosApplication.java
----------------------------------------------------------------------
diff --git 
a/wicket-examples/src/main/java/org/apache/wicket/examples/media/VideosApplication.java
 
b/wicket-examples/src/main/java/org/apache/wicket/examples/media/VideosApplication.java
new file mode 100644
index 0000000..c17a393
--- /dev/null
+++ 
b/wicket-examples/src/main/java/org/apache/wicket/examples/media/VideosApplication.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.wicket.examples.media;
+
+import org.apache.wicket.Page;
+import org.apache.wicket.examples.WicketExampleApplication;
+import org.apache.wicket.markup.html.IPackageResourceGuard;
+import org.apache.wicket.markup.html.SecurePackageResourceGuard;
+
+
+/**
+ * Application class for the videos examples.
+ * 
+ * @author Tobias Soloschenko
+ */
+public class VideosApplication extends WicketExampleApplication
+{
+       /**
+        * Constructor
+        */
+       public VideosApplication()
+       {
+
+       }
+
+       /**
+        * @see org.apache.wicket.Application#getHomePage()
+        */
+       @Override
+       public Class<? extends Page> getHomePage()
+       {
+               return Home.class;
+       }
+
+       /**
+        * @see org.apache.wicket.examples.WicketExampleApplication#init()
+        */
+       @Override
+       protected void init()
+       {
+               IPackageResourceGuard packageResourceGuard = 
getResourceSettings().getPackageResourceGuard();
+               if (packageResourceGuard instanceof SecurePackageResourceGuard)
+               {
+                       SecurePackageResourceGuard guard = 
(SecurePackageResourceGuard)packageResourceGuard;
+                       guard.addPattern("+*.mp4");
+               }
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/95e9eaa2/wicket-examples/src/main/java/org/apache/wicket/examples/media/novideo.gif
----------------------------------------------------------------------
diff --git 
a/wicket-examples/src/main/java/org/apache/wicket/examples/media/novideo.gif 
b/wicket-examples/src/main/java/org/apache/wicket/examples/media/novideo.gif
new file mode 100644
index 0000000..98cc51a
Binary files /dev/null and 
b/wicket-examples/src/main/java/org/apache/wicket/examples/media/novideo.gif 
differ

http://git-wip-us.apache.org/repos/asf/wicket/blob/95e9eaa2/wicket-examples/src/main/java/org/apache/wicket/examples/media/video.mp4
----------------------------------------------------------------------
diff --git 
a/wicket-examples/src/main/java/org/apache/wicket/examples/media/video.mp4 
b/wicket-examples/src/main/java/org/apache/wicket/examples/media/video.mp4
new file mode 100644
index 0000000..cf59777
Binary files /dev/null and 
b/wicket-examples/src/main/java/org/apache/wicket/examples/media/video.mp4 
differ

http://git-wip-us.apache.org/repos/asf/wicket/blob/95e9eaa2/wicket-examples/src/main/resources/org/apache/wicket/examples/homepage/HomePage.html
----------------------------------------------------------------------
diff --git 
a/wicket-examples/src/main/resources/org/apache/wicket/examples/homepage/HomePage.html
 
b/wicket-examples/src/main/resources/org/apache/wicket/examples/homepage/HomePage.html
index 4789751..d83ae2c 100644
--- 
a/wicket-examples/src/main/resources/org/apache/wicket/examples/homepage/HomePage.html
+++ 
b/wicket-examples/src/main/resources/org/apache/wicket/examples/homepage/HomePage.html
@@ -66,6 +66,7 @@
                <tr><td align="right"><a 
href="atmosphere">Atmosphere</a></td><td> - Atmosphere Framework 
integration</td></tr>
                <tr><td align="right"><a href="cdi">CDI</a></td><td> - Context 
Dependency and Injection integration</td></tr>
                <tr><td align="right"><a href="bean-validation">Bean 
Validation</a></td><td> - Bean Validation integration (JSR 303)</td></tr>
+        <tr><td align="right"><a href="videos">HTML5 Media Tags</a></td><td> - 
Integration for HTML5 Media Tags</td></tr>
        </tbody>
                </table>
        </div>

http://git-wip-us.apache.org/repos/asf/wicket/blob/95e9eaa2/wicket-examples/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/wicket-examples/src/main/webapp/WEB-INF/web.xml 
b/wicket-examples/src/main/webapp/WEB-INF/web.xml
index 92f956a..6b91161 100644
--- a/wicket-examples/src/main/webapp/WEB-INF/web.xml
+++ b/wicket-examples/src/main/webapp/WEB-INF/web.xml
@@ -16,9 +16,9 @@
    limitations under the License.
 -->
 <web-app xmlns="http://java.sun.com/xml/ns/javaee";
-                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
-                xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd";
-                version="2.5">
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd";
+      version="3.0"> 
 
        <display-name>Wicket Examples</display-name>
 
@@ -160,6 +160,15 @@
                  
<param-value>org.apache.wicket.examples.images.ImagesApplication</param-value>
                </init-param>
        </filter>
+       
+       <filter>
+               <filter-name>VideosApplication</filter-name>
+               
<filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
+               <init-param>
+                 <param-name>applicationClassName</param-name>
+                 
<param-value>org.apache.wicket.examples.media.VideosApplication</param-value>
+               </init-param>
+       </filter>
 
        <filter>
                <filter-name>LibraryApplication</filter-name>
@@ -542,6 +551,13 @@
                <dispatcher>REQUEST</dispatcher>
                <dispatcher>INCLUDE</dispatcher>
        </filter-mapping>
+       
+       <filter-mapping>
+               <filter-name>VideosApplication</filter-name>
+               <url-pattern>/videos/*</url-pattern>
+               <dispatcher>REQUEST</dispatcher>
+               <dispatcher>INCLUDE</dispatcher>
+       </filter-mapping>
 
        <filter-mapping>
                <filter-name>HelloWorldApplication</filter-name>

Reply via email to