initial commit

This commit is contained in:
Tilman Kranz 2024-09-21 16:05:22 +02:00
commit 5f95d9cef6
55 changed files with 12483 additions and 0 deletions

29
COPYING.txt Normal file
View File

@ -0,0 +1,29 @@
This software includes sources and binaries from:
jQuery
Copyright 2014 jQuery Foundation and other contributors
http://jquery.com/
MediaElement.js
Copyright 2010-2013, John Dyer (http://j.hn)
http://mediaelementjs.com/
MediaElement Playlist Feature (plugin) -
Andrew Berezovsky <andrew.berezovsky@gmail.com>
and Junaid Qadir Baloch <shekhanzai.baloch@gmail.com>
https://github.com/duozersk/mep-feature-playlist
JavaScript-ID3-Reader
Copyright (c) 2008 Jacob Seidelin, http://blog.nihilogic.dk/ BSD License
Copyright (c) 2009 Opera Software ASA BSD License
Copyright (c) 2010 AntÃâ³nio Afonso BSD License
Copyright (c) 2010 Joshua Kifer BSD License
https://github.com/aadsm/JavaScript-ID3-Reader
This software is:
MyPlayer
Copyright 2014 tilt@linuxfoo.de MIT License
See the file LICENSE.txt for licensing information
or contact the author for additional information.

20
LICENSE.txt Normal file
View File

@ -0,0 +1,20 @@
MyPlayer
Copyright (C) 2014 tilt@linuxfoo.de
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

32
README.txt Normal file
View File

@ -0,0 +1,32 @@
Project: MyPlayer - A Web-MP3-Player with Playlist Support
Author: tilt@linuxfoo.de
Release: 01-10-2014
License: MIT
About:
This project provides a JavaScript constructor MyPlayer({...options...}) that can be used
to embed lists of audio files as read from an index document or an M3U into a web document.
They will be displayed in a playback GUI with a playlist that can optionally be filled
from the "title" and "artist" values of the files' ID3 tags (v1 and v2 are supported).
The player is "detachable", meaning it can start in a detached state or the user can open
it in a new window, preventing that playback breaks when the user leaves the page.
Tested Compatibility:
MP3: Firefox, Chrome, Internet Exploder
OGG Audio: Firefox, Chrome
How to Use:
See demos/index.html for several examples.
How to Hack:
Directory src contains the input files. See player.js for the MyPLayer implementation.
Use build.sh (with the Google closure compiler) to rebuild myplayer.min.js.
The Flash and Silverlight plugins are taken from mediaelement.js and are included
in binary form only. If you want to modify them, use the mediaelement.js sources.

2
RELEASE.txt Normal file
View File

@ -0,0 +1,2 @@
2-10-2014: fixed a bug in EXTINF parsing (time=-1).
1-10-2014: initial release.

BIN
css/ajax-loader.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
css/background.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

BIN
css/bigplay.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

1
css/bigplay.svg Normal file
View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?> <!-- Generator: Adobe Fireworks CS6, Export SVG Extension by Aaron Beall (http://fireworks.abeall.com) . Version: 0.6.1 --> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg id="bigplay-gradient.fw-Page%201" viewBox="0 0 100 200" style="background-color:#ffffff00" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" x="0px" y="0px" width="100px" height="200px" > <defs> <radialGradient id="gradient1" cx="50%" cy="50%" r="50%"> <stop stop-color="#222222" stop-opacity="0" offset="70%"/> <stop stop-color="#222222" stop-opacity="0.0118" offset="70.202%"/> <stop stop-color="#333333" stop-opacity="1" offset="85%"/> <stop stop-color="#333333" stop-opacity="0" offset="100%"/> </radialGradient> <radialGradient id="gradient2" cx="50%" cy="50%" r="50%"> <stop stop-color="#bbbbbb" stop-opacity="0" offset="70%"/> <stop stop-color="#bbbbbb" stop-opacity="0.0118" offset="70.202%"/> <stop stop-color="#bbbbbb" stop-opacity="1" offset="85%"/> <stop stop-color="#bbbbbb" stop-opacity="0" offset="100%"/> </radialGradient> <filter id="filter1" x="-100%" y="-100%" width="300%" height="300%"> <!-- Glow --> <feColorMatrix result="out" in="SourceGraphic" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0"/> <feMorphology result="out" in="out" operator="dilate" radius="3"/> <feGaussianBlur result="out" in="out" stdDeviation="1.5"/> <feBlend in="SourceGraphic" in2="out" mode="normal" result="Glow1"/> </filter> <filter id="filter2" x="-100%" y="-100%" width="300%" height="300%"> <!-- Glow --> <feColorMatrix result="out" in="SourceGraphic" type="matrix" values="0 0 0 0.8667 0 0 0 0 0.8667 0 0 0 0 0.8667 0 0 0 0 0.251 0"/> <feMorphology result="out" in="out" operator="dilate" radius="3"/> <feGaussianBlur result="out" in="out" stdDeviation="1.5"/> <feBlend in="SourceGraphic" in2="out" mode="normal" result="Glow2"/> </filter> </defs> <g id="Background"> </g> <g id="dark%20shadow"> <path d="M 22 50 C 22 34.5358 34.5358 22 50 22 C 65.4642 22 78 34.5358 78 50 C 78 65.4642 65.4642 78 50 78 C 34.5358 78 22 65.4642 22 50 ZM 5 50 C 5 74.8531 25.1469 95 50 95 C 74.8531 95 95 74.8531 95 50 C 95 25.1469 74.8531 5 50 5 C 25.1469 5 5 25.1469 5 50 Z" fill="url(#gradient1)"/> <path d="M 22 150 C 22 134.5358 34.5358 122 50 122 C 65.4642 122 78 134.5358 78 150 C 78 165.4642 65.4642 178 50 178 C 34.5358 178 22 165.4642 22 150 ZM 5 150 C 5 174.8531 25.1469 195 50 195 C 74.8531 195 95 174.8531 95 150 C 95 125.1469 74.8531 105 50 105 C 25.1469 105 5 125.1469 5 150 Z" fill="url(#gradient2)"/> </g> <g id="dark"> <path id="Polygon" filter="url(#filter1)" d="M 72.5 49.5 L 38.75 68.9856 L 38.75 30.0144 L 72.5 49.5 Z" fill="#ffffff"/> <path id="Ellipse" d="M 13 50.5 C 13 29.7891 29.7891 13 50.5 13 C 71.2109 13 88 29.7891 88 50.5 C 88 71.2109 71.2109 88 50.5 88 C 29.7891 88 13 71.2109 13 50.5 Z" stroke="#ffffff" stroke-width="5" fill="none"/> </g> <g id="light"> <path id="Polygon2" filter="url(#filter2)" d="M 72.5 149.5 L 38.75 168.9856 L 38.75 130.0144 L 72.5 149.5 Z" fill="#ffffff"/> <path id="Ellipse2" d="M 13 150.5 C 13 129.7891 29.7891 113 50.5 113 C 71.2109 113 88 129.7891 88 150.5 C 88 171.211 71.2109 188 50.5 188 C 29.7891 188 13 171.211 13 150.5 Z" stroke="#ffffff" stroke-width="5" fill="none"/> </g> </svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
css/controls-playlist.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
css/controls.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

1
css/controls.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 10 KiB

0
css/custom.css Normal file
View File

4
css/index.css Normal file
View File

@ -0,0 +1,4 @@
div.home { font-size: 1em; }
div.home a { display: inline-block; margin: 0 .2em 0 .2em; text-decoration: none; }
h1 { margin-top: 0; }

69
css/local.css Normal file
View File

@ -0,0 +1,69 @@
html {
overflow: hidden;
height: 100%
}
body {
background: black;
}
.mejs-audio {
}
.mejs-controls {
top: 0!important;
padding: 3px 0 0 0;
height: 2em!important;
background: none!important;
border-top: 2em!important;
}
.mejs-controls .mejs-time-rail .mejs-time-loaded {
background: #5a1a7a!important;
}
.mejs-controls .mejs-time-rail .mejs-time-float {
top: 2.5em!important;
}
.mejs-controls .mejs-time-rail .mejs-time-float .mejs-time-float-corner {
display: none!important;
}
.mejs li {
font-size: 0.8em!important;
line-height: 1em!important;
color: #ccddff;
}
.mejs-playlist {
width: 430px!important;
height: 265px!important;
}
.popupButton {
display: inline-block!important;
position: absolute;
top: 2px;
}
.popupButton button {
overflow: hidden;
width: 25px;
height: 22px;
padding: 0;
margin: 0;
border: 0;
background: url(popup.png);
cursor: pointer;
}
.playerDetached {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
text-align: center;
font-size: small;
font-family: sans-serif;
color: #cacaca;
}
.ajaxLoader {
width: 16px;
height: 16px;
display: inline-block;
background: url(ajax-loader.gif);
}
noscript {
color: white;
font-family: sans-serif;
}

1001
css/mediaelementplayer.css Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,68 @@
/*
Document : mep-feature-playlist.css
Author : Andrew Berezovsky <andrew.berezovsky@gmail.com>
Original Author : Junaid Qadir Baloch <shekhanzai.baloch@gmail.com>
*/
/* Start: Show/Hide Playlist*/
.mejs-controls .mejs-show-playlist button {
background: transparent url(controls-playlist.png) no-repeat;
background-position: -16px -16px;
}
.mejs-controls .mejs-hide-playlist button {
background: transparent url(controls-playlist.png) no-repeat;
background-position: -16px 0;
}
/* End: Show/Hide Playlist */
/* Start: Previous */
.mejs-controls .mejs-prevtrack button {
background: transparent url(controls-playlist.png) no-repeat;
background-position: 0 -16px;
}
/* End: Previous */
/* Start: Next */
.mejs-controls .mejs-nexttrack button {
background: transparent url(controls-playlist.png) no-repeat;
}
/* End: Next */
/* Start: Shuffle */
.mejs-controls .mejs-shuffle-on button {
background: transparent url(controls-playlist.png) no-repeat;
background-position: -32px 0;
}
.mejs-controls .mejs-shuffle-off button {
background: transparent url(controls-playlist.png) no-repeat;
background-position: -32px -16px;
}
/* End: Shuffle */
/*Start: Playlist*/
.mejs-playlist {
position: absolute;
left: 0;
height: 200px!important;
overflow-y: auto;
}
.mejs-playlist ul {
margin: 0;
padding: 5px;
}
.mejs-playlist li {
color: white;
font-size: 11px;
height: 16px;
overflow: hidden;
margin: 2px;
cursor: pointer;
}
.mejs-playlist li:hover {
color: #a8a8a8;
}
.mejs-playlist li.current {
color: white;
font-weight: bold;
}
/*End: Playlist*/

3
css/myplayer.css Normal file
View File

@ -0,0 +1,3 @@
@import url('mediaelementplayer.css');
@import url('mep-feature-playlist.css');
@import url('local.css');

BIN
css/popup.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 744 B

26
demo/autoplay.html Normal file
View File

@ -0,0 +1,26 @@
<html>
<head>
<base href="." />
<title>MyPlayer Autoplay/Loop Demo</title>
<script type="text/javascript" src="../js/jquery.js"></script>
<script type="text/javascript" src="../js/myplayer.min.js"></script>
<link rel="stylesheet" href="../css/myplayer.css" />
<script type="text/javascript">$(function(){MyPlayer({
mode: 'm3u',
m3u: './snd/play.m3u',
id3: true,
autoplay: true,
loop: false
})});</script>
</head>
<body>
<noscript>
Javascript is required to use the MP3 player.
Please choose of the alternatives listed below.
</noscript>
</body>
</html>

28
demo/detachable.html Normal file
View File

@ -0,0 +1,28 @@
<html>
<head>
<base href="." />
<title>MyPlayer Detachable Demo</title>
<script type="text/javascript" src="../js/jquery.js"></script>
<script type="text/javascript" src="../js/myplayer.min.js"></script>
<link rel="stylesheet" href="../css/myplayer.css" />
<script type="text/javascript">$(function(){MyPlayer({
mode: 'm3u',
m3u: './snd/play.m3u',
detachable: false
})});</script>
<style type="text/css">
h1, p { color: white; }
</style>
</head>
<body>
<noscript>
Javascript is required to use the MP3 player.
Please choose of the alternatives listed below.
</noscript>
</body>
</html>

34
demo/element.html Normal file
View File

@ -0,0 +1,34 @@
<html>
<head>
<base href="." />
<title>MyPlayer Element Demo</title>
<script type="text/javascript" src="../js/jquery.js"></script>
<script type="text/javascript" src="../js/myplayer.min.js"></script>
<link rel="stylesheet" href="../css/myplayer.css" />
<script type="text/javascript">$(function(){MyPlayer({
element: '#myplayer',
mode: 'm3u',
m3u: './snd/play.m3u'
})});</script>
<style type="text/css">
h1, p { color: white; }
</style>
</head>
<body>
<noscript>
Javascript is required to use the MP3 player.
Please choose of the alternatives listed below.
</noscript>
<h1>I Am A Heading</h1>
<p>I am a paragraph. The player UI will follow below.</p>
<div id="myplayer"></div>
</body>
</html>

23
demo/extm3u.html Normal file
View File

@ -0,0 +1,23 @@
<html>
<head>
<base href="." />
<title>MyPlayer EXTM3U Demo</title>
<script type="text/javascript" src="../js/jquery.js"></script>
<script type="text/javascript" src="../js/myplayer.min.js"></script>
<link rel="stylesheet" href="../css/myplayer.css" />
<script type="text/javascript">$(function(){MyPlayer({
mode: 'm3u',
m3u: './snd/play.extm3u'
})});</script>
</head>
<body>
<noscript>
Javascript is required to use the MP3 player.
Please choose of the alternatives listed below.
</noscript>
</body>
</html>

24
demo/filematch.html Normal file
View File

@ -0,0 +1,24 @@
<html>
<head>
<base href="." />
<title>MyPlayer filematch Demo</title>
<script type="text/javascript" src="../js/jquery.js"></script>
<script type="text/javascript" src="../js/myplayer.min.js"></script>
<link rel="stylesheet" href="../css/myplayer.css" />
<script type="text/javascript">$(function(){MyPlayer({
mode: 'm3u',
m3u: './snd/play.m3u',
filematch: /(^|\/)[0-9][^\/]*\.mp3/i
})});</script>
</head>
<body>
<noscript>
Javascript is required to use the MP3 player.
Please choose of the alternatives listed below.
</noscript>
</body>
</html>

24
demo/id3.html Normal file
View File

@ -0,0 +1,24 @@
<html>
<head>
<base href="." />
<title>MyPlayer ID3 Demo</title>
<script type="text/javascript" src="../js/jquery.js"></script>
<script type="text/javascript" src="../js/myplayer.min.js"></script>
<link rel="stylesheet" href="../css/myplayer.css" />
<script type="text/javascript">$(function(){MyPlayer({
mode: 'm3u',
m3u: './snd/play.m3u',
id3: true
})});</script>
</head>
<body>
<noscript>
Javascript is required to use the MP3 player.
Please choose of the alternatives listed below.
</noscript>
</body>
</html>

255
demo/index.html Normal file
View File

@ -0,0 +1,255 @@
<html>
<head>
<title>MyPlayer Demos</title>
</head>
<body>
<a name="top"></a>
<p>[<a title="Back to Index" target="_self" href="../index.html">Back to Index</a>]</p>
<h1>MyPlayer Usage by Examples</h1>
<h2>Table of Contents</h2>
<ul>
<li><a href="#always" title="Alwas Required" target="_self">Always Required</a> - Including MyPlayer. Setting up MIME-Types.</li>
<li><a href="#list" title="Mode &quot;list&quot;" target="_self">Mode "list"</a> - Playing a JavaScript array of audio file URLs and titles.</li>
<li><a href="#mp3url" title="Mode &quot;mp3url&quot;" target="_self">Mode "mp3url"</a> - Reading lists of audio files from index documents.</li>
<li><a href="#m3u" title="Mode &quot;m3u&quot;" target="_self">Mode "m3u"</a> - Reading lists of audio files from <tt>.m3u</tt> files.</li>
<li><a href="#element" title="Option &quot;element&quot;" target="_self">Option "element"</a> - Where the player/playlist should be placed.</li>
<li><a href="#detachable" title="Option &quot;detachable&quot;" target="_self">Option "detachable"</a> - If the player can be detached or not.</li>
<li><a href="#id3" title="Option &quot;id3&quot;" target="_self">Option "id3"</a> - Interpreting ID3-tags.</li>
<li><a href="#autoplay" title="Option &quot;autoplay/loop/shuffle&quot;" target="_self">Options "autoplay", "loop" and "shuffle"</a> - Player behavior and defaults.</li>
<li><a href="#types" title="Option &quot;types&quot;" target="_self">Option "types"</a> - Specifying filename-endings to consider.</li>
<li><a href="#filematch" title="Option &quot;filematch&quot;" target="_self">Option "filematch"</a> - Specifying an URL-matching expression.</li>
<li><a href="#network" title="Option &quot;network&quot;" target="_self">Option "network"</a> - Limited support for network streams.</li>
</ul>
<h2><a name="always">Always Required</a></h2>
<p>To embed MyPlayer in your webpage put this in the <tt>&lt;head&gt;</tt>
section of your document:
<pre>&lt;script type="text/javascript" src="/path/to/js/jquery.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="/path/to/js/myplayer.min.js"&gt;&lt;/script&gt;
&lt;link rel="stylesheet" href="/path/to/css/myplayer.css" /&gt;</pre>
<p>Some (most?) webservers should be configured to serve audio files with their correct
MIME-Types so that playback in the browser works reliably. The following example
for the Apache webserver could be included in a file <tt>.htaccess</tt> in the
directory holding the audio files:</p>
<pre>AddType audio/mpeg .mp3
AddType audio/ogg .ogg</pre>
<p>This example will enable correct MIME-Types when serving files that end with
<tt>.mp3</tt> or <tt>.ogg</tt>.</p>
<h2><a name="list">Mode "list"</a></h2>
<p>If you have URLs of audio files as a JavaScript array, create the player
with option <tt>mode</tt> set to <tt>"list"</tt>. The list items are passed
either in object notation or as a plain strings containing the URLs:</p>
<pre>&lt;script type="text/javascript"&gt;$(function(){MyPlayer({
mode: 'list',
list: [
{url: '/something.mp3', title: 'Something'},
{url: 'http://example.com/snd/else.mp3'},
"./entirely.ogg"
]
})});&lt;/script&gt;</pre>
<p>Demo: <a title="MyPlayer list Demo" href="list.html" target="_blank">list.html</a></p>
<p><i>Note:</i> The property <tt>title</tt> is optional, and if it is
omitted, the last component of the URL path is used as a title in
the playlist. In above example, the second entry's title would be
<tt>else.mp3</tt> and the third one's would be <tt>entirely.ogg</tt>.</p>
<h2><a name="mp3url">Mode "mp3url"</a></h2>
<p>Play all links ending with <tt>.mp3</tt> found at a given URL <tt>mp3url</tt>:.
<pre>&lt;script type="text/javascript"&gt;$(function(){MyPlayer({
mode: 'mp3url',
mp3url: '/directory/with/your/mp3s/'
})});&lt;/script&gt;</pre>
<p><i>Note:</i> Directory indexes should be enabled on the directory containing
the files, when using the Apache webserver this can be possible by placing an
<tt>.htaccess</tt> file into that directory:</p>
<pre>Options +Indexes</pre>
<p>Demo: <a title="MyPlayer mp3url Demo" href="mp3url.html" target="_blank">mp3url.html</a></p>
<h2><a name="m3u">Mode "m3u"</a></h2>
<p>Play all links found in an M3U-File specified by URL <tt>m3u</tt>:</p>
<pre>&lt;script type="text/javascript"&gt;$(function(){MyPlayer({
mode: 'm3u',
m3u: '/some/place/play.m3u'
})});&lt;/script&gt;</pre>
<p>Demo: <a title="MyPlayer m3u Demo" href="m3u.html" target="_blank">m3u.html</a></p>
<p>If the M3U is in EXTM3U format, the player will attempt to parse the EXTINF
information (playtime, title) where available.</p>
<p>Demo: <a title="MyPlayer extm3u Demo" href="extm3u.html" target="_blank">extm3u.html</a></p>
<p><i>Note:</i> The player will to some degree try to resolve relative entries
in an M3U. If an entry is encountered that is not an absolute <tt>https?|ftp|file</tt>
URL, it will try to make the entry absolute by prepending it with the path
of the M3U.</p>
<p>Demo: <a title="MyPlayer relative m3u Demo" href="relative-m3u.html" target="_blank">relative-m3u.html</a></p>
<h2><a name="element">Option "element"</a></h2>
<p>The default for the player is to append its UI to the <tt>&lt;body&gt;</tt>
of the current document. Using the <tt>element</tt> option you have more
control over the placement of the player UI. This option uses jQuery selector
notation.</p>
<p>Append the player UI to the contents of the element with ID <tt>myplayer</tt>:</p>
<pre>&lt;script type="text/javascript"&gt;$(function(){MyPlayer({
element: '#myplayer',
mode: 'm3u',
m3u: '/some/place/play.m3u'
})});&lt;/script&gt;</pre>
<p>Demo: <a title="MyPlayer element Demo" href="element.html" target="_blank">element.html</a></p>
<h2><a name="detachable">Option "detachable"</a></h2>
<p>The default for the player is to offer a "detach" button that will cause
it to re-open itself in a separate (popup) window. If you do not
want this, set the option <tt>detachable</tt> to <tt>false</tt>:</p>
<pre>&lt;script type="text/javascript"&gt;$(function(){MyPlayer({
mode: 'm3u',
m3u: '/some/place/play.m3u',
detachable: false
})});&lt;/script&gt;</pre>
<p>Demo: <a title="MyPlayer detachable Demo" href="detachable.html" target="_blank">detachable.html</a></p>
<h2><a name="id3">Option "id3"</a></h2>
<p><i>Important Note:</i> My tests prove the ID3 implementation provided
here to be unreliable. Please use this option with caution. If you want
to provide neatly formatted metadata for your tracks, please also consider
the <tt><a href="#m3u">m3u</a></tt> option with EXTINF information.</p>
<p>Setting the option <tt>id3</tt> to <tt>true</tt> will cause the player
to attempt reading artist name and track title from the ID3 tags found in
the <tt>.mp3</tt> files.</p>
<p>Playback can commence before the lookups are complete (they might take
a while). An Ajax loading indicator is displayed for a few seconds next to
the tracks currently being looked up.</p>
<pre>&lt;script type="text/javascript"&gt;$(function(){MyPlayer({
mode: 'm3u',
m3u: '/some/place/play.m3u',
id3: true
})});&lt;/script&gt;</pre>
<p>Demo: <a title="MyPlayer id3 Demo" href="id3.html" target="_blank">id3.html</a></p>
<p><i>Note:</i> If you do not want the animated loading indicator, you
can prevent it by setting the option <tt>loader</tt> to <tt>false</tt>.</p>
<h2><a name="autoplay">Options "autoplay", "loop", "shuffle"</a></h2>
<p>Setting the option <tt>autoplay</tt> to <tt>true</tt> will cause the
player to immediately start playback when the site is ready.</p>
<p>Setting the option <tt>loop</tt> to <tt>false</tt> will cause the
"Loop" function to be disabled when the player is loaded.</p>
<p>Setting the option <tt>shuffle</tt> to <tt>true</tt> will cause the
"Shuffle" function to be enabled when the player is loaded.</p>
<pre>&lt;script type="text/javascript"&gt;$(function(){MyPlayer({
mode: 'm3u',
m3u: '/some/place/play.m3u',
autoplay: true,
loop: false,
shuffle: true
})});&lt;/script&gt;</pre>
<p>Demo: <a title="MyPlayer autoplay/loop/shuffle Demo" href="autoplay.html" target="_blank">autoplay.html</a></p>
<h2><a name="types">Option "types"</a></h2>
<p>Setting the option <tt>types</tt> to a non-empty array of strings
will interpret those strings as filename endings to consider for playback.
The matching will be performed case-insensitive.</p>
<p>The following example will build the playlist from the lines in
the given <tt>play.m3u</tt>, but it will only consider entries that end
with <tt>.ogg</tt>:</p>
<pre>&lt;script type="text/javascript"&gt;$(function(){MyPlayer({
mode: 'm3u',
m3u: '/some/place/play.m3u',
types: ['ogg']
})});&lt;/script&gt;</pre>
<p>Demo: <a title="MyPlayer types Demo" href="types.html" target="_blank">types.html</a></p>
<h2><a name="filematch">Option "filematch"</a></h2>
<p>Setting the option <tt>filematch</tt> to a RegExp object will cause
filename matching to be performed using that regular expression.</p>
<p><i>Note:</i> If this option and the option <tt>types</tt> are both
present, then this option has no effect, and the values in the array
<tt>types</tt> apply instead.</p>
<p>The following example will build the playlist from the lines in
the given <tt>play.m3u</tt>, but it will only consider entries that
start with a digit and end with <tt>.ogg</tt>. Please note that
matching is performed on the entire URL, so in order to match
the filename only, more complex regular expressing is neccessary:</p>
<pre>&lt;script type="text/javascript"&gt;$(function(){MyPlayer({
mode: 'm3u',
m3u: '/some/place/play.m3u',
filematch: /(^|\/)[0-9][^\/]*\.mp3/i
})});&lt;/script&gt;</pre>
<p>Demo: <a title="MyPlayer filematch Demo" href="filematch.html" target="_blank">filematch.html</a></p>
<h2><a name="network">Option "network"</a></h2>
<p>Setting the option <tt>network</tt> to <tt>true</tt> enables limited support
for network streams (native playback does not work with some broadcast servers).</p>
<p>All filename matching will be disabled, meaning the <tt>types</tt>
and <tt>filematch</tt> options have no effect.</p>
<p>The timerail will be disabled in the GUI.</p>
<p>Play an M3U containing only network stream entries:</p>
<pre>&lt;script type="text/javascript"&gt;$(function(){MyPlayer({
mode: 'm3u',
m3u: 'http://example.com/streaming.m3u',
network: true
})});&lt;/script&gt;</pre>
<p>Demo: <a title="MyPlayer network Demo" href="network.html" target="_blank">network.html</a></p>
<p><i>Implementation Note:</i> if <tt>network</tt> is set to <tt>true</tt> then
<tt>mediaelement.js</tt> will be forced to mode <tt>'native'</tt> on network streams
(this is accomplished by a patch to <tt>mediaelement.js</tt>).</p>
<p>[<a title="Back to Top" target="_self" href="#top">Back to Top</a>]</p>
</body>
</html>

29
demo/list.html Normal file
View File

@ -0,0 +1,29 @@
<html>
<head>
<base href="." />
<title>MyPlayer M3U Demo</title>
<script type="text/javascript" src="../js/jquery.js"></script>
<script type="text/javascript" src="../js/myplayer.min.js"></script>
<link rel="stylesheet" href="../css/myplayer.css" />
<script type="text/javascript">$(function(){MyPlayer({
mode: 'list',
list: [
{ url: './snd/dreamz.mp3',
title: 'tilt - Dreamz' },
{ url: './snd/dreamz.mp3',
title: 'tilt - Dreamz (#2)' },
'./snd/dreamz.mp3',
]
})});</script>
</head>
<body>
<noscript>
Javascript is required to use the MP3 player.
Please choose of the alternatives listed below.
</noscript>
</body>
</html>

23
demo/m3u.html Normal file
View File

@ -0,0 +1,23 @@
<html>
<head>
<base href="." />
<title>MyPlayer M3U Demo</title>
<script type="text/javascript" src="../js/jquery.js"></script>
<script type="text/javascript" src="../js/myplayer.min.js"></script>
<link rel="stylesheet" href="../css/myplayer.css" />
<script type="text/javascript">$(function(){MyPlayer({
mode: 'm3u',
m3u: './snd/play.m3u'
})});</script>
</head>
<body>
<noscript>
Javascript is required to use the MP3 player.
Please choose of the alternatives listed below.
</noscript>
</body>
</html>

23
demo/mp3url.html Normal file
View File

@ -0,0 +1,23 @@
<html>
<head>
<base href="." />
<title>MyPlayer mp3url Demo</title>
<script type="text/javascript" src="../js/jquery.js"></script>
<script type="text/javascript" src="../js/myplayer.min.js"></script>
<link rel="stylesheet" href="../css/myplayer.css" />
<script type="text/javascript">$(function(){MyPlayer({
mode: 'mp3url',
mp3url: './snd/'
})});</script>
</head>
<body>
<noscript>
Javascript is required to use the MP3 player.
Please choose of the alternatives listed below.
</noscript>
</body>
</html>

24
demo/network.html Normal file
View File

@ -0,0 +1,24 @@
<html>
<head>
<base href="." />
<title>MyPlayer M3U With Streams Demo</title>
<script type="text/javascript" src="../js/jquery.js"></script>
<script type="text/javascript" src="../js/myplayer.min.js"></script>
<link rel="stylesheet" href="../css/myplayer.css" />
<script type="text/javascript">$(function(){MyPlayer({
mode: 'm3u',
m3u: './snd/network.m3u',
network: true
})});</script>
</head>
<body>
<noscript>
Javascript is required to use the MP3 player.
Please choose of the alternatives listed below.
</noscript>
</body>
</html>

10
demo/php/.htaccess Normal file
View File

@ -0,0 +1,10 @@
RewriteEngine on
# (as suggested by www.zeilenwechsel.de)
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond $1#%{REQUEST_URI} ([^#]*)#(.*)\1$
RewriteRule ^(.*)$ %2index.php/$1 [QSA,L]

View File

@ -0,0 +1,7 @@
<?php
$waveform = array(
'snddir' => dirname(__FILE__).'/../../snd',
'cachedir' => dirname(__FILE__).'/../../tmp'
);

View File

@ -0,0 +1,18 @@
<?php
function fatal_error($msg, $status = '505 Internal Server Error') {
header('Status: '.$status);
echo $msg."\n";
return 1;
}
function sanitize_path_request($path_info) {
return preg_replace(
array('|^/|', '/[^A-Za-z0-9\-\.]/'),
array('', ''),
$path_info
);
}

View File

@ -0,0 +1,5 @@
<?php
require_once('config.inc.php');
require_once('functions.inc.php');

32
demo/php/index.php Normal file
View File

@ -0,0 +1,32 @@
<?php
set_include_path(dirname(__FILE__).'/include');
require_once('init.inc.php');
$path = sanitize_path_request($_SERVER['PATH_INFO']);
$cachefile = $waveform['cachedir'].'/'.sha1($path);
$mp3file = $waveform['snddir'].'/'.$path;
if(!is_file($mp3file))
exit(fatal_error("Error: requested file $mp3file not found"));
if(!file_exists($cachefile)) {
$cmdline = 'waveform draw "'.$mp3file.'" "'.$cachefile.'" 0 -1';
$system_rv = null;
system($cmdline, $system_rv);
if($system_rv!=0) {
if(file_Exists($cachefile))
unlink($cachefile);
exit(fatal_error('Error: generating the waveform diagram failed'));
}
}
header('Content-type: image/jpeg');
echo file_get_contents($cachefile);

23
demo/relative-m3u.html Normal file
View File

@ -0,0 +1,23 @@
<html>
<head>
<base href="." />
<title>MyPlayer M3U (Relative Entries) Demo</title>
<script type="text/javascript" src="../js/jquery.js"></script>
<script type="text/javascript" src="../js/myplayer.min.js"></script>
<link rel="stylesheet" href="../css/myplayer.css" />
<script type="text/javascript">$(function(){MyPlayer({
mode: 'm3u',
m3u: './snd/relative.m3u'
})});</script>
</head>
<body>
<noscript>
Javascript is required to use the MP3 player.
Please choose of the alternatives listed below.
</noscript>
</body>
</html>

3
demo/snd/.htaccess Normal file
View File

@ -0,0 +1,3 @@
Options +Indexes
AddType audio/ogg .ogg
AddType audio/mpeg .mp3

BIN
demo/snd/dreamz.mp3 Executable file

Binary file not shown.

5
demo/snd/network.m3u Normal file
View File

@ -0,0 +1,5 @@
#EXTM3U
#EXTINF:-1,NoLife-radio
http://37.187.79.56:2868/stream
#EXTINF:-1,ZaycevFM (128k)
http://radio.zaycev.fm:8999/ZaycevFM(128)

3
demo/snd/play.extm3u Normal file
View File

@ -0,0 +1,3 @@
#EXTM3U
#EXTINF:59, tilt - Dreamz
dreamz.mp3

1
demo/snd/play.m3u Normal file
View File

@ -0,0 +1 @@
snd/dreamz.mp3

1
demo/snd/relative.m3u Normal file
View File

@ -0,0 +1 @@
dreamz.mp3

24
demo/stream-m3u.html Normal file
View File

@ -0,0 +1,24 @@
<html>
<head>
<base href="." />
<title>MyPlayer M3U With Streams Demo</title>
<script type="text/javascript" src="../js/jquery.js"></script>
<script type="text/javascript" src="../js/myplayer.min.js"></script>
<link rel="stylesheet" href="../css/myplayer.css" />
<script type="text/javascript">$(function(){MyPlayer({
mode: 'm3u',
m3u: './snd/streaming.m3u',
filematch: /./
})});</script>
</head>
<body>
<noscript>
Javascript is required to use the MP3 player.
Please choose of the alternatives listed below.
</noscript>
</body>
</html>

24
demo/types.html Normal file
View File

@ -0,0 +1,24 @@
<html>
<head>
<base href="." />
<title>MyPlayer types Demo</title>
<script type="text/javascript" src="../js/jquery.js"></script>
<script type="text/javascript" src="../js/myplayer.min.js"></script>
<link rel="stylesheet" href="../css/myplayer.css" />
<script type="text/javascript">$(function(){MyPlayer({
mode: 'm3u',
m3u: './snd/play.m3u',
types: ['ogg']
})});</script>
</head>
<body>
<noscript>
Javascript is required to use the MP3 player.
Please choose of the alternatives listed below.
</noscript>
</body>
</html>

27
demo/waveform.html Normal file
View File

@ -0,0 +1,27 @@
<html>
<head>
<base href="." />
<title>MyPlayer M3U Demo</title>
<script type="text/javascript" src="../js/jquery.js"></script>
<script type="text/javascript" src="../js/myplayer.min.js"></script>
<link rel="stylesheet" href="../css/myplayer.css" />
<script type="text/javascript">$(function(){MyPlayer({
mode: 'list',
waveform: true,
list: [
{ url: './snd/dreamz.mp3',
title: 'tilt - Dreamz' }
]
})});</script>
</head>
<body>
<noscript>
Javascript is required to use the MP3 player.
Please choose of the alternatives listed below.
</noscript>
</body>
</html>

44
index.html Normal file
View File

@ -0,0 +1,44 @@
<html>
<head>
<title>MyPlayer - An Audio Player for the Web with Playlist and ID3 Support</title>
<link rel="stylesheet" href="css/index.css">
</head>
<body>
<div class="home"><a href="http://tk-sls.de">//tk-sls.de</a></div>
<h1>&nbsp;MyPlayer</h1>
<p>An audio player (mp3, ogg) for the web with M3U-playlist and ID3-support.</p>
<p>Based on mediaelement.js. MIT-licensed. Cooks coffee (almost).</p>
<h2>About:</h2>
<p>This project provides a JavaScript constructor <tt>MyPlayer({...options...})</tt> that can be used
to embed lists of audio files as read from an index document or an M3U into a web document.</p>
<p>They will be displayed in a playback GUI with a playlist that can optionally be filled
from the "title" and "artist" values of the files' ID3 tags (v1 and v2 are supported).</p>
<p>The player is "detachable", meaning the user can open it in a new window,
preventing that playback breaks when the user leaves the page.</p>
<h2>Resources:</h2>
<p>Documentation &amp; Examples: <a href="demo/index.html">demo/index.html</a></p>
<p>Current release is: 11-20-2015</p>
<p>Download URL (latest tarball): <a title="MyPlayer Download (.tar.gz)" href="http://tk-sls.de/ref/myplayer.dist.tar.gz">http://tk-sls.de/ref/myplayer.dist.tar.gz</a></p>
<p>Project website: <a title="MyPlayer Project Website" href="http://tk-sls.de/ref/myplayer/">http://tk-sls.de/ref/myplayer/</a></p>
<h2>Additional Reading:</h2>
<p>License: <a href="LICENSE.txt">MIT</a>.</p>
<p>See <a href="README.txt">README.txt</a> for further information.</p>
<h2>Author Contact:</h2>
<p>Please send questions to: tilt at linuxfoo dot de</p>
</body>
</html>

9597
js/jquery.js vendored Normal file

File diff suppressed because it is too large Load Diff

231
js/myplayer.min.js vendored Normal file
View File

@ -0,0 +1,231 @@
/*
jQuery
Copyright 2014 jQuery Foundation and other contributors
http://jquery.com/
MediaElement.js
Copyright 2010-2013, John Dyer (http://j.hn)
MediaElement Playlist Feature (plugin) -
Andrew Berezovsky <andrew.berezovsky@gmail.com>
and Junaid Qadir Baloch <shekhanzai.baloch@gmail.com>
JavaScript-ID3-Reader
Copyright (c) 2008 Jacob Seidelin, http://blog.nihilogic.dk/ BSD License
Copyright (c) 2009 Opera Software ASA BSD License
Copyright (c) 2010 António Afonso BSD License
Copyright (c) 2010 Joshua Kifer BSD License
MyPlayer
Copyright (c) 2014 tilt@linuxfoo.de MIT License
*/
var mejs=mejs||{};mejs.version="2.18.2";mejs.meIndex=0;
mejs.plugins={silverlight:[{version:[3,0],types:"video/mp4 video/m4v video/mov video/wmv audio/wma audio/m4a audio/mp3 audio/wav audio/mpeg".split(" ")}],flash:[{version:[9,0,124],types:"video/mp4 video/m4v video/mov video/flv video/rtmp video/x-flv audio/flv audio/x-flv audio/mp3 audio/m4a audio/mpeg video/youtube video/x-youtube video/dailymotion video/x-dailymotion application/x-mpegURL".split(" ")}],youtube:[{version:null,types:["video/youtube","video/x-youtube","audio/youtube","audio/x-youtube"]}],
vimeo:[{version:null,types:["video/vimeo","video/x-vimeo"]}]};
mejs.Utility={encodeUrl:function(c){return encodeURIComponent(c)},escapeHTML:function(c){return c.toString().split("&").join("&amp;").split("<").join("&lt;").split('"').join("&quot;")},absolutizeUrl:function(c){var a=document.createElement("div");return a.innerHTML='<a href="'+this.escapeHTML(c)+'">x</a>',a.firstChild.href},getScriptPath:function(c){for(var a,b,f,e,d,g=0,h="",k="",l=document.getElementsByTagName("script"),n=l.length,m=c.length;n>g;g++){f=l[g].src;a=f.lastIndexOf("/");-1<a?(d=f.substring(a+
1),e=f.substring(0,a+1)):(d=f,e="");for(a=0;m>a;a++)if(k=c[a],b=d.indexOf(k),-1<b){h=e;break}if(""!==h)break}return h},calculateTimeFormat:function(c,a,b){0>c&&(c=0);"undefined"==typeof b&&(b=25);var f=a.timeFormat,e=f[0],d=f[1]==f[0],g=d?2:1,h=":",k=Math.floor(c/3600)%24,l=Math.floor(c/60)%60,n=Math.floor(c%60);c=[[Math.floor((c%1*b).toFixed(3)),"f"],[n,"s"],[l,"m"],[k,"h"]];f.length<g&&(h=f[g]);g=!1;b=0;for(k=c.length;k>b;b++)if(-1!==f.indexOf(c[b][1]))g=!0;else if(g){l=!1;for(n=b;k>n;n++)if(0<
c[n][0]){l=!0;break}if(!l)break;d||(f=e+f);f=c[b][1]+h+f;d&&(f=c[b][1]+f);e=c[b][1]}a.currentTimeFormat=f},twoDigitsString:function(c){return 10>c?"0"+c:String(c)},secondsToTimeCode:function(c,a,b,f){if(0>c&&(c=0),"object"!=typeof a)a=a?"hh:mm:ss":"m:ss",a={currentTimeFormat:b?a+":ff":a,framesPerSecond:f||25};b=a.framesPerSecond;"undefined"==typeof b&&(b=25);a=a.currentTimeFormat;f=Math.floor(c/3600)%24;var e=Math.floor(c/60)%60,d=Math.floor(c%60);lis=[[Math.floor((c%1*b).toFixed(3)),"f"],[d,"s"],
[e,"m"],[f,"h"]];c=a;i=0;for(len=lis.length;i<len;i++)c=c.replace(lis[i][1]+lis[i][1],this.twoDigitsString(lis[i][0])),c=c.replace(lis[i][1],lis[i][0]);return c},timeCodeToSeconds:function(c,a,b,f){"undefined"==typeof b?b=!1:"undefined"==typeof f&&(f=25);c=c.split(":");a=parseInt(c[0],10);var e=parseInt(c[1],10),d=parseInt(c[2],10),g=0;return b&&(g=parseInt(c[3])/f),3600*a+60*e+d+g},convertSMPTEtoSeconds:function(c){if("string"!=typeof c)return!1;c=c.replace(",",".");var a=0,b=-1!=c.indexOf(".")?
c.split(".")[1].length:0,f=1;c=c.split(":").reverse();for(var e=0;e<c.length;e++)f=1,0<e&&(f=Math.pow(60,e)),a+=Number(c[e])*f;return Number(a.toFixed(b))},removeSwf:function(c){var a=document.getElementById(c);a&&/object|embed/i.test(a.nodeName)&&(mejs.MediaFeatures.isIE?(a.style.display="none",function(){4==a.readyState?mejs.Utility.removeObjectInIE(c):setTimeout(arguments.callee,10)}()):a.parentNode.removeChild(a))},removeObjectInIE:function(c){if(c=document.getElementById(c)){for(var a in c)"function"==
typeof c[a]&&(c[a]=null);c.parentNode.removeChild(c)}}};
mejs.PluginDetector={hasPluginVersion:function(c,a){var b=this.plugins[c];return a[1]=a[1]||0,a[2]=a[2]||0,b[0]>a[0]||b[0]==a[0]&&b[1]>a[1]||b[0]==a[0]&&b[1]==a[1]&&b[2]>=a[2]?!0:!1},nav:window.navigator,ua:window.navigator.userAgent.toLowerCase(),plugins:[],addPlugin:function(c,a,b,f,e){this.plugins[c]=this.detectPlugin(a,b,f,e)},detectPlugin:function(c,a,b,f){var e,d,g=[0,0,0];if("undefined"!=typeof this.nav.plugins&&"object"==typeof this.nav.plugins[c]){if(e=this.nav.plugins[c].description,e&&
("undefined"==typeof this.nav.mimeTypes||!this.nav.mimeTypes[a]||this.nav.mimeTypes[a].enabledPlugin))for(g=e.replace(c,"").replace(/^\s+/,"").replace(/\sr/gi,".").split("."),c=0;c<g.length;c++)g[c]=parseInt(g[c].match(/\d+/),10)}else if("undefined"!=typeof window.ActiveXObject)try{(d=new ActiveXObject(b))&&(g=f(d))}catch(h){}return g}};
mejs.PluginDetector.addPlugin("flash","Shockwave Flash","application/x-shockwave-flash","ShockwaveFlash.ShockwaveFlash",function(c){var a=[];c=c.GetVariable("$version");return c&&(c=c.split(" ")[1].split(","),a=[parseInt(c[0],10),parseInt(c[1],10),parseInt(c[2],10)]),a});
mejs.PluginDetector.addPlugin("silverlight","Silverlight Plug-In","application/x-silverlight-2","AgControl.AgControl",function(c){var a=[0,0,0,0],b=function(a,b,d,c){for(;a.isVersionSupported(b[0]+"."+b[1]+"."+b[2]+"."+b[3]);)b[d]+=c;b[d]-=c};return b(c,a,0,1),b(c,a,1,1),b(c,a,2,1E4),b(c,a,2,1E3),b(c,a,2,100),b(c,a,2,10),b(c,a,2,1),b(c,a,3,1),a});
mejs.MediaFeatures={init:function(){var c,a,b=this,f=document;c=mejs.PluginDetector.nav;var e=mejs.PluginDetector.ua.toLowerCase(),d=["source","track","audio","video"];b.isiPad=null!==e.match(/ipad/i);b.isiPhone=null!==e.match(/iphone/i);b.isiOS=b.isiPhone||b.isiPad;b.isAndroid=null!==e.match(/android/i);b.isBustedAndroid=null!==e.match(/android 2\.[12]/);b.isBustedNativeHTTPS="https:"===location.protocol&&(null!==e.match(/android [12]\./)||null!==e.match(/macintosh.* version.* safari/));b.isIE=-1!=
c.appName.toLowerCase().indexOf("microsoft")||null!==c.appName.toLowerCase().match(/trident/gi);b.isChrome=null!==e.match(/chrome/gi);b.isChromium=null!==e.match(/chromium/gi);b.isFirefox=null!==e.match(/firefox/gi);b.isWebkit=null!==e.match(/webkit/gi);b.isGecko=null!==e.match(/gecko/gi)&&!b.isWebkit&&!b.isIE;b.isOpera=null!==e.match(/opera/gi);b.hasTouch="ontouchstart"in window;b.svg=!!document.createElementNS&&!!document.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect;for(c=0;c<
d.length;c++)a=document.createElement(d[c]);b.supportsMediaTag="undefined"!=typeof a.canPlayType||b.isBustedAndroid;try{a.canPlayType("video/mp4")}catch(g){b.supportsMediaTag=!1}b.hasSemiNativeFullScreen="undefined"!=typeof a.webkitEnterFullscreen;b.hasNativeFullscreen="undefined"!=typeof a.requestFullscreen;b.hasWebkitNativeFullScreen="undefined"!=typeof a.webkitRequestFullScreen;b.hasMozNativeFullScreen="undefined"!=typeof a.mozRequestFullScreen;b.hasMsNativeFullScreen="undefined"!=typeof a.msRequestFullscreen;
b.hasTrueNativeFullScreen=b.hasWebkitNativeFullScreen||b.hasMozNativeFullScreen||b.hasMsNativeFullScreen;b.nativeFullScreenEnabled=b.hasTrueNativeFullScreen;b.hasMozNativeFullScreen?b.nativeFullScreenEnabled=document.mozFullScreenEnabled:b.hasMsNativeFullScreen&&(b.nativeFullScreenEnabled=document.msFullscreenEnabled);b.isChrome&&(b.hasSemiNativeFullScreen=!1);b.hasTrueNativeFullScreen&&(b.fullScreenEventName="",b.hasWebkitNativeFullScreen?b.fullScreenEventName="webkitfullscreenchange":b.hasMozNativeFullScreen?
b.fullScreenEventName="mozfullscreenchange":b.hasMsNativeFullScreen&&(b.fullScreenEventName="MSFullscreenChange"),b.isFullScreen=function(){return b.hasMozNativeFullScreen?f.mozFullScreen:b.hasWebkitNativeFullScreen?f.webkitIsFullScreen:b.hasMsNativeFullScreen?null!==f.msFullscreenElement:void 0},b.requestFullScreen=function(a){b.hasWebkitNativeFullScreen?a.webkitRequestFullScreen():b.hasMozNativeFullScreen?a.mozRequestFullScreen():b.hasMsNativeFullScreen&&a.msRequestFullscreen()},b.cancelFullScreen=
function(){b.hasWebkitNativeFullScreen?document.webkitCancelFullScreen():b.hasMozNativeFullScreen?document.mozCancelFullScreen():b.hasMsNativeFullScreen&&document.msExitFullscreen()});b.hasSemiNativeFullScreen&&e.match(/mac os x 10_5/i)&&(b.hasNativeFullScreen=!1,b.hasSemiNativeFullScreen=!1)}};mejs.MediaFeatures.init();
mejs.HtmlMediaElement={pluginType:"native",isFullScreen:!1,setCurrentTime:function(c){this.currentTime=c},setMuted:function(c){this.muted=c},setVolume:function(c){this.volume=c},stop:function(){this.pause()},setSrc:function(c){for(var a=this.getElementsByTagName("source");0<a.length;)this.removeChild(a[0]);if("string"==typeof c)this.src=c;else for(var b,a=0;a<c.length;a++)if(b=c[a],this.canPlayType(b.type)){this.src=b.src;break}},setVideoSize:function(c,a){this.width=c;this.height=a}};
mejs.PluginMediaElement=function(c,a,b){this.id=c;this.pluginType=a;this.src=b;this.events={};this.attributes={}};
mejs.PluginMediaElement.prototype={pluginElement:null,pluginType:"",isFullScreen:!1,playbackRate:-1,defaultPlaybackRate:-1,seekable:[],played:[],paused:!0,ended:!1,seeking:!1,duration:0,error:null,tagName:"",muted:!1,volume:1,currentTime:0,play:function(){null!=this.pluginApi&&("youtube"==this.pluginType||"vimeo"==this.pluginType?this.pluginApi.playVideo():this.pluginApi.playMedia(),this.paused=!1)},load:function(){null!=this.pluginApi&&("youtube"==this.pluginType||"vimeo"==this.pluginType||this.pluginApi.loadMedia(),
this.paused=!1)},pause:function(){null!=this.pluginApi&&("youtube"==this.pluginType||"vimeo"==this.pluginType?this.pluginApi.pauseVideo():this.pluginApi.pauseMedia(),this.paused=!0)},stop:function(){null!=this.pluginApi&&("youtube"==this.pluginType||"vimeo"==this.pluginType?this.pluginApi.stopVideo():this.pluginApi.stopMedia(),this.paused=!0)},canPlayType:function(c){var a,b,f,e=mejs.plugins[this.pluginType];for(a=0;a<e.length;a++)if(f=e[a],mejs.PluginDetector.hasPluginVersion(this.pluginType,f.version))for(b=
0;b<f.types.length;b++)if(c==f.types[b])return"probably";return""},positionFullscreenButton:function(c,a,b){null!=this.pluginApi&&this.pluginApi.positionFullscreenButton&&this.pluginApi.positionFullscreenButton(Math.floor(c),Math.floor(a),b)},hideFullscreenButton:function(){null!=this.pluginApi&&this.pluginApi.hideFullscreenButton&&this.pluginApi.hideFullscreenButton()},setSrc:function(c){if("string"==typeof c)this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(c)),this.src=mejs.Utility.absolutizeUrl(c);
else{var a,b;for(a=0;a<c.length;a++)if(b=c[a],this.canPlayType(b.type)){this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(b.src));this.src=mejs.Utility.absolutizeUrl(b.src);break}}},setCurrentTime:function(c){null!=this.pluginApi&&("youtube"==this.pluginType||"vimeo"==this.pluginType?this.pluginApi.seekTo(c):this.pluginApi.setCurrentTime(c),this.currentTime=c)},setVolume:function(c){null!=this.pluginApi&&("youtube"==this.pluginType?this.pluginApi.setVolume(100*c):this.pluginApi.setVolume(c),this.volume=
c)},setMuted:function(c){null!=this.pluginApi&&("youtube"==this.pluginType?(c?this.pluginApi.mute():this.pluginApi.unMute(),this.muted=c,this.dispatchEvent({type:"volumechange"})):this.pluginApi.setMuted(c),this.muted=c)},setVideoSize:function(c,a){this.pluginElement&&this.pluginElement.style&&(this.pluginElement.style.width=c+"px",this.pluginElement.style.height=a+"px");null!=this.pluginApi&&this.pluginApi.setVideoSize&&this.pluginApi.setVideoSize(c,a)},setFullscreen:function(c){null!=this.pluginApi&&
this.pluginApi.setFullscreen&&this.pluginApi.setFullscreen(c)},enterFullScreen:function(){null!=this.pluginApi&&this.pluginApi.setFullscreen&&this.setFullscreen(!0)},exitFullScreen:function(){null!=this.pluginApi&&this.pluginApi.setFullscreen&&this.setFullscreen(!1)},addEventListener:function(c,a,b){this.events[c]=this.events[c]||[];this.events[c].push(a)},removeEventListener:function(c,a){if(!c)return this.events={},!0;var b=this.events[c];if(!b)return!0;if(!a)return this.events[c]=[],!0;for(var f=
0;f<b.length;f++)if(b[f]===a)return this.events[c].splice(f,1),!0;return!1},dispatchEvent:function(c){var a,b=this.events[c.type];if(b)for(a=0;a<b.length;a++)b[a].apply(this,[c])},hasAttribute:function(c){return c in this.attributes},removeAttribute:function(c){delete this.attributes[c]},getAttribute:function(c){return this.hasAttribute(c)?this.attributes[c]:""},setAttribute:function(c,a){this.attributes[c]=a},remove:function(){mejs.Utility.removeSwf(this.pluginElement.id);mejs.MediaPluginBridge.unregisterPluginElement(this.pluginElement.id)}};
mejs.MediaPluginBridge={pluginMediaElements:{},htmlMediaElements:{},registerPluginElement:function(c,a,b){this.pluginMediaElements[c]=a;this.htmlMediaElements[c]=b},unregisterPluginElement:function(c){delete this.pluginMediaElements[c];delete this.htmlMediaElements[c]},initPlugin:function(c){var a=this.pluginMediaElements[c],b=this.htmlMediaElements[c];if(a){switch(a.pluginType){case "flash":a.pluginElement=a.pluginApi=document.getElementById(c);break;case "silverlight":a.pluginElement=document.getElementById(a.id),
a.pluginApi=a.pluginElement.Content.MediaElementJS}null!=a.pluginApi&&a.success&&a.success(a,b)}},fireEvent:function(c,a,b){var f,e;if(c=this.pluginMediaElements[c]){a={type:a,target:c};for(f in b)c[f]=b[f],a[f]=b[f];e=b.bufferedTime||0;a.target.buffered=a.buffered={start:function(a){return 0},end:function(a){return e},length:1};c.dispatchEvent(a)}}};
mejs.MediaElementDefaults={mode:"auto",plugins:["flash","silverlight","youtube","vimeo"],enablePluginDebug:!1,httpsBasicAuthSite:!1,type:"",pluginPath:mejs.Utility.getScriptPath(["mediaelement.js","mediaelement.min.js","mediaelement-and-player.js","mediaelement-and-player.min.js"]),flashName:"flashmediaelement.swf",flashStreamer:"",flashScriptAccess:"sameDomain",enablePluginSmoothing:!1,enablePseudoStreaming:!1,pseudoStreamingStartQueryParam:"start",silverlightName:"silverlightmediaelement.xap",defaultVideoWidth:480,
defaultVideoHeight:270,pluginWidth:-1,pluginHeight:-1,pluginVars:[],timerRate:250,startVolume:.8,success:function(){},error:function(){}};mejs.MediaElement=function(c,a){return mejs.HtmlMediaElementShim.create(c,a)};
mejs.HtmlMediaElementShim={create:function(c,a){var b,f,e={},d="string"==typeof c?document.getElementById(c):c,g=d.tagName.toLowerCase(),h=(g="audio"===g||"video"===g)?d.getAttribute("src"):d.getAttribute("href"),k=d.getAttribute("poster"),l=d.getAttribute("autoplay"),n=d.getAttribute("preload"),m=d.getAttribute("controls");for(f in mejs.MediaElementDefaults)e[f]=mejs.MediaElementDefaults[f];for(f in a)e[f]=a[f];return h="undefined"==typeof h||null===h||""==h?null:h,k="undefined"==typeof k||null===
k?"":k,n="undefined"==typeof n||null===n||"false"===n?"none":n,l=!("undefined"==typeof l||null===l||"false"===l),m=!("undefined"==typeof m||null===m||"false"===m),b=this.determinePlayback(d,e,mejs.MediaFeatures.supportsMediaTag,g,h),b.url=null!==b.url?mejs.Utility.absolutizeUrl(b.url):"","native"==b.method?(mejs.MediaFeatures.isBustedAndroid&&(d.src=b.url,d.addEventListener("click",function(){d.play()},!1)),this.updateNative(b,e,l,n)):""!==b.method?this.createPlugin(b,e,k,l,n,m):(this.createErrorMessage(b,
e,k),this)},determinePlayback:function(c,a,b,f,e){var d,g,h,k,l,n,m=[],p={method:"",url:"",htmlMediaElement:c,isVideo:"audio"!=c.tagName.toLowerCase()};if("undefined"!=typeof a.type&&""!==a.type)if("string"==typeof a.type)m.push({type:a.type,url:e});else for(d=0;d<a.type.length;d++)m.push({type:a.type[d],url:e});else if(null!==e)h=this.formatType(e,c.getAttribute("type")),m.push({type:h,url:e});else for(d=0;d<c.childNodes.length;d++)g=c.childNodes[d],1==g.nodeType&&"source"==g.tagName.toLowerCase()&&
(e=g.getAttribute("src"),h=this.formatType(e,g.getAttribute("type")),n=g.getAttribute("media"),(!n||!window.matchMedia||window.matchMedia&&window.matchMedia(n).matches)&&m.push({type:h,url:e}));if(!f&&0<m.length&&null!==m[0].url&&-1<this.getTypeFromFile(m[0].url).indexOf("audio")&&(p.isVideo=!1),mejs.MediaFeatures.isBustedAndroid&&(c.canPlayType=function(a){return null!==a.match(/video\/(mp4|m4v)/gi)?"maybe":""}),mejs.MediaFeatures.isChromium&&(c.canPlayType=function(a){return null!==a.match(/video\/(webm|ogv|ogg)/gi)?
"maybe":""}),!(!b||"auto"!==a.mode&&"auto_plugin"!==a.mode&&"native"!==a.mode||mejs.MediaFeatures.isBustedNativeHTTPS&&!0===a.httpsBasicAuthSite)){f||(l=document.createElement(p.isVideo?"video":"audio"),c.parentNode.insertBefore(l,c),c.style.display="none",p.htmlMediaElement=c=l);for(d=0;d<m.length;d++)if("video/m3u8"==m[d].type||""!==c.canPlayType(m[d].type).replace(/no/,"")||""!==c.canPlayType(m[d].type.replace(/mp3/,"mpeg")).replace(/no/,"")||""!==c.canPlayType(m[d].type.replace(/m4a/,"mp4")).replace(/no/,
"")){p.method="native";p.url=m[d].url;break}if("native"===p.method&&(null!==p.url&&(c.src=p.url),"auto_plugin"!==a.mode))return p}if("auto"===a.mode||"auto_plugin"===a.mode||"shim"===a.mode)for(d=0;d<m.length;d++)for(h