001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.wicket.markup.html.media;
018
019import org.apache.wicket.markup.ComponentTag;
020import org.apache.wicket.markup.html.WebMarkupContainer;
021import org.apache.wicket.model.IModel;
022import org.apache.wicket.request.cycle.RequestCycle;
023import org.apache.wicket.request.mapper.parameter.PageParameters;
024import org.apache.wicket.request.resource.PackageResource;
025import org.apache.wicket.request.resource.PackageResourceReference;
026import org.apache.wicket.request.resource.ResourceReference;
027import org.apache.wicket.util.resource.IResourceStream;
028
029/**
030 * The source of an audio or a video media component
031 *
032 * @author Tobias Soloschenko
033 * @author Andrew Lombardi
034 * @since 7.0.0
035 */
036public class Source extends WebMarkupContainer
037{
038        private static final long serialVersionUID = 1L;
039
040        private boolean displayType;
041
042        private String type;
043
044        private String media;
045
046        private PageParameters pageParameters;
047
048        private final ResourceReference resourceReference;
049
050        private final String url;
051
052        /**
053         * Creates a source
054         * 
055         * @param id
056         *            the component id
057         */
058        public Source(String id)
059        {
060                this(id, null, null, null, null);
061        }
062
063        /**
064         * Creates a source
065         * 
066         * @param id
067         *            the component id
068         * @param model
069         *            the internally used model
070         */
071        public Source(String id, IModel<?> model)
072        {
073                this(id, model, null, null, null);
074        }
075
076        /**
077         * Creates a source
078         * 
079         * @param id
080         *            the component id
081         * @param resourceReference
082         *            the resource reference to provide the source data
083         */
084        public Source(String id, ResourceReference resourceReference)
085        {
086                this(id, null, null, null, resourceReference);
087        }
088
089        /**
090         * Creates a source
091         * 
092         * @param id
093         *            the component id
094         * @param model
095         *            the internally used model
096         * @param resourceReference
097         *            the resource reference to provide the source data
098         */
099        public Source(String id, IModel<?> model, ResourceReference resourceReference)
100        {
101                this(id, model, null, null, resourceReference);
102        }
103
104        /**
105         * Creates a source
106         * 
107         * @param id
108         *            the component id
109         * @param pageParameters
110         *            the the page parameters applied to the source URL
111         * @param resourceReference
112         *            the resource reference to provide the source data
113         */
114        public Source(String id, ResourceReference resourceReference,
115                PageParameters pageParameters)
116        {
117                this(id, null, null, pageParameters, resourceReference);
118        }
119
120        /**
121         * Creates a source
122         * 
123         * @param id
124         *            the component id
125         * @param model
126         *            the internally used model
127         * @param resourceReference
128         *            the resource reference to provide the source data
129         * @param pageParameters
130         *            the the page parameters applied to the source URL
131         */
132        public Source(String id, IModel<?> model, ResourceReference resourceReference,
133                PageParameters pageParameters)
134        {
135                this(id, model, null, pageParameters, resourceReference);
136        }
137
138        /**
139         * Creates a source
140         * 
141         * @param id
142         *            the component id
143         * @param url
144         *            an external URL to provide the source information
145         */
146        public Source(String id, String url)
147        {
148                this(id, null, url, null, null);
149        }
150
151        /**
152         * Creates a source
153         * 
154         * @param id
155         *            the component id
156         * @param model
157         *            the internally used model
158         * @param url
159         *            an external URL to provide the source information
160         */
161        public Source(String id, IModel<?> model, String url)
162        {
163                this(id, model, url, null, null);
164        }
165
166        private Source(String id, IModel<?> model, String url, PageParameters pageParameters,
167                ResourceReference resourceReference)
168        {
169                super(id, model);
170                this.url = url;
171                this.pageParameters = pageParameters;
172                this.resourceReference = resourceReference;
173        }
174
175        @Override
176        protected void onComponentTag(ComponentTag tag)
177        {
178                checkComponentTag(tag, "source");
179                super.onComponentTag(tag);
180
181                if (resourceReference != null)
182                {
183                        CharSequence url = RequestCycle.get().urlFor(resourceReference, pageParameters);
184                        tag.put("src", url);
185                }
186                else if (url != null)
187                {
188                        tag.put("src", url);
189                }
190
191                if (getDisplayType())
192                {
193                        if (type != null)
194                        {
195                                tag.put("type", type);
196                        }
197                        else if (resourceReference != null)
198                        {
199                                // if package resource reference we can get the content
200                                // type of the package resource
201                                if(resourceReference instanceof PackageResourceReference){
202                                        PackageResource resource = ((PackageResourceReference)resourceReference).getResource();
203                                        IResourceStream resourceStream = resource.getResourceStream();
204                                        String contentType = resourceStream.getContentType();
205                                        tag.put("type", contentType);
206                                }
207                        }
208                }
209
210                String _media = getMedia();
211                if (_media != null)
212                {
213                        tag.put("media", _media);
214                }
215
216        }
217
218        /**
219         * If the type is going to be displayed
220         *
221         * @return If the type is going to be displayed
222         */
223        public boolean getDisplayType()
224        {
225                return displayType;
226        }
227
228        /**
229         * Sets if the type is going to be displayed
230         *
231         * @param displayType
232         *            if the type is going to be displayed
233         */
234        public void setDisplayType(boolean displayType)
235        {
236                this.displayType = displayType;
237        }
238
239        /**
240         * Gets the type
241         *
242         * @see #setType(String)
243         *
244         * @return the type of this media element
245         */
246        public String getType()
247        {
248                return type;
249        }
250
251        /**
252         * Sets the type<br>
253         * <br>
254         *
255         * * The following list shows some examples of how to use the codecs= MIME parameter in the type
256         * attribute.<br>
257         * <br>
258         *
259         * H.264 Constrained baseline profile video (main and extended video compatible) level 3 and
260         * Low-Complexity AAC audio in MP4 container<br>
261         * &lt;source src='video.mp4' <b>type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'</b>&gt;<br>
262         * H.264 Extended profile video (baseline-compatible) level 3 and Low-Complexity AAC audio in
263         * MP4 container<br>
264         * &lt;source src='video.mp4' <b>type='video/mp4; codecs="avc1.58A01E, mp4a.40.2"'</b>&gt;<br>
265         * H.264 Main profile video level 3 and Low-Complexity AAC audio in MP4 container<br>
266         * &lt;source src='video.mp4' <b>type='video/mp4; codecs="avc1.4D401E, mp4a.40.2"'</b>&gt;<br>
267         * H.264 'High' profile video (incompatible with main, baseline, or extended profiles) level 3
268         * and Low-Complexity AAC audio in MP4 container<br>
269         * &lt;source src='video.mp4' <b>type='video/mp4; codecs="avc1.64001E, mp4a.40.2"'</b>&gt;<br>
270         * MPEG-4 Visual Simple Profile Level 0 video and Low-Complexity AAC audio in MP4 container<br>
271         * &lt;source src='video.mp4' <b>type='video/mp4; codecs="mp4v.20.8, mp4a.40.2"'</b>&gt;<br>
272         * MPEG-4 Advanced Simple Profile Level 0 video and Low-Complexity AAC audio in MP4 container<br>
273         * &lt;source src='video.mp4' <b>type='video/mp4; codecs="mp4v.20.240, mp4a.40.2"'</b>&gt;<br>
274         * MPEG-4 Visual Simple Profile Level 0 video and AMR audio in 3GPP container<br>
275         * &lt;source src='video.3gp' <b>type='video/3gpp; codecs="mp4v.20.8, samr"'</b>&gt;<br>
276         * Theora video and Vorbis audio in Ogg container<br>
277         * &lt;source src='video.ogv' <b>type='video/ogg; codecs="theora, vorbis"'</b>&gt;<br>
278         * Theora video and Speex audio in Ogg container<br>
279         * &lt;source src='video.ogv' <b>type='video/ogg; codecs="theora, speex"'</b>&gt;<br>
280         * Vorbis audio alone in Ogg container<br>
281         * &lt;source src='audio.ogg' <b>type='audio/ogg; codecs=vorbis'</b>&gt;<br>
282         * Speex audio alone in Ogg container<br>
283         * &lt;source src='audio.spx' <b>type='audio/ogg; codecs=speex'</b>&gt;<br>
284         * FLAC audio alone in Ogg container<br>
285         * &lt;source src='audio.oga' <b>type='audio/ogg; codecs=flac'</b>&gt;<br>
286         * Dirac video and Vorbis audio in Ogg container<br>
287         * &lt;source src='video.ogv' <b>type='video/ogg; codecs="dirac, vorbis"'</b>&gt;<br>
288         * Theora video and Vorbis audio in Matroska container<br>
289         * &lt;source src='video.mkv' <b>type='video/x-matroska; codecs="theora, vorbis"'</b>&gt;<br>
290         *
291         * @param type
292         *            the type of this media element
293         */
294        public void setType(String type)
295        {
296                this.type = type;
297        }
298
299        /**
300         * The media for which the content of this source should be shown
301         *
302         * @see #setMedia(String)
303         * @return The media for which the content of this source should be shown
304         */
305        public String getMedia()
306        {
307                return media;
308        }
309
310        /**
311         * Sets the media for which the content of this source should be shown<br>
312         * <br>
313         *
314         * &lt;source src="movie.ogg" type="video/ogg" <b>media="screen and (min-width:320px)"&gt;<br>
315         *
316         * @param media
317         *            the media for which to content of this source should be shown
318         */
319        public void setMedia(String media)
320        {
321                this.media = media;
322        }
323
324        /**
325         * Gets the page parameter applied to the URL of the source
326         * 
327         * @return the page parameter applied to the URL of the source
328         */
329        public PageParameters getPageParameters()
330        {
331                return pageParameters;
332        }
333
334        /**
335         * Sets the page parameter applied to the URL of the source
336         * 
337         * @param pageParameters
338         *            the page parameter which are going to be applied to the URL of the source
339         */
340        public void setPageParameters(PageParameters pageParameters)
341        {
342                this.pageParameters = pageParameters;
343        }
344}