Repository: wicket Updated Branches: refs/heads/pr-86-media_tags [created] ac7cf808d
WICKET-5819 Media tags - audio / video implementation Project: http://git-wip-us.apache.org/repos/asf/wicket/repo Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/33844413 Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/33844413 Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/33844413 Branch: refs/heads/pr-86-media_tags Commit: 3384441307eba0477e9692d1c6080b673dce9748 Parents: f0340a3 Author: klopfdreh <klopfdreh@tobiass-mbp> Authored: Thu Jan 22 22:52:18 2015 +0100 Committer: klopfdreh <klopfdreh@tobiass-mbp> Committed: Thu Jan 22 22:52:18 2015 +0100 ---------------------------------------------------------------------- .../util/resource/PackageResourceStream.java | 27 +- .../markup/html/media/MediaComponent.java | 472 +++++++++++++++++++ .../media/MediaStreamingResourceReference.java | 306 ++++++++++++ .../wicket/markup/html/media/MediaUtils.java | 49 ++ .../apache/wicket/markup/html/media/Source.java | 257 ++++++++++ .../apache/wicket/markup/html/media/Track.java | 274 +++++++++++ .../wicket/markup/html/media/audio/Audio.java | 97 ++++ .../wicket/markup/html/media/video/Video.java | 208 ++++++++ .../wicket/markup/html/media/Application.java | 37 ++ .../html/media/MediaTagsExtendedTestPage.html | 12 + .../html/media/MediaTagsExtendedTestPage.java | 55 +++ .../wicket/markup/html/media/MediaTagsTest.java | 95 ++++ .../markup/html/media/MediaTagsTestPage.html | 10 + .../markup/html/media/MediaTagsTestPage.java | 57 +++ .../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 18 files changed, 1954 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/wicket/blob/33844413/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:j...@apache.org">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/33844413/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..02c2b8d --- /dev/null +++ b/wicket-core/src/main/java/org/apache/wicket/markup/html/media/MediaComponent.java @@ -0,0 +1,472 @@ +/* + * 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 media component is used to provide basic functionality to the video and audo 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; + + // use Boolean instead of elementary data types to get a lightweight component + private Boolean autoplay; + + private Boolean loop; + + private Boolean muted; + + private Boolean controls; + + private Preload preload; + + private String startTime; + + private String endTime; + + private String mediaGroup; + + private Cors crossorigin; + + private PageParameters pageParameters; + + private MediaStreamingResourceReference mediaStreamingResourceReference; + + private String url; + + public MediaComponent(String id) + { + super(id); + } + + public MediaComponent(String id, IModel<?> model) + { + super(id, model); + } + + public MediaComponent(String id, MediaStreamingResourceReference mediaStreamingResourceReference) + { + this(id); + this.mediaStreamingResourceReference = mediaStreamingResourceReference; + } + + public MediaComponent(String id, IModel<?> model, + MediaStreamingResourceReference mediaStreamingResourceReference) + { + this(id, model); + this.mediaStreamingResourceReference = mediaStreamingResourceReference; + } + + public MediaComponent(String id, + MediaStreamingResourceReference mediaStreamingResourceReference, + PageParameters pageParameters) + { + this(id); + this.mediaStreamingResourceReference = mediaStreamingResourceReference; + this.pageParameters = pageParameters; + } + + public MediaComponent(String id, IModel<?> model, + MediaStreamingResourceReference mediaStreamingResourceReference, + PageParameters pageParameters) + { + this(id, model); + this.mediaStreamingResourceReference = mediaStreamingResourceReference; + this.pageParameters = pageParameters; + } + + public MediaComponent(String id, String url) + { + this(id); + this.url = url; + } + + public MediaComponent(String id, IModel<?> model, String url) + { + this(id, model); + this.url = url; + } + + public MediaComponent(String id, String url, PageParameters pageParameters) + { + this(id); + this.url = url; + this.pageParameters = pageParameters; + } + + public MediaComponent(String id, IModel<?> model, String url, PageParameters pageParameters) + { + this(id, model); + this.url = url; + this.pageParameters = pageParameters; + } + + @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 (this.startTime != null) + { + timeManagement = timeManagement += "#t=" + this.startTime + + (this.endTime != null ? "," + this.endTime : ""); + } + + if (this.mediaStreamingResourceReference != null) + { + tag.put("src", + RequestCycle.get() + .urlFor(this.mediaStreamingResourceReference, this.pageParameters) + + timeManagement); + } + + if (this.url != null) + { + tag.put("src", this.url + timeManagement); + } + + if (this.mediaGroup != null) + { + tag.put("mediagroup", this.mediaGroup); + } + + if (this.autoplay != null && this.autoplay) + { + tag.put("autoplay", "autoplay"); + } + + if (this.loop != null && this.loop) + { + tag.put("loop", "loop"); + } + + if (this.muted != null && this.muted) + { + tag.put("muted", "muted"); + } + + // Use getter here because controls should be visible by default + if (this.getControls()) + { + tag.put("controls", "controls"); + } + + if (this.preload != null) + { + tag.put("preload", this.preload.name()); + } + + if (this.crossorigin != null) + { + tag.put("crossorigin", this.crossorigin.getRealName()); + } + } + + /** + * If the playback is autoplayed on load + * + * @return If the playback is autoplayed on load + */ + public Boolean getAutoplay() + { + return this.autoplay != null ? this.autoplay : false; + } + + /** + * 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 getLoop() + { + return this.loop != null ? this.loop : false; + } + + /** + * Sets the playback to be looped + * + * @param loop + * If the playback is looped + */ + public void setLoop(Boolean loop) + { + this.loop = loop; + } + + /** + * If the playback is muted initially + * + * @return If the playback is muted initially + */ + public Boolean getMuted() + { + return this.muted != null ? this.muted : false; + } + + /** + * 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 getControls() + { + return this.controls != null ? this.controls : true; + } + + /** + * 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 this.preload; + } + + /** + * Sets the type of preload <br> + * <br> + * <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.<br> + * <br> + * <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.<br> + * <br> + * <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. + * + * @param preload + * 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 this.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 this.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 this.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 this.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>use_credentials</b>: Cross-origin CORS requests for the element will have the credentials + * flag set.<br> + * <br> + * <b>no_cores</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; + } + + /** + * To be used for the preload attribute + * + * @see {@link #setPreload(Preload)} + */ + public enum Preload + { + none, metadata, auto + } + + /** + * To be used for the crossorigin attribute + * + * @see {@link #setCrossorigin(Cors)} + */ + public enum Cors + { + anonymous("anonymous"), use_credentials("user-credentials"), no_cors(""); + + private String realName; + + private Cors(String realName) + { + this.realName = realName; + } + + public String getRealName() + { + return this.realName; + } + } + +} http://git-wip-us.apache.org/repos/asf/wicket/blob/33844413/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..0051c8c --- /dev/null +++ b/wicket-core/src/main/java/org/apache/wicket/markup/html/media/MediaStreamingResourceReference.java @@ -0,0 +1,306 @@ +package org.apache.wicket.markup.html.media; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.Locale; + +import org.apache.wicket.Application; +import org.apache.wicket.WicketRuntimeException; +import org.apache.wicket.core.util.resource.PackageResourceStream; +import org.apache.wicket.protocol.http.servlet.ResponseIOException; +import org.apache.wicket.request.Request; +import org.apache.wicket.request.Response; +import org.apache.wicket.request.cycle.RequestCycle; +import org.apache.wicket.request.http.WebRequest; +import org.apache.wicket.request.http.WebResponse; +import org.apache.wicket.request.resource.AbstractResource; +import org.apache.wicket.request.resource.ContentDisposition; +import org.apache.wicket.request.resource.IResource; +import org.apache.wicket.request.resource.ResourceReference; + +/** + * 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 ResourceReference +{ + + private static final long serialVersionUID = 1L; + + private Integer buffer; + + public MediaStreamingResourceReference(Class<?> scope, String name, Locale locale, + String style, String variation) + { + super(scope, name, locale, style, variation); + } + + public MediaStreamingResourceReference(Class<?> scope, String name) + { + super(scope, name, RequestCycle.get().getRequest().getLocale(), null, null); + } + + public MediaStreamingResourceReference(Key key) + { + super(key); + } + + public MediaStreamingResourceReference(String name) + { + super(name); + } + + @Override + public IResource getResource() + { + AbstractResource mediaStreamingResource = new AbstractResource() + { + private static final long serialVersionUID = 1L; + private Long startbyte; + private Long endbyte; + private PackageResourceStream packageResourceStream; + + @Override + protected ResourceResponse newResourceResponse(Attributes attributes) + { + try + { + Request request = attributes.getRequest(); + Response response = attributes.getResponse(); + if (request instanceof WebRequest && response instanceof WebResponse) + { + WebRequest webRequest = (WebRequest)request; + WebResponse webResponse = (WebResponse)response; + + this.packageResourceStream = new PackageResourceStream( + MediaStreamingResourceReference.this.getScope(), + MediaStreamingResourceReference.this.getName(), + MediaStreamingResourceReference.this.getLocale(), + MediaStreamingResourceReference.this.getStyle(), + MediaStreamingResourceReference.this.getVariation()); + long length = this.packageResourceStream.length().bytes(); + + ResourceResponse resourceResponse = new ResourceResponse(); + resourceResponse.setContentType(this.packageResourceStream.getContentType()); + resourceResponse.setFileName(MediaStreamingResourceReference.this.getName()); + resourceResponse.setContentDisposition(ContentDisposition.ATTACHMENT); + resourceResponse.setLastModified(this.packageResourceStream.lastModifiedTime()); + + // We accept ranges, so that the player can + // load and play content from a specific byte position + webResponse.setHeader("Accept-Range", "bytes"); + + // Calculating the response code and the byte range to be played + String rangeHeader = webRequest.getHeader("range"); + if (rangeHeader == null || "".equals(rangeHeader)) + { + resourceResponse.setStatusCode(200); + resourceResponse.setContentLength(length); + } + else + { + rangeHeader = rangeHeader.replaceAll(" ", ""); + // If the range header is filled 206 for + // 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 + String range = rangeHeader.substring(rangeHeader.indexOf('=') + 1, + rangeHeader.length()); + String[] rangeParts = range.split("-"); + if (rangeParts[0].equals("0")) + { + webResponse.setHeader("Content-Range", "bytes 0-" + (length - 1) + + "/" + length); + resourceResponse.setContentLength(length); + } + else + { + this.startbyte = Long.parseLong(rangeParts[0]); + if (rangeParts.length == 2) + { + this.endbyte = Long.parseLong(rangeParts[1]); + } + else + { + this.endbyte = length - 1; + } + webResponse.setHeader("Content-Range", "bytes " + this.startbyte + + "-" + this.endbyte + "/" + length); + resourceResponse.setContentLength((this.endbyte - this.startbyte) + 1); + } + } + + resourceResponse.setWriteCallback(new WriteCallback() + { + @Override + public void writeData(Attributes attributes) throws IOException + { + try + { + InputStream inputStream = packageResourceStream.getInputStream(); + OutputStream outputStream = attributes.getResponse() + .getOutputStream(); + byte[] buffer = new byte[MediaStreamingResourceReference.this.getBuffer()]; + + if (startbyte != null || endbyte != null) + { + // skipping the first bytes which are + // not requested by the client + inputStream.skip(startbyte); + + long totalBytes = 0; + int actualReadBytes = 0; + + while ((actualReadBytes = inputStream.read(buffer)) != -1) + { + totalBytes = totalBytes + buffer.length; + long lowerBuffer = endbyte - totalBytes; + if (lowerBuffer <= 0) + { + buffer = (byte[])resizeArray(buffer, + actualReadBytes); + outputStream.write(buffer); + break; + } + else + { + outputStream.write(buffer); + } + } + } + else + { + while (inputStream.read(buffer) != -1) + { + outputStream.write(buffer); + } + } + } + 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) + { + StringWriter stringWriter = printStack(e); + throw new WicketRuntimeException(stringWriter.toString()); + } + } + }); + + return resourceResponse; + } + else + { + throw new IllegalStateException( + "Either the request is no web request or the response is no web response"); + } + } + catch (Exception e) + { + StringWriter stringWriter = this.printStack(e); + throw new WicketRuntimeException(stringWriter.toString()); + } + finally + { + if (this.packageResourceStream != null) + { + try + { + this.packageResourceStream.close(); + } + catch (IOException e) + { + StringWriter stringWriter = this.printStack(e); + throw new WicketRuntimeException(stringWriter.toString()); + } + } + } + } + + /** + * Prints the stack trace to a print writer + * + * @param exception + * the exception + * @return the string writer containing the stack trace + */ + private StringWriter printStack(Exception exception) + { + StringWriter stringWriter = new StringWriter(); + PrintWriter printWriter = new PrintWriter(stringWriter); + exception.printStackTrace(printWriter); + return stringWriter; + } + }; + return mediaStreamingResource; + + } + + /** + * Sets the buffer size used to send the data to the client + * + * @return the buffer size used to send the data to the client + */ + public Integer getBuffer() + { + return this.buffer != null ? this.buffer : 4048; + } + + /** + * Sets the buffer size used to send the data to the client + * + * @param buffer + * the buffer size used to send the data to the client + */ + public void setBuffer(Integer buffer) + { + this.buffer = buffer; + } + + /** + * 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 Object resizeArray(Object oldArray, int newSize) + { + int oldSize = java.lang.reflect.Array.getLength(oldArray); + Class elementType = oldArray.getClass().getComponentType(); + Object newArray = java.lang.reflect.Array.newInstance(elementType, newSize); + int preserveLength = Math.min(oldSize, newSize); + if (preserveLength > 0) + { + System.arraycopy(oldArray, 0, newArray, 0, preserveLength); + } + return newArray; + } + + /** + * Gets the type of the media this resource reference belongs to + * + * @return the 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/33844413/wicket-core/src/main/java/org/apache/wicket/markup/html/media/MediaUtils.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/html/media/MediaUtils.java b/wicket-core/src/main/java/org/apache/wicket/markup/html/media/MediaUtils.java new file mode 100755 index 0000000..d06a704 --- /dev/null +++ b/wicket-core/src/main/java/org/apache/wicket/markup/html/media/MediaUtils.java @@ -0,0 +1,49 @@ +/* + * 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.Application; +import org.apache.wicket.markup.html.IPackageResourceGuard; +import org.apache.wicket.markup.html.SecurePackageResourceGuard; + +/** + * Helper method to provide access to basic media files like subtitles + * + * @author Tobias Soloschenko + * + */ +public class MediaUtils +{ + + /** + * Method that has to be called within the init method of the web application to make + * translation files accessible + */ + public static void init() + { + IPackageResourceGuard packageResourceGuard = Application.get() + .getResourceSettings() + .getPackageResourceGuard(); + if (packageResourceGuard instanceof SecurePackageResourceGuard) + { + SecurePackageResourceGuard securePackageResourceGuard = (SecurePackageResourceGuard)packageResourceGuard; + securePackageResourceGuard.addPattern("+*.vtt"); + securePackageResourceGuard.addPattern("+*.srt"); + } + } + +} http://git-wip-us.apache.org/repos/asf/wicket/blob/33844413/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..0963f06 --- /dev/null +++ b/wicket-core/src/main/java/org/apache/wicket/markup/html/media/Source.java @@ -0,0 +1,257 @@ +/* + * 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 MediaStreamingResourceReference mediaStreamingResourceReference; + + private PageParameters pageParameters; + + private String url; + + public Source(String id) + { + super(id); + } + + public Source(String id, IModel<?> model) + { + super(id, model); + } + + public Source(String id, MediaStreamingResourceReference mediaStreamingResourceReference) + { + this(id); + this.mediaStreamingResourceReference = mediaStreamingResourceReference; + } + + public Source(String id, IModel<?> model, + MediaStreamingResourceReference mediaStreamingResourceReference) + { + this(id, model); + this.mediaStreamingResourceReference = mediaStreamingResourceReference; + } + + public Source(String id, MediaStreamingResourceReference mediaStreamingResourceReference, + PageParameters pageParameters) + { + this(id); + this.mediaStreamingResourceReference = mediaStreamingResourceReference; + this.pageParameters = pageParameters; + } + + public Source(String id, IModel<?> model, + MediaStreamingResourceReference mediaStreamingResourceReference, + PageParameters pageParameters) + { + this(id, model); + this.mediaStreamingResourceReference = mediaStreamingResourceReference; + this.pageParameters = pageParameters; + } + + public Source(String id, String url) + { + this(id); + this.url = url; + } + + public Source(String id, IModel<?> model, String url) + { + this(id, model); + this.url = url; + } + + public Source(String id, String url, PageParameters pageParameters) + { + this(id); + this.url = url; + this.pageParameters = pageParameters; + } + + public Source(String id, IModel<?> model, String url, PageParameters pageParameters) + { + this(id, model); + this.url = url; + this.pageParameters = pageParameters; + } + + @Override + protected void onComponentTag(ComponentTag tag) + { + this.checkComponentTag(tag, "source"); + super.onComponentTag(tag); + + if (this.mediaStreamingResourceReference != null) + { + tag.put("src", + RequestCycle.get() + .urlFor(this.mediaStreamingResourceReference, this.pageParameters)); + } + + if (this.url != null) + { + tag.put("src", this.url); + } + + if (this.getDisplayType()) + { + if (this.type != null) + { + tag.put("type", this.type); + } + else if (this.mediaStreamingResourceReference != null) + { + tag.put("type", this.mediaStreamingResourceReference.getType()); + } + } + + if (this.media != null) + { + tag.put("media", this.media); + } + + } + + /** + * If the type is going to be displayed + * + * @return If the type is going to be displayed + */ + public Boolean getDisplayType() + { + return this.displayType != null ? this.displayType : false; + } + + /** + * 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 this.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> + * <source src='video.mp4' <b>type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'</b>><br> + * H.264 Extended profile video (baseline-compatible) level 3 and Low-Complexity AAC audio in + * MP4 container<br> + * <source src='video.mp4' <b>type='video/mp4; codecs="avc1.58A01E, mp4a.40.2"'</b>><br> + * H.264 Main profile video level 3 and Low-Complexity AAC audio in MP4 container<br> + * <source src='video.mp4' <b>type='video/mp4; codecs="avc1.4D401E, mp4a.40.2"'</b>><br> + * H.264 'High' profile video (incompatible with main, baseline, or extended profiles) level 3 + * and Low-Complexity AAC audio in MP4 container<br> + * <source src='video.mp4' <b>type='video/mp4; codecs="avc1.64001E, mp4a.40.2"'</b>><br> + * MPEG-4 Visual Simple Profile Level 0 video and Low-Complexity AAC audio in MP4 container<br> + * <source src='video.mp4' <b>type='video/mp4; codecs="mp4v.20.8, mp4a.40.2"'</b>><br> + * MPEG-4 Advanced Simple Profile Level 0 video and Low-Complexity AAC audio in MP4 container<br> + * <source src='video.mp4' <b>type='video/mp4; codecs="mp4v.20.240, mp4a.40.2"'</b>><br> + * MPEG-4 Visual Simple Profile Level 0 video and AMR audio in 3GPP container<br> + * <source src='video.3gp' <b>type='video/3gpp; codecs="mp4v.20.8, samr"'</b>><br> + * Theora video and Vorbis audio in Ogg container<br> + * <source src='video.ogv' <b>type='video/ogg; codecs="theora, vorbis"'</b>><br> + * Theora video and Speex audio in Ogg container<br> + * <source src='video.ogv' <b>type='video/ogg; codecs="theora, speex"'</b>><br> + * Vorbis audio alone in Ogg container<br> + * <source src='audio.ogg' <b>type='audio/ogg; codecs=vorbis'</b>><br> + * Speex audio alone in Ogg container<br> + * <source src='audio.spx' <b>type='audio/ogg; codecs=speex'</b>><br> + * FLAC audio alone in Ogg container<br> + * <source src='audio.oga' <b>type='audio/ogg; codecs=flac'</b>><br> + * Dirac video and Vorbis audio in Ogg container<br> + * <source src='video.ogv' <b>type='video/ogg; codecs="dirac, vorbis"'</b>><br> + * Theora video and Vorbis audio in Matroska container<br> + * <source src='video.mkv' <b>type='video/x-matroska; codecs="theora, vorbis"'</b>><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 this.media; + } + + /** + * Sets the media for which the content of this source should be shown<br> + * <br> + * + * <source src="movie.ogg" type="video/ogg" <b>media="screen and (min-width:320px)"><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/33844413/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..587ffcd --- /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; + + private Kind kind; + + private String label; + + private Boolean defaultTrack; + + private Locale srclang; + + private ResourceReference resourceReference; + + private String url; + + private PageParameters pageParameters; + + public Track(String id) + { + super(id); + } + + public Track(String id, IModel<?> model) + { + super(id, model); + } + + public Track(String id, ResourceReference resourceReference) + { + this(id); + this.resourceReference = resourceReference; + } + + public Track(String id, IModel<?> model, ResourceReference resourceReference) + { + this(id, model); + this.resourceReference = resourceReference; + } + + public Track(String id, ResourceReference resourceReference, PageParameters pageParameters) + { + this(id); + this.resourceReference = resourceReference; + this.pageParameters = pageParameters; + } + + public Track(String id, IModel<?> model, ResourceReference resourceReference, + PageParameters pageParameters) + { + this(id, model); + this.resourceReference = resourceReference; + this.pageParameters = pageParameters; + } + + public Track(String id, String url) + { + this(id); + this.url = url; + } + + public Track(String id, IModel<?> model, String url) + { + this(id, model); + this.url = url; + } + + public Track(String id, String url, PageParameters pageParameters) + { + this(id); + this.url = url; + this.pageParameters = pageParameters; + } + + public Track(String id, IModel<?> model, String url, PageParameters pageParameters) + { + this(id, model); + this.url = url; + this.pageParameters = pageParameters; + } + + @Override + protected void onComponentTag(ComponentTag tag) + { + this.checkComponentTag(tag, "track"); + super.onComponentTag(tag); + + if (this.resourceReference != null) + { + tag.put("src", RequestCycle.get().urlFor(this.resourceReference, this.pageParameters)); + } + + if (this.url != null) + { + tag.put("src", this.url); + } + + if (this.kind != null) + { + tag.put("kind", this.kind.name()); + } + + if (this.label != null) + { + tag.put("label", this.label); + } + + if (this.defaultTrack != null && this.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 + if (this.srclang != null) + { + tag.put("srclang", this.srclang.getLanguage()); + } + else if (this.resourceReference != null && this.resourceReference.getLocale() != null) + { + tag.put("srclang", this.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 this.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 the + * kind + */ + public void setKind(Kind kind) + { + this.kind = kind; + } + + /** + * The label for this track + * + * @return the label + */ + public String getLabel() + { + return this.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 getDefaultTrack() + { + return this.defaultTrack != null ? this.defaultTrack : false; + } + + /** + * 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 this.srclang; + } + + /** + * Sets the src lang + * + * @param srclang + * the src lang to set + */ + public void setSrclang(Locale srclang) + { + this.srclang = srclang; + } + + /** + * To be used for the kind attribute + */ + public enum Kind + { + subtitles, captions, descriptions, chapters, metadata + } +} http://git-wip-us.apache.org/repos/asf/wicket/blob/33844413/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..d1f0fe2 --- /dev/null +++ b/wicket-core/src/main/java/org/apache/wicket/markup/html/media/audio/Audio.java @@ -0,0 +1,97 @@ +/* + * 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, url, pageParameters); + } + + public Audio(String id, IModel<?> model, String url, PageParameters pageParameters) + { + super(id, model, url, pageParameters); + } + + @Override + protected void onComponentTag(ComponentTag tag) + { + this.checkComponentTag(tag, "audio"); + super.onComponentTag(tag); + } +} http://git-wip-us.apache.org/repos/asf/wicket/blob/33844413/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..c463a07 --- /dev/null +++ b/wicket-core/src/main/java/org/apache/wicket/markup/html/media/video/Video.java @@ -0,0 +1,208 @@ +/* + * 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, url, pageParameters); + } + + public Video(String id, IModel<?> model, String url, PageParameters pageParameters) + { + super(id, model, url, pageParameters); + } + + @Override + protected void onComponentTag(ComponentTag tag) + { + this.checkComponentTag(tag, "video"); + super.onComponentTag(tag); + + if (this.width != null) + { + tag.put("width", this.width); + } + + if (this.height != null) + { + tag.put("height", this.height); + } + + if (this.poster != null) + { + tag.put("poster", RequestCycle.get().urlFor(this.poster, this.posterPageParameters)); + } + } + + /** + * The image to be displayed if the video isn't available + * + * @return the resource reference of the image + */ + public ResourceReference getPoster() + { + return this.poster; + } + + /** + * Gets the posters page parameters + * + * @return the page parameters for the poster + */ + public PageParameters getPosterPageParameters() + { + return this.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 this.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 this.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/33844413/wicket-core/src/test/java/org/apache/wicket/markup/html/media/Application.java ---------------------------------------------------------------------- diff --git a/wicket-core/src/test/java/org/apache/wicket/markup/html/media/Application.java b/wicket-core/src/test/java/org/apache/wicket/markup/html/media/Application.java new file mode 100755 index 0000000..7a15513 --- /dev/null +++ b/wicket-core/src/test/java/org/apache/wicket/markup/html/media/Application.java @@ -0,0 +1,37 @@ +/* + * 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.protocol.http.WebApplication; + +public class Application extends WebApplication +{ + + @Override + public Class<? extends Page> getHomePage() + { + return MediaTagsTestPage.class; + } + + @Override + protected void init() + { + super.init(); + MediaUtils.init(); + } +} http://git-wip-us.apache.org/repos/asf/wicket/blob/33844413/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/33844413/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..3f17ad7 --- /dev/null +++ b/wicket-core/src/test/java/org/apache/wicket/markup/html/media/MediaTagsExtendedTestPage.java @@ -0,0 +1,55 @@ +/* + * 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/33844413/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..0863365 --- /dev/null +++ b/wicket-core/src/test/java/org/apache/wicket/markup/html/media/MediaTagsTest.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; + +import org.apache.wicket.util.tester.TagTester; +import org.apache.wicket.util.tester.WicketTester; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class MediaTagsTest +{ + private WicketTester wicketTester; + + @Before + public void setup() + { + wicketTester = new WicketTester(new Application()); + } + + @Test + public void testAudioTagIsRenderedRight() + { + wicketTester.startPage(MediaTagsTestPage.class); + String lastResponseAsString = wicketTester.getLastResponse().getDocument(); + TagTester createTagByAttribute = TagTester.createTagByAttribute(lastResponseAsString, + "audio"); + Assert.assertTrue(createTagByAttribute.hasAttribute("autoplay")); + Assert.assertTrue(createTagByAttribute.hasAttribute("controls")); + Assert.assertTrue(createTagByAttribute.hasAttribute("loop")); + Assert.assertTrue(createTagByAttribute.hasAttribute("muted")); + Assert.assertEquals("user-credentials", createTagByAttribute.getAttribute("crossorigin")); + String attribute = createTagByAttribute.getAttribute("src"); + Assert.assertTrue("The time period is set right in the src attribute", + attribute.contains("#t=5,10")); + Assert.assertTrue("page parameter is in the url of the src attribute", + attribute.contains("test=test")); + } + + @Test + public void testVideoTagIsRenderedRight() + { + wicketTester.startPage(MediaTagsTestPage.class); + String lastResponseAsString = wicketTester.getLastResponse().getDocument(); + TagTester createTagByAttribute = TagTester.createTagByAttribute(lastResponseAsString, + "video"); + String attribute = createTagByAttribute.getAttribute("poster"); + Assert.assertTrue("page parameter is in the url of the poster", + attribute.contains("test2=test2")); + String attributesrc = createTagByAttribute.getAttribute("src"); + Assert.assertTrue("video url is in the src attribute", + attributesrc.contains("dummyVideo.m4a")); + Assert.assertEquals("500", createTagByAttribute.getAttribute("width")); + Assert.assertEquals("400", createTagByAttribute.getAttribute("height")); + } + + @Test + public void testextendedVideoTagIsRenderedRight() + { + wicketTester.startPage(MediaTagsExtendedTestPage.class); + String lastResponseAsString = wicketTester.getLastResponse().getDocument(); + TagTester createTagByAttribute = TagTester.createTagByAttribute(lastResponseAsString, + "video"); + Assert.assertTrue(createTagByAttribute.hasChildTag("source")); + Assert.assertTrue(createTagByAttribute.hasChildTag("track")); + + + TagTester sourceTag = TagTester.createTagByAttribute(lastResponseAsString, "source"); + Assert.assertEquals("video/mp4", sourceTag.getAttribute("type")); + Assert.assertEquals("screen and (device-width:500px)", sourceTag.getAttribute("media")); + Assert.assertEquals("http://www.mytestpage.xc/video.m4a", sourceTag.getAttribute("src")); + + TagTester trackTag = TagTester.createTagByAttribute(lastResponseAsString, "track"); + + Assert.assertTrue(trackTag.getAttribute("src").contains("dummySubtitles")); + Assert.assertEquals("subtitles", trackTag.getAttribute("kind")); + Assert.assertEquals("Subtitles of video", trackTag.getAttribute("label")); + Assert.assertEquals("default", trackTag.getAttribute("default")); + Assert.assertEquals("de", trackTag.getAttribute("srclang")); + } +} http://git-wip-us.apache.org/repos/asf/wicket/blob/33844413/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/33844413/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..8393f42 --- /dev/null +++ b/wicket-core/src/test/java/org/apache/wicket/markup/html/media/MediaTagsTestPage.java @@ -0,0 +1,57 @@ +/* + * 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.use_credentials); + audio.setLoop(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/33844413/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/33844413/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/33844413/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/33844413/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