/*
* 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;
import org.apache.wicket.request.resource.ResourceReference;
/**
* The media component is used to provide basic functionality to the video and audio component.
*
* @author Tobias Soloschenko
* @author Andrew Lombardi
* @since 7.0.0
*/
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 {
/**
* no authentication required
*/
ANONYMOUS("anonymous"),
/**
* user credentials required
*/
USER_CREDENTIALS("user-credentials"),
/**
* no cross origin
*/
NO_CORS("");
private final String realName;
private Cors(String realName)
{
this.realName = realName;
}
/**
* Gets the real name for the cors option
*
* @return the real name
*/
public String getRealName()
{
return realName;
}
}
/**
* To be used for the <em>preload</em> attribute
*
* @see {@link #setPreload(Preload)}
*/
public enum Preload {
/**
* preloads nothing
*/
NONE("none"),
/**
* preloads only meta data like first picture, etc.
*/
METADATA("metadata"),
/**
* auto detection what is going to be preload
*/
AUTO("auto");
private final String realName;
private Preload(String realname)
{
realName = realname;
}
/**
* Gets the real name for the preload option
*
* @return the real name
*/
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 String type;
private PageParameters pageParameters;
private final ResourceReference resourceReference;
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);
}
/**
* Creates a media component
*
* @param id
* The component id
* @param resourceReference
* the resource reference of the media file
*/
public MediaComponent(String id, ResourceReference resourceReference)
{
this(id, null, null, null, resourceReference);
}
/**
* Creates a media component
*
* @param id
* The component id
* @param model
* the internally used model
* @param resourceReference
* the resource reference of the media file
*/
public MediaComponent(String id, IModel<?> model, ResourceReference resourceReference)
{
this(id, model, null, null, resourceReference);
}
/**
* Creates a media component
*
* @param id
* The component id
* @param resourceReference
* the resource reference of the media file
* @param pageParameters
* the page parameters to be used to be prepended to the media URL
*/
public MediaComponent(String id, ResourceReference resourceReference,
PageParameters pageParameters)
{
this(id, null, null, pageParameters, resourceReference);
}
/**
* Creates a media component
*
* @param id
* The component id
* @param model
* the internally used model
* @param resourceReference
* the resource reference of the media file
* @param pageParameters
* the page parameters to be used to be prepended to the media URL
*/
public MediaComponent(String id, IModel<?> model, ResourceReference resourceReference,
PageParameters pageParameters)
{
this(id, model, null, pageParameters, resourceReference);
}
/**
* Creates a media component
*
* @param id
* The component id
* @param url
* an external URL to be used for the media component
*/
public MediaComponent(String id, String url)
{
this(id, null, url, null, null);
}
/**
* Creates a media component
*
* @param id
* The component id
* @param model
* the internally used model
* @param url
* an external URL to be used for the media component
*/
public MediaComponent(String id, IModel<?> model, String url)
{
this(id, model, url, null, null);
}
/**
* Creates a media component
*
* @param id
* The component id
* @param model
* the internally used model
* @param url
* an external URL to be used for the media component
* @param pageParameters
* the page parameters to be used to be prepended to the media URL
*/
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,
ResourceReference resourceReference)
{
super(id, model);
this.url = url;
this.pageParameters = pageParameters;
this.resourceReference = resourceReference;
}
@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 (resourceReference != null)
{
CharSequence urlToMediaReference = RequestCycle.get().urlFor(resourceReference,
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());
}
String type = getType();
if (type != null)
{
tag.put("type", type);
}
}
/**
* 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;
}
/**
* Gets the page parameter applied to the URL of the media component
*
* @return the page parameter applied to the URL of the media component
*/
public PageParameters getPageParameters()
{
return pageParameters;
}
/**
* Sets the page parameter applied to the URL of the media component
*
* @param pageParameters
* the page parameter which are going to be applied to the URL of the media component
*/
public void setPageParameters(PageParameters pageParameters)
{
this.pageParameters = pageParameters;
}
/**
* 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;
}
/**
* 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>
* <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;
}
}