Añadir playlist a la web y la letra a las canciones

This commit is contained in:
Ales (Shagi) Zabala Alava 2018-10-14 20:52:05 +02:00
parent 97ef33c529
commit d872d6fe97
157 changed files with 40940 additions and 2446 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
/cajonDesastre
/bideoak/home
/bideoak/playlist
/bideoak/static

View File

@ -19,8 +19,123 @@
</head>
<body>
<header id="header">
<h1><a href="/">Negro Mate</a></h1>
<h1><a href="/home/">Negro Mate</a></h1>
</header>
<div id="content">
<h1>404</h1>
<p><b>Original:</b> La 204, Zikatriz</p>
<video id="404-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/404/404.jpg">
<source src="/404/404.mp4" type='video/mp4'>
<track kind="captions" src="/404/404.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<script>
videojs('404-video', {
/*
plugins: {
ass: {
'src': ["/404/404.ass"],
// videoWidth: 640,
// videoHeight: 360,
enableSvg: false,
}
},
*/
});
</script>
<p class="lyrics">
Tengo un 404<br/>
en el navegador<br/>
fotos, audios, videos, documentos<br/>
todo voló<br/>
veo carpetas vacías<br/>
con nada en su interior<br/>
piensas que coño ha pasado<br/>
buscas algo quedará<br/>
tenía un mazo de cosas<br/>
flipas, con lo que perdí<br/>
buscas alguien que se enrolle<br/>
para bajar algo de él<br/>
y me han jodido<br/>
me han jodido bien<br/>
y me han jodido<br/>
bien jodido!<br/>
sientes una pena muy fuerte<br/>
cuando ya no esta allí<br/>
y es por culpa de ese backup<br/>
que nunca llegué a hacer<br/>
y me han jodido<br/>
y me han jodido bien<br/>
y me han jodido<br/>
y me han jodido bien!<br/>
y me han jodido<br/>
y me han jodido bien<br/>
y me han jodido<br/>
por tenerlo ahi subido!<br/>
</p>
<ul class="files">
<li><a href="/404/404.mp4">404.mp4</a></li>
<li><a href="/404/404.srt">404.srt</a></li>
<li><a href="/404/404.ass">404.ass</a></li>
</ul>
</div>
<nav id="menu">
<ul>
@ -80,56 +195,6 @@
<p id="playlist"><a href="/playlist/">Playlist</a></p>
<p id="libreto"><a href="/static/libreto/libreto.pdf"><img src="/static/libreto/libreto.png">Libreto</a>
</nav>
<div id="content">
<h1>404</h1>
<p><b>Original:</b> La 204, Zikatriz</p>
<video id="404-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/404/404.jpg">
<source src="/404/404.mp4" type='video/mp4'>
<track kind="captions" src="/404/404.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<ul class="files">
<li><a href="/404/404.mp4">404.mp4</a></li>
<li><a href="/404/404.srt">404.srt</a></li>
<li><a href="/404/404.ass">404.ass</a></li>
</ul>
<script>
videojs('404-video', {
/*
plugins: {
ass: {
'src': ["/404/404.ass"],
// videoWidth: 640,
// videoHeight: 360,
enableSvg: false,
}
},
*/
});
</script>
</div>
</body>
</html>

View File

@ -19,8 +19,183 @@
</head>
<body>
<header id="header">
<h1><a href="/">Negro Mate</a></h1>
<h1><a href="/home/">Negro Mate</a></h1>
</header>
<div id="content">
<h1>Mala persona</h1>
<p><b>Autoría:</b> Autodefensa Informática</p>
<video id="Autodefensa_Informatica_Mala_persona-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/Autodefensa_Informatica_Mala_persona/Autodefensa_Informatica_Mala_persona.jpg">
<source src="/Autodefensa_Informatica_Mala_persona/Autodefensa_Informatica_Mala_persona.ogv" type='video/ogg'>
<track kind="captions" src="/Autodefensa_Informatica_Mala_persona/Autodefensa_Informatica_Mala_persona.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<script>
videojs('Autodefensa_Informatica_Mala_persona-video', {
/*
plugins: {
ass: {
'src': ["/Autodefensa_Informatica_Mala_persona/Autodefensa_Informatica_Mala_persona.ass"],
// videoWidth: 640,
// videoHeight: 360,
enableSvg: false,
}
},
*/
});
</script>
<p class="lyrics">
Autodefensa Informática - Mala persona<br/>
En la celda de castigo de una cárcel de un presidio de un penaooo<br/>
Estoy cumpliendo condena, estoy sufriendo una pena<br/>
Que es la ausencia de mi libertaaaaaaaa<br/>
Yo, un hombre tranquilo que no envía spam a sus amigos<br/>
(Poropopó)<br/>
Porque soy consciente y online protejo mi privacidad<br/>
(Poropopó)<br/>
¡No uso Facebook, Google ni Whatsaaaaaapp!<br/>
Más, al encender mi linux tras un largo día de curreleooo<br/>
(Poropopó)<br/>
Un amigo mío me envió un correo que me dió un mareoooo<br/>
(Poropopó)<br/>
¡A su Facebook me quería invitaaaar!<br/>
Sólo porque lo borré, con presteza y con espanto, de la lista de contactos y en sus muelas me cagué!<br/>
¡Me llaman mala personaaaa!<br/>
¡Me llaman mala personaaaa!<br/>
¡Me llaman mala personaaaa!<br/>
Y es que yo, no uso Facebook nunca jamás<br/>
No uso Whatsapp ni Google Plus<br/>
No uso Windows uso Debiáaaaan<br/>
¡Y tengo cuenta en RiseUp!<br/>
Pues yo quedé un día con un amigo para charlar<br/>
(Poropopó)<br/>
Le pitaba el móvil, no le paraban de llegar whatsapps<br/>
(Poropopó)<br/>
Y los nervios me crispó a reventaaaaar!<br/>
Pues, yo le dije al tipo que lo apagara, muy buen rollero<br/>
(Poropopó)<br/>
Y me dijo &#34;Pisha, que esto es de un grupo de Hipsters Poperos&#34;<br/>
(Poropopó)<br/>
Y a la mierda lo tuve que de mandaaaaar!!<br/>
Sólo por decirle basta, me cagüen tí y en el Whatsapp, y en sus grupos y en sus farsas, no te enteras que te quieren controlar!<br/>
¡Me llaman mala personaaaa!<br/>
¡Me llaman mala personaaaa!<br/>
¡Me llaman mala personaaaa!<br/>
Y es que yo, no uso Facebook nunca jamás<br/>
No uso Whatsapp ni Google Plus<br/>
No uso Windows uso Debiáaaaan<br/>
¡Y tengo cuenta en RiseUp!<br/>
Yo, que no tengo Windows, no uso Gmail ni tampoco Hangouts,<br/>
(Poropopó)<br/>
Porque soy consciente y online protejo mi privacidad<br/>
(Poropopó)<br/>
No uso Facebook, Google ni Whatsaaaaaap!<br/>
Más, al llegar a casa en la puerta había cien mil maderos<br/>
(IBAN TÓ PUESTOS, IBAN TÓ PUESTOS)<br/>
De ser terrorista me acusaban a mí los muy pendejos<br/>
(Poropopó)<br/>
Y a la trena me fuí a paraaaaar!!!<br/>
Sólo porque no seré, un demócrata bocazas, que farfulla y que se cansa, con su sempiterno mantra, &#34;Que me espíen, yo no tengo ná que esconder&#34;<br/>
¡Me llaman mala personaaaa!<br/>
¡Me llaman mala personaaaa!<br/>
¡Me llaman mala personaaaa!<br/>
Y es que yo, no uso Facebook nunca jamás<br/>
No uso Whatsapp ni Google Plus<br/>
No uso Windows uso Debiáaaaan<br/>
¡Y tengo cuenta en RiseUp!<br/>
</p>
<ul class="files">
<li><a href="/Autodefensa_Informatica_Mala_persona/Autodefensa_Informatica_Mala_persona.ass">Autodefensa_Informatica_Mala_persona.ass</a></li>
<li><a href="/Autodefensa_Informatica_Mala_persona/Autodefensa_Informatica_Mala_persona.srt">Autodefensa_Informatica_Mala_persona.srt</a></li>
<li><a href="/Autodefensa_Informatica_Mala_persona/Autodefensa_Informatica_Mala_persona.ogv">Autodefensa_Informatica_Mala_persona.ogv</a></li>
</ul>
</div>
<nav id="menu">
<ul>
@ -80,56 +255,6 @@
<p id="playlist"><a href="/playlist/">Playlist</a></p>
<p id="libreto"><a href="/static/libreto/libreto.pdf"><img src="/static/libreto/libreto.png">Libreto</a>
</nav>
<div id="content">
<h1>Mala persona</h1>
<p><b>Autoría:</b> Autodefensa Informática</p>
<video id="Autodefensa_Informatica_Mala_persona-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/Autodefensa_Informatica_Mala_persona/Autodefensa_Informatica_Mala_persona.jpg">
<source src="/Autodefensa_Informatica_Mala_persona/Autodefensa_Informatica_Mala_persona.ogv" type='video/ogg'>
<track kind="captions" src="/Autodefensa_Informatica_Mala_persona/Autodefensa_Informatica_Mala_persona.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<ul class="files">
<li><a href="/Autodefensa_Informatica_Mala_persona/Autodefensa_Informatica_Mala_persona.ass">Autodefensa_Informatica_Mala_persona.ass</a></li>
<li><a href="/Autodefensa_Informatica_Mala_persona/Autodefensa_Informatica_Mala_persona.srt">Autodefensa_Informatica_Mala_persona.srt</a></li>
<li><a href="/Autodefensa_Informatica_Mala_persona/Autodefensa_Informatica_Mala_persona.ogv">Autodefensa_Informatica_Mala_persona.ogv</a></li>
</ul>
<script>
videojs('Autodefensa_Informatica_Mala_persona-video', {
/*
plugins: {
ass: {
'src': ["/Autodefensa_Informatica_Mala_persona/Autodefensa_Informatica_Mala_persona.ass"],
// videoWidth: 640,
// videoHeight: 360,
enableSvg: false,
}
},
*/
});
</script>
</div>
</body>
</html>

Binary file not shown.

View File

@ -19,8 +19,157 @@
</head>
<body>
<header id="header">
<h1><a href="/">Negro Mate</a></h1>
<h1><a href="/home/">Negro Mate</a></h1>
</header>
<div id="content">
<h1>A quién le importa</h1>
<p><b>Original:</b> A quién le importa, Alaska</p>
<video id="a_quien_le_importa-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/a_quien_le_importa/a_quien_le_importa.jpg">
<source src="/a_quien_le_importa/a_quien_le_importa.webm" type='video/webm'>
<track kind="captions" src="/a_quien_le_importa/a_quien_le_importa.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<script>
videojs('a_quien_le_importa-video', {
/*
plugins: {
ass: {
'src': ["/a_quien_le_importa/a_quien_le_importa.ass"],
// videoWidth: 640,
// videoHeight: 360,
enableSvg: false,
}
},
*/
});
</script>
<p class="lyrics">
La gente me señala<br/>
me critica, me taguea<br/>
en el facebook y en el insta<br/>
y a mi me importa un bledo<br/>
Que más me da<br/>
lo que haya en esas redes<br/>
todos son mierdas y comerciales<br/>
ya sé que me critican<br/>
me consta que me espían<br/>
la vida te corroen<br/>
tu intimidad destrozan<br/>
no aceptaré yo esas conciciones<br/>
yo montaré mis propias redes<br/>
mi destino es federar<br/>
usuarios y encriptar<br/>
lo que hablan entre sí<br/>
A quién le importa lo que yo haga<br/>
a quién le importa lo que yo escriba<br/>
yo uso tor, tails instalaré<br/>
no me espiaréis<br/>
A quién le importa lo que yo haga<br/>
a quién le importa lo que yo escriba<br/>
yo uso tor, tails instalaré<br/>
no me espiaréis<br/>
Quiza la culpa es mia<br/>
por aceptar la eula<br/>
pero es que nunca es tarde<br/>
para cambiar las cosas<br/>
puedes empezar quitándote de google<br/>
y siendo fiel a tus servidores<br/>
mi destino es federar<br/>
usuarios y encriptar<br/>
lo que hablan entre sí<br/>
A quién le importa lo que yo haga<br/>
a quién le importa lo que yo escriba<br/>
yo uso tor, tails instalaré<br/>
no me espiaréis<br/>
A quién le importa lo que yo haga<br/>
a quién le importa lo que yo escriba<br/>
yo uso tor, tails instalaré<br/>
no me espiaréis<br/>
A quién le importa lo que yo haga<br/>
a quién le importa lo que yo escriba<br/>
yo uso tor, tails instalaré<br/>
no me espiaréis<br/>
</p>
<ul class="files">
<li><a href="/a_quien_le_importa/a_quien_le_importa.ass">a_quien_le_importa.ass</a></li>
<li><a href="/a_quien_le_importa/a_quien_le_importa.webm">a_quien_le_importa.webm</a></li>
<li><a href="/a_quien_le_importa/a_quien_le_importa.srt">a_quien_le_importa.srt</a></li>
</ul>
</div>
<nav id="menu">
<ul>
@ -80,56 +229,6 @@
<p id="playlist"><a href="/playlist/">Playlist</a></p>
<p id="libreto"><a href="/static/libreto/libreto.pdf"><img src="/static/libreto/libreto.png">Libreto</a>
</nav>
<div id="content">
<h1>A quién le importa</h1>
<p><b>Original:</b> A quién le importa, Alaska</p>
<video id="a_quien_le_importa-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/a_quien_le_importa/a_quien_le_importa.jpg">
<source src="/a_quien_le_importa/a_quien_le_importa.webm" type='video/webm'>
<track kind="captions" src="/a_quien_le_importa/a_quien_le_importa.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<ul class="files">
<li><a href="/a_quien_le_importa/a_quien_le_importa.ass">a_quien_le_importa.ass</a></li>
<li><a href="/a_quien_le_importa/a_quien_le_importa.webm">a_quien_le_importa.webm</a></li>
<li><a href="/a_quien_le_importa/a_quien_le_importa.srt">a_quien_le_importa.srt</a></li>
</ul>
<script>
videojs('a_quien_le_importa-video', {
/*
plugins: {
ass: {
'src': ["/a_quien_le_importa/a_quien_le_importa.ass"],
// videoWidth: 640,
// videoHeight: 360,
enableSvg: false,
}
},
*/
});
</script>
</div>
</body>
</html>

View File

@ -19,8 +19,107 @@
</head>
<body>
<header id="header">
<h1><a href="/">Negro Mate</a></h1>
<h1><a href="/home/">Negro Mate</a></h1>
</header>
<div id="content">
<h1>Anónimo instalador</h1>
<p><b>Original:</b> No hay tregua, Barricada</p>
<p><b>Autoría:</b> Negro Mate, Xavieros</p>
<video id="anonimo_instalador-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/anonimo_instalador/anonimo_instalador.jpg">
<source src="/anonimo_instalador/anonimo_instalador.mp4" type='video/mp4'>
<track kind="captions" src="/anonimo_instalador/anonimo_instalador.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<script>
videojs('anonimo_instalador-video', {
/*
plugins: {
ass: {
'src': ["/anonimo_instalador/anonimo_instalador.ass"],
// videoWidth: 640,
// videoHeight: 360,
enableSvg: false,
}
},
*/
});
</script>
<p class="lyrics">
Viene el movil con google instalado<br/>
Tus mejores datos en sus server están<br/>
no es muy difícil de evitar<br/>
puedes empezar con Line-a-ge<br/>
Ahí está la salida!<br/>
Estas asustado, la garantía va en ello<br/>
pero alguien debe quitar spywares<br/>
Tu maldito movil nuevo<br/>
te lo venden con backdoors<br/>
ese móvil va con Android<br/>
tu lo has de liberar!<br/>
Anónimo instalador<br/>
nunca tendrá google tu control<br/>
porque cuando se aprende a rootear el móvil<br/>
también se aprende a liberarlo!<br/>
Estas asustado, la garantía va en ello<br/>
pero alguien debe quitar spywares<br/>
Estas asustado, la garantía va en ello<br/>
pero alguien debe quitar spywares<br/>
</p>
<ul class="files">
<li><a href="/anonimo_instalador/anonimo_instalador.ass">anonimo_instalador.ass</a></li>
<li><a href="/anonimo_instalador/anonimo_instalador.mp4">anonimo_instalador.mp4</a></li>
<li><a href="/anonimo_instalador/anonimo_instalador.srt">anonimo_instalador.srt</a></li>
</ul>
</div>
<nav id="menu">
<ul>
@ -80,58 +179,6 @@
<p id="playlist"><a href="/playlist/">Playlist</a></p>
<p id="libreto"><a href="/static/libreto/libreto.pdf"><img src="/static/libreto/libreto.png">Libreto</a>
</nav>
<div id="content">
<h1>Anónimo instalador</h1>
<p><b>Original:</b> No hay tregua, Barricada</p>
<p><b>Autoría:</b> Negro Mate, Xavieros</p>
<video id="anonimo_instalador-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/anonimo_instalador/anonimo_instalador.jpg">
<source src="/anonimo_instalador/anonimo_instalador.mp4" type='video/mp4'>
<track kind="captions" src="/anonimo_instalador/anonimo_instalador.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<ul class="files">
<li><a href="/anonimo_instalador/anonimo_instalador.ass">anonimo_instalador.ass</a></li>
<li><a href="/anonimo_instalador/anonimo_instalador.mp4">anonimo_instalador.mp4</a></li>
<li><a href="/anonimo_instalador/anonimo_instalador.srt">anonimo_instalador.srt</a></li>
</ul>
<script>
videojs('anonimo_instalador-video', {
/*
plugins: {
ass: {
'src': ["/anonimo_instalador/anonimo_instalador.ass"],
// videoWidth: 640,
// videoHeight: 360,
enableSvg: false,
}
},
*/
});
</script>
</div>
</body>
</html>

View File

@ -19,8 +19,122 @@
</head>
<body>
<header id="header">
<h1><a href="/">Negro Mate</a></h1>
<h1><a href="/home/">Negro Mate</a></h1>
</header>
<div id="content">
<h1>Autosuficiencia</h1>
<p><b>Original:</b> Autosuficiencia, Parálisis permanente</p>
<video id="autosuficiencia-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/autosuficiencia/autosuficiencia.jpg">
<source src="/autosuficiencia/autosuficiencia.mp4" type='video/mp4'>
<track kind="captions" src="/autosuficiencia/autosuficiencia.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<script>
videojs('autosuficiencia-video', {
/*
plugins: {
},
*/
});
</script>
<p class="lyrics">
me miro en el espejo y soy feliz<br/>
y no pienso nunca mas que en wikileaks<br/>
y no pienso nunca mas que en wikileaks<br/>
leo emilios que anonymous filtro<br/>
oigo cintas que el gobierbo oculto<br/>
oigo cintas que el gobierno oculto<br/>
encerrado en la embajada<br/>
todo me da igual<br/>
ya no necesito a nadie<br/>
no saldre jamas<br/>
#FIXME<br/>
me tumbo en el suelo de mi habitación<br/>
buscando sensores y microfonos<br/>
encerrado en la embajada<br/>
todo me da igual<br/>
ya no necesito a nadie<br/>
no saldre jamas<br/>
ahora soy un heroe viviente<br/>
ya no necesito gente<br/>
ya soy autosuficiente al fin<br/>
me miro en el espejo y soy feliz<br/>
y no pienso nunca en nadie mas que en wikileaks<br/>
leo emilios que anonymous filtro<br/>
oigo cintas que el gobierno oculto<br/>
encerrado en la embajada<br/>
todo me da igual<br/>
ya no necesito a nadie<br/>
no saldre jamas<br/>
ahora soy un heroe viviente<br/>
ya no necesito gente<br/>
ya soy autosuficiente al fin<br/>
Me miro en el espejo y soy feliz<br/>
</p>
<ul class="files">
<li><a href="/autosuficiencia/autosuficiencia.srt">autosuficiencia.srt</a></li>
<li><a href="/autosuficiencia/autosuficiencia.mp4">autosuficiencia.mp4</a></li>
</ul>
</div>
<nav id="menu">
<ul>
@ -80,47 +194,6 @@
<p id="playlist"><a href="/playlist/">Playlist</a></p>
<p id="libreto"><a href="/static/libreto/libreto.pdf"><img src="/static/libreto/libreto.png">Libreto</a>
</nav>
<div id="content">
<h1>Autosuficiencia</h1>
<p><b>Original:</b> Autosuficiencia, Parálisis permanente</p>
<video id="autosuficiencia-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/autosuficiencia/autosuficiencia.jpg">
<source src="/autosuficiencia/autosuficiencia.mp4" type='video/mp4'>
<track kind="captions" src="/autosuficiencia/autosuficiencia.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<ul class="files">
<li><a href="/autosuficiencia/autosuficiencia.srt">autosuficiencia.srt</a></li>
<li><a href="/autosuficiencia/autosuficiencia.mp4">autosuficiencia.mp4</a></li>
</ul>
<script>
videojs('autosuficiencia-video', {
/*
plugins: {
},
*/
});
</script>
</div>
</body>
</html>

View File

@ -19,8 +19,127 @@
</head>
<body>
<header id="header">
<h1><a href="/">Negro Mate</a></h1>
<h1><a href="/home/">Negro Mate</a></h1>
</header>
<div id="content">
<h1>Debian Samba</h1>
<p><b>Original:</b> La bamba, Richie Valens</p>
<video id="debianSamba-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/debianSamba/debianSamba.jpg">
<source src="/debianSamba/debianSamba.mp4" type='video/mp4'>
<track kind="captions" src="/debianSamba/debianSamba.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<script>
videojs('debianSamba-video', {
/*
plugins: {
ass: {
'src': ["/debianSamba/debianSamba.ass"],
// videoWidth: 640,
// videoHeight: 360,
enableSvg: false,
}
},
*/
});
</script>
<p class="lyrics">
Para instalar la Debian<br/>
Para instalar la Debian<br/>
Se necesita un CD una memoria<br/>
Un CD una memoria<br/>
si la red no tira<br/>
Si la red no tira<br/>
Que tipo de memoria<br/>
USB USB USB<br/>
Yo no soy windowsero<br/>
yo no soy windowsero<br/>
ni uso mac, ni uso mac ni uso mac<br/>
Debian Debian<br/>
Debian Debian<br/>
Para instalar la Debian<br/>
Para instalar la Debian<br/>
Se necesita un CD una memoria<br/>
Un CD una memoria si la red no tira<br/>
si la red no tira<br/>
Para instalar la Debian<br/>
Para instalar la Debian<br/>
se necesita un CD una memoria<br/>
un CD una memoria<br/>
si la red no tira<br/>
si la red no tira<br/>
Qué tipo de memoria<br/>
USB USB USB<br/>
Debian Debian<br/>
Debian Debian<br/>
Debian Debian<br/>
Debian Debian<br/>
</p>
<ul class="files">
<li><a href="/debianSamba/debianSamba.ass">debianSamba.ass</a></li>
<li><a href="/debianSamba/debianSamba.srt">debianSamba.srt</a></li>
<li><a href="/debianSamba/debianSamba.mp4">debianSamba.mp4</a></li>
</ul>
</div>
<nav id="menu">
<ul>
@ -80,56 +199,6 @@
<p id="playlist"><a href="/playlist/">Playlist</a></p>
<p id="libreto"><a href="/static/libreto/libreto.pdf"><img src="/static/libreto/libreto.png">Libreto</a>
</nav>
<div id="content">
<h1>Debian Samba</h1>
<p><b>Original:</b> La bamba, Richie Valens</p>
<video id="debianSamba-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/debianSamba/debianSamba.jpg">
<source src="/debianSamba/debianSamba.mp4" type='video/mp4'>
<track kind="captions" src="/debianSamba/debianSamba.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<ul class="files">
<li><a href="/debianSamba/debianSamba.srt">debianSamba.srt</a></li>
<li><a href="/debianSamba/debianSamba.mp4">debianSamba.mp4</a></li>
<li><a href="/debianSamba/debian samba.ass">debian samba.ass</a></li>
</ul>
<script>
videojs('debianSamba-video', {
/*
plugins: {
ass: {
'src': ["/debianSamba/debian samba.ass"],
// videoWidth: 640,
// videoHeight: 360,
enableSvg: false,
}
},
*/
});
</script>
</div>
</body>
</html>

View File

@ -19,8 +19,126 @@
</head>
<body>
<header id="header">
<h1><a href="/">Negro Mate</a></h1>
<h1><a href="/home/">Negro Mate</a></h1>
</header>
<div id="content">
<h1>En verde y negro</h1>
<p><b>Original:</b> Blanco y negro, Barricada</p>
<video id="en_verde_y_negro-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/en_verde_y_negro/en_verde_y_negro.jpg">
<source src="/en_verde_y_negro/en_verde_y_negro.mp4" type='video/mp4'>
<track kind="captions" src="/en_verde_y_negro/en_verde_y_negro.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<script>
videojs('en_verde_y_negro-video', {
/*
plugins: {
},
*/
});
</script>
<p class="lyrics">
Veo todo en verde y negro<br/>
man bash acaba siendo amigo mudo<br/>
las mismas teclas, todo son sustos<br/>
en el vimtuto o o or <br/>
quiero ser un hacker de la hostia<br/>
hacerlo todo en la shell, un día tras otro<br/>
y un buen rato después poder llegar a casa<br/>
sin usar el ratón, tecleando todo el día<br/>
Tengo tiempo para aprender, hoy la red parece distinta<br/>
durante horas puedo ser capaz<br/>
de romper claves, conectarme para esnifar<br/>
aprendiendo en cada esquina<br/>
solo quiero ser un hacker de la hostia<br/>
acceder otra vez, a todos sus servers<br/>
y un buen rato despues saber llegar a ser root<br/>
chuparles los datos y joderles de por vida.<br/>
Casi nunca sé donde estoy<br/>
no me importa el sistema, ni la ubicación,<br/>
me preguntaré, que coño hay aquí<br/>
dispuesto a buscar un proxy si hace falta,<br/>
porque sé que el tor me anonimiza<br/>
combate al gran hermano<br/>
veo todo en verde y negro, verde y negro.<br/>
Sé que el tor me anonimiza<br/>
combate al gran hermano<br/>
veo todo en verde y negro...<br/>
Solo quiero ser, un hacker de la hostia<br/>
siempre poder tener, contenidos libres<br/>
y el software también, un grupo de gente<br/>
liberando la red, construyendo en anarquía<br/>
Solo quiero ser, un hacker de la hostia<br/>
siempre poder tener, contenidos libres<br/>
y el software también, un grupo de gente<br/>
liberando la red, construyendo en anarquía<br/>
</p>
<ul class="files">
<li><a href="/en_verde_y_negro/en_verde_y_negro.srt">en_verde_y_negro.srt</a></li>
<li><a href="/en_verde_y_negro/en_verde_y_negro.mp4">en_verde_y_negro.mp4</a></li>
</ul>
</div>
<nav id="menu">
<ul>
@ -80,47 +198,6 @@
<p id="playlist"><a href="/playlist/">Playlist</a></p>
<p id="libreto"><a href="/static/libreto/libreto.pdf"><img src="/static/libreto/libreto.png">Libreto</a>
</nav>
<div id="content">
<h1>En verde y negro</h1>
<p><b>Original:</b> Blanco y negro, Barricada</p>
<video id="en_verde_y_negro-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/en_verde_y_negro/en_verde_y_negro.jpg">
<source src="/en_verde_y_negro/en_verde_y_negro.mp4" type='video/mp4'>
<track kind="captions" src="/en_verde_y_negro/en_verde_y_negro.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<ul class="files">
<li><a href="/en_verde_y_negro/en_verde_y_negro.srt">en_verde_y_negro.srt</a></li>
<li><a href="/en_verde_y_negro/en_verde_y_negro.mp4">en_verde_y_negro.mp4</a></li>
</ul>
<script>
videojs('en_verde_y_negro-video', {
/*
plugins: {
},
*/
});
</script>
</div>
</body>
</html>

View File

@ -19,8 +19,80 @@
</head>
<body>
<header id="header">
<h1><a href="/">Negro Mate</a></h1>
<h1><a href="/home/">Negro Mate</a></h1>
</header>
<div id="content">
<h1>GNU es un acrónimo</h1>
<p><b>Original:</b> Txus, La Polla Records</p>
<video id="gnu_Es_un_acronimo-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/gnu_Es_un_acronimo/gnu_Es_un_acronimo.jpg">
<source src="/gnu_Es_un_acronimo/gnu_Es_un_acronimo.mp4" type='video/mp4'>
<track kind="captions" src="/gnu_Es_un_acronimo/gnu_Es_un_acronimo.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<script>
videojs('gnu_Es_un_acronimo-video', {
/*
plugins: {
},
*/
});
</script>
<p class="lyrics">
GNU es un acronimo gnu esta compuesto<br/>
tiene todo iniciales es un nombre corto y recursivo<br/>
linux no puede ser eso no hay quien lo aguante<br/>
tiene que llevar el gnu por delante<br/>
bill esta furioso bill no esta contento<br/>
alguien va a tumbar su imperio<br/>
se monta una charla, stallman anda suelto<br/>
va a empezar la charla, corre!<br/>
en su repo hay parches de la peña<br/>
Bill no flipes tanto<br/>
vamos a tumbarlo<br/>
</p>
<ul class="files">
<li><a href="/gnu_Es_un_acronimo/gnu_Es_un_acronimo.mp4">gnu_Es_un_acronimo.mp4</a></li>
<li><a href="/gnu_Es_un_acronimo/gnu_Es_un_acronimo.srt">gnu_Es_un_acronimo.srt</a></li>
</ul>
</div>
<nav id="menu">
<ul>
@ -80,47 +152,6 @@
<p id="playlist"><a href="/playlist/">Playlist</a></p>
<p id="libreto"><a href="/static/libreto/libreto.pdf"><img src="/static/libreto/libreto.png">Libreto</a>
</nav>
<div id="content">
<h1>GNU es un acrónimo</h1>
<p><b>Original:</b> Txus, La Polla Records</p>
<video id="gnu_Es_un_acronimo-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/gnu_Es_un_acronimo/gnu_Es_un_acronimo.jpg">
<source src="/gnu_Es_un_acronimo/gnu_Es_un_acronimo.mp4" type='video/mp4'>
<track kind="captions" src="/gnu_Es_un_acronimo/gnu_Es_un_acronimo.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<ul class="files">
<li><a href="/gnu_Es_un_acronimo/gnu_Es_un_acronimo.mp4">gnu_Es_un_acronimo.mp4</a></li>
<li><a href="/gnu_Es_un_acronimo/gnu_Es_un_acronimo.srt">gnu_Es_un_acronimo.srt</a></li>
</ul>
<script>
videojs('gnu_Es_un_acronimo-video', {
/*
plugins: {
},
*/
});
</script>
</div>
</body>
</html>

View File

@ -19,8 +19,86 @@
</head>
<body>
<header id="header">
<h1><a href="/">Negro Mate</a></h1>
<h1><a href="/home/">Negro Mate</a></h1>
</header>
<div id="content">
<h1>GNU es un acrónimo</h1>
<p><b>Original:</b> Txus, Kojón Prieto</p>
<video id="gnu_Kojonprieto-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/gnu_Kojonprieto/gnu_Kojonprieto.jpg">
<source src="/gnu_Kojonprieto/gnu_Kojonprieto.mp4" type='video/mp4'>
<track kind="captions" src="/gnu_Kojonprieto/gnu_Kojonprieto.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<script>
videojs('gnu_Kojonprieto-video', {
/*
plugins: {
},
*/
});
</script>
<p class="lyrics">
GNU es un acronimo gnu esta compuesto<br/>
tiene todo iniciales es un nombre corto y recursivo<br/>
linux no puede ser eso no hay quien lo aguante<br/>
tiene que llevar el gnu por delante<br/>
bill esta furioso bill no esta contento<br/>
alguien va a tumbar su imperio<br/>
se monta una charla, stallman anda suelto<br/>
va a empezar la charla, corre!<br/>
Bill no flipes tanto, vamos a tumbarlo<br/>
en su repo hay parches de la peña<br/>
Bill no flipes tanto, vamos a tumbarlo<br/>
Vamos a tumbarlo,<br/>
¡VAMOS A TUMBARLO!<br/>
Bill no flipes tanto, vamos a tumbarlo<br/>
</p>
<ul class="files">
<li><a href="/gnu_Kojonprieto/gnu_Kojonprieto.srt">gnu_Kojonprieto.srt</a></li>
<li><a href="/gnu_Kojonprieto/gnu_Kojonprieto.mp4">gnu_Kojonprieto.mp4</a></li>
</ul>
</div>
<nav id="menu">
<ul>
@ -80,47 +158,6 @@
<p id="playlist"><a href="/playlist/">Playlist</a></p>
<p id="libreto"><a href="/static/libreto/libreto.pdf"><img src="/static/libreto/libreto.png">Libreto</a>
</nav>
<div id="content">
<h1>GNU es un acrónimo</h1>
<p><b>Original:</b> Txus, Kojón Prieto</p>
<video id="gnu_Kojonprieto-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/gnu_Kojonprieto/gnu_Kojonprieto.jpg">
<source src="/gnu_Kojonprieto/gnu_Kojonprieto.mp4" type='video/mp4'>
<track kind="captions" src="/gnu_Kojonprieto/gnu_Kojonprieto.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<ul class="files">
<li><a href="/gnu_Kojonprieto/gnu_Kojonprieto.srt">gnu_Kojonprieto.srt</a></li>
<li><a href="/gnu_Kojonprieto/gnu_Kojonprieto.mp4">gnu_Kojonprieto.mp4</a></li>
</ul>
<script>
videojs('gnu_Kojonprieto-video', {
/*
plugins: {
},
*/
});
</script>
</div>
</body>
</html>

View File

@ -0,0 +1,168 @@
1
00:00:01,200 --> 00:00:03,960
la licencia GPL
2
00:00:10,200 --> 00:00:12,960
aprendimos a quererte
3
00:00:12,960 --> 00:00:15,960
con tu emacs y tus manias
4
00:00:15,760 --> 00:00:17,800
en el MIT una impresora
5
00:00:17,800 --> 00:00:21,360
dio comienzo a esta historia
6
00:00:21,360 --> 00:00:24,360
así se forja la senda,
7
00:00:24,360 --> 00:00:27,360
de la libertad duradera
8
00:00:26,960 --> 00:00:29,240
de tu querida licencia
9
00:00:29,240 --> 00:00:32,000
la licencia GPL
10
00:00:32,000 --> 00:00:35,000
de tu querida licencia
11
00:00:35,000 --> 00:00:38,000
la licencia GPL
12
00:00:44,000 --> 00:00:47,000
la free software foundation
13
00:00:47,100 --> 00:00:50,200
el copyleft instauraba
14
00:00:50,000 --> 00:00:52,000
para un código elegante
15
00:00:52,000 --> 00:00:55,000
de libertad asegurada
16
00:00:55,100 --> 00:00:57,200
así se forja la senda,
17
00:00:57,000 --> 00:01:00,100
de la libertad duradera
18
00:01:00,100 --> 00:01:03,240
de tu querida licencia
19
00:01:03,240 --> 00:01:05,960
la licencia GPL
20
00:01:06,480 --> 00:01:08,960
de tu querida licencia
21
00:01:09,000 --> 00:01:11,960
la licencia GPL
22
00:01:35,320 --> 00:01:37,960
aprendimos a quererte
23
00:01:38,000 --> 00:01:40,400
con tu emacs y tus manias
24
00:01:40,100 --> 00:01:42,960
en el MIT una impresora
25
00:01:43,000 --> 00:01:45,960
dio comienzo a esta historia
26
00:01:45,960 --> 00:01:48,960
seguiremos programando
27
00:01:48,960 --> 00:01:51,720
lineas como descosidas
28
00:01:51,720 --> 00:01:54,260
copiando, modificando
29
00:01:54,260 --> 00:01:57,240
compartiendo nuestras lineas
30
00:01:57,240 --> 00:01:59,440
así se forja la senda,
31
00:02:00,240 --> 00:02:02,440
de la libertad duradera
32
00:02:02,440 --> 00:02:05,200
por tu querida licencia
33
00:02:05,200 --> 00:02:08,200
la licencia GPL
34
00:02:08,300 --> 00:02:10,700
por tu querida licencia
35
00:02:10,800 --> 00:02:13,700
la licencia GPL
36
00:02:13,800 --> 00:02:15,400
la licencia
37
00:02:16,500 --> 00:02:18,160
la licencia
38
00:02:19,600 --> 00:02:21,160
la licencia
39
00:02:25,400 --> 00:02:27,400
GPL
40
00:03:00,000 --> 00:03:02,400
GPL
41
00:03:05,100 --> 00:03:06,000
aupa GPL
42
00:03:06,000 --> 00:03:07,400
aupa el copyleft

View File

@ -0,0 +1,127 @@
WEBVTT
00:00:01.200 --> 00:00:03.960
la licencia GPL
00:00:10.200 --> 00:00:12.960
aprendimos a quererte
00:00:12.960 --> 00:00:15.960
con tu emacs y tus manias
00:00:15.760 --> 00:00:17.800
en el MIT una impresora
00:00:17.800 --> 00:00:21.360
dio comienzo a esta historia
00:00:21.360 --> 00:00:24.360
así se forja la senda,
00:00:24.360 --> 00:00:27.360
de la libertad duradera
00:00:26.960 --> 00:00:29.240
de tu querida licencia
00:00:29.240 --> 00:00:32.000
la licencia GPL
00:00:32.000 --> 00:00:35.000
de tu querida licencia
00:00:35.000 --> 00:00:38.000
la licencia GPL
00:00:44.000 --> 00:00:47.000
la free software foundation
00:00:47.100 --> 00:00:50.200
el copyleft instauraba
00:00:50.000 --> 00:00:52.000
para un código elegante
00:00:52.000 --> 00:00:55.000
de libertad asegurada
00:00:55.100 --> 00:00:57.200
así se forja la senda,
00:00:57.000 --> 00:01:00.100
de la libertad duradera
00:01:00.100 --> 00:01:03.240
de tu querida licencia
00:01:03.240 --> 00:01:05.960
la licencia GPL
00:01:06.480 --> 00:01:08.960
de tu querida licencia
00:01:09.000 --> 00:01:11.960
la licencia GPL
00:01:35.320 --> 00:01:37.960
aprendimos a quererte
00:01:38.000 --> 00:01:40.400
con tu emacs y tus manias
00:01:40.100 --> 00:01:42.960
en el MIT una impresora
00:01:43.000 --> 00:01:45.960
dio comienzo a esta historia
00:01:45.960 --> 00:01:48.960
seguiremos programando
00:01:48.960 --> 00:01:51.720
lineas como descosidas
00:01:51.720 --> 00:01:54.260
copiando, modificando
00:01:54.260 --> 00:01:57.240
compartiendo nuestras lineas
00:01:57.240 --> 00:01:59.440
así se forja la senda,
00:02:00.240 --> 00:02:02.440
de la libertad duradera
00:02:02.440 --> 00:02:05.200
por tu querida licencia
00:02:05.200 --> 00:02:08.200
la licencia GPL
00:02:08.300 --> 00:02:10.700
por tu querida licencia
00:02:10.800 --> 00:02:13.700
la licencia GPL
00:02:13.800 --> 00:02:15.400
la licencia
00:02:16.500 --> 00:02:18.160
la licencia
00:02:19.600 --> 00:02:21.160
la licencia
00:02:25.400 --> 00:02:27.400
GPL
00:03:00.000 --> 00:03:02.400
GPL
00:03:05.100 --> 00:03:06.000
aupa GPL
00:03:06.000 --> 00:03:07.400
aupa el copyleft

View File

@ -19,8 +19,153 @@
</head>
<body>
<header id="header">
<h1><a href="/">Negro Mate</a></h1>
<h1><a href="/home/">Negro Mate</a></h1>
</header>
<div id="content">
<h1>Hasta siempre GPL</h1>
<p><b>Original:</b> Hasta siempre comandante, Boikot</p>
<p><b>Autoría:</b> Negro Mate, Carlos</p>
<video id="hastasiempreGPL-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/hastasiempreGPL/hastasiempreGPL.jpg">
<source src="/hastasiempreGPL/hastasiempreGPL.mp4" type='video/mp4'>
<track kind="captions" src="/hastasiempreGPL/hastasiempreGPL.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<script>
videojs('hastasiempreGPL-video', {
/*
plugins: {
ass: {
'src': ["/hastasiempreGPL/hastasiempreGPL.ass"],
// videoWidth: 640,
// videoHeight: 360,
enableSvg: false,
}
},
*/
});
</script>
<p class="lyrics">
la licencia GPL<br/>
aprendimos a quererte<br/>
con tu emacs y tus manias<br/>
en el MIT una impresora<br/>
dio comienzo a esta historia<br/>
así se forja la senda,<br/>
de la libertad duradera<br/>
de tu querida licencia<br/>
la licencia GPL<br/>
de tu querida licencia<br/>
la licencia GPL<br/>
la free software foundation<br/>
el copyleft instauraba<br/>
para un código elegante<br/>
de libertad asegurada<br/>
así se forja la senda,<br/>
de la libertad duradera<br/>
de tu querida licencia<br/>
la licencia GPL<br/>
de tu querida licencia<br/>
la licencia GPL<br/>
aprendimos a quererte<br/>
con tu emacs y tus manias<br/>
en el MIT una impresora<br/>
dio comienzo a esta historia<br/>
seguiremos programando<br/>
lineas como descosidas<br/>
copiando, modificando<br/>
compartiendo nuestras lineas<br/>
así se forja la senda,<br/>
de la libertad duradera<br/>
por tu querida licencia<br/>
la licencia GPL<br/>
por tu querida licencia<br/>
la licencia GPL<br/>
la licencia<br/>
la licencia<br/>
la licencia<br/>
GPL<br/>
GPL<br/>
aupa GPL<br/>
aupa el copyleft<br/>
</p>
<ul class="files">
<li><a href="/hastasiempreGPL/hastasiempreGPL.mp4">hastasiempreGPL.mp4</a></li>
<li><a href="/hastasiempreGPL/hastasiempreGPL.srt">hastasiempreGPL.srt</a></li>
<li><a href="/hastasiempreGPL/hastasiempreGPL.ass">hastasiempreGPL.ass</a></li>
</ul>
</div>
<nav id="menu">
<ul>
@ -80,47 +225,6 @@
<p id="playlist"><a href="/playlist/">Playlist</a></p>
<p id="libreto"><a href="/static/libreto/libreto.pdf"><img src="/static/libreto/libreto.png">Libreto</a>
</nav>
<div id="content">
<h1>Hasta siempre GPL</h1>
<p><b>Original:</b> Hasta siempre comandante, Boikot</p>
<p><b>Autoría:</b> Negro Mate, Carlos</p>
<video id="hastasiempreGPL-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/hastasiempreGPL/hastasiempreGPL.jpg">
<source src="/hastasiempreGPL/hastasiempreGPL.mp4" type='video/mp4'>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<ul class="files">
<li><a href="/hastasiempreGPL/hastasiempreGPL.ssa">hastasiempreGPL.ssa</a></li>
<li><a href="/hastasiempreGPL/hastasiempreGPL.mp4">hastasiempreGPL.mp4</a></li>
</ul>
<script>
videojs('hastasiempreGPL-video', {
/*
plugins: {
},
*/
});
</script>
</div>
</body>
</html>

View File

@ -19,8 +19,131 @@
</head>
<body>
<header id="header">
<h1><a href="/">Negro Mate</a></h1>
<h1><a href="/home/">Negro Mate</a></h1>
</header>
<div id="content">
<h1>He probado todos los linux</h1>
<p><b>Original:</b> El tractor amarillo, Zapato Veloz</p>
<video id="he_probado_todos_los_linux-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/he_probado_todos_los_linux/he_probado_todos_los_linux.jpg">
<source src="/he_probado_todos_los_linux/he_probado_todos_los_linux.mp4" type='video/mp4'>
<track kind="captions" src="/he_probado_todos_los_linux/he_probado_todos_los_linux.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<script>
videojs('he_probado_todos_los_linux-video', {
/*
plugins: {
ass: {
'src': ["/he_probado_todos_los_linux/he_probado_todos_los_linux.ass"],
// videoWidth: 640,
// videoHeight: 360,
enableSvg: false,
}
},
*/
});
</script>
<p class="lyrics">
me miraste con ojos de gacela<br/>
cuando viste el awesome en mi sistema<br/>
me pusiste cara de pantera<br/>
cuando viste que el raton era una mierda<br/>
sabes bien, que soy un sysadmin<br/>
y conozco mejor como funciona<br/>
cuando llegue el proximo upgrade<br/>
lloraras, si no tienes estable<br/>
he probado todos los linux<br/>
y me quedo con la debian<br/>
he probado todos los linux<br/>
y la debian es la pera<br/>
hay que usar la debian<br/>
que es la mas libre de todas<br/>
tienes paquete anarka<br/>
y se organiza en asamblea<br/>
que sea de pago y de multinacional<br/>
tu prefieres un sistema comercial<br/>
que tenga soporte ultra premium<br/>
y por llamar te cobren un dineral<br/>
pero yo que conozco el sistema<br/>
y se lo que vale la comunidad<br/>
que son los que hacen, y usan los programas<br/>
y saben una barbaridad<br/>
he probado todos los linux<br/>
y me quedo con la debian<br/>
he probado todos los linux<br/>
y la debian es la pera<br/>
hay que usar la debian<br/>
que es la mas libre de todas<br/>
tiene paquete anarka<br/>
y se organiza en asamblea<br/>
</p>
<ul class="files">
<li><a href="/he_probado_todos_los_linux/he_probado_todos_los_linux.mp4">he_probado_todos_los_linux.mp4</a></li>
<li><a href="/he_probado_todos_los_linux/he_probado_todos_los_linux.ass">he_probado_todos_los_linux.ass</a></li>
<li><a href="/he_probado_todos_los_linux/he_probado_todos_los_linux.srt">he_probado_todos_los_linux.srt</a></li>
</ul>
</div>
<nav id="menu">
<ul>
@ -80,56 +203,6 @@
<p id="playlist"><a href="/playlist/">Playlist</a></p>
<p id="libreto"><a href="/static/libreto/libreto.pdf"><img src="/static/libreto/libreto.png">Libreto</a>
</nav>
<div id="content">
<h1>He probado todos los linux</h1>
<p><b>Original:</b> El tractor amarillo, Zapato Veloz</p>
<video id="he_probado_todos_los_linux-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/he_probado_todos_los_linux/he_probado_todos_los_linux.jpg">
<source src="/he_probado_todos_los_linux/he_probado_todos_los_linux.mp4" type='video/mp4'>
<track kind="captions" src="/he_probado_todos_los_linux/he_probado_todos_los_linux.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<ul class="files">
<li><a href="/he_probado_todos_los_linux/he_probado_todos_los_linux.mp4">he_probado_todos_los_linux.mp4</a></li>
<li><a href="/he_probado_todos_los_linux/he_probado_todos_los_linux.ass">he_probado_todos_los_linux.ass</a></li>
<li><a href="/he_probado_todos_los_linux/he_probado_todos_los_linux.srt">he_probado_todos_los_linux.srt</a></li>
</ul>
<script>
videojs('he_probado_todos_los_linux-video', {
/*
plugins: {
ass: {
'src': ["/he_probado_todos_los_linux/he_probado_todos_los_linux.ass"],
// videoWidth: 640,
// videoHeight: 360,
enableSvg: false,
}
},
*/
});
</script>
</div>
</body>
</html>

View File

@ -1,273 +1,38 @@
<!DOCTYPE html>
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>Negro Mate</title>
<link href="/static/js/videojs/video-js.css" rel="stylesheet">
<link href="/static/js/libjass/lib/libjass.css" rel="stylesheet">
<link href="/static/js/videojs-playlist-ui/dist/videojs-playlist-ui.vertical.css" rel="stylesheet">
<link href="/static/css/main.css" rel="stylesheet">
<script>
window.HELP_IMPROVE_VIDEOJS = false;
</script>
<script src="/static/js/videojs/video.js"></script>
<script src="/static/js/libjass/lib/libjass.js"></script>
<script src="/static/js/videojs-playlist/dist/videojs-playlist.js"></script>
<script src="/static/js/videojs-playlist-ui/dist/videojs-playlist-ui.js"></script>
<script src="/static/js/videojs-ass/src/videojs.ass.js"></script>
</head>
<body>
<header id="header">
<h1><a href="/">Negro Mate</a></h1>
</header>
<nav id="menu">
<ul>
<li><a href="/mas_commits">Más commits</a></li>
<li><a href="/yoquierosermakero">Yo quiero ser makero</a></li>
<li><a href="/salve">Salve</a></li>
<li><a href="/en_verde_y_negro">En verde y negro</a></li>
<li><a href="/debianSamba">Debian Samba</a></li>
<li><a href="/hastasiempreGPL">Hasta siempre GPL</a></li>
<li><a href="/anonimo_instalador">Anónimo instalador</a></li>
<li><a href="/404">404</a></li>
<li><a href="/jo_ta_ke">Jo ta ke</a></li>
<li><a href="/kodea_aldatu">Kodea aldatu</a></li>
<li><a href="/otro_hackmeeting">Otro hackmeeting</a></li>
<li><a href="/txoria_txori">Kodea itxita utziko banu</a></li>
<li><a href="/trolesniuno">Troles ni uno</a></li>
<li><a href="/ni_yo_ni_nadie">Ni yo ni nadie</a></li>
<li><a href="/pringado">Pringado</a></li>
<li><a href="/Autodefensa_Informatica_Mala_persona">Mala persona</a></li>
<li><a href="/te_hemos_echado_y_no_mas_servers_viejos">No más servers viejos</a></li>
<li><a href="/gnu_Es_un_acronimo">GNU es un acrónimo</a></li>
<li><a href="/autosuficiencia">Autosuficiencia</a></li>
<li><a href="/gnu_Kojonprieto">GNU es un acrónimo</a></li>
<li><a href="/usuariado">Usuariado</a></li>
<li><a href="/quiero_ser_root">Quiero ser root</a></li>
<li><a href="/ynomeimportanada">Y no me importa nada</a></li>
<li><a href="/a_quien_le_importa">A quién le importa</a></li>
<li><a href="/tengo_una_debian_de_servidor">Tengo una debian de servidor</a></li>
<li><a href="/he_probado_todos_los_linux">He probado todos los linux</a></li>
</ul>
<p id="playlist"><a href="/playlist/">Playlist</a></p>
<p id="libreto"><a href="/static/libreto/libreto.pdf"><img src="/static/libreto/libreto.png">Libreto</a>
</nav>
<div id="content">
<div class="songs">
<figure>
<legend><a href="/mas_commits">Más commits</a></legend>
<a href="/mas_commits"><img src="/mas_commits/mas_commits_thumbnail.jpg"></a>
</figure>
<figure>
<legend><a href="/yoquierosermakero">Yo quiero ser makero</a></legend>
<a href="/yoquierosermakero"><img src="/yoquierosermakero/yoquierosermakero_thumbnail.jpg"></a>
</figure>
<figure>
<legend><a href="/salve">Salve</a></legend>
<a href="/salve"><img src="/salve/salve_thumbnail.jpg"></a>
</figure>
<figure>
<legend><a href="/en_verde_y_negro">En verde y negro</a></legend>
<a href="/en_verde_y_negro"><img src="/en_verde_y_negro/en_verde_y_negro_thumbnail.jpg"></a>
</figure>
<figure>
<legend><a href="/debianSamba">Debian Samba</a></legend>
<a href="/debianSamba"><img src="/debianSamba/debianSamba_thumbnail.jpg"></a>
</figure>
<figure>
<legend><a href="/hastasiempreGPL">Hasta siempre GPL</a></legend>
<a href="/hastasiempreGPL"><img src="/hastasiempreGPL/hastasiempreGPL_thumbnail.jpg"></a>
</figure>
<figure>
<legend><a href="/anonimo_instalador">Anónimo instalador</a></legend>
<a href="/anonimo_instalador"><img src="/anonimo_instalador/anonimo_instalador_thumbnail.jpg"></a>
</figure>
<figure>
<legend><a href="/404">404</a></legend>
<a href="/404"><img src="/404/404_thumbnail.jpg"></a>
</figure>
<figure>
<legend><a href="/jo_ta_ke">Jo ta ke</a></legend>
<a href="/jo_ta_ke"><img src="/jo_ta_ke/jo_ta_ke_thumbnail.jpg"></a>
</figure>
<figure>
<legend><a href="/kodea_aldatu">Kodea aldatu</a></legend>
<a href="/kodea_aldatu"><img src="/kodea_aldatu/kodea_aldatu_thumbnail.jpg"></a>
</figure>
<figure>
<legend><a href="/otro_hackmeeting">Otro hackmeeting</a></legend>
<a href="/otro_hackmeeting"><img src="/otro_hackmeeting/otro_hackmeeting_thumbnail.jpg"></a>
</figure>
<figure>
<legend><a href="/txoria_txori">Kodea itxita utziko banu</a></legend>
<a href="/txoria_txori"><img src="/txoria_txori/txoria_txori_thumbnail.jpg"></a>
</figure>
<figure>
<legend><a href="/trolesniuno">Troles ni uno</a></legend>
<a href="/trolesniuno"><img src="/trolesniuno/trolesniuno_thumbnail.jpg"></a>
</figure>
<figure>
<legend><a href="/ni_yo_ni_nadie">Ni yo ni nadie</a></legend>
<a href="/ni_yo_ni_nadie"><img src="/ni_yo_ni_nadie/ni_yo_ni_nadie_thumbnail.jpg"></a>
</figure>
<figure>
<legend><a href="/pringado">Pringado</a></legend>
<a href="/pringado"><img src="/pringado/pringado_thumbnail.jpg"></a>
</figure>
<figure>
<legend><a href="/Autodefensa_Informatica_Mala_persona">Mala persona</a></legend>
<a href="/Autodefensa_Informatica_Mala_persona"><img src="/Autodefensa_Informatica_Mala_persona/Autodefensa_Informatica_Mala_persona_thumbnail.jpg"></a>
</figure>
<figure>
<legend><a href="/te_hemos_echado_y_no_mas_servers_viejos">No más servers viejos</a></legend>
<a href="/te_hemos_echado_y_no_mas_servers_viejos"><img src="/te_hemos_echado_y_no_mas_servers_viejos/te_hemos_echado_y_no_mas_servers_viejos_thumbnail.jpg"></a>
</figure>
<figure>
<legend><a href="/gnu_Es_un_acronimo">GNU es un acrónimo</a></legend>
<a href="/gnu_Es_un_acronimo"><img src="/gnu_Es_un_acronimo/gnu_Es_un_acronimo_thumbnail.jpg"></a>
</figure>
<figure>
<legend><a href="/autosuficiencia">Autosuficiencia</a></legend>
<a href="/autosuficiencia"><img src="/autosuficiencia/autosuficiencia_thumbnail.jpg"></a>
</figure>
<figure>
<legend><a href="/gnu_Kojonprieto">GNU es un acrónimo</a></legend>
<a href="/gnu_Kojonprieto"><img src="/gnu_Kojonprieto/gnu_Kojonprieto_thumbnail.jpg"></a>
</figure>
<figure>
<legend><a href="/usuariado">Usuariado</a></legend>
<a href="/usuariado"><img src="/usuariado/usuariado_thumbnail.jpg"></a>
</figure>
<figure>
<legend><a href="/quiero_ser_root">Quiero ser root</a></legend>
<a href="/quiero_ser_root"><img src="/quiero_ser_root/quiero_ser_root_thumbnail.jpg"></a>
</figure>
<figure>
<legend><a href="/ynomeimportanada">Y no me importa nada</a></legend>
<a href="/ynomeimportanada"><img src="/ynomeimportanada/ynomeimportanada_thumbnail.jpg"></a>
</figure>
<figure>
<legend><a href="/a_quien_le_importa">A quién le importa</a></legend>
<a href="/a_quien_le_importa"><img src="/a_quien_le_importa/a_quien_le_importa_thumbnail.jpg"></a>
</figure>
<figure>
<legend><a href="/tengo_una_debian_de_servidor">Tengo una debian de servidor</a></legend>
<a href="/tengo_una_debian_de_servidor"><img src="/tengo_una_debian_de_servidor/tengo_una_debian_de_servidor_thumbnail.jpg"></a>
</figure>
<figure>
<legend><a href="/he_probado_todos_los_linux">He probado todos los linux</a></legend>
<a href="/he_probado_todos_los_linux"><img src="/he_probado_todos_los_linux/he_probado_todos_los_linux_thumbnail.jpg"></a>
</figure>
</div>
</div>
</body>
<head>
<title>Negro Mate</title>
<style>
body {
background-color: #232323;
}
h1 {
text-align: center;
font-size: 50pt;
border: 5px solid black;
background: white;
margin: 1em auto 0;
min-width: 300px;
width: 30%;
}
a {
font-size: 200pt;
font-weight: bold;
background-color: white;
color: black;
display: block;
line-height: 210pt;
margin: 10pt auto 0;
width: 210pt;
height: 210pt;
text-align: center;
border-radius: 105pt;
text-decoration: none;
}
</style>
</head>
<body>
<h1>Negro mate</h1>
<a href="/home/">#</a>
</body>
</html>

View File

@ -19,8 +19,154 @@
</head>
<body>
<header id="header">
<h1><a href="/">Negro Mate</a></h1>
<h1><a href="/home/">Negro Mate</a></h1>
</header>
<div id="content">
<h1>Jo ta ke</h1>
<p><b>Original:</b> Jo ta ke, Sutagar</p>
<video id="jo_ta_ke-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/jo_ta_ke/jo_ta_ke.jpg">
<source src="/jo_ta_ke/jo_ta_ke.mp4" type='video/mp4'>
<track kind="captions" src="/jo_ta_ke/jo_ta_ke.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<script>
videojs('jo_ta_ke-video', {
/*
plugins: {
},
*/
});
</script>
<p class="lyrics">
Sartu ginen bai<br/>
Pikoloen sarean<br/>
Haien datuak<br/>
Gure esku daude orain<br/>
Torturatuen<br/>
argazki ta zerrendak<br/>
bortzatzaileak<br/>
ordaindu beharko dute<br/>
Nik ez diat inoiz esango<br/>
Datu emailea zein den<br/>
Nik aspaldi egin nuen aukera<br/>
Jo ta ke! Argitaratu arte!<br/>
Bidali<br/>
Ezer ezkutatu gabe<br/>
Kopiatu<br/>
Toki guztietan<br/>
Adi egon<br/>
Hau geldiezina da<br/>
Azkenik<br/>
Dena jakingo da<br/>
Sartu ginen bai<br/>
Pikoloen sarean<br/>
Haien datuak<br/>
Gure esku daude orain<br/>
Torturatuen<br/>
argazki ta zerrendak<br/>
bortzatzaileak<br/>
ordaindu beharko dute<br/>
dokumentuak<br/>
dituzte izkutatuak<br/>
eta egia<br/>
daukate bahituta<br/>
ez da nahikoa<br/>
guk topatuko dugu<br/>
egindakoa ordaindu beharko dute<br/>
Nik ez diat inoiz esango<br/>
Datu emailea zein den<br/>
Nik aspaldi egin nuen aukera<br/>
Jo ta ke! Argitaratu arte!<br/>
Bidali<br/>
Ezer ezkutatu gabe<br/>
Kopiatu<br/>
Toki guztietan<br/>
Adi egon<br/>
Hau geldiezina da<br/>
Azkenik<br/>
Dena jakingo da<br/>
Jo ta Ke! Argitaratu arte!<br/>
</p>
<ul class="files">
<li><a href="/jo_ta_ke/jo_ta_ke.srt">jo_ta_ke.srt</a></li>
<li><a href="/jo_ta_ke/jo_ta_ke.mp4">jo_ta_ke.mp4</a></li>
</ul>
</div>
<nav id="menu">
<ul>
@ -80,47 +226,6 @@
<p id="playlist"><a href="/playlist/">Playlist</a></p>
<p id="libreto"><a href="/static/libreto/libreto.pdf"><img src="/static/libreto/libreto.png">Libreto</a>
</nav>
<div id="content">
<h1>Jo ta ke</h1>
<p><b>Original:</b> Jo ta ke, Sutagar</p>
<video id="jo_ta_ke-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/jo_ta_ke/jo_ta_ke.jpg">
<source src="/jo_ta_ke/jo_ta_ke.mp4" type='video/mp4'>
<track kind="captions" src="/jo_ta_ke/jo_ta_ke.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<ul class="files">
<li><a href="/jo_ta_ke/jo_ta_ke.srt">jo_ta_ke.srt</a></li>
<li><a href="/jo_ta_ke/jo_ta_ke.mp4">jo_ta_ke.mp4</a></li>
</ul>
<script>
videojs('jo_ta_ke-video', {
/*
plugins: {
},
*/
});
</script>
</div>
</body>
</html>

View File

@ -19,8 +19,155 @@
</head>
<body>
<header id="header">
<h1><a href="/">Negro Mate</a></h1>
<h1><a href="/home/">Negro Mate</a></h1>
</header>
<div id="content">
<h1>Kodea aldatu</h1>
<p><b>Original:</b> Lepoan hartu, R.I.P.</p>
<video id="kodea_aldatu-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/kodea_aldatu/kodea_aldatu.jpg">
<source src="/kodea_aldatu/kodea_aldatu.mp4" type='video/mp4'>
<track kind="captions" src="/kodea_aldatu/kodea_aldatu.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<script>
videojs('kodea_aldatu-video', {
/*
plugins: {
ass: {
'src': ["/kodea_aldatu/kodea_aldatu_es_eu.ass"],
// videoWidth: 640,
// videoHeight: 360,
enableSvg: false,
}
},
*/
});
</script>
<p class="lyrics">
tra la ra<br/>
tra la ra la la<br/>
tra la ra...<br/>
cambia el codigo y tira palante<br/>
tra la ra...
cambia el codigo y tira palante<br/>
cambia el codigo y tira palante
tra la ra...<br/>
tra la ra...<br/>
tra la ra la la<br/>
tra la ra...<br/>
cambia el codigo y tira palante<br/>
Hemos encontrado un bug en el codigo<br/>
la pantalla llena de lineas rojas<br/>
corregido y enviado el commit<br/>
arreglado en la siguiente version<br/>
hackers intercambiad codigo<br/>
commits y pushes entre todos<br/>
si el programa no hace lo que debe<br/>
cambia el codigo y tira palante!<br/>
tra la ra...<br/>
tra la ra la la<br/>
tra la ra...<br/>
cambia el codigo y tira palante<br/>
Hemos encontrado un bug en el codigo<br/>
la pantalla llena de lineas rojas<br/>
corregido y enviado el commit<br/>
arreglado en la siguiente version<br/>
hackers intercambiad codigo<br/>
commits y pushes entre todos<br/>
si el programa no hace lo que debe<br/>
cambia el codigo y tira palante!<br/>
tra la ra...<br/>
tra la ra la la<br/>
tra la ra...<br/>
cambia el codigo y tira palante<br/>
Hemos encontrado un bug en el codigo<br/>
la pantalla llena de lineas rojas<br/>
corregido y enviado el commit<br/>
arreglado en la siguiente version<br/>
hackers intercambiad codigo<br/>
commits y pushes entre todos<br/>
si el programa no hace lo que debe<br/>
cambia el codigo y tira palante!<br/>
</p>
<ul class="files">
<li><a href="/kodea_aldatu/kodea_aldatu.srt">kodea_aldatu.srt</a></li>
<li><a href="/kodea_aldatu/kodea_aldatu.mp4">kodea_aldatu.mp4</a></li>
<li><a href="/kodea_aldatu/kodea_aldatu_es.srt">kodea_aldatu_es.srt</a></li>
<li><a href="/kodea_aldatu/kodea_aldatu_es_eu.ass">kodea_aldatu_es_eu.ass</a></li>
</ul>
</div>
<nav id="menu">
<ul>
@ -80,58 +227,6 @@
<p id="playlist"><a href="/playlist/">Playlist</a></p>
<p id="libreto"><a href="/static/libreto/libreto.pdf"><img src="/static/libreto/libreto.png">Libreto</a>
</nav>
<div id="content">
<h1>Kodea aldatu</h1>
<p><b>Original:</b> Lepoan hartu, R.I.P.</p>
<video id="kodea_aldatu-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/kodea_aldatu/kodea_aldatu.jpg">
<source src="/kodea_aldatu/kodea_aldatu.mp4" type='video/mp4'>
<track kind="captions" src="/kodea_aldatu/kodea_aldatu.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<ul class="files">
<li><a href="/kodea_aldatu/kodea_aldatu.srt">kodea_aldatu.srt</a></li>
<li><a href="/kodea_aldatu/kodea_aldatu.mp4">kodea_aldatu.mp4</a></li>
<li><a href="/kodea_aldatu/kodea_aldatu_es.srt">kodea_aldatu_es.srt</a></li>
<li><a href="/kodea_aldatu/kodea_aldatu_es_eu.ass">kodea_aldatu_es_eu.ass</a></li>
</ul>
<script>
videojs('kodea_aldatu-video', {
/*
plugins: {
ass: {
'src': ["/kodea_aldatu/kodea_aldatu_es_eu.ass"],
// videoWidth: 640,
// videoHeight: 360,
enableSvg: false,
}
},
*/
});
</script>
</div>
</body>
</html>

View File

@ -1,44 +0,0 @@
1
00:00:05,790 --> 00:00:07,790
para instalar la debian
2
00:00:08,790 --> 00:00:12,050
para instalar la debian se necesita
3
00:00:12,050 --> 00:00:15,000
un cd una memoria
4
00:00:15,010 --> 00:00:20,010
que tipo de memoria
5
00:00:20,020 --> 00:00:24,020
usb, usb ,usb
6
00:00:24,030 --> 00:00:26,030
debian debian
7
00:00:26,800 --> 00:00:28,800
debian debian
8
00:00:28,800 --> 00:00:30,800
yo no soy windowsero
9
00:00:30,800 --> 00:00:32,800
yo no soy winsowsero
10
00:00:32,800 --> 00:00:34,800
ni uso mac ni uso mac ni uso mac
11
00:00:34,800 --> 00:00:36,800
debian debian

View File

@ -19,8 +19,170 @@
</head>
<body>
<header id="header">
<h1><a href="/">Negro Mate</a></h1>
<h1><a href="/home/">Negro Mate</a></h1>
</header>
<div id="content">
<h1>Más commits</h1>
<p><b>Original:</b> Más de ti, Barón Rojo</p>
<video id="mas_commits-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/mas_commits/mas_commits.jpg">
<source src="/mas_commits/mas_commits.ogv" type='video/ogg'>
<track kind="captions" src="/mas_commits/mas_commits.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<script>
videojs('mas_commits-video', {
/*
plugins: {
},
*/
});
</script>
<p class="lyrics">
Puede ser<br/>
que no<br/>
Pero este proyecto le falta ilusión<br/>
Los bug reports<br/>
cada vez llegan menos<br/>
Aunque aun<br/>
no ha pasado mucho tiempo<br/>
otra version<br/>
se empieza a echar de menos<br/>
no dudare<br/>
escribir<br/>
siempre que mi código me acerque a tí<br/>
y si al final de compilar<br/>
todo vuelve a funcionar<br/>
quiero mas commits<br/>
puede ser subversion mercurial o git<br/>
mas commits<br/>
no hagas un fork, juntos lo haremos mejor<br/>
El flame ha sido largo<br/>
debo descansar<br/>
tengo ganas de irme no pienso contestar<br/>
ya se que tu<br/>
quieres ayudar<br/>
Otro bugfix<br/>
que podías haber arreglado<br/>
loco por ver<br/>
que bueno has aportado<br/>
no dudare<br/>
escribir<br/>
siempre que mi código me acerque a tí<br/>
y si al final de compilar<br/>
todo vuelve a funcionar<br/>
quiero mas commits<br/>
puede ser subversion mercurial o git<br/>
mas commits<br/>
no hagas un fork, juntos lo haremos<br/>
quiero mas commits<br/>
puede ser subversion mercurial o git<br/>
mas commits<br/>
no hagas un fork, juntos lo haremos mejor<br/>
No voy a parar<br/>
quiero muchos mas<br/>
oye ven aqui<br/>
dime lo que tu quieres de mi<br/>
quiero mas commits<br/>
puede ser subversion mercurial o git<br/>
mas commits<br/>
no hagas un fork, juntos lo haremos<br/>
quiero mas commits<br/>
puede ser subversion mercurial o git<br/>
mas commits<br/>
no hagas un fork, juntos lo haremos<br/>
quiero mas commits<br/>
puede ser subversion mercurial o git<br/>
mas commits<br/>
MAAAAAS COOOOOOMMMMMIIIIIIITSSSS<br/>
</p>
<ul class="files">
<li><a href="/mas_commits/mas_commits.ogv">mas_commits.ogv</a></li>
<li><a href="/mas_commits/mas_commits.srt">mas_commits.srt</a></li>
</ul>
</div>
<nav id="menu">
<ul>
@ -80,47 +242,6 @@
<p id="playlist"><a href="/playlist/">Playlist</a></p>
<p id="libreto"><a href="/static/libreto/libreto.pdf"><img src="/static/libreto/libreto.png">Libreto</a>
</nav>
<div id="content">
<h1>Más commits</h1>
<p><b>Original:</b> Más de ti, Barón Rojo</p>
<video id="mas_commits-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/mas_commits/mas_commits.jpg">
<source src="/mas_commits/mas_commits.ogv" type='video/ogg'>
<track kind="captions" src="/mas_commits/mas_commits.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<ul class="files">
<li><a href="/mas_commits/mas_commits.ogv">mas_commits.ogv</a></li>
<li><a href="/mas_commits/mas_commits.srt">mas_commits.srt</a></li>
</ul>
<script>
videojs('mas_commits-video', {
/*
plugins: {
},
*/
});
</script>
</div>
</body>
</html>

View File

@ -19,8 +19,150 @@
</head>
<body>
<header id="header">
<h1><a href="/">Negro Mate</a></h1>
<h1><a href="/home/">Negro Mate</a></h1>
</header>
<div id="content">
<h1>Ni yo ni nadie</h1>
<p><b>Original:</b> Ni tu ni nadie, Alaska</p>
<video id="ni_yo_ni_nadie-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/ni_yo_ni_nadie/ni_yo_ni_nadie.jpg">
<source src="/ni_yo_ni_nadie/ni_yo_ni_nadie.mp4" type='video/mp4'>
<track kind="captions" src="/ni_yo_ni_nadie/ni_yo_ni_nadie.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<script>
videojs('ni_yo_ni_nadie-video', {
/*
plugins: {
},
*/
});
</script>
<p class="lyrics">
Haces muy mal<br/>
en arreglar ese error<br/>
que nadie más consiguió<br/>
sigue así<br/>
ya verás<br/>
Mira el reloj<br/>
es mucho más tarde que ayer<br/>
no te salvaré esta vez<br/>
no lo haré<br/>
no lo haré<br/>
Dónde está ese error sin solución<br/>
hiciste tú ese commit, no lo hice yo<br/>
ni yo ni nadie, nadie<br/>
va a perdonarte<br/>
Mil alarmas suenan en el nagios<br/>
el error entró en producción<br/>
ni yo ni nadie, nadie<br/>
va a perdonarte<br/>
Vete de aquí<br/>
ya la has liado demasiado<br/>
eso no lo has testeao <br/>
no es necesario mentir<br/>
Que facil es<br/>
arrepentirse después<br/>
pero sin ningun test <br/>
tu que te crees que iba a pasar<br/>
Dónde está ese error sin solución<br/>
hiciste tú ese commit, no lo hice yo<br/>
ni yo ni nadie, nadie<br/>
va a perdonarte<br/>
Mil alarmas suenan en el nagios<br/>
el error entró en producción<br/>
ni yo ni nadie, nadie<br/>
va a perdonarte<br/>
Mil alarmas suenan en el nagios<br/>
el error entró en producción<br/>
ni yo ni nadie, nadie<br/>
va a perdonarte<br/>
Dónde está ese error sin solución<br/>
hiciste tú ese commit, no lo hice yo<br/>
ni yo ni nadie, nadie<br/>
va a perdonarte<br/>
Mil alarmas suenan en el nagios<br/>
el error entró en producción<br/>
ni yo ni nadie, nadie<br/>
va a perdonarte<br/>
</p>
<ul class="files">
<li><a href="/ni_yo_ni_nadie/ni_yo_ni_nadie.srt">ni_yo_ni_nadie.srt</a></li>
<li><a href="/ni_yo_ni_nadie/ni_yo_ni_nadie.mp4">ni_yo_ni_nadie.mp4</a></li>
</ul>
</div>
<nav id="menu">
<ul>
@ -80,47 +222,6 @@
<p id="playlist"><a href="/playlist/">Playlist</a></p>
<p id="libreto"><a href="/static/libreto/libreto.pdf"><img src="/static/libreto/libreto.png">Libreto</a>
</nav>
<div id="content">
<h1>Ni yo ni nadie</h1>
<p><b>Original:</b> Ni tu ni nadie, Alaska</p>
<video id="ni_yo_ni_nadie-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/ni_yo_ni_nadie/ni_yo_ni_nadie.jpg">
<source src="/ni_yo_ni_nadie/ni_yo_ni_nadie.mp4" type='video/mp4'>
<track kind="captions" src="/ni_yo_ni_nadie/ni_yo_ni_nadie.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<ul class="files">
<li><a href="/ni_yo_ni_nadie/ni_yo_ni_nadie.srt">ni_yo_ni_nadie.srt</a></li>
<li><a href="/ni_yo_ni_nadie/ni_yo_ni_nadie.mp4">ni_yo_ni_nadie.mp4</a></li>
</ul>
<script>
videojs('ni_yo_ni_nadie-video', {
/*
plugins: {
},
*/
});
</script>
</div>
</body>
</html>

View File

@ -19,8 +19,143 @@
</head>
<body>
<header id="header">
<h1><a href="/">Negro Mate</a></h1>
<h1><a href="/home/">Negro Mate</a></h1>
</header>
<div id="content">
<h1>Otro hackmeeting</h1>
<p><b>Original:</b> Hijos de Caín, Barón Rojo</p>
<video id="otro_hackmeeting-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/otro_hackmeeting/otro_hackmeeting.jpg">
<source src="/otro_hackmeeting/otro_hackmeeting.mp4" type='video/mp4'>
<track kind="captions" src="/otro_hackmeeting/otro_hackmeeting.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<script>
videojs('otro_hackmeeting-video', {
/*
plugins: {
ass: {
'src': ["/otro_hackmeeting/otro_hackmeeting.ass"],
// videoWidth: 640,
// videoHeight: 360,
enableSvg: false,
}
},
*/
});
</script>
<p class="lyrics">
la lista cuenta una historia<br/>
que en vivo nunca ocurrió<br/>
el drama de unos pocos<br/>
la voluntad nos comió<br/>
el troll mezquino y cobarde<br/>
el siervo de su ego<br/>
la gente no entró en el juego<br/>
fuera se organizó<br/>
Os maldigo, truena la voz de blinge<br/>
que no entiende, y que nos quiere joder<br/>
Alguien rompió con un gesto<br/>
su yugo de esclavitud<br/>
huyó del flame imposible<br/>
y se autogestionó<br/>
Criticado, por quebrantar una ley<br/>
que ya es vieja, y no hay por donde coger<br/>
sufrirás, leerás<br/>
de los troles huirás<br/>
pero aun hay aqui<br/>
otro hackmeeting<br/>
El espíritu hackitita, creció y se multiplicó <br/>
y siempre todos los años<br/>
gente nueva llego<br/>
siempre vivo, mueren los hijos de ayer<br/>
se reinventa, los viejos no tienen poder<br/>
sufrirás, leerás<br/>
de los troles huirás<br/>
pero aun hay aquí<br/>
otro hackmeeting<br/>
en el hackmeeting ya somos, a un tiempo usuario y admin<br/>
quizas un día destruyas, el orgullo que hay en tí<br/>
el destino no está marcado en tu ser<br/>
sigue vivo, y siempre volverá a haber <br/>
OTRO HACKMEETING<br/>
OTRO HACKMEETING<br/>
OTRO HACKMEETING<br/>
OTRO HACKMEETING<br/>
</p>
<ul class="files">
<li><a href="/otro_hackmeeting/otro_hackmeeting_subtitled.mp4">otro_hackmeeting_subtitled.mp4</a></li>
<li><a href="/otro_hackmeeting/otro_hackmeeting.ass">otro_hackmeeting.ass</a></li>
<li><a href="/otro_hackmeeting/otro_hackmeeting.mp4">otro_hackmeeting.mp4</a></li>
<li><a href="/otro_hackmeeting/otro_hackmeeting.srt">otro_hackmeeting.srt</a></li>
</ul>
</div>
<nav id="menu">
<ul>
@ -80,58 +215,6 @@
<p id="playlist"><a href="/playlist/">Playlist</a></p>
<p id="libreto"><a href="/static/libreto/libreto.pdf"><img src="/static/libreto/libreto.png">Libreto</a>
</nav>
<div id="content">
<h1>Otro hackmeeting</h1>
<p><b>Original:</b> Hijos de Caín, Barón Rojo</p>
<video id="otro_hackmeeting-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/otro_hackmeeting/otro_hackmeeting.jpg">
<source src="/otro_hackmeeting/otro_hackmeeting.mp4" type='video/mp4'>
<track kind="captions" src="/otro_hackmeeting/otro_hackmeeting.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<ul class="files">
<li><a href="/otro_hackmeeting/otro_hackmeeting_subtitled.mp4">otro_hackmeeting_subtitled.mp4</a></li>
<li><a href="/otro_hackmeeting/otro_hackmeeting.ass">otro_hackmeeting.ass</a></li>
<li><a href="/otro_hackmeeting/otro_hackmeeting.mp4">otro_hackmeeting.mp4</a></li>
<li><a href="/otro_hackmeeting/otro_hackmeeting.srt">otro_hackmeeting.srt</a></li>
</ul>
<script>
videojs('otro_hackmeeting-video', {
/*
plugins: {
ass: {
'src': ["/otro_hackmeeting/otro_hackmeeting.ass"],
// videoWidth: 640,
// videoHeight: 360,
enableSvg: false,
}
},
*/
});
</script>
</div>
</body>
</html>

View File

@ -19,78 +19,23 @@
</head>
<body>
<header id="header">
<h1><a href="/">Negro Mate</a></h1>
<h1><a href="/home/">Negro Mate</a></h1>
</header>
<nav id="menu">
<ul>
<li><a href="/mas_commits">Más commits</a></li>
<li><a href="/yoquierosermakero">Yo quiero ser makero</a></li>
<li><a href="/salve">Salve</a></li>
<li><a href="/en_verde_y_negro">En verde y negro</a></li>
<li><a href="/debianSamba">Debian Samba</a></li>
<li><a href="/hastasiempreGPL">Hasta siempre GPL</a></li>
<li><a href="/anonimo_instalador">Anónimo instalador</a></li>
<li><a href="/404">404</a></li>
<li><a href="/jo_ta_ke">Jo ta ke</a></li>
<li><a href="/kodea_aldatu">Kodea aldatu</a></li>
<li><a href="/otro_hackmeeting">Otro hackmeeting</a></li>
<li><a href="/txoria_txori">Kodea itxita utziko banu</a></li>
<li><a href="/trolesniuno">Troles ni uno</a></li>
<li><a href="/ni_yo_ni_nadie">Ni yo ni nadie</a></li>
<li><a href="/pringado">Pringado</a></li>
<li><a href="/Autodefensa_Informatica_Mala_persona">Mala persona</a></li>
<li><a href="/te_hemos_echado_y_no_mas_servers_viejos">No más servers viejos</a></li>
<li><a href="/gnu_Es_un_acronimo">GNU es un acrónimo</a></li>
<li><a href="/autosuficiencia">Autosuficiencia</a></li>
<li><a href="/gnu_Kojonprieto">GNU es un acrónimo</a></li>
<li><a href="/usuariado">Usuariado</a></li>
<li><a href="/quiero_ser_root">Quiero ser root</a></li>
<li><a href="/ynomeimportanada">Y no me importa nada</a></li>
<li><a href="/a_quien_le_importa">A quién le importa</a></li>
<li><a href="/tengo_una_debian_de_servidor">Tengo una debian de servidor</a></li>
<li><a href="/he_probado_todos_los_linux">He probado todos los linux</a></li>
</ul>
<p id="playlist"><a href="/playlist/">Playlist</a></p>
<p id="libreto"><a href="/static/libreto/libreto.pdf"><img src="/static/libreto/libreto.png">Libreto</a>
</nav>
<div id="content">
<video id="video-playlist" class="video-js"
controls preload="auto" width="640" height="264"
>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<div class="vjs-playlist"></div>
</div>
<div id="song-playlist">
<video id="video-playlist" class="video-js"
controls preload="auto" width="600" height="400"
>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<div class="vjs-playlist"></div>
</div>
<script>
var player = videojs('video-playlist', {});
@ -103,7 +48,11 @@
type: 'video/ogg'
}],
poster: '/mas_commits/mas_commits.jpg',
thumbnail: '/mas_commits/mas_commits_thumbnail.jpg',
name: 'Más commits',
textTracks:[ { "kind":"captions", "label":"Negro mate", "src":"/mas_commits/mas_commits.vtt", "default":true } ]
},
@ -114,7 +63,11 @@
type: 'video/mp4'
}],
poster: '/yoquierosermakero/yoquierosermakero.jpg',
thumbnail: '/yoquierosermakero/yoquierosermakero_thumbnail.jpg',
name: 'Yo quiero ser makero',
textTracks:[ { "kind":"captions", "label":"Negro mate", "src":"/yoquierosermakero/yoquierosermakero.vtt", "default":true } ]
},
@ -125,7 +78,11 @@
type: 'video/mp4'
}],
poster: '/salve/salve.jpg',
thumbnail: '/salve/salve_thumbnail.jpg',
name: 'Salve',
textTracks:[ { "kind":"captions", "label":"Negro mate", "src":"/salve/salve.vtt", "default":true } ]
},
@ -136,7 +93,11 @@
type: 'video/mp4'
}],
poster: '/en_verde_y_negro/en_verde_y_negro.jpg',
thumbnail: '/en_verde_y_negro/en_verde_y_negro_thumbnail.jpg',
name: 'En verde y negro',
textTracks:[ { "kind":"captions", "label":"Negro mate", "src":"/en_verde_y_negro/en_verde_y_negro.vtt", "default":true } ]
},
@ -147,7 +108,11 @@
type: 'video/mp4'
}],
poster: '/debianSamba/debianSamba.jpg',
thumbnail: '/debianSamba/debianSamba_thumbnail.jpg',
name: 'Debian Samba',
textTracks:[ { "kind":"captions", "label":"Negro mate", "src":"/debianSamba/debianSamba.vtt", "default":true } ]
},
@ -158,7 +123,11 @@
type: 'video/mp4'
}],
poster: '/hastasiempreGPL/hastasiempreGPL.jpg',
thumbnail: '/hastasiempreGPL/hastasiempreGPL_thumbnail.jpg',
name: 'Hasta siempre GPL',
textTracks:[ { "kind":"captions", "label":"Negro mate", "src":"/hastasiempreGPL/hastasiempreGPL.vtt", "default":true } ]
},
@ -169,7 +138,11 @@
type: 'video/mp4'
}],
poster: '/anonimo_instalador/anonimo_instalador.jpg',
thumbnail: '/anonimo_instalador/anonimo_instalador_thumbnail.jpg',
name: 'Anónimo instalador',
textTracks:[ { "kind":"captions", "label":"Negro mate", "src":"/anonimo_instalador/anonimo_instalador.vtt", "default":true } ]
},
@ -180,7 +153,11 @@
type: 'video/mp4'
}],
poster: '/404/404.jpg',
thumbnail: '/404/404_thumbnail.jpg',
name: '404',
textTracks:[ { "kind":"captions", "label":"Negro mate", "src":"/404/404.vtt", "default":true } ]
},
@ -191,7 +168,11 @@
type: 'video/mp4'
}],
poster: '/jo_ta_ke/jo_ta_ke.jpg',
thumbnail: '/jo_ta_ke/jo_ta_ke_thumbnail.jpg',
name: 'Jo ta ke',
textTracks:[ { "kind":"captions", "label":"Negro mate", "src":"/jo_ta_ke/jo_ta_ke.vtt", "default":true } ]
},
@ -202,7 +183,11 @@
type: 'video/mp4'
}],
poster: '/kodea_aldatu/kodea_aldatu.jpg',
thumbnail: '/kodea_aldatu/kodea_aldatu_thumbnail.jpg',
name: 'Kodea aldatu',
textTracks:[ { "kind":"captions", "label":"Negro mate", "src":"/kodea_aldatu/kodea_aldatu.vtt", "default":true } ]
},
@ -213,7 +198,11 @@
type: 'video/mp4'
}],
poster: '/otro_hackmeeting/otro_hackmeeting.jpg',
thumbnail: '/otro_hackmeeting/otro_hackmeeting_thumbnail.jpg',
name: 'Otro hackmeeting',
textTracks:[ { "kind":"captions", "label":"Negro mate", "src":"/otro_hackmeeting/otro_hackmeeting.vtt", "default":true } ]
},
@ -224,7 +213,11 @@
type: 'video/mp4'
}],
poster: '/txoria_txori/txoria_txori.jpg',
thumbnail: '/txoria_txori/txoria_txori_thumbnail.jpg',
name: 'Kodea itxita utziko banu',
textTracks:[ { "kind":"captions", "label":"Negro mate", "src":"/txoria_txori/txoria_txori.vtt", "default":true } ]
},
@ -235,7 +228,11 @@
type: 'video/mp4'
}],
poster: '/trolesniuno/trolesniuno.jpg',
thumbnail: '/trolesniuno/trolesniuno_thumbnail.jpg',
name: 'Troles ni uno',
textTracks:[ { "kind":"captions", "label":"Negro mate", "src":"/trolesniuno/trolesniuno.vtt", "default":true } ]
},
@ -246,7 +243,11 @@
type: 'video/mp4'
}],
poster: '/ni_yo_ni_nadie/ni_yo_ni_nadie.jpg',
thumbnail: '/ni_yo_ni_nadie/ni_yo_ni_nadie_thumbnail.jpg',
name: 'Ni yo ni nadie',
textTracks:[ { "kind":"captions", "label":"Negro mate", "src":"/ni_yo_ni_nadie/ni_yo_ni_nadie.vtt", "default":true } ]
},
@ -257,7 +258,11 @@
type: 'video/webm'
}],
poster: '/pringado/pringado.jpg',
thumbnail: '/pringado/pringado_thumbnail.jpg',
name: 'Pringado',
textTracks:[ { "kind":"captions", "label":"Negro mate", "src":"/pringado/pringado.vtt", "default":true } ]
},
@ -268,7 +273,11 @@
type: 'video/ogg'
}],
poster: '/Autodefensa_Informatica_Mala_persona/Autodefensa_Informatica_Mala_persona.jpg',
thumbnail: '/Autodefensa_Informatica_Mala_persona/Autodefensa_Informatica_Mala_persona_thumbnail.jpg',
name: 'Mala persona',
textTracks:[ { "kind":"captions", "label":"Negro mate", "src":"/Autodefensa_Informatica_Mala_persona/Autodefensa_Informatica_Mala_persona.vtt", "default":true } ]
},
@ -279,7 +288,11 @@
type: 'video/mp4'
}],
poster: '/te_hemos_echado_y_no_mas_servers_viejos/te_hemos_echado_y_no_mas_servers_viejos.jpg',
thumbnail: '/te_hemos_echado_y_no_mas_servers_viejos/te_hemos_echado_y_no_mas_servers_viejos_thumbnail.jpg',
name: 'No más servers viejos',
textTracks:[ { "kind":"captions", "label":"Negro mate", "src":"/te_hemos_echado_y_no_mas_servers_viejos/te_hemos_echado_y_no_mas_servers_viejos.vtt", "default":true } ]
},
@ -290,7 +303,11 @@
type: 'video/mp4'
}],
poster: '/gnu_Es_un_acronimo/gnu_Es_un_acronimo.jpg',
thumbnail: '/gnu_Es_un_acronimo/gnu_Es_un_acronimo_thumbnail.jpg',
name: 'GNU es un acrónimo',
textTracks:[ { "kind":"captions", "label":"Negro mate", "src":"/gnu_Es_un_acronimo/gnu_Es_un_acronimo.vtt", "default":true } ]
},
@ -301,7 +318,11 @@
type: 'video/mp4'
}],
poster: '/autosuficiencia/autosuficiencia.jpg',
thumbnail: '/autosuficiencia/autosuficiencia_thumbnail.jpg',
name: 'Autosuficiencia',
textTracks:[ { "kind":"captions", "label":"Negro mate", "src":"/autosuficiencia/autosuficiencia.vtt", "default":true } ]
},
@ -312,7 +333,11 @@
type: 'video/mp4'
}],
poster: '/gnu_Kojonprieto/gnu_Kojonprieto.jpg',
thumbnail: '/gnu_Kojonprieto/gnu_Kojonprieto_thumbnail.jpg',
name: 'GNU es un acrónimo',
textTracks:[ { "kind":"captions", "label":"Negro mate", "src":"/gnu_Kojonprieto/gnu_Kojonprieto.vtt", "default":true } ]
},
@ -323,7 +348,11 @@
type: 'video/mp4'
}],
poster: '/usuariado/usuariado.jpg',
thumbnail: '/usuariado/usuariado_thumbnail.jpg',
name: 'Usuariado',
textTracks:[ { "kind":"captions", "label":"Negro mate", "src":"/usuariado/usuariado.vtt", "default":true } ]
},
@ -334,18 +363,26 @@
type: 'video/mp4'
}],
poster: '/quiero_ser_root/quiero_ser_root.jpg',
thumbnail: '/quiero_ser_root/quiero_ser_root_thumbnail.jpg',
name: 'Quiero ser root',
textTracks:[ { "kind":"captions", "label":"Negro mate", "src":"/quiero_ser_root/quiero_ser_root.vtt", "default":true } ]
},
{
sources: [{
src: '/ynomeimportanada/ynomeimportanada_subtitulado.mp4',
src: '/ynomeimportanada/ynomeimportanada.mp4',
type: 'video/mp4'
}],
poster: '/ynomeimportanada/ynomeimportanada.jpg',
thumbnail: '/ynomeimportanada/ynomeimportanada_thumbnail.jpg',
name: 'Y no me importa nada',
textTracks:[ { "kind":"captions", "label":"Negro mate", "src":"/ynomeimportanada/ynomeimportanada.vtt", "default":true } ]
},
@ -356,7 +393,11 @@
type: 'video/webm'
}],
poster: '/a_quien_le_importa/a_quien_le_importa.jpg',
thumbnail: '/a_quien_le_importa/a_quien_le_importa_thumbnail.jpg',
name: 'A quién le importa',
textTracks:[ { "kind":"captions", "label":"Negro mate", "src":"/a_quien_le_importa/a_quien_le_importa.vtt", "default":true } ]
},
@ -367,7 +408,11 @@
type: 'video/mp4'
}],
poster: '/tengo_una_debian_de_servidor/tengo_una_debian_de_servidor.jpg',
thumbnail: '/tengo_una_debian_de_servidor/tengo_una_debian_de_servidor_thumbnail.jpg',
name: 'Tengo una debian de servidor',
textTracks:[ { "kind":"captions", "label":"Negro mate", "src":"/tengo_una_debian_de_servidor/tengo_una_debian_de_servidor.vtt", "default":true } ]
},
@ -378,7 +423,11 @@
type: 'video/mp4'
}],
poster: '/he_probado_todos_los_linux/he_probado_todos_los_linux.jpg',
thumbnail: '/he_probado_todos_los_linux/he_probado_todos_los_linux_thumbnail.jpg',
name: 'He probado todos los linux',
textTracks:[ { "kind":"captions", "label":"Negro mate", "src":"/he_probado_todos_los_linux/he_probado_todos_los_linux.vtt", "default":true } ]
},
@ -389,6 +438,5 @@
player.playlistUi();
</script>
</div>
</body>
</html>

View File

@ -19,8 +19,212 @@
</head>
<body>
<header id="header">
<h1><a href="/">Negro Mate</a></h1>
<h1><a href="/home/">Negro Mate</a></h1>
</header>
<div id="content">
<h1>Pringado</h1>
<p><b>Original:</b> Cuidado, Eskorbuto</p>
<video id="pringado-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/pringado/pringado.jpg">
<source src="/pringado/pringado.webm" type='video/webm'>
<track kind="captions" src="/pringado/pringado.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<script>
videojs('pringado-video', {
/*
plugins: {
},
*/
});
</script>
<p class="lyrics">
Gentes ignorantes que aún siguen usando Windows<br/>
Exigen favores que nunca valoran<br/>
Cobardes<br/>
Que van de amiguetes<br/>
Que no se ponen Linux<br/>
Porque no se atreven<br/>
Y es que todo<br/>
tiene un límite<br/>
Así estáis todos<br/>
Amargados<br/>
Pringado<br/>
Lo has arreglado<br/>
Haciendo esos favores<br/>
Te han esclavizado<br/>
Pringado<br/>
Lo has arreglado<br/>
Haciendo esos favores<br/>
te han esclavizado<br/>
Pringado<br/>
Lo has arreglado<br/>
Haciendo esos favores<br/>
te han esclavizado<br/>
Pringado<br/>
lo has arreglado<br/>
haciendo esos favores<br/>
te han esclavizado<br/>
pringado<br/>
lo has arreglado<br/>
haciendo esos favores<br/>
te han esclavizado<br/>
pringado<br/>
lo has arreglado<br/>
haciendo esos favores<br/>
te han esclavizado<br/>
Gentes ignorantes<br/>
que aún siguen usando Windows<br/>
exigen favores que nunca valoran<br/>
cobardes<br/>
que van de amiguetes<br/>
que no se ponen Linux porque no se atreven<br/>
y es que todo<br/>
tiene un límite<br/>
así estáis todos<br/>
amargados<br/>
pringado<br/>
lo has arreglado<br/>
haciendo esos favores<br/>
te han esclavizado<br/>
pringado<br/>
lo has arreglado<br/>
haciendo esos favores<br/>
te han esclavizado<br/>
pringado<br/>
lo has arreglado<br/>
haciendo esos favores<br/>
te han esclavizado<br/>
pringado<br/>
lo has arreglado<br/>
haciendo esos favores<br/>
te han esclavizado<br/>
pringado<br/>
lo has arreglado<br/>
haciendo esos favores<br/>
te han esclavizado<br/>
pringado<br/>
lo has arreglado<br/>
haciendo esos favores<br/>
te han esclavizado<br/>
pringado<br/>
lo has arreglado<br/>
haciendo esos favores<br/>
te han esclavizado<br/>
pringado<br/>
lo has arreglado<br/>
haciendo esos favores<br/>
te han esclavizado<br/>
pringado<br/>
</p>
<ul class="files">
<li><a href="/pringado/pringado.srt">pringado.srt</a></li>
<li><a href="/pringado/pringado.webm">pringado.webm</a></li>
</ul>
</div>
<nav id="menu">
<ul>
@ -80,47 +284,6 @@
<p id="playlist"><a href="/playlist/">Playlist</a></p>
<p id="libreto"><a href="/static/libreto/libreto.pdf"><img src="/static/libreto/libreto.png">Libreto</a>
</nav>
<div id="content">
<h1>Pringado</h1>
<p><b>Original:</b> Cuidado, Eskorbuto</p>
<video id="pringado-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/pringado/pringado.jpg">
<source src="/pringado/pringado.webm" type='video/webm'>
<track kind="captions" src="/pringado/pringado.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<ul class="files">
<li><a href="/pringado/pringado.srt">pringado.srt</a></li>
<li><a href="/pringado/pringado.webm">pringado.webm</a></li>
</ul>
<script>
videojs('pringado-video', {
/*
plugins: {
},
*/
});
</script>
</div>
</body>
</html>

View File

@ -19,8 +19,113 @@
</head>
<body>
<header id="header">
<h1><a href="/">Negro Mate</a></h1>
<h1><a href="/home/">Negro Mate</a></h1>
</header>
<div id="content">
<h1>Quiero ser root</h1>
<p><b>Original:</b> Quiero un camión, Loquillo y los trogloditas</p>
<video id="quiero_ser_root-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/quiero_ser_root/quiero_ser_root.jpg">
<source src="/quiero_ser_root/quiero_ser_root.mp4" type='video/mp4'>
<track kind="captions" src="/quiero_ser_root/quiero_ser_root.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<script>
videojs('quiero_ser_root-video', {
/*
plugins: {
ass: {
'src': ["/quiero_ser_root/quiero_ser_root.ass"],
// videoWidth: 640,
// videoHeight: 360,
enableSvg: false,
}
},
*/
});
</script>
<p class="lyrics">
Yo para ser felíz quiero ser root.<br/>
Yo para ser felíz quiero ser root.<br/>
Poder entrar en cualquier lado,<br/>
mirar los logs y espiar usuarios.<br/>
Yo para ser felíz quiero ser root.<br/>
Yo para ser felíz quiero ser root.<br/>
Yo para ser felíz quiero ser root.<br/>
Poder entrar en cualquier lado,<br/>
mirar los logs y espiar usuarios.<br/>
Yo para ser felíz quiero ser root.<br/>
Yo para ser felíz quiero ser root.<br/>
Yo para ser felíz quiero ser root.<br/>
Poder entrar en cualquier lado,<br/>
mirar los logs y espiar usuarios.<br/>
Yo para ser felíz quiero ser root.<br/>
Yo para ser felíz quiero ser root.<br/>
Yo para ser felíz quiero ser root.<br/>
Poder entrar en cualquier lado,<br/>
mirar los logs y espiar usuarios.<br/>
Yo para ser felíz quiero ser root.<br/>
Yo para ser felíz quiero ser root.<br/>
Yo para ser felíz <br/>
Quiero ser root<br/>
</p>
<ul class="files">
<li><a href="/quiero_ser_root/quiero_ser_root.ass">quiero_ser_root.ass</a></li>
<li><a href="/quiero_ser_root/quiero_ser_root.srt">quiero_ser_root.srt</a></li>
<li><a href="/quiero_ser_root/quiero_ser_root.mp4">quiero_ser_root.mp4</a></li>
</ul>
</div>
<nav id="menu">
<ul>
@ -80,47 +185,6 @@
<p id="playlist"><a href="/playlist/">Playlist</a></p>
<p id="libreto"><a href="/static/libreto/libreto.pdf"><img src="/static/libreto/libreto.png">Libreto</a>
</nav>
<div id="content">
<h1>Quiero ser root</h1>
<p><b>Original:</b> Quiero un camión, Loquillo y los trogloditas</p>
<video id="quiero_ser_root-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/quiero_ser_root/quiero_ser_root.jpg">
<source src="/quiero_ser_root/quiero_ser_root.mp4" type='video/mp4'>
<track kind="captions" src="/quiero_ser_root/quiero_ser_root.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<ul class="files">
<li><a href="/quiero_ser_root/quiero_ser_root.srt">quiero_ser_root.srt</a></li>
<li><a href="/quiero_ser_root/quiero_ser_root.mp4">quiero_ser_root.mp4</a></li>
</ul>
<script>
videojs('quiero_ser_root-video', {
/*
plugins: {
},
*/
});
</script>
</div>
</body>
</html>

View File

@ -0,0 +1,47 @@
[Script Info]
; Script generated by Aegisub 3.1.2
; http://www.aegisub.org/
Title: Default Aegisub file
ScriptType: v4.00+
WrapStyle: 0
ScaledBorderAndShadow: yes
YCbCr Matrix: TV.601
PlayResX: 480
PlayResY: 360
Audio URI: quiero_ser_root.mp4
Video File: quiero_ser_root.mp4
Aegisub Video Aspect Ratio: c1.333333
Aegisub Video Position: 3973
Aegisub Scroll Position: 12
Aegisub Active Line: 21
Aegisub Video Zoom Percent: 1.000000
[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Default,Arial,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,2,2,2,10,10,10,1
[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:35.50,0:00:37.50,Default,,0,0,0,,Yo para ser felíz quiero ser root.
Dialogue: 0,0:00:39.00,0:00:41.50,Default,,0,0,0,,Yo para ser felíz quiero ser root.
Dialogue: 0,0:00:42.00,0:00:44.00,Default,,0,0,0,,Poder entrar en cualquier lado,
Dialogue: 0,0:00:44.00,0:00:45.50,Default,,0,0,0,,mirar los logs y espiar usuarios.
Dialogue: 0,0:00:45.60,0:00:47.60,Default,,0,0,0,,Yo para ser felíz quiero ser root.
Dialogue: 0,0:00:49.10,0:00:51.10,Default,,0,0,0,,Yo para ser felíz quiero ser root.
Dialogue: 0,0:00:52.50,0:00:54.50,Default,,0,0,0,,Yo para ser felíz quiero ser root.
Dialogue: 0,0:00:56.00,0:00:57.70,Default,,0,0,0,,Poder entrar en cualquier lado,
Dialogue: 0,0:00:57.80,0:00:59.60,Default,,0,0,0,,mirar los logs y espiar usuarios.
Dialogue: 0,0:00:59.70,0:01:02.00,Default,,0,0,0,,Yo para ser felíz quiero ser root.
Dialogue: 0,0:01:30.80,0:01:33.00,Default,,0,0,0,,Yo para ser felíz quiero ser root.
Dialogue: 0,0:01:34.30,0:01:36.30,Default,,0,0,0,,Yo para ser felíz quiero ser root.
Dialogue: 0,0:01:37.50,0:01:39.10,Default,,0,0,0,,Poder entrar en cualquier lado,
Dialogue: 0,0:01:39.30,0:01:41.20,Default,,0,0,0,,mirar los logs y espiar usuarios.
Dialogue: 0,0:01:41.30,0:01:43.50,Default,,0,0,0,,Yo para ser felíz quiero ser root.
Dialogue: 0,0:01:44.70,0:01:47.00,Default,,0,0,0,,Yo para ser felíz quiero ser root.
Dialogue: 0,0:01:48.20,0:01:50.30,Default,,0,0,0,,Yo para ser felíz quiero ser root.
Dialogue: 0,0:01:51.70,0:01:53.40,Default,,0,0,0,,Poder entrar en cualquier lado,
Dialogue: 0,0:01:53.50,0:01:55.30,Default,,0,0,0,,mirar los logs y espiar usuarios.
Dialogue: 0,0:01:55.40,0:01:57.50,Default,,0,0,0,,Yo para ser felíz quiero ser root.
Dialogue: 0,0:01:58.80,0:02:00.50,Default,,0,0,0,,Yo para ser felíz quiero ser root.
Dialogue: 0,0:02:02.50,0:02:04.50,Default,,0,0,0,,Yo para ser felíz
Dialogue: 0,0:02:18.30,0:02:29.30,Default,,0,0,0,,Quiero ser root

View File

@ -19,8 +19,123 @@
</head>
<body>
<header id="header">
<h1><a href="/">Negro Mate</a></h1>
<h1><a href="/home/">Negro Mate</a></h1>
</header>
<div id="content">
<h1>Salve</h1>
<p><b>Original:</b> Salve, La Polla Records</p>
<video id="salve-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/salve/salve.jpg">
<source src="/salve/salve.mp4" type='video/mp4'>
<track kind="captions" src="/salve/salve.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<script>
videojs('salve-video', {
/*
plugins: {
ass: {
'src': ["/salve/salve.ass"],
// videoWidth: 640,
// videoHeight: 360,
enableSvg: false,
}
},
*/
});
</script>
<p class="lyrics">
Salve<br/>
la copia<br/>
total o diferencial<br/>
total o diferencial<br/>
A costa de prometer<br/>
servicios en la nube<br/>
algunas empresas<br/>
lo que están haciendo<br/>
es su propia copia<br/>
de los datos de la peña<br/>
usa un servicio gratuito<br/>
pagando con tu intimidad<br/>
salve <br/>
la copia<br/>
total o diferencial<br/>
total o diferencial<br/>
hay que estar majareto<br/>
para hablar de educación<br/>
y al mismo tiempo<br/>
en las escuelas<br/>
os quedais los datos de los niños<br/>
sin derecho al olvido<br/>
para que tengan que ser<br/>
lo que google quiera que sean<br/>
salve<br/>
la copia<br/>
total o diferencial<br/>
total o diferencial<br/>
</p>
<ul class="files">
<li><a href="/salve/salve.srt">salve.srt</a></li>
<li><a href="/salve/salve.mp4">salve.mp4</a></li>
<li><a href="/salve/salve.ass">salve.ass</a></li>
</ul>
</div>
<nav id="menu">
<ul>
@ -80,56 +195,6 @@
<p id="playlist"><a href="/playlist/">Playlist</a></p>
<p id="libreto"><a href="/static/libreto/libreto.pdf"><img src="/static/libreto/libreto.png">Libreto</a>
</nav>
<div id="content">
<h1>Salve</h1>
<p><b>Original:</b> Salve, La Polla Records</p>
<video id="salve-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/salve/salve.jpg">
<source src="/salve/salve.mp4" type='video/mp4'>
<track kind="captions" src="/salve/salve.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<ul class="files">
<li><a href="/salve/salve.srt">salve.srt</a></li>
<li><a href="/salve/salve.mp4">salve.mp4</a></li>
<li><a href="/salve/salve.ass">salve.ass</a></li>
</ul>
<script>
videojs('salve-video', {
/*
plugins: {
ass: {
'src': ["/salve/salve.ass"],
// videoWidth: 640,
// videoHeight: 360,
enableSvg: false,
}
},
*/
});
</script>
</div>
</body>
</html>

View File

@ -19,8 +19,310 @@
</head>
<body>
<header id="header">
<h1><a href="/">Negro Mate</a></h1>
<h1><a href="/home/">Negro Mate</a></h1>
</header>
<div id="content">
<h1>No más servers viejos</h1>
<p><b>Original:</b> No más punkis muertos, M.C.D.</p>
<video id="te_hemos_echado_y_no_mas_servers_viejos-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/te_hemos_echado_y_no_mas_servers_viejos/te_hemos_echado_y_no_mas_servers_viejos.jpg">
<source src="/te_hemos_echado_y_no_mas_servers_viejos/te_hemos_echado_y_no_mas_servers_viejos.mp4" type='video/mp4'>
<track kind="captions" src="/te_hemos_echado_y_no_mas_servers_viejos/te_hemos_echado_y_no_mas_servers_viejos.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<script>
videojs('te_hemos_echado_y_no_mas_servers_viejos-video', {
/*
plugins: {
},
*/
});
</script>
<p class="lyrics">
Por fin, llegó el final<br/>
de la gestíón de este alcalde<br/>
es otra ocasión más<br/>
que un corrupto está acabado<br/>
que bién vamos a estar<br/>
sin el PP en el gobierno<br/>
aquí no volverás<br/>
te hemos echado<br/>
Por fin, llegó el final<br/>
de la gestíón de este alcalde<br/>
es otra ocasión más<br/>
que un corrupto está acabado<br/>
que bién vamos a estar<br/>
sin el PP en el gobierno<br/>
aquí no volverás<br/>
¡te hemos echado!<br/>
Observo al caminar<br/>
toda esa gente<br/>
que han deshauciado<br/>
y encima crees<br/>
que el que ha robado<br/>
es inmigrante, o está en el paro<br/>
por eso y más, no volverás<br/>
¡te hemos echado!<br/>
Por fin, llegó el final<br/>
de la gestíón de este alcalde<br/>
es otra ocasión más<br/>
que un corrupto está acabado<br/>
que bién vamos a estar<br/>
sin el PP en el gobierno<br/>
aquí no volverás<br/>
¡te hemos echado!<br/>
Observo al caminar<br/>
toda esa gente<br/>
que han deshauciado<br/>
y encima crees<br/>
que el que ha robado<br/>
es inmigrante, o está en el paro<br/>
por eso y más, no volverás<br/>
¡te hemos echado!<br/>
NO MAS SERVERS VIEJOS<br/>
No más servers<br/>
No más servers<br/>
¡vieeeeeejos!<br/>
No más servers<br/>
No más servers<br/>
¡vieeeeeejos!<br/>
No más servers<br/>
No más servers<br/>
¡vieeeeeejos!<br/>
Cuantos años llevas<br/>
con esa distro vieja<br/>
cuanto tiempo hace<br/>
que salío esa versión<br/>
Esos script-kiddies<br/>
gobiernos y mafiosos<br/>
están acechando<br/>
a tu alrededor<br/>
Ha llegado la hora<br/>
tienes que actualizar<br/>
o en cualquier momento<br/>
tu server tumbarán<br/>
No más servers viejos<br/>
¡servers viejos no!<br/>
No más servers viejos<br/>
¡servers viejos no!<br/>
No más servers viejos<br/>
¡servers viejos no!<br/>
Cuantos años llevas<br/>
con esa distro vieja<br/>
cuanto tiempo hace<br/>
que salío esa versión<br/>
Esos script-kiddies<br/>
gobiernos y mafiosos<br/>
están acechando<br/>
a tu alrededor<br/>
Ha llegado la hora<br/>
tienes que actualizar<br/>
o en cualquier momento<br/>
tu server tumbarán<br/>
No más servers viejos<br/>
¡servers viejos no!<br/>
No más servers viejos<br/>
¡servers viejos no!<br/>
No más servers viejos<br/>
¡servers viejos no!<br/>
Cuanto tiempo llevas<br/>
con esa distro vieja<br/>
cuanto tiempo hace<br/>
que salío esa versión<br/>
Esos script-kiddies<br/>
gobiernos y mafiosos<br/>
están acechando<br/>
a tu alrededor<br/>
Ha llegado la hora<br/>
tienes que actualizar<br/>
o en cualquier momento<br/>
tu server tumbarán<br/>
No más servers viejos<br/>
¡servers viejos no!<br/>
No más servers viejos<br/>
¡servers viejos no!<br/>
No más servers viejos<br/>
¡servers viejos no!<br/>
No más servers<br/>
No más servers<br/>
¡vieeeeejos!<br/>
No más servers<br/>
No más servers<br/>
¡vieeeeejos!<br/>
No más servers<br/>
No más servers<br/>
¡vieeeeejos!<br/>
No más servers<br/>
No más servers<br/>
¡vieeeeejos!<br/>
No más servers<br/>
No más servers<br/>
¡vieeeeejos!<br/>
No más servers viejos<br/>
¡servers viejos no!<br/>
No más servers viejos<br/>
¡servers viejos no!<br/>
No más servers viejos<br/>
¡servers viejos no!<br/>
</p>
<ul class="files">
<li><a href="/te_hemos_echado_y_no_mas_servers_viejos/te_hemos_echado_y_no_mas_servers_viejos.mp4">te_hemos_echado_y_no_mas_servers_viejos.mp4</a></li>
<li><a href="/te_hemos_echado_y_no_mas_servers_viejos/te_hemos_echado_y_no_mas_servers_viejos.kdenlive">te_hemos_echado_y_no_mas_servers_viejos.kdenlive</a></li>
<li><a href="/te_hemos_echado_y_no_mas_servers_viejos/te_hemos_echado_y_no_mas_servers_viejos.srt">te_hemos_echado_y_no_mas_servers_viejos.srt</a></li>
</ul>
</div>
<nav id="menu">
<ul>
@ -80,49 +382,6 @@
<p id="playlist"><a href="/playlist/">Playlist</a></p>
<p id="libreto"><a href="/static/libreto/libreto.pdf"><img src="/static/libreto/libreto.png">Libreto</a>
</nav>
<div id="content">
<h1>No más servers viejos</h1>
<p><b>Original:</b> No más punkis muertos, M.C.D.</p>
<video id="te_hemos_echado_y_no_mas_servers_viejos-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/te_hemos_echado_y_no_mas_servers_viejos/te_hemos_echado_y_no_mas_servers_viejos.jpg">
<source src="/te_hemos_echado_y_no_mas_servers_viejos/te_hemos_echado_y_no_mas_servers_viejos.mp4" type='video/mp4'>
<track kind="captions" src="/te_hemos_echado_y_no_mas_servers_viejos/te_hemos_echado_y_no_mas_servers_viejos.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<ul class="files">
<li><a href="/te_hemos_echado_y_no_mas_servers_viejos/te_hemos_echado_y_no_mas_servers_viejos.mp4">te_hemos_echado_y_no_mas_servers_viejos.mp4</a></li>
<li><a href="/te_hemos_echado_y_no_mas_servers_viejos/te_hemos_echado_y_no_mas_servers_viejos.kdenlive">te_hemos_echado_y_no_mas_servers_viejos.kdenlive</a></li>
<li><a href="/te_hemos_echado_y_no_mas_servers_viejos/te_hemos_echado_y_no_mas_servers_viejos.srt">te_hemos_echado_y_no_mas_servers_viejos.srt</a></li>
</ul>
<script>
videojs('te_hemos_echado_y_no_mas_servers_viejos-video', {
/*
plugins: {
},
*/
});
</script>
</div>
</body>
</html>

View File

@ -19,8 +19,208 @@
</head>
<body>
<header id="header">
<h1><a href="/">Negro Mate</a></h1>
<h1><a href="/home/">Negro Mate</a></h1>
</header>
<div id="content">
<h1>Tengo una debian de servidor</h1>
<p><b>Original:</b> Tengo una banda, Loquillo y los trogloditas</p>
<video id="tengo_una_debian_de_servidor-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/tengo_una_debian_de_servidor/tengo_una_debian_de_servidor.jpg">
<source src="/tengo_una_debian_de_servidor/tengo_una_debian_de_servidor.mp4" type='video/mp4'>
<track kind="captions" src="/tengo_una_debian_de_servidor/tengo_una_debian_de_servidor.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<script>
videojs('tengo_una_debian_de_servidor-video', {
/*
plugins: {
},
*/
});
</script>
<p class="lyrics">
el ISP me dice<br/>
tu ordena no es normal<br/>
vaya sistema mas raro<br/>
con el que tú vas<br/>
la NSA me dice<br/>
eso a mí me da igual<br/>
pero en el fondo sabe<br/>
que no va a entrar<br/>
cualquier noche un usuario <br/>
UoooOOOOoo<br/>
en su habitación<br/>
cantara a gritos<br/>
esta canción<br/>
cualquier noche un usuario<br/>
UoooOOOOoo<br/>
en su habitación<br/>
cantara a gritos<br/>
esta canción<br/>
porque yo<br/>
tengo una debian<br/>
de servidor<br/>
UoooUooo<br/>
porque yo<br/>
tengo una debian<br/>
de servidor<br/>
el ISP me dice<br/>
tu ordena no es normal<br/>
vaya sistema mas raro<br/>
con el que tú vas<br/>
la NSA me dice<br/>
eso a mí me da igual<br/>
pero en el fondo sabe<br/>
que no va a entrar<br/>
cualquier noche un usuario<br/>
UoooOOOOoo<br/>
en su habitación<br/>
cantara a gritos<br/>
esta canción<br/>
cualquier noche un usuario<br/>
UoooOOOOoo<br/>
en su habitación<br/>
cantara a gritos<br/>
esta canción<br/>
porque yo<br/>
tengo una debian<br/>
de servidor<br/>
UoooUooo<br/>
porque yo<br/>
tengo una debian<br/>
de servidor<br/>
cualquier noche un usuario<br/>
UoooOOOOoo<br/>
en su habitación<br/>
cantara a gritos<br/>
esta canción<br/>
cualquier noche un usuario<br/>
UoooOOOOoo<br/>
en su habitación<br/>
cantara a gritos<br/>
esta canción<br/>
porque yo<br/>
tengo una debian<br/>
de servidor<br/>
UoooUooo<br/>
porque yo<br/>
tengo una debian<br/>
de servidor<br/>
porque yo<br/>
tengo una debian<br/>
de servidor<br/>
UoooUooo<br/>
porque tú<br/>
tienes tu debian<br/>
de servidor<br/>
los debianitas!!!<br/>
</p>
<ul class="files">
<li><a href="/tengo_una_debian_de_servidor/tengo_una_debian_de_servidor.mp4">tengo_una_debian_de_servidor.mp4</a></li>
<li><a href="/tengo_una_debian_de_servidor/tengo_una_debian_de_servidor.srt">tengo_una_debian_de_servidor.srt</a></li>
</ul>
</div>
<nav id="menu">
<ul>
@ -80,47 +280,6 @@
<p id="playlist"><a href="/playlist/">Playlist</a></p>
<p id="libreto"><a href="/static/libreto/libreto.pdf"><img src="/static/libreto/libreto.png">Libreto</a>
</nav>
<div id="content">
<h1>Tengo una debian de servidor</h1>
<p><b>Original:</b> Tengo una banda, Loquillo y los trogloditas</p>
<video id="tengo_una_debian_de_servidor-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/tengo_una_debian_de_servidor/tengo_una_debian_de_servidor.jpg">
<source src="/tengo_una_debian_de_servidor/tengo_una_debian_de_servidor.mp4" type='video/mp4'>
<track kind="captions" src="/tengo_una_debian_de_servidor/tengo_una_debian_de_servidor.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<ul class="files">
<li><a href="/tengo_una_debian_de_servidor/tengo_una_debian_de_servidor.mp4">tengo_una_debian_de_servidor.mp4</a></li>
<li><a href="/tengo_una_debian_de_servidor/tengo_una_debian_de_servidor.srt">tengo_una_debian_de_servidor.srt</a></li>
</ul>
<script>
videojs('tengo_una_debian_de_servidor-video', {
/*
plugins: {
},
*/
});
</script>
</div>
</body>
</html>

View File

@ -19,8 +19,135 @@
</head>
<body>
<header id="header">
<h1><a href="/">Negro Mate</a></h1>
<h1><a href="/home/">Negro Mate</a></h1>
</header>
<div id="content">
<h1>Troles ni uno</h1>
<p><b>Original:</b> Botes de humo, Zikatriz</p>
<video id="trolesniuno-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/trolesniuno/trolesniuno.jpg">
<source src="/trolesniuno/trolesniuno.mp4" type='video/mp4'>
<track kind="captions" src="/trolesniuno/trolesniuno.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<script>
videojs('trolesniuno-video', {
/*
plugins: {
ass: {
'src': ["/trolesniuno/trolesniuno.ass"],
// videoWidth: 640,
// videoHeight: 360,
enableSvg: false,
}
},
*/
});
</script>
<p class="lyrics">
TROLES NI UNO!<br/>
Vaya tocho aquí hay follón<br/>
ya está el troll en acción<br/>
miles de emails verás<br/>
tu paciencia acabarán<br/>
atentos a lo que leeis<br/>
que ya ha respondido a seis<br/>
atentos a lo que leeis<br/>
que ya ha respondido a seis<br/>
TROLES NI UNO!<br/>
TROLES NI UNO!<br/>
TROLES NI UNO!<br/>
Hilos de más de un kilómetro<br/>
te aburren, a tí y al prójimo<br/>
Sus falacias van soltando<br/>
a la vasca van cansando<br/>
La libertad de expresión<br/>
no justifica tu acción<br/>
eso no es libre expresión<br/>
lo tuyo es una agresión<br/>
TROLES NI UNO!<br/>
TROLES NI UNO!<br/>
TROLES NI UNO!<br/>
Vaya tocho aquí hay follón<br/>
ya está el troll en acción<br/>
miles de emails verás<br/>
tu paciencia acabarán<br/>
Atentos a lo que leeis<br/>
que ya ha respondido a seis<br/>
Atentos a lo que leeis<br/>
que ya ha respondido a seis<br/>
TROLES NI UNO!<br/>
TROLES NI UNO!<br/>
TROLES NI UNO!<br/>
</p>
<ul class="files">
<li><a href="/trolesniuno/trolesniuno.mp4">trolesniuno.mp4</a></li>
<li><a href="/trolesniuno/trolesniuno.ass">trolesniuno.ass</a></li>
<li><a href="/trolesniuno/trolesniuno.srt">trolesniuno.srt</a></li>
</ul>
</div>
<nav id="menu">
<ul>
@ -80,56 +207,6 @@
<p id="playlist"><a href="/playlist/">Playlist</a></p>
<p id="libreto"><a href="/static/libreto/libreto.pdf"><img src="/static/libreto/libreto.png">Libreto</a>
</nav>
<div id="content">
<h1>Troles ni uno</h1>
<p><b>Original:</b> Botes de humo, Zikatriz</p>
<video id="trolesniuno-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/trolesniuno/trolesniuno.jpg">
<source src="/trolesniuno/trolesniuno.mp4" type='video/mp4'>
<track kind="captions" src="/trolesniuno/trolesniuno.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<ul class="files">
<li><a href="/trolesniuno/trolesniuno.mp4">trolesniuno.mp4</a></li>
<li><a href="/trolesniuno/trolesniuno.ass">trolesniuno.ass</a></li>
<li><a href="/trolesniuno/trolesniuno.srt">trolesniuno.srt</a></li>
</ul>
<script>
videojs('trolesniuno-video', {
/*
plugins: {
ass: {
'src': ["/trolesniuno/trolesniuno.ass"],
// videoWidth: 640,
// videoHeight: 360,
enableSvg: false,
}
},
*/
});
</script>
</div>
</body>
</html>

View File

@ -19,8 +19,95 @@
</head>
<body>
<header id="header">
<h1><a href="/">Negro Mate</a></h1>
<h1><a href="/home/">Negro Mate</a></h1>
</header>
<div id="content">
<h1>Kodea itxita utziko banu</h1>
<p><b>Original:</b> Txoria txori, Etsaiak</p>
<video id="txoria_txori-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/txoria_txori/txoria_txori.jpg">
<source src="/txoria_txori/txoria_txori.mp4" type='video/mp4'>
<track kind="captions" src="/txoria_txori/txoria_txori.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<script>
videojs('txoria_txori-video', {
/*
plugins: {
ass: {
'src': ["/txoria_txori/txoria_txori.ass"],
// videoWidth: 640,
// videoHeight: 360,
enableSvg: false,
}
},
*/
});
</script>
<p class="lyrics">
kodea itxita utziko banu<br/>
neria izango zen<br/>
ez zuten kopiatuko<br/>
kodea itxita utziko banu<br/>
neria izango zen<br/>
ez zuten kopiatuko<br/>
baina honela<br/>
ez zen gehiago askea izango<br/>
baina honela<br/>
ez zen gehiago askea izango<br/>
eta nik,<br/>
kodea nuen maite!<br/>
eta nik,<br/>
kodea nuen maite!<br/>
</p>
<ul class="files">
<li><a href="/txoria_txori/txoria_txori.mp4">txoria_txori.mp4</a></li>
<li><a href="/txoria_txori/txoria_txori.srt">txoria_txori.srt</a></li>
<li><a href="/txoria_txori/txoria_txori.ass">txoria_txori.ass</a></li>
</ul>
</div>
<nav id="menu">
<ul>
@ -80,56 +167,6 @@
<p id="playlist"><a href="/playlist/">Playlist</a></p>
<p id="libreto"><a href="/static/libreto/libreto.pdf"><img src="/static/libreto/libreto.png">Libreto</a>
</nav>
<div id="content">
<h1>Kodea itxita utziko banu</h1>
<p><b>Original:</b> Txoria txori, Etsaiak</p>
<video id="txoria_txori-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/txoria_txori/txoria_txori.jpg">
<source src="/txoria_txori/txoria_txori.mp4" type='video/mp4'>
<track kind="captions" src="/txoria_txori/txoria_txori.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<ul class="files">
<li><a href="/txoria_txori/txoria_txori.mp4">txoria_txori.mp4</a></li>
<li><a href="/txoria_txori/txoria_txori.srt">txoria_txori.srt</a></li>
<li><a href="/txoria_txori/txoria_txori.ass">txoria_txori.ass</a></li>
</ul>
<script>
videojs('txoria_txori-video', {
/*
plugins: {
ass: {
'src': ["/txoria_txori/txoria_txori.ass"],
// videoWidth: 640,
// videoHeight: 360,
enableSvg: false,
}
},
*/
});
</script>
</div>
</body>
</html>

Binary file not shown.

View File

@ -19,8 +19,213 @@
</head>
<body>
<header id="header">
<h1><a href="/">Negro Mate</a></h1>
<h1><a href="/home/">Negro Mate</a></h1>
</header>
<div id="content">
<h1>Usuariado</h1>
<p><b>Original:</b> El vals del proletariado, SKA-P</p>
<video id="usuariado-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/usuariado/usuariado.jpg">
<source src="/usuariado/usuariado.mp4" type='video/mp4'>
<track kind="captions" src="/usuariado/usuariado.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<script>
videojs('usuariado-video', {
/*
plugins: {
ass: {
'src': ["/usuariado/usuariado.ass"],
// videoWidth: 640,
// videoHeight: 360,
enableSvg: false,
}
},
*/
});
</script>
<p class="lyrics">
Orgulloso de estar<br/>
entre el usuariado<br/>
y copiar y pegar y llorar y llorar<br/>
no se hacer nada mas<br/>
otro lo arreglara<br/>
este es mi windows<br/>
este es mi apple<br/>
soy un usuario<br/>
compro en el mediamarket<br/>
por eso tu que sabes mazo<br/>
sin verguenza yo te pido este favor<br/>
arregla el ordenador<br/>
si señor, arreglamelo<br/>
si señor, si señor, arregla el ordenador<br/>
yo no tengo intención<br/>
si señor, si señor, arregla el ordenador<br/>
arregla el ordenador<br/>
hartita ya me tienes<br/>
de tu windows y office<br/>
que te empeñas en utilizar<br/>
te pongo software libre<br/>
te hago las particiones<br/>
y no lo quieres ni arrancar<br/>
#FIXME<br/>
le das que si a todo<br/>
te mofas de la seguridad<br/>
y cuando la has cagado<br/>
y no funciona nada<br/>
ni un minuto puedes esperar<br/>
USUARIADO<br/>
que calvario!<br/>
USUARIADO<br/>
este es mi windows<br/>
este es mi apple<br/>
soy un usuario<br/>
compro en el mediamaaaaaaarket<br/>
por eso tu que sabes mazo<br/>
sin verguenza yo te pido este favor<br/>
arregla el ordenador<br/>
si señor, arreglamelo<br/>
si señor, si séñor, arregla el ordenador<br/>
yo no tengo intención<br/>
si señor, si señor arregla el ordenador<br/>
arregla el ordenador<br/>
hartita ya me tienes<br/>
de tu windows y office<br/>
que te empeñas en utilizar<br/>
te pongo software libre<br/>
te hago las particiones<br/>
y no lo quieres ni arrancar<br/>
#FIXME<br/>
le das que si a todo<br/>
te mofas de la seguridad<br/>
y cuando la has cagado<br/>
y no funciona nada<br/>
ni un minuto puedes esperar<br/>
USUARIADO<br/>
que calvario<br/>
USUARIADO<br/>
que calvario<br/>
USUARIADO<br/>
que calvario!<br/>
USUARIADO<br/>
que calvario<br/>
USUARIADO<br/>
que calvario<br/>
USUARIADO<br/>
que calvario<br/>
IN<br/>
SO<br/>
POR<br/>
TA<br/>
BLES<br/>
</p>
<ul class="files">
<li><a href="/usuariado/usuariado.ass">usuariado.ass</a></li>
<li><a href="/usuariado/usuariado.mp4">usuariado.mp4</a></li>
<li><a href="/usuariado/usuariado.srt">usuariado.srt</a></li>
</ul>
</div>
<nav id="menu">
<ul>
@ -80,56 +285,6 @@
<p id="playlist"><a href="/playlist/">Playlist</a></p>
<p id="libreto"><a href="/static/libreto/libreto.pdf"><img src="/static/libreto/libreto.png">Libreto</a>
</nav>
<div id="content">
<h1>Usuariado</h1>
<p><b>Original:</b> El vals del proletariado, SKA-P</p>
<video id="usuariado-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/usuariado/usuariado.jpg">
<source src="/usuariado/usuariado.mp4" type='video/mp4'>
<track kind="captions" src="/usuariado/usuariado.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<ul class="files">
<li><a href="/usuariado/usuariado.ass">usuariado.ass</a></li>
<li><a href="/usuariado/usuariado.mp4">usuariado.mp4</a></li>
<li><a href="/usuariado/usuariado.srt">usuariado.srt</a></li>
</ul>
<script>
videojs('usuariado-video', {
/*
plugins: {
ass: {
'src': ["/usuariado/usuariado.ass"],
// videoWidth: 640,
// videoHeight: 360,
enableSvg: false,
}
},
*/
});
</script>
</div>
</body>
</html>

View File

@ -1,56 +0,0 @@
1
00:00:01,000 --> 00:00:04,900
y no me importa nada
2
00:00:05,000 --> 00:00:08,000
que tus colegas vuelen
3
00:00:08,000 --> 00:00:12,000
que llores ante españa
4
00:00:12,000 --> 00:00:16,000
y no me importa nada
5
00:00:35,000 --> 00:00:38,400
y no me importa nada
6
00:00:38,500 --> 00:00:41,500
que se rían en europa
7
00:00:41,500 --> 00:00:46,000
que te partan la cara
8
00:00:46,000 --> 00:00:49,000
y no me importa nada
9
00:00:50,100 --> 00:00:53,500
tus nietas no te quieren
10
00:00:53,500 --> 00:00:57,000
te sientes rechazada
11
00:00:57,000 --> 00:01:01,000
y no me importa nada
12
00:01:02,000 --> 00:01:05,000
que no llegues a juicio
13
00:01:05,000 --> 00:01:08,000
que te dispares en la espalda
14
00:01:08,000 --> 00:01:12,000
y no me importa nada

View File

@ -19,8 +19,97 @@
</head>
<body>
<header id="header">
<h1><a href="/">Negro Mate</a></h1>
<h1><a href="/home/">Negro Mate</a></h1>
</header>
<div id="content">
<h1>Y no me importa nada</h1>
<p><b>Original:</b> Y no me importa nada, Luz Casal</p>
<video id="ynomeimportanada-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/ynomeimportanada/ynomeimportanada.jpg">
<source src="/ynomeimportanada/ynomeimportanada.mp4" type='video/mp4'>
<track kind="captions" src="/ynomeimportanada/ynomeimportanada.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<script>
videojs('ynomeimportanada-video', {
/*
plugins: {
ass: {
'src': ["/ynomeimportanada/ynomeimportanada.ass"],
// videoWidth: 640,
// videoHeight: 360,
enableSvg: false,
}
},
*/
});
</script>
<p class="lyrics">
y no me importa nada<br/>
que tus colegas vuelen<br/>
que llores ante españa<br/>
y no me importa nada<br/>
y no me importa nada<br/>
que se rían en europa<br/>
que te partan la cara<br/>
y no me importa nada<br/>
tus nietas no te quieren<br/>
te sientes rechazada<br/>
y no me importa nada<br/>
que no llegues a juicio<br/>
que te dispares en la espalda<br/>
y no me importa nada<br/>
</p>
<ul class="files">
<li><a href="/ynomeimportanada/ynomeimportanada_subtitulado.mp4">ynomeimportanada_subtitulado.mp4</a></li>
<li><a href="/ynomeimportanada/ynomeimportanada.mp4">ynomeimportanada.mp4</a></li>
<li><a href="/ynomeimportanada/ynomeimportanada.ass">ynomeimportanada.ass</a></li>
<li><a href="/ynomeimportanada/ynomeimportanada.srt">ynomeimportanada.srt</a></li>
</ul>
</div>
<nav id="menu">
<ul>
@ -80,56 +169,6 @@
<p id="playlist"><a href="/playlist/">Playlist</a></p>
<p id="libreto"><a href="/static/libreto/libreto.pdf"><img src="/static/libreto/libreto.png">Libreto</a>
</nav>
<div id="content">
<h1>Y no me importa nada</h1>
<p><b>Original:</b> Y no me importa nada, Luz Casal</p>
<video id="ynomeimportanada-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/ynomeimportanada/ynomeimportanada.jpg">
<source src="/ynomeimportanada/ynomeimportanada_subtitulado.mp4" type='video/mp4'>
<track kind="captions" src="/ynomeimportanada/ynomeimportanada.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<ul class="files">
<li><a href="/ynomeimportanada/ynomeimportanada_subtitulado.mp4">ynomeimportanada_subtitulado.mp4</a></li>
<li><a href="/ynomeimportanada/ynomeimportanada.ass">ynomeimportanada.ass</a></li>
<li><a href="/ynomeimportanada/ynomeimportanada.srt">ynomeimportanada.srt</a></li>
</ul>
<script>
videojs('ynomeimportanada-video', {
/*
plugins: {
ass: {
'src': ["/ynomeimportanada/ynomeimportanada.ass"],
// videoWidth: 640,
// videoHeight: 360,
enableSvg: false,
}
},
*/
});
</script>
</div>
</body>
</html>

View File

@ -19,8 +19,115 @@
</head>
<body>
<header id="header">
<h1><a href="/">Negro Mate</a></h1>
<h1><a href="/home/">Negro Mate</a></h1>
</header>
<div id="content">
<h1>Yo quiero ser makero</h1>
<p><b>Original:</b> Yo quiero ser torero, Korroskada</p>
<video id="yoquierosermakero-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/yoquierosermakero/yoquierosermakero.jpg">
<source src="/yoquierosermakero/yoquierosermakero.mp4" type='video/mp4'>
<track kind="captions" src="/yoquierosermakero/yoquierosermakero.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<script>
videojs('yoquierosermakero-video', {
/*
plugins: {
ass: {
'src': ["/yoquierosermakero/yoquierosermakero.ass"],
// videoWidth: 640,
// videoHeight: 360,
enableSvg: false,
}
},
*/
});
</script>
<p class="lyrics">
En el trabajo el ordena no tira<br/>
Y en mi casa ni se enciende<br/>
En el barrio me miran mal<br/>
Las licencias sin pagar<br/>
En el trabajo el ordena no tira<br/>
Y en mi casa ni se enciende<br/>
En el barrio me miran mal<br/>
Las licencias sin pagar<br/>
Estoy harto lo que yo quiero es ser<br/>
Makero!<br/>
Yo quiero ser makero<br/>
Makero, yo quiero ser<br/>
Makero, mucho dinero<br/>
Para gastarlo como yo quiero<br/>
Yo quiero ser makero<br/>
Makero, yo quiero ser<br/>
Makero, mucho dinero<br/>
Para gastarlo como yo quiero<br/>
Que mi cartera ya no pueda<br/>
mi aficción siempre fue<br/>
un iphone<br/>
una tableta<br/>
y un buen ipod para correr<br/>
Esoy harto lo que yo quiero es ser<br/>
</p>
<ul class="files">
<li><a href="/yoquierosermakero/yoquierosermakero.ass">yoquierosermakero.ass</a></li>
<li><a href="/yoquierosermakero/yoquierosermakero.srt">yoquierosermakero.srt</a></li>
<li><a href="/yoquierosermakero/yoquierosermakero.mp4">yoquierosermakero.mp4</a></li>
</ul>
</div>
<nav id="menu">
<ul>
@ -80,47 +187,6 @@
<p id="playlist"><a href="/playlist/">Playlist</a></p>
<p id="libreto"><a href="/static/libreto/libreto.pdf"><img src="/static/libreto/libreto.png">Libreto</a>
</nav>
<div id="content">
<h1>Yo quiero ser makero</h1>
<p><b>Original:</b> Yo quiero ser torero, Korroskada</p>
<video id="yoquierosermakero-video" class="video-js"
controls preload="auto" width="640" height="264"
poster="/yoquierosermakero/yoquierosermakero.jpg">
<source src="/yoquierosermakero/yoquierosermakero.mp4" type='video/mp4'>
<track kind="captions" src="/yoquierosermakero/yoquierosermakero.vtt" srclang="nm" label="Negro mate" default>
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
<ul class="files">
<li><a href="/yoquierosermakero/yoquierosermakero.srt">yoquierosermakero.srt</a></li>
<li><a href="/yoquierosermakero/yoquierosermakero.mp4">yoquierosermakero.mp4</a></li>
</ul>
<script>
videojs('yoquierosermakero-video', {
/*
plugins: {
},
*/
});
</script>
</div>
</body>
</html>

View File

@ -1,104 +0,0 @@
http://www.molbr.co.uk/piperrak/autosuficiencia/
Me miro en el espejo y soy feliz
y no pienso nunca en nadie mas k mi
y no pienso nunca en nadie mas k mi
leo emilios que anonymous filtró
oigo cintas que el gobierno ocultó
oigo cintas que el gobierno ocultó
Encerrado en la embajada,
todo me da igual
ya no necesito a nadie
no saldre jamás
y me baño en agua fria sin parar
y me corto con cuchillas de afeitar
y me corto con cuchillas de afeitar
me tumbo en el suelo de mi habitacion
buscando sensores y microfonos
buscando sensores y microfonos
Encerrado en la embajada,
todo me da igual
ya no necesito a nadie
no saldre jamás
Ahora soy un héroe viviente
ya no necesito gente
ya soy autosuficiente
al fin!!
Me miro en el espejo y soy feliz
y no pienso nunca en nadie mas k mi
y no pienso nunca en nadie mas k mi
leo emilios que anonymous filtró
oigo cintas que el gobierno ocultó
oigo cintas que el gobierno ocultó
Encerrado en la embajada,
todo me da igual
ya no necesito a nadie
no saldre jamás
Ahora soy independiente
ya no necesito gente
ya soy autosuficiente
al fin!!
Me miro en el espejo y soy feliz!!!
==============================================================================
Me miro en el espejo y soy feliz
y no pienso nunca en nadie mas k mi
y no pienso nunca en nadie mas k mi
leo libros que no entiendo mas que yo
oigo cintas que e gravado con mi voz
oigo cintas que e gravado con mi voz
Encerrado en mi casa,
todo me da igual
ya no necesito a nadie
no saldre jamás
y me baño en agua fria sin parar
y me corto con cuchillas de afeitar
y me corto con cuchillas de afeitar
me tumbo en el suelo de mi habitacion
y veo mi cuerpo en descomposición
y veo mi cuerpo en descomposición
Encerrado en mi casa,
todo me da igual
ya no necesito a nadie
no saldre jamás
Ahora soy independiente
ya no necesito gente
ya soy autosuficiente
al fin!!
Me miro en el espejo y soy feliz
y no pienso nunca en nadie mas k mi
y no pienso nunca en nadie mas k mi
leo libros que no entiendo mas que yo
oigo cintas que e gravado con mi voz
oigo cintas que e gravado con mi voz
Encerrado en mi casa,
todo me da igual
ya no necesito a nadie
no saldre jamás
Ahora soy independiente
ya no necesito gente
ya soy autosuficiente
al fin!!
Me miro en el espejo y soy feliz!!!

View File

@ -1,111 +0,0 @@
http://www.youtube.com/watch?v=rLl6ofNXL20
Veo todo en verde y negro
el prompt acaba siendo amigo mudo
las mismas teclas, todo son sustos
en el vimtuto o o or
quiero ser un hacker de la hostia
hacerlo todo en la shell, un día tras otro
y un buen rato después poder llegar a casa
sin usar el ratón, tecleando todo el día
Tengo tiempo para aprender, hoy la red parece distinta
durante horas puedo ser capaz
de romper claves, conectarme para esnifar
aprendiendo en cada esquina
solo quiero ser un hacker de la hostia
acceder otra vez, a todos sus servers
y un buen rato despues saber llegar a ser root
chuparles los datos y joderles de por vida.
Casi nunca sé donde estoy
no me importa el sistema, ni la protección,
me preguntaré, que coño hay aquí
dispuesto a buscar un proxy si hace falta,
porque sé que el tor me anonimiza
combate al gran hermano
veo todo en verde y negro, verde y negro.
Porque sé que el tor me anonimiza
combate al gran hermano
veo todo en verde y negro, verde y negro.
Porque sé lo que es ser, un hacker de la hostia
siempre poder tener, contenidos libres
y el software también, un grupo de gente
liberando la red, construyendo en anarquía
Ya sé lo que es ser, un hacker de la hostia
siempre poder tener, contenidos libres
y el software también, un grupo de gente
liberando la red, construyendo en anarquía
====================================================
Veo todo en blanco y negro
el vaso acaba siendo amigo mudo
las mismas caras, los mismos gestos
amigo mudo.
Quiero ser más rápido que ellos
echar todo a perder, un día trás otro
y un buen rato después saber llegar a casa
antes de que el sol me diga que es de dia.
Tengo tiempo para crecer , la ciudad parece distinta
durante horas puedo ser capaz
de emocionarme en estas calles y andar inmortal
aprendiendo cada esquina,
solo quiero ser más rápido que ellos
echar todo a perder, un día trás otro
y un buen rato después saber llegar a casa
antes de que el sol me diga que es de dia.
Casi nunca se donde estoy
no me inportan los dias ni la dirección,
te preguntarás que coño hago aquí
dispuesto a buscar pelea si hace falta,
porque sé que es un baile salvaje
combate a mala cara
veo todo en blanco y negro, blanco y negro.
Sé que es un baile salvaje
combate a mala cara
veo todo en blanco y negro, blanco y negro.
Sólo quiero ser...
Veo todo en blanco y negro
el vaso acaba siendo amigo mudo
las mismas caras, los mismos gestos
amigo mudo.
Quiero ser más rápido que ellos
echar todo a perder, un día trás otro
y un buen rato después saber llegar a casa
antes de que el sol me diga que es de dia.
Tengo tiempo para crecer , la ciudad parece distinta
durante horas puedo ser capaz
de emocionarme en estas calles y andar inmortal
aprendiendo cada esquina,
solo quiero ser más rápido que ellos
echar todo a perder, un día trás otro
y un buen rato después saber llegar a casa
antes de que el sol me diga que es de dia.
Casi nunca se donde estoy
no me inportan los dias ni la dirección,
te preguntarás que coño hago aquí
dispuesto a buscar pelea si hace falta,
porque sé que es un baile salvaje
combate a mala cara
veo todo en blanco y negro, blanco y negro.
Sé que es un baile salvaje
combate a mala cara
veo todo en blanco y negro, blanco y negro.
Sólo quiero ser...

View File

@ -1,36 +0,0 @@
1
00:00:14,000 --> 00:00:19,590
GNU es un acronimo gnu esta compuesto
2
00:00:20,000 --> 00:00:26,590
tiene todo iniciales es un nombre corto y recursivo
3
00:00:27,000 --> 00:00:31,000
linux no puede ser eso no hay quien lo aguante
4
00:00:31,000 --> 00:00:33,590
tiene que llevar el gnu por delante
5
00:00:34,000 --> 00:00:36,590
bill esta furioso bill no esta contento
6
00:00:37,000 --> 00:00:41,000
alguien va a pagar sus nervios
7
00:00:41,010 --> 00:00:44,010
se monta una charla, stallman anda suelto
8
00:00:44,020 --> 00:00:49,020
va a empezar la charla, corre!
9
00:01:20,000 --> 00:01:24,000
en su repo hay parches de la peña

View File

@ -1,9 +0,0 @@
Para lo que quieras lo podrás usar
free software, oh free software
y a quien tú quieras se lo podrás pasar
porque es libre, eso es porque es libre
porque lo puedes abrir
y lo puedes compartir
y si lo quieres vender
también lo puedes hacer
porque es libre! libre!

View File

@ -1,59 +0,0 @@
Aprendimos a quererte
Con tu emacs y tu asperger
en el MIT una impresora
dio comienzo a esta historia
Así se forja la senda,
de la libertad duradera
por tu querida licencia
la licencia GPL.
Aprendimos a quererte
Desde la histórica altura
Donde el sol de tu bravura
Le puso un cerco a la muerte.
Aquí se queda la clara,
La entrañable transparencia,
De tu querida presencia
Comandante che guevara.
Tu mano gloriosa y fuerte
Sobre la historia dispara
Cuando todo santa clara
Se despierta para verte.
Aquí se queda la clara,
La entrañable transparencia,
De tu querida presencia
Comandante che guevara.
Vienes quemando la brisa
Con soles de primavera
Para plantar la bandera
Con la luz de tu sonrisa.
Aquí se queda la clara,
La entrañable transparencia,
De tu querida presencia
Comandante che guevara.
Tu amor revolucionario
Te conduce a nueva empresa
Donde esperan la firmeza
De tu brazo libertario.
Aquí se queda la clara,
La entrañable transparencia,
De tu querida presencia
Comandante che guevara.
Seguiremos adelante
Como junto a ti seguimos
Y con fidel te decimos:
Hasta siempre comandante.
Aquí se queda la clara,
La entrañable transparencia,
De tu querida presencia
Comandante che guevara

View File

@ -1,11 +0,0 @@
Instalacion, instalacion
que mas podia hacer yo
si mi sistema ya peto
y reinstalar va a ser
la unica solucion
Ubuntu o mint
o debian sid
con cual me quedo yo
si distros hay un monton
y yo soy un novato del copon

View File

@ -1,5 +0,0 @@
Hacktivista te hiciste cuando supisteeee
que los tekis la okupa tambien la visteeeen
las licencias, las eulas y las patenteeees

View File

@ -1,17 +0,0 @@
Voy a facebook
abandono mi intimidad
escapar de gnu social
acabar con tanto email y chats
porque allí
encontraré amistad
seré un friki inpresentable
en sociedad
tendre likes y amigos
sin parar
aunque no conozca a nadie
que más da

View File

@ -1,51 +0,0 @@
Puede ser, que no pero a este proyecto le falta ilusión
los bug reports, cada vez tiene menos
Aunque, aún no ha pasado mucho tiempo
otra versión, se empieza a echar de menos
No dudaré, escribir siempre que mi código me acerque a ti
Y si al final de compilar todo vuelve a funcionar
Quiero más commits
puede ser subversion mercurial o git
Mas commits
No hagas un fork, juntos lo haremos mejor.
El flame ha sido largo debo descansar
tengo ganas de irme no pienso contestar
ya se que tu quieres ayudar
Otro bugfix que podías haber arreglado
loco por ver que nuevo has aportado
Cae la luz, oscuridad es como un momento mágico y sensual
Y si al final de este ritual he logrado conectar.
Quiero más commits
puede ser subversion mercurial o git
Mas commits
No hagas un fork, juntos lo haremos mejor.
Quiero más commits
puede ser subversion mercurial o git
Mas commits
No hagas un fork, juntos lo haremos mejor.
Quiero más commits
puede ser subversion mercurial o git
Mas commits
No hagas un fork, juntos lo haremos mejor.
No voy a parar, quiero mucho más
Vamos ven aquí, dime lo que tu quieres de mí
Quiero más de ti
Nada es suficiente si no estás aquí
Más de ti
Todo es mejor si me haces sentir.
Quiero más de ti
Nada es suficiente si no estás aquí
Más de ti
Todo es mejor si me haces sentir tu calor.

View File

@ -1,21 +0,0 @@
Por fin, llego el final
de la gestión
de este alcalde
es otro día más
que un corrupto, está acabado
que bien vamos a estar
sin el PP en el gobierno
aquí no volverás
te hemos echado.
-...
...
Observo otra vez más
toda esa gente que has desahuciado
y encima crees que el que ha robado
es inmigrante o está en el paro
por eso y más, no volverás
te hemos echado

View File

@ -1,22 +0,0 @@
No mas servers no mas servers
vieeeeeeejooos! (BIS)
Cuanto tiempo llevas
con esa distro vieja
Cuanto tiempo hace
que salio esa version
Esos script-kiddies
gobiernos y mafiosos
están acechando
a tu alrededor
Ha llegado la hora
tienes que actualizar
o en cualquier momento
tu server tumbarán
No mas servers viejos
servers viejos no!

View File

@ -1,17 +0,0 @@
Yo no soy windowsero
Yo no soy windowsero
Ni uso Mac
Ni uso Mac
Ni uso Mac
Debian, debian.
Debian, debian.
Para instalar la debian
Para instalar la debian
se necesita un cd o una memoria
qué tipo de memoria
usb, usb, usb
Debian, Debian
Debian, Debian

View File

@ -1,9 +0,0 @@
gentes ignorantes que aun siguen usando windows
exigen favores que nunca valoran
cobardes
que van de amiguetes
que no se ponen linux porque no se atreven
y es que todo tiene un límite
asi estais todos limitados
pringado lo has arreglado
haciendo esos favores te han esclavizado (BIS)

View File

@ -1,54 +0,0 @@
Desde santurce a Bilbao, vengo por toda la orilla...
Mirarás al cielo y verás
una gran nube sucia
no lo pienses, no lo dudes
Altos Hornos de nuestra ciudad
Mirarás las fachadas
llenas de mie***, llenas de mie***
Desde Santurce a Bilbao, vengo por toda la orilla
Somos ratas en Bizkaia
somos ratas contaminadas
y vivimos en un pueblo
que naufraga, que naufraga, fraga, fraga
El orgulloso puente colgante
por debajo el gran Nervión
donde reposan los excrementos
despidiendo mal olor
En sus orillas cuanta gente
lucha por subsistir.
Desde Santurce a Bilbao, vengo por toda la orilla
Somos ratas en Bizkaia
somos ratas contaminadas
y vivimos en un pueblo
que naufraga, que naufraga, fraga, fraga
fraga, naufraga.
Desde mandrake a manjaro, he probao todos los linux,
Entre el google y facebook, tienen todo cotrolado
Nos vigilan todo el rato, entre el google y facebook
Mirarás a google y verás
Una gran nube sucia.
no lo uses, no lo busques
es otro espía, y nada más
llenas de ads, llenas de ads
No lo busques, en el google
No
No te jodas, toda la vida
Hay opciones,
para el que busca, busca, busca
Somos marcas, disociadas,
Somos masas etiquetadas
Y no vales nada, nada, nada

View File

@ -1,16 +0,0 @@
Salve
la copia
total o diferencial
total o diferencial
A costa de prometer
servicios en la nube
algunos vivillos
lo que están haciendo
es vender los datos
y la intimidad
de la peña
compre un pedazo de nube
pagando con su intimidad

View File

@ -1,52 +0,0 @@
Soy gnome,
y con debian soy feliz,
los datos en la home
y el sistema en la raíz.
Soy gnome,
y no me gusta compilar
todo lo que quieras tú
lo puedes instalar.
Soy 7 veces más fuerte que tu,
muy veloz
y siempre actualizada estoy.
Soy el hurd,
un kernel que todavía no se puede usar,
uso linux mientras no lo pueda instalar.
Soy gnome,
un escritorio simple y funcional,
si me quieres utilizar,
solo me has de instalar.
Evitando a los troyanos,
a los trolls y a los profetas,
con mi mula y con mi zorro,
voy navegando de aquí para allá,
ten cuidado no me ataques
si es que estás haciendo spam,
no sea que cometas una barbaridad.
Soy 7 veces más fuerte que tu,
muy veloz
y siempre actualizado estoy.
Soy gnome,
y con debian soy feliz,
los datos en la home
y el sistema en la raíz.
Soy stallman,
el más anciano del lugar,
y solo uso linxs para navegar.
Por esas rutas, bajo la terminal,
me encuentro fallos en winbugs que nunca diré.
Trabajo holgado, en mil y una cosas,
con ñus y pingüinos de momento estaré.
Soy 7 veces más fuerte que tu,
muy veloz
y siempre actualizada estoy.

View File

@ -1,10 +0,0 @@
Tu, tu pass es débil!
Tu, tu pass es débil!
Tu password es una mierda
La descifra hasta mi abuela..
Tu nombre no es un password
Ni en el facebook, ni en el banco
Tu pass es fatal, son cifras nada más

View File

@ -1,36 +0,0 @@
[Script Info]
; Script generated by Aegisub 3.1.2
; http://www.aegisub.org/
Title: Default Aegisub file
ScriptType: v4.00+
WrapStyle: 0
ScaledBorderAndShadow: yes
YCbCr Matrix: TV.601
PlayResX: 1280
PlayResY: 720
Audio URI: tu_pass_es_debil.mp4
Aegisub Scroll Position: 0
Aegisub Active Line: 3
Aegisub Video Zoom Percent: 0.500000
Video File: tu_pass_es_debil.mp4
Aegisub Video Aspect Ratio: c1.777778
Aegisub Video Position: 1841
[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Default,Arial,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,2,2,2,10,10,10,1
[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:50.00,0:00:52.00,Default,,0,0,0,,tu
Dialogue: 0,0:00:52.00,0:00:54.00,Default,,0,0,0,,tu pass
Dialogue: 0,0:00:54.00,0:00:56.00,Default,,0,0,0,,es débil
Dialogue: 0,0:00:58.50,0:01:00.50,Default,,0,0,0,,tu
Dialogue: 0,0:01:00.50,0:01:02.50,Default,,0,0,0,,tu pass
Dialogue: 0,0:01:02.50,0:01:04.50,Default,,0,0,0,,es débil
Dialogue: 0,0:00:50.00,0:00:52.00,Default,,0,0,0,,tu
Dialogue: 0,0:00:52.00,0:00:54.00,Default,,0,0,0,,tu pass
Dialogue: 0,0:00:54.00,0:00:56.00,Default,,0,0,0,,es débil
Dialogue: 0,0:00:50.00,0:00:52.00,Default,,0,0,0,,tu
Dialogue: 0,0:00:52.00,0:00:54.00,Default,,0,0,0,,tu pass
Dialogue: 0,0:00:54.00,0:00:56.00,Default,,0,0,0,,es débil

Binary file not shown.

View File

@ -1,28 +0,0 @@
Gnu es un acrónimo
Gnu está compuesto
Tiene todo iniciales,
es un nombre corto
y recursivo
Linux no puede ser
Eso no hay quien lo aguante
tiene que llevar
el gnu por delante
txus está
txus está nevioso
alguien va a pagar sus nervios
se ha montado una bronca
txus está en el suelo
ahora está contento
muerto!
se ha montado una charla
stallman anda suelto
corre!
en su repo hay
parches de la peña
txus no bebas tanto,
no pierdas la cabeza

View File

@ -1,18 +0,0 @@
Yo voy de negro
porque uso debian sid
te recito todos los puertos
hasta el mil
Para buscame mejor
que me hagas un ping
piiiiing!
Yo voy de negro
porque mola mogollon
porque el sed será
siempre mi editor
y las notas las tomo
en ensamblador,
ensambladooooor!

View File

@ -1,17 +0,0 @@
Ya tengo los virus
Ya tengo troyanos
Pero ya veis que os sirve de poco
habéis conseguido, infectarme
el sistema de pega que os preparé
y ahora qué
y ahora qué
y ahora qué me instalaréis
no podeis hacer nada contra mi
queréis espiarme pero
no podéis
porque de esos datos
mierda sacaréis
y ahora qué

View File

@ -1,7 +1,18 @@
#!/usr/bin/env python
from pathlib import Path
import sys
from pathlib import Path, PurePath
from negromateweb.builder import Builder
builder = Builder(Path('bideoak'))
if len(sys.argv) == 2:
root_path = sys.argv[1]
else:
# root_path = '/nm/'
root_path = '/'
builder = Builder(
Path('../bideoak'),
Path('../libreto/libreto.pdf'),
root_path=PurePath(root_path)
)
builder.build()

View File

@ -1,14 +1,16 @@
import json
import os
from shutil import copytree
from shutil import copytree, copy
from pathlib import Path, PurePath
import subprocess
from jinja2 import Template, Environment, PackageLoader, select_autoescape
import asstosrt
import srt
import webvtt
class VideoPage:
class SongPage:
THUMBNAIL_GEOMETRY = '200x200'
def __init__(self, path):
@ -17,6 +19,7 @@ class VideoPage:
self.author = None
self.path = path
self.video = None
self.video_type = None
self.vtt = None
self.srt = None
self.ass = None
@ -38,6 +41,15 @@ class VideoPage:
self.author = self.metadata['author']
elif entry.name.endswith('mp4'):
self.video = entry
self.video_type = 'video/mp4'
self.files.append(entry)
elif entry.name.endswith('webm'):
self.video = entry
self.video_type = 'video/webm'
self.files.append(entry)
elif entry.name.endswith('ogv'):
self.video = entry
self.video_type = 'video/ogg'
self.files.append(entry)
elif entry.name.endswith('vtt'):
self.vtt = entry
@ -56,13 +68,19 @@ class VideoPage:
else:
self.files.append(entry)
if self.srt is None and self.ass is not None:
self.srt = self.path / "{}.srt".format(self.path.name)
with self.ass.open('r') as assfile, self.srt.open('w') as srtfile:
srtfile.write(asstosrt.convert(assfile))
self.files.append(self.srt)
if self.vtt is None and self.srt is not None:
srtfile = self.path / self.srt
self.vtt = self.path / "{}.vtt".format(self.path.name)
webvtt.from_srt(str(self.srt.absolute())).save(str(self.vtt.absolute()))
if self.cover is None and self.video is not None:
self.cover = self.path / "{}.jpg".format(self.name)
self.cover = self.path / "{}.jpg".format(self.path.name)
command = [
'ffmpeg',
'-loglevel', 'quiet',
@ -77,7 +95,7 @@ class VideoPage:
subprocess.check_call(command)
if self.thumbnail is None and self.cover is not None:
self.thumbnail = self.path / "{}_thumbnail.jpg".format(self.name)
self.thumbnail = self.path / "{}_thumbnail.jpg".format(self.path.name)
subprocess.check_call([
'convert',
str(self.cover.absolute()),
@ -86,19 +104,29 @@ class VideoPage:
])
def get_context_data(self):
parsed_srt = None
if self.srt:
with self.srt.open('r') as srtfile:
try:
srt_str = srtfile.read().encode('utf-8').decode('utf-8-sig')
parsed_srt = list(srt.parse(srt_str))
except Exception as e:
print("{}: srt parse error: {}".format(self.path.name, e))
return {
'video': self,
'song': self,
'parsed_srt': parsed_srt,
}
def render(self, builder, context):
ctx = self.get_context_data()
ctx.update(context)
builder.render('video.html', self.path, ctx)
builder.render('song.html', self.path, ctx)
class Builder:
def __init__(self, root_folder, root_path=PurePath('/')):
def __init__(self, root_folder, libreto, root_path=PurePath('/')):
self.root_folder = root_folder
self.libreto = libreto
self.root_path = root_path
self.static_dir = Path(__file__).parent / 'static'
@ -119,34 +147,45 @@ class Builder:
page.write(page_template.render(context))
def build(self):
videos = []
songs = []
for entry in self.root_folder.iterdir():
if entry.name == 'static':
if entry.name in ['static', 'playlist', 'home']:
continue
if entry.is_dir():
print("building {}".format(entry.name))
try:
videopage = VideoPage(entry)
songpage = SongPage(entry)
except Exception as e:
raise e
print("Error: {}".format(e))
continue
videos.append(videopage)
songs.append(songpage)
global_context = {
'videos': videos,
'songs': songs,
'root_path': self.root_path,
}
for video in videos:
video.render(self, global_context)
for song in songs:
song.render(self, global_context)
self.render('home.html', self.root_folder, global_context)
self.render('index.html', self.root_folder, global_context)
home = self.root_folder / 'home'
if not home.exists():
home.mkdir()
self.render('home.html', home, global_context)
playlist = self.root_folder / 'playlist'
if not playlist.exists():
playlist.mkdir()
self.render('playlist.html', playlist, global_context)
static = self.root_folder / 'static'
if not static.exists():
path.mkdir()
static.mkdir()
subprocess.check_call([
'rsync',
@ -154,3 +193,6 @@ class Builder:
str(self.static_dir),
str(self.root_folder.absolute()),
])
libreto = self.root_folder / 'static/libreto/libreto.pdf'
copy(str(self.libreto.absolute()), str(libreto.absolute()))

2
web/negromateweb/static/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
node_modules
package-lock.json

View File

@ -39,7 +39,7 @@ header#header {
padding: 0.5em 1em;
}
#libreto {
#libreto, #playlist {
border: 1px solid #aaa;
border-radius: 0.5em;
text-align: center;
@ -58,12 +58,12 @@ header#header {
flex: 10;
}
.videos {
.songs {
display: flex;
flex-wrap: wrap;
}
.videos figure {
.songs figure {
flex: 1;
border: 1px solid gray;
text-align: center;
@ -71,10 +71,33 @@ header#header {
border-radius: 0.5em;
}
.videos figure legend {
.songs figure legend {
font-weight: bold;
}
video {
width: 100%;
}
.lyrics {
line-height: 1.2em;
}
#song-playlist #video-playlist {
margin-left: auto;
margin-right: auto;
}
.vjs-mouse.vjs-playlist {
font-size: 15pt;
}
.vjs-mouse.vjs-playlist .vjs-playlist-item-list {
display: flex;
flex-wrap: wrap;
}
.vjs-playlist .vjs-playlist-item {
flex: 1 100px;
}

View File

@ -0,0 +1,166 @@
<a name="3.5.2"></a>
## [3.5.2](https://github.com/brightcove/videojs-playlist-ui/compare/v3.5.1...v3.5.2) (2018-10-03)
### Bug Fixes
* Remove the playlist UI when the player is disposed. ([#81](https://github.com/brightcove/videojs-playlist-ui/issues/81)) ([c519585](https://github.com/brightcove/videojs-playlist-ui/commit/c519585))
* Remove the postinstall script to prevent install issues ([#76](https://github.com/brightcove/videojs-playlist-ui/issues/76)) ([fbe09e2](https://github.com/brightcove/videojs-playlist-ui/commit/fbe09e2))
### Chores
* update to generator-videojs-plugin[@7](https://github.com/7).2.0 ([0235fee](https://github.com/brightcove/videojs-playlist-ui/commit/0235fee))
* **package:** update rollup to version 0.66.0 ([#79](https://github.com/brightcove/videojs-playlist-ui/issues/79)) ([dc86980](https://github.com/brightcove/videojs-playlist-ui/commit/dc86980))
<a name="3.5.1"></a>
## [3.5.1](https://github.com/brightcove/videojs-playlist-ui/compare/v3.5.0...v3.5.1) (2018-08-23)
### Chores
* generator v7 ([#72](https://github.com/brightcove/videojs-playlist-ui/issues/72)) ([c8cb58d](https://github.com/brightcove/videojs-playlist-ui/commit/c8cb58d))
<a name="3.5.0"></a>
# [3.5.0](https://github.com/brightcove/videojs-playlist-ui/compare/v3.4.2...v3.5.0) (2018-08-20)
### Features
* set dataset attributes on playlist items when they have a data object ([#68](https://github.com/brightcove/videojs-playlist-ui/issues/68)) ([e16f2dd](https://github.com/brightcove/videojs-playlist-ui/commit/e16f2dd))
<a name="3.4.2"></a>
## [3.4.2](https://github.com/brightcove/videojs-playlist-ui/compare/v3.4.1...v3.4.2) (2018-08-03)
### Bug Fixes
* babel the es dist, by updating the generator ([#65](https://github.com/brightcove/videojs-playlist-ui/issues/65)) ([f63f77b](https://github.com/brightcove/videojs-playlist-ui/commit/f63f77b))
### Chores
* **package:** update dependencies, enable greenkeeper ([#62](https://github.com/brightcove/videojs-playlist-ui/issues/62)) ([63a89a7](https://github.com/brightcove/videojs-playlist-ui/commit/63a89a7))
<a name="3.4.1"></a>
## [3.4.1](https://github.com/brightcove/videojs-playlist-ui/compare/v3.0.7...v3.4.1) (2018-07-20)
### Bug Fixes
* css builds ([#63](https://github.com/brightcove/videojs-playlist-ui/issues/63)) ([603ec73](https://github.com/brightcove/videojs-playlist-ui/commit/603ec73))
### Reverts
* unintended pkg changes ([#64](https://github.com/brightcove/videojs-playlist-ui/issues/64)) ([be83683](https://github.com/brightcove/videojs-playlist-ui/commit/be83683))
<a name="3.0.8"></a>
## [3.0.8](https://github.com/brightcove/videojs-playlist-ui/compare/v3.0.6...v3.0.8) (2018-07-20)
### Bug Fixes
* update rollup to fix test build ([d329710](https://github.com/brightcove/videojs-playlist-ui/commit/d329710))
* revert: generator update from 3.0.7
<a name="3.0.7"></a>
## [3.0.7](https://github.com/brightcove/videojs-playlist-ui/compare/v3.4.0...v3.0.7) (2018-07-05)
### Chores
* generator v6 ([#58](https://github.com/brightcove/videojs-playlist-ui/issues/58)) ([e9c2b00](https://github.com/brightcove/videojs-playlist-ui/commit/e9c2b00))
<a name="3.4.0"></a>
# [3.4.0](https://github.com/brightcove/videojs-playlist-ui/compare/v3.3.0...v3.4.0) (2018-03-29)
### Features
* Expose the version of the plugin at the `VERSION` property. ([#56](https://github.com/brightcove/videojs-playlist-ui/issues/56)) ([cb2da9d](https://github.com/brightcove/videojs-playlist-ui/commit/cb2da9d))
### Bug Fixes
* Truncate longer video titles with ellipses when they overflow ([#57](https://github.com/brightcove/videojs-playlist-ui/issues/57)) ([18d8a18](https://github.com/brightcove/videojs-playlist-ui/commit/18d8a18))
### Chores
* Update tooling via the plugin generator. ([#55](https://github.com/brightcove/videojs-playlist-ui/issues/55)) ([b753ab3](https://github.com/brightcove/videojs-playlist-ui/commit/b753ab3))
<a name="3.3.0"></a>
# [3.3.0](https://github.com/brightcove/videojs-playlist-ui/compare/v3.2.1...v3.3.0) (2017-12-04)
### Features
* Support horizontal playlist display. ([#54](https://github.com/brightcove/videojs-playlist-ui/issues/54)) ([85965b6](https://github.com/brightcove/videojs-playlist-ui/commit/85965b6))
<a name="3.2.1"></a>
## [3.2.1](https://github.com/brightcove/videojs-playlist-ui/compare/v3.2.0...v3.2.1) (2017-11-29)
### Bug Fixes
* Do not concatenate playlist items if the plugin is re-initialized. ([#53](https://github.com/brightcove/videojs-playlist-ui/issues/53)) ([7953ad6](https://github.com/brightcove/videojs-playlist-ui/commit/7953ad6))
<a name="3.2.0"></a>
# [3.2.0](https://github.com/brightcove/videojs-playlist-ui/compare/v3.1.0...v3.2.0) (2017-11-29)
### Features
* Support the 'playlistsorted' event added in videojs-playlist 4.1.0. ([#52](https://github.com/brightcove/videojs-playlist-ui/issues/52)) ([6d79ac1](https://github.com/brightcove/videojs-playlist-ui/commit/6d79ac1))
<a name="3.1.0"></a>
# [3.1.0](https://github.com/brightcove/videojs-playlist-ui/compare/v3.0.6...v3.1.0) (2017-11-15)
### Features
* Better support for multiple in-page players by more intelligently finding a player's associated playlist element. ([#50](https://github.com/brightcove/videojs-playlist-ui/issues/50)) ([50bd97c](https://github.com/brightcove/videojs-playlist-ui/commit/50bd97c))
<a name="3.0.6"></a>
## [3.0.6](https://github.com/brightcove/videojs-playlist-ui/compare/v3.0.5...v3.0.6) (2017-09-05)
### Bug Fixes
* breaking changed caused by dist files being renamed ([#46](https://github.com/brightcove/videojs-playlist-ui/issues/46)) ([52140f4](https://github.com/brightcove/videojs-playlist-ui/commit/52140f4))
* simplify removal of vjs-ad-playing class ([#45](https://github.com/brightcove/videojs-playlist-ui/issues/45)) ([b49dc82](https://github.com/brightcove/videojs-playlist-ui/commit/b49dc82))
<a name="3.0.5"></a>
## [3.0.5](https://github.com/brightcove/videojs-playlist-ui/compare/v3.0.3...v3.0.5) (2017-05-19)
### Chores
* Update tooling using generator v5 prerelease. ([#42](https://github.com/brightcove/videojs-playlist-ui/issues/42)) ([6153b64](https://github.com/brightcove/videojs-playlist-ui/commit/6153b64))
# CHANGELOG
## 3.0.4
* @incompl Fix collision in CSS
* @incompl Fix accessibility for image thumbnails
## 3.0.3
* chore: @brandonocasey Fix Video.js 6 deprecation warnings
* chore: @brandonocasey Update unit tests to use karma
## 3.0.2
* @misteroneill More complete documentation and examples
## 3.0.1
* @misteroneill Update videojs-playlist to v3.0.0 [#24](https://github.com/brightcove/videojs-playlist-ui/pull/24)
* @diniscorreia Fix documentation for placeholder element [#30](https://github.com/brightcove/videojs-playlist-ui/pull/30)
* @diniscorreia Fix querySelector for list creation [#29](https://github.com/brightcove/videojs-playlist-ui/pull/29)
## 3.0.0
* Redesigned UI. Bigger thumbnails, more room for video titles, and more.
## 2.3.1
* @misteroneill More complete documentation and examples [#32](https://github.com/brightcove/videojs-playlist-ui/pull/32)
* @misteroneill Update to videojs-playlist 3.0.0 [#31](https://github.com/brightcove/videojs-playlist-ui/pull/31)
## 2.3.0
* Keep vjs-ad-playing class after postroll until ended event
## 2.2.0
* Fixup babelify and have a proper browserify endpoint
...
## 0.1.0
* Initial release

View File

@ -0,0 +1,30 @@
# CONTRIBUTING
We welcome contributions from everyone!
## Getting Started
Make sure you have Node.js 4.8 or higher and npm installed.
1. Fork this repository and clone your fork
1. Install dependencies: `npm install`
1. Run a development server: `npm start`
### Making Changes
Refer to the [video.js plugin conventions][conventions] for more detail on best practices and tooling for video.js plugin authorship.
When you've made your changes, push your commit(s) to your fork and issue a pull request against the original repository.
### Running Tests
Testing is a crucial part of any software project. For all but the most trivial changes (typos, etc) test cases are expected. Tests are run in actual browsers using [Karma][karma].
- In all available and supported browsers: `npm test`
- In a specific browser: `npm run test:chrome`, `npm run test:firefox`, etc.
- While development server is running (`npm start`), navigate to [`http://localhost:9999/test/`][local]
[karma]: http://karma-runner.github.io/
[local]: http://localhost:9999/test/
[conventions]: https://github.com/videojs/generator-videojs-plugin/blob/master/docs/conventions.md

View File

@ -0,0 +1,13 @@
Copyright Brightcove, Inc.
Licensed 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.

View File

@ -0,0 +1,110 @@
# videojs-playlist-ui
[![Build Status](https://travis-ci.org/brightcove/videojs-playlist-ui.svg?branch=master)](https://travis-ci.org/brightcove/videojs-playlist-ui)
[![Greenkeeper badge](https://badges.greenkeeper.io/brightcove/videojs-playlist-ui.svg)](https://greenkeeper.io/)
[![Slack Status](http://slack.videojs.com/badge.svg)](http://slack.videojs.com)
[![NPM](https://nodei.co/npm/videojs-playlist-ui.png?downloads=true&downloadRank=true)](https://nodei.co/npm/videojs-playlist-ui/)
A playlist video picker for video.js and videojs-playlist
Maintenance Status: Stable
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
- [Getting Started](#getting-started)
- [Root Element](#root-element)
- [Using Automatic Discovery (default, example)](#using-automatic-discovery-default-example)
- [Using a Custom Class (example)](#using-a-custom-class-example)
- [Using a Custom Element (example)](#using-a-custom-element-example)
- [Other Options](#other-options)
- [`className`](#classname)
- [playOnSelect](#playonselect)
- [Playlists and Advertisements](#playlists-and-advertisements)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## Getting Started
Include the plugin script in your page, and a placeholder list element with the class `vjs-playlist` to house the playlist menu:
```html
<!-- Include the playlist menu styles somewhere in your page: -->
<link href="videojs-playlist-ui.vertical.css" rel="stylesheet">
<!-- The playlist menu will be built automatically in here: -->
<div class="vjs-playlist"></div>
<!-- Include video.js, the videojs-playlist plugin and this plugin: -->
<script src="video.js"></script>
<script src="videojs-playlist.js"></script>
<script src="videojs-playlist-ui.js"></script>
<script>
// Initialize the plugin and build the playlist!
videojs(document.querySelector('video')).playlistUi();
</script>
```
There's also a [working example](example.html) of the plugin you can check out if you're having trouble.
## Root Element
Before this plugin will work at all, it needs an element in the DOM to which to attach itself. There are three ways to find or provide this element.
> **NOTE:** In v2.x of this plugin, the root element was expected to be a list element (i.e., `<ol>` or `<ul>`). As of v3.x, the plugin creates a list; so, this root element _must_ be a non-list container element (e.g., `<div>`).
### Using Automatic Discovery (default, [example](example.html))
By default, the plugin will search for the first element in the DOM with the `vjs-playlist` class.
To defend against problems caused by multiple playlist players on a page, the plugin will only use an element with the `vjs-playlist` class if that element has not been used by another player's playlist.
### Using a Custom Class ([example](example-custom-class.html))
A custom `className` option can be passed to override the class the plugin will search for to find the root element. The same defense against multiple playlist players is reused in this case.
```js
player.playlistUi({
className: 'hello-world'
});
```
### Using a Custom Element ([example](example-custom-element.html))
A custom element can be passed using the `el` option to explicitly define a specific root element.
```js
player.playlistUi({
el: document.getElementById('hello-world')
});
```
> **NOTE:** Previously, the plugin supported passing the element in lieu of passing options. That feature is deprecated and will be removed in 4.0. Please use the `el` option going forward.
## Other Options
The options passed to the plugin are passed to the internal `PlaylistMenu` [video.js Component][components]; so, you may pass in [any option][components-options] that is accepted by a component.
In addition, the options object may contain the following specialized properties:
#### `className`
Type: `string`
Default: `"vjs-playlist"`
As mentioned [above](#using-a-custom-class), the name of the class to search for to populate the playlist menu.
#### playOnSelect
Type: `boolean`
Default: `false`
The default behavior is that the play state is expected to stay the same between videos. If the player is playing when switching playlist items, continue playing. If paused, stay paused.
When this boolean is set to `true`, clicking on the playlist menu items will always play the video.
## Playlists and Advertisements
The `PlaylistMenu` automatically adapts to ad integrations based on [videojs-contrib-ads][contrib-ads]. When a linear ad is being played, the menu will darken and stop responding to click or touch events. If you'd prefer to allow your viewers to change videos during ad playback, you can override this behavior through CSS. You will also need to make sure that your ad integration is properly cancelled and cleaned up before switching -- consult the documentation for your ad library for details on how to do that.
[components]: https://github.com/videojs/video.js/blob/master/docs/guides/components.md
[components-options]: https://github.com/videojs/video.js/blob/master/docs/guides/options.md#component-options
[contrib-ads]: https://github.com/videojs/videojs-contrib-ads

View File

@ -0,0 +1,504 @@
/*! @name videojs-playlist-ui @version 3.5.2 @license Apache-2.0 */
'use strict';
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var document = _interopDefault(require('global/document'));
var videojs = _interopDefault(require('video.js'));
function _inheritsLoose(subClass, superClass) {
subClass.prototype = Object.create(superClass.prototype);
subClass.prototype.constructor = subClass;
subClass.__proto__ = superClass;
}
var version = "3.5.2";
var dom = videojs.dom || videojs;
var registerPlugin = videojs.registerPlugin || videojs.plugin; // Array#indexOf analog for IE8
var indexOf = function indexOf(array, target) {
for (var i = 0, length = array.length; i < length; i++) {
if (array[i] === target) {
return i;
}
}
return -1;
}; // see https://github.com/Modernizr/Modernizr/blob/master/feature-detects/css/pointerevents.js
var supportsCssPointerEvents = function () {
var element = document.createElement('x');
element.style.cssText = 'pointer-events:auto';
return element.style.pointerEvents === 'auto';
}();
var defaults = {
className: 'vjs-playlist',
playOnSelect: false,
supportsCssPointerEvents: supportsCssPointerEvents
}; // we don't add `vjs-playlist-now-playing` in addSelectedClass
// so it won't conflict with `vjs-icon-play
// since it'll get added when we mouse out
var addSelectedClass = function addSelectedClass(el) {
el.addClass('vjs-selected');
};
var removeSelectedClass = function removeSelectedClass(el) {
el.removeClass('vjs-selected');
if (el.thumbnail) {
dom.removeClass(el.thumbnail, 'vjs-playlist-now-playing');
}
};
var upNext = function upNext(el) {
el.addClass('vjs-up-next');
};
var notUpNext = function notUpNext(el) {
el.removeClass('vjs-up-next');
};
var createThumbnail = function createThumbnail(thumbnail) {
if (!thumbnail) {
var placeholder = document.createElement('div');
placeholder.className = 'vjs-playlist-thumbnail vjs-playlist-thumbnail-placeholder';
return placeholder;
}
var picture = document.createElement('picture');
picture.className = 'vjs-playlist-thumbnail';
if (typeof thumbnail === 'string') {
// simple thumbnails
var img = document.createElement('img');
img.src = thumbnail;
img.alt = '';
picture.appendChild(img);
} else {
// responsive thumbnails
// additional variations of a <picture> are specified as
// <source> elements
for (var i = 0; i < thumbnail.length - 1; i++) {
var _variant = thumbnail[i];
var source = document.createElement('source'); // transfer the properties of each variant onto a <source>
for (var prop in _variant) {
source[prop] = _variant[prop];
}
picture.appendChild(source);
} // the default version of a <picture> is specified by an <img>
var variant = thumbnail[thumbnail.length - 1];
var _img = document.createElement('img');
_img.alt = '';
for (var _prop in variant) {
_img[_prop] = variant[_prop];
}
picture.appendChild(_img);
}
return picture;
};
var Component = videojs.getComponent('Component');
var PlaylistMenuItem =
/*#__PURE__*/
function (_Component) {
_inheritsLoose(PlaylistMenuItem, _Component);
function PlaylistMenuItem(player, playlistItem, settings) {
var _this;
if (!playlistItem.item) {
throw new Error('Cannot construct a PlaylistMenuItem without an item option');
}
_this = _Component.call(this, player, playlistItem) || this;
_this.item = playlistItem.item;
_this.playOnSelect = settings.playOnSelect;
_this.emitTapEvents();
_this.on(['click', 'tap'], _this.switchPlaylistItem_);
_this.on('keydown', _this.handleKeyDown_);
return _this;
}
var _proto = PlaylistMenuItem.prototype;
_proto.handleKeyDown_ = function handleKeyDown_(event) {
// keycode 13 is <Enter>
// keycode 32 is <Space>
if (event.which === 13 || event.which === 32) {
this.switchPlaylistItem_();
}
};
_proto.switchPlaylistItem_ = function switchPlaylistItem_(event) {
this.player_.playlist.currentItem(indexOf(this.player_.playlist(), this.item));
if (this.playOnSelect) {
this.player_.play();
}
};
_proto.createEl = function createEl() {
var li = document.createElement('li');
var item = this.options_.item;
if (typeof item.data === 'object') {
var dataKeys = Object.keys(item.data);
dataKeys.forEach(function (key) {
var value = item.data[key];
li.dataset[key] = value;
});
}
li.className = 'vjs-playlist-item';
li.setAttribute('tabIndex', 0); // Thumbnail image
this.thumbnail = createThumbnail(item.thumbnail);
li.appendChild(this.thumbnail); // Duration
if (item.duration) {
var duration = document.createElement('time');
var time = videojs.formatTime(item.duration);
duration.className = 'vjs-playlist-duration';
duration.setAttribute('datetime', 'PT0H0M' + item.duration + 'S');
duration.appendChild(document.createTextNode(time));
li.appendChild(duration);
} // Now playing
var nowPlayingEl = document.createElement('span');
var nowPlayingText = this.localize('Now Playing');
nowPlayingEl.className = 'vjs-playlist-now-playing-text';
nowPlayingEl.appendChild(document.createTextNode(nowPlayingText));
nowPlayingEl.setAttribute('title', nowPlayingText);
this.thumbnail.appendChild(nowPlayingEl); // Title container contains title and "up next"
var titleContainerEl = document.createElement('div');
titleContainerEl.className = 'vjs-playlist-title-container';
this.thumbnail.appendChild(titleContainerEl); // Up next
var upNextEl = document.createElement('span');
var upNextText = this.localize('Up Next');
upNextEl.className = 'vjs-up-next-text';
upNextEl.appendChild(document.createTextNode(upNextText));
upNextEl.setAttribute('title', upNextText);
titleContainerEl.appendChild(upNextEl); // Video title
var titleEl = document.createElement('cite');
var titleText = item.name || this.localize('Untitled Video');
titleEl.className = 'vjs-playlist-name';
titleEl.appendChild(document.createTextNode(titleText));
titleEl.setAttribute('title', titleText);
titleContainerEl.appendChild(titleEl);
return li;
};
return PlaylistMenuItem;
}(Component);
var PlaylistMenu =
/*#__PURE__*/
function (_Component2) {
_inheritsLoose(PlaylistMenu, _Component2);
function PlaylistMenu(player, options) {
var _this2;
if (!player.playlist) {
throw new Error('videojs-playlist is required for the playlist component');
}
_this2 = _Component2.call(this, player, options) || this;
_this2.items = [];
if (options.horizontal) {
_this2.addClass('vjs-playlist-horizontal');
} else {
_this2.addClass('vjs-playlist-vertical');
} // If CSS pointer events aren't supported, we have to prevent
// clicking on playlist items during ads with slightly more
// invasive techniques. Details in the stylesheet.
if (options.supportsCssPointerEvents) {
_this2.addClass('vjs-csspointerevents');
}
_this2.createPlaylist_();
if (!videojs.browser.TOUCH_ENABLED) {
_this2.addClass('vjs-mouse');
}
_this2.on(player, ['loadstart', 'playlistchange', 'playlistsorted'], function (event) {
_this2.update();
}); // Keep track of whether an ad is playing so that the menu
// appearance can be adapted appropriately
_this2.on(player, 'adstart', function () {
_this2.addClass('vjs-ad-playing');
});
_this2.on(player, 'adend', function () {
_this2.removeClass('vjs-ad-playing');
});
_this2.on('dispose', function () {
_this2.empty_();
player.playlistMenu = null;
});
_this2.on(player, 'dispose', function () {
_this2.dispose();
});
return _this2;
}
var _proto2 = PlaylistMenu.prototype;
_proto2.createEl = function createEl() {
return dom.createEl('div', {
className: this.options_.className
});
};
_proto2.empty_ = function empty_() {
if (this.items && this.items.length) {
this.items.forEach(function (i) {
return i.dispose();
});
this.items.length = 0;
}
};
_proto2.createPlaylist_ = function createPlaylist_() {
var playlist = this.player_.playlist() || [];
var list = this.el_.querySelector('.vjs-playlist-item-list');
var overlay = this.el_.querySelector('.vjs-playlist-ad-overlay');
if (!list) {
list = document.createElement('ol');
list.className = 'vjs-playlist-item-list';
this.el_.appendChild(list);
}
this.empty_(); // create new items
for (var i = 0; i < playlist.length; i++) {
var item = new PlaylistMenuItem(this.player_, {
item: playlist[i]
}, this.options_);
this.items.push(item);
list.appendChild(item.el_);
} // Inject the ad overlay. IE<11 doesn't support "pointer-events:
// none" so we use this element to block clicks during ad
// playback.
if (!overlay) {
overlay = document.createElement('li');
overlay.className = 'vjs-playlist-ad-overlay';
list.appendChild(overlay);
} else {
// Move overlay to end of list
list.appendChild(overlay);
} // select the current playlist item
var selectedIndex = this.player_.playlist.currentItem();
if (this.items.length && selectedIndex >= 0) {
addSelectedClass(this.items[selectedIndex]);
var thumbnail = this.items[selectedIndex].$('.vjs-playlist-thumbnail');
if (thumbnail) {
dom.addClass(thumbnail, 'vjs-playlist-now-playing');
}
}
};
_proto2.update = function update() {
// replace the playlist items being displayed, if necessary
var playlist = this.player_.playlist();
if (this.items.length !== playlist.length) {
// if the menu is currently empty or the state is obviously out
// of date, rebuild everything.
this.createPlaylist_();
return;
}
for (var i = 0; i < this.items.length; i++) {
if (this.items[i].item !== playlist[i]) {
// if any of the playlist items have changed, rebuild the
// entire playlist
this.createPlaylist_();
return;
}
} // the playlist itself is unchanged so just update the selection
var currentItem = this.player_.playlist.currentItem();
for (var _i = 0; _i < this.items.length; _i++) {
var item = this.items[_i];
if (_i === currentItem) {
addSelectedClass(item);
if (document.activeElement !== item.el()) {
dom.addClass(item.thumbnail, 'vjs-playlist-now-playing');
}
notUpNext(item);
} else if (_i === currentItem + 1) {
removeSelectedClass(item);
upNext(item);
} else {
removeSelectedClass(item);
notUpNext(item);
}
}
};
return PlaylistMenu;
}(Component);
/**
* Returns a boolean indicating whether an element has child elements.
*
* Note that this is distinct from whether it has child _nodes_.
*
* @param {HTMLElement} el
* A DOM element.
*
* @return {boolean}
* Whether the element has child elements.
*/
var hasChildEls = function hasChildEls(el) {
for (var i = 0; i < el.childNodes.length; i++) {
if (dom.isEl(el.childNodes[i])) {
return true;
}
}
return false;
};
/**
* Finds the first empty root element.
*
* @param {string} className
* An HTML class name to search for.
*
* @return {HTMLElement}
* A DOM element to use as the root for a playlist.
*/
var findRoot = function findRoot(className) {
var all = document.querySelectorAll('.' + className);
var el;
for (var i = 0; i < all.length; i++) {
if (!hasChildEls(all[i])) {
el = all[i];
break;
}
}
return el;
};
/**
* Initialize the plugin on a player.
*
* @param {Object} [options]
* An options object.
*
* @param {HTMLElement} [options.el]
* A DOM element to use as a root node for the playlist.
*
* @param {string} [options.className]
* An HTML class name to use to find a root node for the playlist.
*
* @param {boolean} [options.playOnSelect = false]
* If true, will attempt to begin playback upon selecting a new
* playlist item in the UI.
*/
var playlistUi = function playlistUi(options) {
var player = this;
if (!player.playlist) {
throw new Error('videojs-playlist plugin is required by the videojs-playlist-ui plugin');
}
if (dom.isEl(options)) {
videojs.log.warn('videojs-playlist-ui: Passing an element directly to playlistUi() is deprecated, use the "el" option instead!');
options = {
el: options
};
}
options = videojs.mergeOptions(defaults, options); // If the player is already using this plugin, remove the pre-existing
// PlaylistMenu, but retain the element and its location in the DOM because
// it will be re-used.
if (player.playlistMenu) {
var el = player.playlistMenu.el(); // Catch cases where the menu may have been disposed elsewhere or the
// element removed from the DOM.
if (el) {
var parentNode = el.parentNode;
var nextSibling = el.nextSibling; // Disposing the menu will remove `el` from the DOM, but we need to
// empty it ourselves to be sure.
player.playlistMenu.dispose();
dom.emptyEl(el); // Put the element back in its place.
if (nextSibling) {
parentNode.insertBefore(el, nextSibling);
} else {
parentNode.appendChild(el);
}
options.el = el;
}
}
if (!dom.isEl(options.el)) {
options.el = findRoot(options.className);
}
player.playlistMenu = new PlaylistMenu(player, options);
}; // register components
videojs.registerComponent('PlaylistMenu', PlaylistMenu);
videojs.registerComponent('PlaylistMenuItem', PlaylistMenuItem); // register the plugin
registerPlugin('playlistUi', playlistUi);
playlistUi.VERSION = version;
module.exports = playlistUi;

View File

@ -0,0 +1 @@
.vjs-playlist{padding:0;background-color:#1a1a1a;color:#fff;list-style-type:none}.vjs-playlist img{display:block;height:auto;width:auto}.vjs-playlist .vjs-playlist-item-list{position:relative;margin:0;padding:0;list-style:none}.vjs-playlist .vjs-playlist-item{position:relative;cursor:pointer;overflow:hidden}.vjs-playlist .vjs-playlist-thumbnail-placeholder{background:#303030}.vjs-playlist .vjs-playlist-now-playing-text{display:none;position:absolute;top:0;left:0;padding-left:2px;margin:.8rem}.vjs-playlist .vjs-playlist-duration{position:absolute;top:.5rem;left:.5rem;padding:2px 5px 3px;margin-left:2px;background-color:rgba(26,26,26,0.8)}.vjs-playlist .vjs-playlist-title-container{position:absolute;bottom:0;box-sizing:border-box;width:100%;padding:.5rem .8rem;text-shadow:1px 1px 2px black, -1px 1px 2px black, 1px -1px 2px black, -1px -1px 2px black}.vjs-playlist .vjs-playlist-name{display:block;max-height:2.5em;padding:0 0 4px 2px;font-style:normal;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;line-height:20px}.vjs-playlist .vjs-playlist-description{margin:0;text-overflow:ellipsis;overflow:hidden}.vjs-playlist .vjs-up-next-text{display:none;padding:.1rem 2px;font-size:.8em;text-transform:uppercase}.vjs-playlist .vjs-up-next .vjs-up-next-text{display:block}.vjs-playlist .vjs-selected{background-color:#141a21}.vjs-playlist .vjs-selected img{opacity:.2}.vjs-playlist .vjs-selected .vjs-playlist-duration{display:none}.vjs-playlist .vjs-selected .vjs-playlist-now-playing-text{display:block}.vjs-playlist .vjs-selected .vjs-playlist-title-container{text-shadow:none}.vjs-playlist-vertical{overflow-x:hidden;overflow-y:auto}.vjs-playlist-vertical img{width:100%;min-height:54px}.vjs-playlist-vertical .vjs-playlist-item{margin-bottom:5px}.vjs-playlist-vertical .vjs-playlist-thumbnail{display:block;width:100%}.vjs-playlist-vertical .vjs-playlist-thumbnail-placeholder{height:100px}.vjs-playlist-horizontal{overflow-x:auto;overflow-y:hidden}.vjs-playlist-horizontal img{min-width:100px;height:100%}.vjs-playlist-horizontal .vjs-playlist-item-list{height:100%;white-space:nowrap}.vjs-playlist-horizontal .vjs-playlist-item{display:inline-block;height:100%;margin-right:5px}.vjs-playlist-horizontal .vjs-playlist-thumbnail{display:block;height:100%}.vjs-playlist-horizontal .vjs-playlist-thumbnail-placeholder{height:100%;width:180px}.vjs-playlist.vjs-ad-playing{overflow:hidden}.vjs-playlist.vjs-ad-playing.vjs-csspointerevents{pointer-events:none;overflow:auto}.vjs-playlist.vjs-ad-playing.vjs-csspointerevents .vjs-playlist-ad-overlay{pointer-events:auto}.vjs-playlist.vjs-ad-playing .vjs-playlist-ad-overlay{display:block;position:absolute;top:0;left:0;width:100%;height:100%;background-color:#1a1a1a;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";background-color:rgba(0,0,0,0.5)}.vjs-playlist{font-size:14px}.vjs-playlist .vjs-playlist-description{height:42px;line-height:21px}.vjs-mouse.vjs-playlist{font-size:15px}.vjs-mouse.vjs-playlist .vjs-playlist-description{height:45px;line-height:23px}@media (min-width: 600px){.vjs-mouse.vjs-playlist{font-size:17px}.vjs-mouse.vjs-playlist .vjs-playlist-description{height:51px;line-height:26px}.vjs-playlist .vjs-playlist-name{line-height:22px}}@media (max-width: 520px){.vjs-playlist .vjs-selected .vjs-playlist-now-playing-text,.vjs-playlist .vjs-up-next .vjs-up-next-text{display:none}.vjs-mouse.vjs-playlist .vjs-selected .vjs-playlist-now-playing-text,.vjs-mouse.vjs-playlist .vjs-up-next .vjs-up-next-text{display:none}}@media (min-width: 521px){.vjs-playlist img{min-height:85px}}@media (max-width: 750px){.vjs-playlist .vjs-playlist-duration{display:none}}

View File

@ -0,0 +1,500 @@
/*! @name videojs-playlist-ui @version 3.5.2 @license Apache-2.0 */
import document from 'global/document';
import videojs from 'video.js';
function _inheritsLoose(subClass, superClass) {
subClass.prototype = Object.create(superClass.prototype);
subClass.prototype.constructor = subClass;
subClass.__proto__ = superClass;
}
var version = "3.5.2";
var dom = videojs.dom || videojs;
var registerPlugin = videojs.registerPlugin || videojs.plugin; // Array#indexOf analog for IE8
var indexOf = function indexOf(array, target) {
for (var i = 0, length = array.length; i < length; i++) {
if (array[i] === target) {
return i;
}
}
return -1;
}; // see https://github.com/Modernizr/Modernizr/blob/master/feature-detects/css/pointerevents.js
var supportsCssPointerEvents = function () {
var element = document.createElement('x');
element.style.cssText = 'pointer-events:auto';
return element.style.pointerEvents === 'auto';
}();
var defaults = {
className: 'vjs-playlist',
playOnSelect: false,
supportsCssPointerEvents: supportsCssPointerEvents
}; // we don't add `vjs-playlist-now-playing` in addSelectedClass
// so it won't conflict with `vjs-icon-play
// since it'll get added when we mouse out
var addSelectedClass = function addSelectedClass(el) {
el.addClass('vjs-selected');
};
var removeSelectedClass = function removeSelectedClass(el) {
el.removeClass('vjs-selected');
if (el.thumbnail) {
dom.removeClass(el.thumbnail, 'vjs-playlist-now-playing');
}
};
var upNext = function upNext(el) {
el.addClass('vjs-up-next');
};
var notUpNext = function notUpNext(el) {
el.removeClass('vjs-up-next');
};
var createThumbnail = function createThumbnail(thumbnail) {
if (!thumbnail) {
var placeholder = document.createElement('div');
placeholder.className = 'vjs-playlist-thumbnail vjs-playlist-thumbnail-placeholder';
return placeholder;
}
var picture = document.createElement('picture');
picture.className = 'vjs-playlist-thumbnail';
if (typeof thumbnail === 'string') {
// simple thumbnails
var img = document.createElement('img');
img.src = thumbnail;
img.alt = '';
picture.appendChild(img);
} else {
// responsive thumbnails
// additional variations of a <picture> are specified as
// <source> elements
for (var i = 0; i < thumbnail.length - 1; i++) {
var _variant = thumbnail[i];
var source = document.createElement('source'); // transfer the properties of each variant onto a <source>
for (var prop in _variant) {
source[prop] = _variant[prop];
}
picture.appendChild(source);
} // the default version of a <picture> is specified by an <img>
var variant = thumbnail[thumbnail.length - 1];
var _img = document.createElement('img');
_img.alt = '';
for (var _prop in variant) {
_img[_prop] = variant[_prop];
}
picture.appendChild(_img);
}
return picture;
};
var Component = videojs.getComponent('Component');
var PlaylistMenuItem =
/*#__PURE__*/
function (_Component) {
_inheritsLoose(PlaylistMenuItem, _Component);
function PlaylistMenuItem(player, playlistItem, settings) {
var _this;
if (!playlistItem.item) {
throw new Error('Cannot construct a PlaylistMenuItem without an item option');
}
_this = _Component.call(this, player, playlistItem) || this;
_this.item = playlistItem.item;
_this.playOnSelect = settings.playOnSelect;
_this.emitTapEvents();
_this.on(['click', 'tap'], _this.switchPlaylistItem_);
_this.on('keydown', _this.handleKeyDown_);
return _this;
}
var _proto = PlaylistMenuItem.prototype;
_proto.handleKeyDown_ = function handleKeyDown_(event) {
// keycode 13 is <Enter>
// keycode 32 is <Space>
if (event.which === 13 || event.which === 32) {
this.switchPlaylistItem_();
}
};
_proto.switchPlaylistItem_ = function switchPlaylistItem_(event) {
this.player_.playlist.currentItem(indexOf(this.player_.playlist(), this.item));
if (this.playOnSelect) {
this.player_.play();
}
};
_proto.createEl = function createEl() {
var li = document.createElement('li');
var item = this.options_.item;
if (typeof item.data === 'object') {
var dataKeys = Object.keys(item.data);
dataKeys.forEach(function (key) {
var value = item.data[key];
li.dataset[key] = value;
});
}
li.className = 'vjs-playlist-item';
li.setAttribute('tabIndex', 0); // Thumbnail image
this.thumbnail = createThumbnail(item.thumbnail);
li.appendChild(this.thumbnail); // Duration
if (item.duration) {
var duration = document.createElement('time');
var time = videojs.formatTime(item.duration);
duration.className = 'vjs-playlist-duration';
duration.setAttribute('datetime', 'PT0H0M' + item.duration + 'S');
duration.appendChild(document.createTextNode(time));
li.appendChild(duration);
} // Now playing
var nowPlayingEl = document.createElement('span');
var nowPlayingText = this.localize('Now Playing');
nowPlayingEl.className = 'vjs-playlist-now-playing-text';
nowPlayingEl.appendChild(document.createTextNode(nowPlayingText));
nowPlayingEl.setAttribute('title', nowPlayingText);
this.thumbnail.appendChild(nowPlayingEl); // Title container contains title and "up next"
var titleContainerEl = document.createElement('div');
titleContainerEl.className = 'vjs-playlist-title-container';
this.thumbnail.appendChild(titleContainerEl); // Up next
var upNextEl = document.createElement('span');
var upNextText = this.localize('Up Next');
upNextEl.className = 'vjs-up-next-text';
upNextEl.appendChild(document.createTextNode(upNextText));
upNextEl.setAttribute('title', upNextText);
titleContainerEl.appendChild(upNextEl); // Video title
var titleEl = document.createElement('cite');
var titleText = item.name || this.localize('Untitled Video');
titleEl.className = 'vjs-playlist-name';
titleEl.appendChild(document.createTextNode(titleText));
titleEl.setAttribute('title', titleText);
titleContainerEl.appendChild(titleEl);
return li;
};
return PlaylistMenuItem;
}(Component);
var PlaylistMenu =
/*#__PURE__*/
function (_Component2) {
_inheritsLoose(PlaylistMenu, _Component2);
function PlaylistMenu(player, options) {
var _this2;
if (!player.playlist) {
throw new Error('videojs-playlist is required for the playlist component');
}
_this2 = _Component2.call(this, player, options) || this;
_this2.items = [];
if (options.horizontal) {
_this2.addClass('vjs-playlist-horizontal');
} else {
_this2.addClass('vjs-playlist-vertical');
} // If CSS pointer events aren't supported, we have to prevent
// clicking on playlist items during ads with slightly more
// invasive techniques. Details in the stylesheet.
if (options.supportsCssPointerEvents) {
_this2.addClass('vjs-csspointerevents');
}
_this2.createPlaylist_();
if (!videojs.browser.TOUCH_ENABLED) {
_this2.addClass('vjs-mouse');
}
_this2.on(player, ['loadstart', 'playlistchange', 'playlistsorted'], function (event) {
_this2.update();
}); // Keep track of whether an ad is playing so that the menu
// appearance can be adapted appropriately
_this2.on(player, 'adstart', function () {
_this2.addClass('vjs-ad-playing');
});
_this2.on(player, 'adend', function () {
_this2.removeClass('vjs-ad-playing');
});
_this2.on('dispose', function () {
_this2.empty_();
player.playlistMenu = null;
});
_this2.on(player, 'dispose', function () {
_this2.dispose();
});
return _this2;
}
var _proto2 = PlaylistMenu.prototype;
_proto2.createEl = function createEl() {
return dom.createEl('div', {
className: this.options_.className
});
};
_proto2.empty_ = function empty_() {
if (this.items && this.items.length) {
this.items.forEach(function (i) {
return i.dispose();
});
this.items.length = 0;
}
};
_proto2.createPlaylist_ = function createPlaylist_() {
var playlist = this.player_.playlist() || [];
var list = this.el_.querySelector('.vjs-playlist-item-list');
var overlay = this.el_.querySelector('.vjs-playlist-ad-overlay');
if (!list) {
list = document.createElement('ol');
list.className = 'vjs-playlist-item-list';
this.el_.appendChild(list);
}
this.empty_(); // create new items
for (var i = 0; i < playlist.length; i++) {
var item = new PlaylistMenuItem(this.player_, {
item: playlist[i]
}, this.options_);
this.items.push(item);
list.appendChild(item.el_);
} // Inject the ad overlay. IE<11 doesn't support "pointer-events:
// none" so we use this element to block clicks during ad
// playback.
if (!overlay) {
overlay = document.createElement('li');
overlay.className = 'vjs-playlist-ad-overlay';
list.appendChild(overlay);
} else {
// Move overlay to end of list
list.appendChild(overlay);
} // select the current playlist item
var selectedIndex = this.player_.playlist.currentItem();
if (this.items.length && selectedIndex >= 0) {
addSelectedClass(this.items[selectedIndex]);
var thumbnail = this.items[selectedIndex].$('.vjs-playlist-thumbnail');
if (thumbnail) {
dom.addClass(thumbnail, 'vjs-playlist-now-playing');
}
}
};
_proto2.update = function update() {
// replace the playlist items being displayed, if necessary
var playlist = this.player_.playlist();
if (this.items.length !== playlist.length) {
// if the menu is currently empty or the state is obviously out
// of date, rebuild everything.
this.createPlaylist_();
return;
}
for (var i = 0; i < this.items.length; i++) {
if (this.items[i].item !== playlist[i]) {
// if any of the playlist items have changed, rebuild the
// entire playlist
this.createPlaylist_();
return;
}
} // the playlist itself is unchanged so just update the selection
var currentItem = this.player_.playlist.currentItem();
for (var _i = 0; _i < this.items.length; _i++) {
var item = this.items[_i];
if (_i === currentItem) {
addSelectedClass(item);
if (document.activeElement !== item.el()) {
dom.addClass(item.thumbnail, 'vjs-playlist-now-playing');
}
notUpNext(item);
} else if (_i === currentItem + 1) {
removeSelectedClass(item);
upNext(item);
} else {
removeSelectedClass(item);
notUpNext(item);
}
}
};
return PlaylistMenu;
}(Component);
/**
* Returns a boolean indicating whether an element has child elements.
*
* Note that this is distinct from whether it has child _nodes_.
*
* @param {HTMLElement} el
* A DOM element.
*
* @return {boolean}
* Whether the element has child elements.
*/
var hasChildEls = function hasChildEls(el) {
for (var i = 0; i < el.childNodes.length; i++) {
if (dom.isEl(el.childNodes[i])) {
return true;
}
}
return false;
};
/**
* Finds the first empty root element.
*
* @param {string} className
* An HTML class name to search for.
*
* @return {HTMLElement}
* A DOM element to use as the root for a playlist.
*/
var findRoot = function findRoot(className) {
var all = document.querySelectorAll('.' + className);
var el;
for (var i = 0; i < all.length; i++) {
if (!hasChildEls(all[i])) {
el = all[i];
break;
}
}
return el;
};
/**
* Initialize the plugin on a player.
*
* @param {Object} [options]
* An options object.
*
* @param {HTMLElement} [options.el]
* A DOM element to use as a root node for the playlist.
*
* @param {string} [options.className]
* An HTML class name to use to find a root node for the playlist.
*
* @param {boolean} [options.playOnSelect = false]
* If true, will attempt to begin playback upon selecting a new
* playlist item in the UI.
*/
var playlistUi = function playlistUi(options) {
var player = this;
if (!player.playlist) {
throw new Error('videojs-playlist plugin is required by the videojs-playlist-ui plugin');
}
if (dom.isEl(options)) {
videojs.log.warn('videojs-playlist-ui: Passing an element directly to playlistUi() is deprecated, use the "el" option instead!');
options = {
el: options
};
}
options = videojs.mergeOptions(defaults, options); // If the player is already using this plugin, remove the pre-existing
// PlaylistMenu, but retain the element and its location in the DOM because
// it will be re-used.
if (player.playlistMenu) {
var el = player.playlistMenu.el(); // Catch cases where the menu may have been disposed elsewhere or the
// element removed from the DOM.
if (el) {
var parentNode = el.parentNode;
var nextSibling = el.nextSibling; // Disposing the menu will remove `el` from the DOM, but we need to
// empty it ourselves to be sure.
player.playlistMenu.dispose();
dom.emptyEl(el); // Put the element back in its place.
if (nextSibling) {
parentNode.insertBefore(el, nextSibling);
} else {
parentNode.appendChild(el);
}
options.el = el;
}
}
if (!dom.isEl(options.el)) {
options.el = findRoot(options.className);
}
player.playlistMenu = new PlaylistMenu(player, options);
}; // register components
videojs.registerComponent('PlaylistMenu', PlaylistMenu);
videojs.registerComponent('PlaylistMenuItem', PlaylistMenuItem); // register the plugin
registerPlugin('playlistUi', playlistUi);
playlistUi.VERSION = version;
export default playlistUi;

View File

@ -0,0 +1,508 @@
/*! @name videojs-playlist-ui @version 3.5.2 @license Apache-2.0 */
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('global/document'), require('video.js')) :
typeof define === 'function' && define.amd ? define(['global/document', 'video.js'], factory) :
(global.videojsPlaylistUi = factory(global.document,global.videojs));
}(this, (function (document,videojs) { 'use strict';
document = document && document.hasOwnProperty('default') ? document['default'] : document;
videojs = videojs && videojs.hasOwnProperty('default') ? videojs['default'] : videojs;
function _inheritsLoose(subClass, superClass) {
subClass.prototype = Object.create(superClass.prototype);
subClass.prototype.constructor = subClass;
subClass.__proto__ = superClass;
}
var version = "3.5.2";
var dom = videojs.dom || videojs;
var registerPlugin = videojs.registerPlugin || videojs.plugin; // Array#indexOf analog for IE8
var indexOf = function indexOf(array, target) {
for (var i = 0, length = array.length; i < length; i++) {
if (array[i] === target) {
return i;
}
}
return -1;
}; // see https://github.com/Modernizr/Modernizr/blob/master/feature-detects/css/pointerevents.js
var supportsCssPointerEvents = function () {
var element = document.createElement('x');
element.style.cssText = 'pointer-events:auto';
return element.style.pointerEvents === 'auto';
}();
var defaults = {
className: 'vjs-playlist',
playOnSelect: false,
supportsCssPointerEvents: supportsCssPointerEvents
}; // we don't add `vjs-playlist-now-playing` in addSelectedClass
// so it won't conflict with `vjs-icon-play
// since it'll get added when we mouse out
var addSelectedClass = function addSelectedClass(el) {
el.addClass('vjs-selected');
};
var removeSelectedClass = function removeSelectedClass(el) {
el.removeClass('vjs-selected');
if (el.thumbnail) {
dom.removeClass(el.thumbnail, 'vjs-playlist-now-playing');
}
};
var upNext = function upNext(el) {
el.addClass('vjs-up-next');
};
var notUpNext = function notUpNext(el) {
el.removeClass('vjs-up-next');
};
var createThumbnail = function createThumbnail(thumbnail) {
if (!thumbnail) {
var placeholder = document.createElement('div');
placeholder.className = 'vjs-playlist-thumbnail vjs-playlist-thumbnail-placeholder';
return placeholder;
}
var picture = document.createElement('picture');
picture.className = 'vjs-playlist-thumbnail';
if (typeof thumbnail === 'string') {
// simple thumbnails
var img = document.createElement('img');
img.src = thumbnail;
img.alt = '';
picture.appendChild(img);
} else {
// responsive thumbnails
// additional variations of a <picture> are specified as
// <source> elements
for (var i = 0; i < thumbnail.length - 1; i++) {
var _variant = thumbnail[i];
var source = document.createElement('source'); // transfer the properties of each variant onto a <source>
for (var prop in _variant) {
source[prop] = _variant[prop];
}
picture.appendChild(source);
} // the default version of a <picture> is specified by an <img>
var variant = thumbnail[thumbnail.length - 1];
var _img = document.createElement('img');
_img.alt = '';
for (var _prop in variant) {
_img[_prop] = variant[_prop];
}
picture.appendChild(_img);
}
return picture;
};
var Component = videojs.getComponent('Component');
var PlaylistMenuItem =
/*#__PURE__*/
function (_Component) {
_inheritsLoose(PlaylistMenuItem, _Component);
function PlaylistMenuItem(player, playlistItem, settings) {
var _this;
if (!playlistItem.item) {
throw new Error('Cannot construct a PlaylistMenuItem without an item option');
}
_this = _Component.call(this, player, playlistItem) || this;
_this.item = playlistItem.item;
_this.playOnSelect = settings.playOnSelect;
_this.emitTapEvents();
_this.on(['click', 'tap'], _this.switchPlaylistItem_);
_this.on('keydown', _this.handleKeyDown_);
return _this;
}
var _proto = PlaylistMenuItem.prototype;
_proto.handleKeyDown_ = function handleKeyDown_(event) {
// keycode 13 is <Enter>
// keycode 32 is <Space>
if (event.which === 13 || event.which === 32) {
this.switchPlaylistItem_();
}
};
_proto.switchPlaylistItem_ = function switchPlaylistItem_(event) {
this.player_.playlist.currentItem(indexOf(this.player_.playlist(), this.item));
if (this.playOnSelect) {
this.player_.play();
}
};
_proto.createEl = function createEl() {
var li = document.createElement('li');
var item = this.options_.item;
if (typeof item.data === 'object') {
var dataKeys = Object.keys(item.data);
dataKeys.forEach(function (key) {
var value = item.data[key];
li.dataset[key] = value;
});
}
li.className = 'vjs-playlist-item';
li.setAttribute('tabIndex', 0); // Thumbnail image
this.thumbnail = createThumbnail(item.thumbnail);
li.appendChild(this.thumbnail); // Duration
if (item.duration) {
var duration = document.createElement('time');
var time = videojs.formatTime(item.duration);
duration.className = 'vjs-playlist-duration';
duration.setAttribute('datetime', 'PT0H0M' + item.duration + 'S');
duration.appendChild(document.createTextNode(time));
li.appendChild(duration);
} // Now playing
var nowPlayingEl = document.createElement('span');
var nowPlayingText = this.localize('Now Playing');
nowPlayingEl.className = 'vjs-playlist-now-playing-text';
nowPlayingEl.appendChild(document.createTextNode(nowPlayingText));
nowPlayingEl.setAttribute('title', nowPlayingText);
this.thumbnail.appendChild(nowPlayingEl); // Title container contains title and "up next"
var titleContainerEl = document.createElement('div');
titleContainerEl.className = 'vjs-playlist-title-container';
this.thumbnail.appendChild(titleContainerEl); // Up next
var upNextEl = document.createElement('span');
var upNextText = this.localize('Up Next');
upNextEl.className = 'vjs-up-next-text';
upNextEl.appendChild(document.createTextNode(upNextText));
upNextEl.setAttribute('title', upNextText);
titleContainerEl.appendChild(upNextEl); // Video title
var titleEl = document.createElement('cite');
var titleText = item.name || this.localize('Untitled Video');
titleEl.className = 'vjs-playlist-name';
titleEl.appendChild(document.createTextNode(titleText));
titleEl.setAttribute('title', titleText);
titleContainerEl.appendChild(titleEl);
return li;
};
return PlaylistMenuItem;
}(Component);
var PlaylistMenu =
/*#__PURE__*/
function (_Component2) {
_inheritsLoose(PlaylistMenu, _Component2);
function PlaylistMenu(player, options) {
var _this2;
if (!player.playlist) {
throw new Error('videojs-playlist is required for the playlist component');
}
_this2 = _Component2.call(this, player, options) || this;
_this2.items = [];
if (options.horizontal) {
_this2.addClass('vjs-playlist-horizontal');
} else {
_this2.addClass('vjs-playlist-vertical');
} // If CSS pointer events aren't supported, we have to prevent
// clicking on playlist items during ads with slightly more
// invasive techniques. Details in the stylesheet.
if (options.supportsCssPointerEvents) {
_this2.addClass('vjs-csspointerevents');
}
_this2.createPlaylist_();
if (!videojs.browser.TOUCH_ENABLED) {
_this2.addClass('vjs-mouse');
}
_this2.on(player, ['loadstart', 'playlistchange', 'playlistsorted'], function (event) {
_this2.update();
}); // Keep track of whether an ad is playing so that the menu
// appearance can be adapted appropriately
_this2.on(player, 'adstart', function () {
_this2.addClass('vjs-ad-playing');
});
_this2.on(player, 'adend', function () {
_this2.removeClass('vjs-ad-playing');
});
_this2.on('dispose', function () {
_this2.empty_();
player.playlistMenu = null;
});
_this2.on(player, 'dispose', function () {
_this2.dispose();
});
return _this2;
}
var _proto2 = PlaylistMenu.prototype;
_proto2.createEl = function createEl() {
return dom.createEl('div', {
className: this.options_.className
});
};
_proto2.empty_ = function empty_() {
if (this.items && this.items.length) {
this.items.forEach(function (i) {
return i.dispose();
});
this.items.length = 0;
}
};
_proto2.createPlaylist_ = function createPlaylist_() {
var playlist = this.player_.playlist() || [];
var list = this.el_.querySelector('.vjs-playlist-item-list');
var overlay = this.el_.querySelector('.vjs-playlist-ad-overlay');
if (!list) {
list = document.createElement('ol');
list.className = 'vjs-playlist-item-list';
this.el_.appendChild(list);
}
this.empty_(); // create new items
for (var i = 0; i < playlist.length; i++) {
var item = new PlaylistMenuItem(this.player_, {
item: playlist[i]
}, this.options_);
this.items.push(item);
list.appendChild(item.el_);
} // Inject the ad overlay. IE<11 doesn't support "pointer-events:
// none" so we use this element to block clicks during ad
// playback.
if (!overlay) {
overlay = document.createElement('li');
overlay.className = 'vjs-playlist-ad-overlay';
list.appendChild(overlay);
} else {
// Move overlay to end of list
list.appendChild(overlay);
} // select the current playlist item
var selectedIndex = this.player_.playlist.currentItem();
if (this.items.length && selectedIndex >= 0) {
addSelectedClass(this.items[selectedIndex]);
var thumbnail = this.items[selectedIndex].$('.vjs-playlist-thumbnail');
if (thumbnail) {
dom.addClass(thumbnail, 'vjs-playlist-now-playing');
}
}
};
_proto2.update = function update() {
// replace the playlist items being displayed, if necessary
var playlist = this.player_.playlist();
if (this.items.length !== playlist.length) {
// if the menu is currently empty or the state is obviously out
// of date, rebuild everything.
this.createPlaylist_();
return;
}
for (var i = 0; i < this.items.length; i++) {
if (this.items[i].item !== playlist[i]) {
// if any of the playlist items have changed, rebuild the
// entire playlist
this.createPlaylist_();
return;
}
} // the playlist itself is unchanged so just update the selection
var currentItem = this.player_.playlist.currentItem();
for (var _i = 0; _i < this.items.length; _i++) {
var item = this.items[_i];
if (_i === currentItem) {
addSelectedClass(item);
if (document.activeElement !== item.el()) {
dom.addClass(item.thumbnail, 'vjs-playlist-now-playing');
}
notUpNext(item);
} else if (_i === currentItem + 1) {
removeSelectedClass(item);
upNext(item);
} else {
removeSelectedClass(item);
notUpNext(item);
}
}
};
return PlaylistMenu;
}(Component);
/**
* Returns a boolean indicating whether an element has child elements.
*
* Note that this is distinct from whether it has child _nodes_.
*
* @param {HTMLElement} el
* A DOM element.
*
* @return {boolean}
* Whether the element has child elements.
*/
var hasChildEls = function hasChildEls(el) {
for (var i = 0; i < el.childNodes.length; i++) {
if (dom.isEl(el.childNodes[i])) {
return true;
}
}
return false;
};
/**
* Finds the first empty root element.
*
* @param {string} className
* An HTML class name to search for.
*
* @return {HTMLElement}
* A DOM element to use as the root for a playlist.
*/
var findRoot = function findRoot(className) {
var all = document.querySelectorAll('.' + className);
var el;
for (var i = 0; i < all.length; i++) {
if (!hasChildEls(all[i])) {
el = all[i];
break;
}
}
return el;
};
/**
* Initialize the plugin on a player.
*
* @param {Object} [options]
* An options object.
*
* @param {HTMLElement} [options.el]
* A DOM element to use as a root node for the playlist.
*
* @param {string} [options.className]
* An HTML class name to use to find a root node for the playlist.
*
* @param {boolean} [options.playOnSelect = false]
* If true, will attempt to begin playback upon selecting a new
* playlist item in the UI.
*/
var playlistUi = function playlistUi(options) {
var player = this;
if (!player.playlist) {
throw new Error('videojs-playlist plugin is required by the videojs-playlist-ui plugin');
}
if (dom.isEl(options)) {
videojs.log.warn('videojs-playlist-ui: Passing an element directly to playlistUi() is deprecated, use the "el" option instead!');
options = {
el: options
};
}
options = videojs.mergeOptions(defaults, options); // If the player is already using this plugin, remove the pre-existing
// PlaylistMenu, but retain the element and its location in the DOM because
// it will be re-used.
if (player.playlistMenu) {
var el = player.playlistMenu.el(); // Catch cases where the menu may have been disposed elsewhere or the
// element removed from the DOM.
if (el) {
var parentNode = el.parentNode;
var nextSibling = el.nextSibling; // Disposing the menu will remove `el` from the DOM, but we need to
// empty it ourselves to be sure.
player.playlistMenu.dispose();
dom.emptyEl(el); // Put the element back in its place.
if (nextSibling) {
parentNode.insertBefore(el, nextSibling);
} else {
parentNode.appendChild(el);
}
options.el = el;
}
}
if (!dom.isEl(options.el)) {
options.el = findRoot(options.className);
}
player.playlistMenu = new PlaylistMenu(player, options);
}; // register components
videojs.registerComponent('PlaylistMenu', PlaylistMenu);
videojs.registerComponent('PlaylistMenuItem', PlaylistMenuItem); // register the plugin
registerPlugin('playlistUi', playlistUi);
playlistUi.VERSION = version;
return playlistUi;
})));

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
.vjs-playlist{padding:0;background-color:#1a1a1a;color:#fff;list-style-type:none}.vjs-playlist img{display:block;height:auto;width:auto}.vjs-playlist .vjs-playlist-item-list{position:relative;margin:0;padding:0;list-style:none}.vjs-playlist .vjs-playlist-item{position:relative;cursor:pointer;overflow:hidden}.vjs-playlist .vjs-playlist-thumbnail-placeholder{background:#303030}.vjs-playlist .vjs-playlist-now-playing-text{display:none;position:absolute;top:0;left:0;padding-left:2px;margin:.8rem}.vjs-playlist .vjs-playlist-duration{position:absolute;top:.5rem;left:.5rem;padding:2px 5px 3px;margin-left:2px;background-color:rgba(26,26,26,0.8)}.vjs-playlist .vjs-playlist-title-container{position:absolute;bottom:0;box-sizing:border-box;width:100%;padding:.5rem .8rem;text-shadow:1px 1px 2px black, -1px 1px 2px black, 1px -1px 2px black, -1px -1px 2px black}.vjs-playlist .vjs-playlist-name{display:block;max-height:2.5em;padding:0 0 4px 2px;font-style:normal;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;line-height:20px}.vjs-playlist .vjs-playlist-description{margin:0;text-overflow:ellipsis;overflow:hidden}.vjs-playlist .vjs-up-next-text{display:none;padding:.1rem 2px;font-size:.8em;text-transform:uppercase}.vjs-playlist .vjs-up-next .vjs-up-next-text{display:block}.vjs-playlist .vjs-selected{background-color:#141a21}.vjs-playlist .vjs-selected img{opacity:.2}.vjs-playlist .vjs-selected .vjs-playlist-duration{display:none}.vjs-playlist .vjs-selected .vjs-playlist-now-playing-text{display:block}.vjs-playlist .vjs-selected .vjs-playlist-title-container{text-shadow:none}.vjs-playlist-vertical{overflow-x:hidden;overflow-y:auto}.vjs-playlist-vertical img{width:100%;min-height:54px}.vjs-playlist-vertical .vjs-playlist-item{margin-bottom:5px}.vjs-playlist-vertical .vjs-playlist-thumbnail{display:block;width:100%}.vjs-playlist-vertical .vjs-playlist-thumbnail-placeholder{height:100px}.vjs-playlist-horizontal{overflow-x:auto;overflow-y:hidden}.vjs-playlist-horizontal img{min-width:100px;height:100%}.vjs-playlist-horizontal .vjs-playlist-item-list{height:100%;white-space:nowrap}.vjs-playlist-horizontal .vjs-playlist-item{display:inline-block;height:100%;margin-right:5px}.vjs-playlist-horizontal .vjs-playlist-thumbnail{display:block;height:100%}.vjs-playlist-horizontal .vjs-playlist-thumbnail-placeholder{height:100%;width:180px}.vjs-playlist.vjs-ad-playing{overflow:hidden}.vjs-playlist.vjs-ad-playing.vjs-csspointerevents{pointer-events:none;overflow:auto}.vjs-playlist.vjs-ad-playing.vjs-csspointerevents .vjs-playlist-ad-overlay{pointer-events:auto}.vjs-playlist.vjs-ad-playing .vjs-playlist-ad-overlay{display:block;position:absolute;top:0;left:0;width:100%;height:100%;background-color:#1a1a1a;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";background-color:rgba(0,0,0,0.5)}.vjs-playlist{font-size:14px}.vjs-playlist .vjs-playlist-description{height:42px;line-height:21px}.vjs-mouse.vjs-playlist{font-size:15px}.vjs-mouse.vjs-playlist .vjs-playlist-description{height:45px;line-height:23px}@media (min-width: 600px){.vjs-mouse.vjs-playlist{font-size:17px}.vjs-mouse.vjs-playlist .vjs-playlist-description{height:51px;line-height:26px}.vjs-playlist .vjs-playlist-name{line-height:22px}}@media (max-width: 520px){.vjs-playlist .vjs-selected .vjs-playlist-now-playing-text,.vjs-playlist .vjs-up-next .vjs-up-next-text{display:none}.vjs-mouse.vjs-playlist .vjs-selected .vjs-playlist-now-playing-text,.vjs-mouse.vjs-playlist .vjs-up-next .vjs-up-next-text{display:none}}@media (min-width: 521px){.vjs-playlist img{min-height:85px}}@media (max-width: 750px){.vjs-playlist .vjs-playlist-duration{display:none}}

View File

@ -0,0 +1 @@
.vjs-playlist{padding:0;background-color:#1a1a1a;color:#fff;list-style-type:none}.vjs-playlist img{display:block;height:auto;width:auto}.vjs-playlist .vjs-playlist-item-list{position:relative;margin:0;padding:0;list-style:none}.vjs-playlist .vjs-playlist-item{position:relative;cursor:pointer;overflow:hidden}.vjs-playlist .vjs-playlist-thumbnail-placeholder{background:#303030}.vjs-playlist .vjs-playlist-now-playing-text{display:none;position:absolute;top:0;left:0;padding-left:2px;margin:.8rem}.vjs-playlist .vjs-playlist-duration{position:absolute;top:.5rem;left:.5rem;padding:2px 5px 3px;margin-left:2px;background-color:rgba(26,26,26,0.8)}.vjs-playlist .vjs-playlist-title-container{position:absolute;bottom:0;box-sizing:border-box;width:100%;padding:.5rem .8rem;text-shadow:1px 1px 2px black, -1px 1px 2px black, 1px -1px 2px black, -1px -1px 2px black}.vjs-playlist .vjs-playlist-name{display:block;max-height:2.5em;padding:0 0 4px 2px;font-style:normal;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;line-height:20px}.vjs-playlist .vjs-playlist-description{margin:0;text-overflow:ellipsis;overflow:hidden}.vjs-playlist .vjs-up-next-text{display:none;padding:.1rem 2px;font-size:.8em;text-transform:uppercase}.vjs-playlist .vjs-up-next .vjs-up-next-text{display:block}.vjs-playlist .vjs-selected{background-color:#141a21}.vjs-playlist .vjs-selected img{opacity:.2}.vjs-playlist .vjs-selected .vjs-playlist-duration{display:none}.vjs-playlist .vjs-selected .vjs-playlist-now-playing-text{display:block}.vjs-playlist .vjs-selected .vjs-playlist-title-container{text-shadow:none}.vjs-playlist-vertical{overflow-x:hidden;overflow-y:auto}.vjs-playlist-vertical img{width:100%;min-height:54px}.vjs-playlist-vertical .vjs-playlist-item{margin-bottom:5px}.vjs-playlist-vertical .vjs-playlist-thumbnail{display:block;width:100%}.vjs-playlist-vertical .vjs-playlist-thumbnail-placeholder{height:100px}.vjs-playlist-horizontal{overflow-x:auto;overflow-y:hidden}.vjs-playlist-horizontal img{min-width:100px;height:100%}.vjs-playlist-horizontal .vjs-playlist-item-list{height:100%;white-space:nowrap}.vjs-playlist-horizontal .vjs-playlist-item{display:inline-block;height:100%;margin-right:5px}.vjs-playlist-horizontal .vjs-playlist-thumbnail{display:block;height:100%}.vjs-playlist-horizontal .vjs-playlist-thumbnail-placeholder{height:100%;width:180px}.vjs-playlist.vjs-ad-playing{overflow:hidden}.vjs-playlist.vjs-ad-playing.vjs-csspointerevents{pointer-events:none;overflow:auto}.vjs-playlist.vjs-ad-playing.vjs-csspointerevents .vjs-playlist-ad-overlay{pointer-events:auto}.vjs-playlist.vjs-ad-playing .vjs-playlist-ad-overlay{display:block;position:absolute;top:0;left:0;width:100%;height:100%;background-color:#1a1a1a;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";background-color:rgba(0,0,0,0.5)}.vjs-playlist{font-size:14px}.vjs-playlist .vjs-playlist-description{height:42px;line-height:21px}.vjs-mouse.vjs-playlist{font-size:15px}.vjs-mouse.vjs-playlist .vjs-playlist-description{height:45px;line-height:23px}@media (min-width: 600px){.vjs-mouse.vjs-playlist{font-size:17px}.vjs-mouse.vjs-playlist .vjs-playlist-description{height:51px;line-height:26px}.vjs-playlist .vjs-playlist-name{line-height:22px}}@media (max-width: 520px){.vjs-playlist .vjs-selected .vjs-playlist-now-playing-text,.vjs-playlist .vjs-up-next .vjs-up-next-text{display:none}.vjs-mouse.vjs-playlist .vjs-selected .vjs-playlist-now-playing-text,.vjs-mouse.vjs-playlist .vjs-up-next .vjs-up-next-text{display:none}}@media (min-width: 521px){.vjs-playlist img{min-height:85px}}@media (max-width: 750px){.vjs-playlist .vjs-playlist-duration{display:none}}

View File

@ -0,0 +1,18 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>videojs-playlist-ui Demo</title>
</head>
<body>
<ul>
<li><a href="example.html">Example</a></li>
<li><a href="example-two-players.html">Example with Two Playlist Players</a></li>
<li><a href="example-custom-class.html">Example with Custom Class</a></li>
<li><a href="example-custom-element.html">Example with Custom Element</a></li>
<li><a href="example-horizontal.html">Example, Horizontal Implementation</a></li>
<li><a href="example-custom-data.html">Example with Custom Data Attributes</a></li>
<li><a href="test/debug.html">Run unit tests in browser.</a></li>
</ul>
</body>
</html>

View File

@ -0,0 +1,143 @@
{
"_from": "videojs-playlist-ui",
"_id": "videojs-playlist-ui@3.5.2",
"_inBundle": false,
"_integrity": "sha512-c/TWpWPJaSnRiyD4NVmMeTTyEigGdKvJL5PV+G6fRhBtvnnm+luNiXnCMD2PemHERLK0l3sx6L7v9AhRJ4n97g==",
"_location": "/videojs-playlist-ui",
"_phantomChildren": {},
"_requested": {
"type": "tag",
"registry": true,
"raw": "videojs-playlist-ui",
"name": "videojs-playlist-ui",
"escapedName": "videojs-playlist-ui",
"rawSpec": "",
"saveSpec": null,
"fetchSpec": "latest"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npmjs.org/videojs-playlist-ui/-/videojs-playlist-ui-3.5.2.tgz",
"_shasum": "4928554f73fced290061834e7bce1ad298c97943",
"_spec": "videojs-playlist-ui",
"_where": "/home/shagi/negro_mate/web/negromateweb/static",
"author": {
"name": "Brightcove, Inc."
},
"browserslist": [
"defaults",
"ie 11"
],
"bugs": {
"url": "https://github.com/brightcove/videojs-playlist-ui/issues"
},
"bundleDependencies": false,
"dependencies": {
"global": "^4.3.2",
"video.js": "^6 || ^7"
},
"deprecated": false,
"description": "A user interface for the videojs-playlist API",
"devDependencies": {
"conventional-changelog-cli": "^2.0.1",
"conventional-changelog-videojs": "^3.0.0",
"doctoc": "^1.3.1",
"husky": "^1.0.0-rc.13",
"jsdoc": "git+https://github.com/BrandonOCasey/jsdoc.git#feat/plugin-from-cli",
"karma": "^3.0.0",
"lint-staged": "^7.2.2",
"node-sass": "^4.5.3",
"not-prerelease": "^1.0.1",
"npm-merge-driver-install": "^1.0.0",
"npm-run-all": "^4.1.3",
"pkg-ok": "^2.2.0",
"postcss-cli": "^6.0.0",
"rollup": "^0.66.0",
"shx": "^0.3.2",
"sinon": "^6.1.5",
"videojs-generate-karma-config": "~3.0.0",
"videojs-generate-postcss-config": "~2.0.1",
"videojs-generate-rollup-config": "~2.2.0",
"videojs-generator-verify": "~1.0.3",
"videojs-playlist": "^4.2.4",
"videojs-standard": "~7.1.0"
},
"files": [
"CONTRIBUTING.md",
"dist/",
"docs/",
"index.html",
"scripts/",
"src/",
"test/"
],
"generator-videojs-plugin": {
"version": "7.3.2"
},
"homepage": "https://github.com/brightcove/videojs-playlist-ui#readme",
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"keywords": [
"playlist",
"videojs",
"videojs-plugin"
],
"license": "Apache-2.0",
"lint-staged": {
"*.js": [
"vjsstandard --fix",
"git add"
],
"README.md": [
"npm run docs:toc",
"git add"
]
},
"main": "dist/videojs-playlist-ui.cjs.js",
"module": "dist/videojs-playlist-ui.es.js",
"name": "videojs-playlist-ui",
"repository": {
"type": "git",
"url": "git+https://github.com/brightcove/videojs-playlist-ui.git"
},
"scripts": {
"build": "npm-run-all -p build:*",
"build:css": "npm-run-all build:css:sass build:css:copy-vertical build:css:copy-no-prefix",
"build:css:copy-no-prefix": "shx cp dist/videojs-playlist-ui.css dist/videojs-playlist-ui.vertical.no-prefix.css",
"build:css:copy-vertical": "shx cp dist/videojs-playlist-ui.css dist/videojs-playlist-ui.vertical.css",
"build:css:sass": "node-sass src/plugin.scss dist/videojs-playlist-ui.css --output-style=compressed --linefeed=lf",
"build:js": "rollup -c scripts/rollup.config.js",
"clean": "shx rm -rf ./dist ./test/dist",
"docs": "npm-run-all docs:*",
"docs:api": "jsdoc src -g plugins/markdown -r -d docs/api",
"docs:toc": "doctoc README.md",
"lint": "vjsstandard",
"postclean": "shx mkdir -p ./dist ./test/dist",
"posttest": "shx cat test/dist/coverage/text.txt",
"prebuild": "npm run clean",
"prepublishOnly": "npm run build && vjsverify",
"pretest": "npm-run-all lint build",
"preversion": "npm test",
"server": "karma start scripts/karma.conf.js --singleRun=false --auto-watch",
"start": "npm-run-all -p server watch",
"test": "karma start scripts/karma.conf.js",
"update-changelog": "conventional-changelog -p videojs -i CHANGELOG.md -s",
"version": "is-prerelease || npm run update-changelog && git add CHANGELOG.md",
"watch": "npm-run-all -p watch:*",
"watch:css": "npm run build:css:sass -- -w",
"watch:js": "npm run build:js -- -w"
},
"version": "3.5.2",
"vjsstandard": {
"ignore": [
"dist",
"docs",
"test/dist"
]
}
}

View File

@ -0,0 +1,13 @@
const generate = require('videojs-generate-karma-config');
module.exports = function(config) {
// see https://github.com/videojs/videojs-generate-karma-config
// for options
const options = {};
config = generate(config, options);
// any other custom stuff not supported by options here!
};

View File

@ -0,0 +1,9 @@
const generate = require('videojs-generate-postcss-config');
module.exports = function(context) {
const result = generate({}, context);
// do custom stuff here
return result;
};

View File

@ -0,0 +1,11 @@
const generate = require('videojs-generate-rollup-config');
// see https://github.com/videojs/videojs-generate-rollup-config
// for options
const options = {};
const config = generate(options);
// Add additonal builds/customization here!
// export the builds to rollup
export default Object.values(config.builds);

View File

@ -0,0 +1,479 @@
import document from 'global/document';
import videojs from 'video.js';
import {version as VERSION} from '../package.json';
const dom = videojs.dom || videojs;
const registerPlugin = videojs.registerPlugin || videojs.plugin;
// Array#indexOf analog for IE8
const indexOf = function(array, target) {
for (let i = 0, length = array.length; i < length; i++) {
if (array[i] === target) {
return i;
}
}
return -1;
};
// see https://github.com/Modernizr/Modernizr/blob/master/feature-detects/css/pointerevents.js
const supportsCssPointerEvents = (() => {
const element = document.createElement('x');
element.style.cssText = 'pointer-events:auto';
return element.style.pointerEvents === 'auto';
})();
const defaults = {
className: 'vjs-playlist',
playOnSelect: false,
supportsCssPointerEvents
};
// we don't add `vjs-playlist-now-playing` in addSelectedClass
// so it won't conflict with `vjs-icon-play
// since it'll get added when we mouse out
const addSelectedClass = function(el) {
el.addClass('vjs-selected');
};
const removeSelectedClass = function(el) {
el.removeClass('vjs-selected');
if (el.thumbnail) {
dom.removeClass(el.thumbnail, 'vjs-playlist-now-playing');
}
};
const upNext = function(el) {
el.addClass('vjs-up-next');
};
const notUpNext = function(el) {
el.removeClass('vjs-up-next');
};
const createThumbnail = function(thumbnail) {
if (!thumbnail) {
const placeholder = document.createElement('div');
placeholder.className = 'vjs-playlist-thumbnail vjs-playlist-thumbnail-placeholder';
return placeholder;
}
const picture = document.createElement('picture');
picture.className = 'vjs-playlist-thumbnail';
if (typeof thumbnail === 'string') {
// simple thumbnails
const img = document.createElement('img');
img.src = thumbnail;
img.alt = '';
picture.appendChild(img);
} else {
// responsive thumbnails
// additional variations of a <picture> are specified as
// <source> elements
for (let i = 0; i < thumbnail.length - 1; i++) {
const variant = thumbnail[i];
const source = document.createElement('source');
// transfer the properties of each variant onto a <source>
for (const prop in variant) {
source[prop] = variant[prop];
}
picture.appendChild(source);
}
// the default version of a <picture> is specified by an <img>
const variant = thumbnail[thumbnail.length - 1];
const img = document.createElement('img');
img.alt = '';
for (const prop in variant) {
img[prop] = variant[prop];
}
picture.appendChild(img);
}
return picture;
};
const Component = videojs.getComponent('Component');
class PlaylistMenuItem extends Component {
constructor(player, playlistItem, settings) {
if (!playlistItem.item) {
throw new Error('Cannot construct a PlaylistMenuItem without an item option');
}
super(player, playlistItem);
this.item = playlistItem.item;
this.playOnSelect = settings.playOnSelect;
this.emitTapEvents();
this.on(['click', 'tap'], this.switchPlaylistItem_);
this.on('keydown', this.handleKeyDown_);
}
handleKeyDown_(event) {
// keycode 13 is <Enter>
// keycode 32 is <Space>
if (event.which === 13 || event.which === 32) {
this.switchPlaylistItem_();
}
}
switchPlaylistItem_(event) {
this.player_.playlist.currentItem(indexOf(this.player_.playlist(), this.item));
if (this.playOnSelect) {
this.player_.play();
}
}
createEl() {
const li = document.createElement('li');
const item = this.options_.item;
if (typeof item.data === 'object') {
const dataKeys = Object.keys(item.data);
dataKeys.forEach(key => {
const value = item.data[key];
li.dataset[key] = value;
});
}
li.className = 'vjs-playlist-item';
li.setAttribute('tabIndex', 0);
// Thumbnail image
this.thumbnail = createThumbnail(item.thumbnail);
li.appendChild(this.thumbnail);
// Duration
if (item.duration) {
const duration = document.createElement('time');
const time = videojs.formatTime(item.duration);
duration.className = 'vjs-playlist-duration';
duration.setAttribute('datetime', 'PT0H0M' + item.duration + 'S');
duration.appendChild(document.createTextNode(time));
li.appendChild(duration);
}
// Now playing
const nowPlayingEl = document.createElement('span');
const nowPlayingText = this.localize('Now Playing');
nowPlayingEl.className = 'vjs-playlist-now-playing-text';
nowPlayingEl.appendChild(document.createTextNode(nowPlayingText));
nowPlayingEl.setAttribute('title', nowPlayingText);
this.thumbnail.appendChild(nowPlayingEl);
// Title container contains title and "up next"
const titleContainerEl = document.createElement('div');
titleContainerEl.className = 'vjs-playlist-title-container';
this.thumbnail.appendChild(titleContainerEl);
// Up next
const upNextEl = document.createElement('span');
const upNextText = this.localize('Up Next');
upNextEl.className = 'vjs-up-next-text';
upNextEl.appendChild(document.createTextNode(upNextText));
upNextEl.setAttribute('title', upNextText);
titleContainerEl.appendChild(upNextEl);
// Video title
const titleEl = document.createElement('cite');
const titleText = item.name || this.localize('Untitled Video');
titleEl.className = 'vjs-playlist-name';
titleEl.appendChild(document.createTextNode(titleText));
titleEl.setAttribute('title', titleText);
titleContainerEl.appendChild(titleEl);
return li;
}
}
class PlaylistMenu extends Component {
constructor(player, options) {
if (!player.playlist) {
throw new Error('videojs-playlist is required for the playlist component');
}
super(player, options);
this.items = [];
if (options.horizontal) {
this.addClass('vjs-playlist-horizontal');
} else {
this.addClass('vjs-playlist-vertical');
}
// If CSS pointer events aren't supported, we have to prevent
// clicking on playlist items during ads with slightly more
// invasive techniques. Details in the stylesheet.
if (options.supportsCssPointerEvents) {
this.addClass('vjs-csspointerevents');
}
this.createPlaylist_();
if (!videojs.browser.TOUCH_ENABLED) {
this.addClass('vjs-mouse');
}
this.on(player, ['loadstart', 'playlistchange', 'playlistsorted'], (event) => {
this.update();
});
// Keep track of whether an ad is playing so that the menu
// appearance can be adapted appropriately
this.on(player, 'adstart', () => {
this.addClass('vjs-ad-playing');
});
this.on(player, 'adend', () => {
this.removeClass('vjs-ad-playing');
});
this.on('dispose', () => {
this.empty_();
player.playlistMenu = null;
});
this.on(player, 'dispose', () => {
this.dispose();
});
}
createEl() {
return dom.createEl('div', {className: this.options_.className});
}
empty_() {
if (this.items && this.items.length) {
this.items.forEach(i => i.dispose());
this.items.length = 0;
}
}
createPlaylist_() {
const playlist = this.player_.playlist() || [];
let list = this.el_.querySelector('.vjs-playlist-item-list');
let overlay = this.el_.querySelector('.vjs-playlist-ad-overlay');
if (!list) {
list = document.createElement('ol');
list.className = 'vjs-playlist-item-list';
this.el_.appendChild(list);
}
this.empty_();
// create new items
for (let i = 0; i < playlist.length; i++) {
const item = new PlaylistMenuItem(this.player_, {
item: playlist[i]
}, this.options_);
this.items.push(item);
list.appendChild(item.el_);
}
// Inject the ad overlay. IE<11 doesn't support "pointer-events:
// none" so we use this element to block clicks during ad
// playback.
if (!overlay) {
overlay = document.createElement('li');
overlay.className = 'vjs-playlist-ad-overlay';
list.appendChild(overlay);
} else {
// Move overlay to end of list
list.appendChild(overlay);
}
// select the current playlist item
const selectedIndex = this.player_.playlist.currentItem();
if (this.items.length && selectedIndex >= 0) {
addSelectedClass(this.items[selectedIndex]);
const thumbnail = this.items[selectedIndex].$('.vjs-playlist-thumbnail');
if (thumbnail) {
dom.addClass(thumbnail, 'vjs-playlist-now-playing');
}
}
}
update() {
// replace the playlist items being displayed, if necessary
const playlist = this.player_.playlist();
if (this.items.length !== playlist.length) {
// if the menu is currently empty or the state is obviously out
// of date, rebuild everything.
this.createPlaylist_();
return;
}
for (let i = 0; i < this.items.length; i++) {
if (this.items[i].item !== playlist[i]) {
// if any of the playlist items have changed, rebuild the
// entire playlist
this.createPlaylist_();
return;
}
}
// the playlist itself is unchanged so just update the selection
const currentItem = this.player_.playlist.currentItem();
for (let i = 0; i < this.items.length; i++) {
const item = this.items[i];
if (i === currentItem) {
addSelectedClass(item);
if (document.activeElement !== item.el()) {
dom.addClass(item.thumbnail, 'vjs-playlist-now-playing');
}
notUpNext(item);
} else if (i === currentItem + 1) {
removeSelectedClass(item);
upNext(item);
} else {
removeSelectedClass(item);
notUpNext(item);
}
}
}
}
/**
* Returns a boolean indicating whether an element has child elements.
*
* Note that this is distinct from whether it has child _nodes_.
*
* @param {HTMLElement} el
* A DOM element.
*
* @return {boolean}
* Whether the element has child elements.
*/
const hasChildEls = (el) => {
for (let i = 0; i < el.childNodes.length; i++) {
if (dom.isEl(el.childNodes[i])) {
return true;
}
}
return false;
};
/**
* Finds the first empty root element.
*
* @param {string} className
* An HTML class name to search for.
*
* @return {HTMLElement}
* A DOM element to use as the root for a playlist.
*/
const findRoot = (className) => {
const all = document.querySelectorAll('.' + className);
let el;
for (let i = 0; i < all.length; i++) {
if (!hasChildEls(all[i])) {
el = all[i];
break;
}
}
return el;
};
/**
* Initialize the plugin on a player.
*
* @param {Object} [options]
* An options object.
*
* @param {HTMLElement} [options.el]
* A DOM element to use as a root node for the playlist.
*
* @param {string} [options.className]
* An HTML class name to use to find a root node for the playlist.
*
* @param {boolean} [options.playOnSelect = false]
* If true, will attempt to begin playback upon selecting a new
* playlist item in the UI.
*/
const playlistUi = function(options) {
const player = this;
if (!player.playlist) {
throw new Error('videojs-playlist plugin is required by the videojs-playlist-ui plugin');
}
if (dom.isEl(options)) {
videojs.log.warn('videojs-playlist-ui: Passing an element directly to playlistUi() is deprecated, use the "el" option instead!');
options = {el: options};
}
options = videojs.mergeOptions(defaults, options);
// If the player is already using this plugin, remove the pre-existing
// PlaylistMenu, but retain the element and its location in the DOM because
// it will be re-used.
if (player.playlistMenu) {
const el = player.playlistMenu.el();
// Catch cases where the menu may have been disposed elsewhere or the
// element removed from the DOM.
if (el) {
const parentNode = el.parentNode;
const nextSibling = el.nextSibling;
// Disposing the menu will remove `el` from the DOM, but we need to
// empty it ourselves to be sure.
player.playlistMenu.dispose();
dom.emptyEl(el);
// Put the element back in its place.
if (nextSibling) {
parentNode.insertBefore(el, nextSibling);
} else {
parentNode.appendChild(el);
}
options.el = el;
}
}
if (!dom.isEl(options.el)) {
options.el = findRoot(options.className);
}
player.playlistMenu = new PlaylistMenu(player, options);
};
// register components
videojs.registerComponent('PlaylistMenu', PlaylistMenu);
videojs.registerComponent('PlaylistMenuItem', PlaylistMenuItem);
// register the plugin
registerPlugin('playlistUi', playlistUi);
playlistUi.VERSION = VERSION;
export default playlistUi;

View File

@ -0,0 +1,288 @@
// The default color for the playlist menu background, almost black
$background-color: #1a1a1a;
// The color used to emphasize the currently playing video and for effects
$highlight-color: #141a21;
// The primary foreground color
$main-color: #fff;
// Background color for thumbnail placeholders
$placeholder-background-color: #303030;
// Rules common to mouse and touch devices
.vjs-playlist {
padding: 0;
background-color: $background-color;
color: $main-color;
list-style-type: none;
img {
display: block;
// Needed because sometimes IE10 adds width / height properties
height: auto;
width: auto;
}
.vjs-playlist-item-list {
position: relative;
margin: 0;
padding: 0;
list-style: none;
}
.vjs-playlist-item {
position: relative;
cursor: pointer;
overflow: hidden;
}
.vjs-playlist-thumbnail-placeholder {
background: $placeholder-background-color;
}
.vjs-playlist-now-playing-text {
display: none;
position: absolute;
top: 0;
left: 0;
// This keeps this element aligned vertically with vjs-playlist-name.
padding-left: 2px;
margin: .8rem;
}
.vjs-playlist-duration {
position: absolute;
top: .5rem;
left: .5rem;
padding: 2px 5px 3px;
margin-left: 2px;
background-color: rgba(26, 26, 26, 0.8);
}
.vjs-playlist-title-container {
position: absolute;
bottom: 0;
box-sizing: border-box;
width: 100%;
padding: .5rem .8rem;
text-shadow: 1px 1px 2px black,
-1px 1px 2px black,
1px -1px 2px black,
-1px -1px 2px black;
}
.vjs-playlist-name {
display: block;
max-height: 2.5em;
// So drop shadow doesn't get cut off as overflow
padding: 0 0 4px 2px;
font-style: normal;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
// line-height: normal was causing overflow cutoff issues on Android, since normal
// lets different user agents pick a value. Here we set a consistent precise value.
line-height: 20px;
}
.vjs-playlist-description {
margin: 0;
text-overflow: ellipsis;
overflow: hidden;
}
.vjs-up-next-text {
display: none;
padding: .1rem 2px;
font-size: .8em;
text-transform: uppercase;
}
.vjs-up-next {
.vjs-up-next-text {
display: block;
}
}
// Selected item rules
.vjs-selected {
background-color: $highlight-color;
img {
opacity: .2;
}
.vjs-playlist-duration {
display: none;
}
.vjs-playlist-now-playing-text {
display: block;
}
.vjs-playlist-title-container {
text-shadow: none;
}
}
}
// Vertical/default playlist orientation
.vjs-playlist-vertical {
overflow-x: hidden;
overflow-y: auto;
img {
width: 100%;
min-height: 54px;
}
.vjs-playlist-item {
margin-bottom: 5px;
}
.vjs-playlist-thumbnail {
display: block;
width: 100%;
}
.vjs-playlist-thumbnail-placeholder {
height: 100px;
}
}
// Horizontal playlist orientation
.vjs-playlist-horizontal {
overflow-x: auto;
overflow-y: hidden;
img {
min-width: 100px;
height: 100%;
}
.vjs-playlist-item-list {
height: 100%;
white-space: nowrap;
}
.vjs-playlist-item {
display: inline-block;
height: 100%;
margin-right: 5px;
}
.vjs-playlist-thumbnail {
display: block;
height: 100%;
}
.vjs-playlist-thumbnail-placeholder {
height: 100%;
width: 180px;
}
}
// Prevent interaction with the playlist menu while ads are playing
// on browsers that don't support pointer-events (IE<11), prevent scrolling
// past the ad overlay
.vjs-playlist.vjs-ad-playing {
overflow: hidden;
}
// prevent clicks and scrolling from affecting the playlist during ads
.vjs-playlist.vjs-ad-playing.vjs-csspointerevents {
pointer-events: none;
overflow: auto;
// Fix for IE11 pointer-events bug that allowed clicking playlist during ads
.vjs-playlist-ad-overlay {
pointer-events: auto;
}
}
// darken the playlist menu display to indicate it's not interactive during ads
.vjs-playlist.vjs-ad-playing .vjs-playlist-ad-overlay {
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
// IE8 fallback
background-color: #1a1a1a;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
// modern browsers
background-color: rgba(0, 0, 0, 0.5);
}
// Parametric rules. These are specialized for touch and mouse-based devices
@mixin playlist-base($base-font-size: 14px) {
font-size: $base-font-size;
.vjs-playlist-description {
height: $base-font-size * 3;
line-height: ceil($base-font-size * 1.5);
}
}
// Touch-device playlist dimensions
.vjs-playlist {
@include playlist-base();
}
// Mouse-only playlist dimensions
.vjs-mouse.vjs-playlist {
@include playlist-base(15px);
}
// Larger font size for larger player
@media (min-width: 600px) {
.vjs-mouse.vjs-playlist {
@include playlist-base(17px);
}
.vjs-playlist .vjs-playlist-name {
line-height: 22px;
}
}
// Don't show now playing / up next when there isn't room
@media (max-width: 520px) {
// These styles exist both with and without .vjs-mouse
.vjs-playlist .vjs-selected .vjs-playlist-now-playing-text,
.vjs-playlist .vjs-up-next .vjs-up-next-text {
display: none;
}
.vjs-mouse.vjs-playlist .vjs-selected .vjs-playlist-now-playing-text,
.vjs-mouse.vjs-playlist .vjs-up-next .vjs-up-next-text {
display: none;
}
}
// If now playing / up next are shown, make sure there is room.
// Only affects thumbnails with very wide aspect ratio, which get
// stretched vertically. We could avoid the stretching by making this a
// CSS background image and using background-size: cover; but then it'd
// get clipped, so not sure that's better.
@media (min-width: 521px) {
.vjs-playlist img {
min-height: 85px;
}
}
// Don't show duration when there isn't room
@media (max-width: 750px) {
.vjs-playlist .vjs-playlist-duration {
display: none;
}
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

View File

@ -0,0 +1,576 @@
/* eslint-disable no-console */
import document from 'global/document';
import window from 'global/window';
import QUnit from 'qunit';
import videojs from 'video.js';
import 'videojs-playlist';
import '../src/plugin';
const playlist = [{
name: 'Movie 1',
description: 'Movie 1 description',
duration: 100,
data: {
id: '1',
foo: 'bar'
},
sources: [{
src: '//example.com/movie1.mp4',
type: 'video/mp4'
}]
}, {
sources: [{
src: '//example.com/movie2.mp4',
type: 'video/mp4'
}],
thumbnail: '//example.com/movie2.jpg'
}];
const resolveUrl = url => {
const a = document.createElement('a');
a.href = url;
return a.href;
};
const dom = videojs.dom || videojs;
const Html5 = videojs.getTech('Html5');
QUnit.test('the environment is sane', function(assert) {
assert.ok(true, 'everything is swell');
});
function setup() {
this.oldVideojsBrowser = videojs.browser;
videojs.browser = videojs.mergeOptions({}, videojs.browser);
this.fixture = document.querySelector('#qunit-fixture');
// force HTML support so the tests run in a reasonable
// environment under phantomjs
this.realIsHtmlSupported = Html5.isSupported;
Html5.isSupported = function() {
return true;
};
// create a video element
const video = document.createElement('video');
this.fixture.appendChild(video);
// create a video.js player
this.player = videojs(video);
// Create two playlist container elements.
this.fixture.appendChild(dom.createEl('div', {className: 'vjs-playlist'}));
this.fixture.appendChild(dom.createEl('div', {className: 'vjs-playlist'}));
}
function teardown() {
videojs.browser = this.oldVideojsBrowser;
Html5.isSupported = this.realIsHtmlSupported;
this.player.dispose();
this.player = null;
dom.emptyEl(this.fixture);
}
QUnit.module('videojs-playlist-ui', {beforeEach: setup, afterEach: teardown});
QUnit.test('registers itself', function(assert) {
assert.ok(this.player.playlistUi, 'registered the plugin');
});
QUnit.test('errors if used without the playlist plugin', function(assert) {
assert.throws(function() {
this.player.playlist = null;
this.player.playlistUi();
}, 'threw on init');
});
QUnit.test('is empty if the playlist plugin isn\'t initialized', function(assert) {
this.player.playlistUi();
const items = this.fixture.querySelectorAll('.vjs-playlist-item');
assert.ok(this.fixture.querySelector('.vjs-playlist'), 'created the menu');
assert.strictEqual(items.length, 0, 'displayed no items');
});
QUnit.test('can be initialized with an element (deprecated form)', function(assert) {
const elem = dom.createEl('div');
this.player.playlist(playlist);
this.player.playlistUi(elem);
assert.strictEqual(
elem.querySelectorAll('li.vjs-playlist-item').length,
playlist.length,
'created an element for each playlist item'
);
});
QUnit.test('can be initialized with an element', function(assert) {
const elem = dom.createEl('div');
this.player.playlist(playlist);
this.player.playlistUi({el: elem});
assert.strictEqual(
elem.querySelectorAll('li.vjs-playlist-item').length,
playlist.length,
'created an element for each playlist item'
);
});
QUnit.test('can look for an element with the class "vjs-playlist" that is not already in use', function(assert) {
const firstEl = this.fixture.querySelectorAll('.vjs-playlist')[0];
const secondEl = this.fixture.querySelectorAll('.vjs-playlist')[1];
// Give the firstEl a child, so the plugin thinks it is in use and moves on
// to the next one.
firstEl.appendChild(dom.createEl('div'));
this.player.playlist(playlist);
this.player.playlistUi();
assert.strictEqual(this.player.playlistMenu.el(), secondEl, 'used the first matching/empty element');
assert.strictEqual(
secondEl.querySelectorAll('li.vjs-playlist-item').length,
playlist.length,
'found an element for each playlist item'
);
});
QUnit.test('can look for an element with a custom class that is not already in use', function(assert) {
const firstEl = dom.createEl('div', {className: 'super-playlist'});
const secondEl = dom.createEl('div', {className: 'super-playlist'});
// Give the firstEl a child, so the plugin thinks it is in use and moves on
// to the next one.
firstEl.appendChild(dom.createEl('div'));
this.fixture.appendChild(firstEl);
this.fixture.appendChild(secondEl);
this.player.playlist(playlist);
this.player.playlistUi({
className: 'super-playlist'
});
assert.strictEqual(this.player.playlistMenu.el(), secondEl, 'used the first matching/empty element');
assert.strictEqual(
this.fixture.querySelectorAll('li.vjs-playlist-item').length,
playlist.length,
'created an element for each playlist item'
);
});
QUnit.test('specializes the class name if touch input is absent', function(assert) {
videojs.browser.TOUCH_ENABLED = false;
this.player.playlist(playlist);
this.player.playlistUi();
assert.ok(this.player.playlistMenu.hasClass('vjs-mouse'), 'marked the playlist menu');
});
QUnit.test('can be re-initialized without doubling the contents of the list', function(assert) {
const el = this.fixture.querySelectorAll('.vjs-playlist')[0];
this.player.playlist(playlist);
this.player.playlistUi();
this.player.playlistUi();
this.player.playlistUi();
assert.strictEqual(this.player.playlistMenu.el(), el, 'used the first matching/empty element');
assert.strictEqual(
el.querySelectorAll('li.vjs-playlist-item').length,
playlist.length,
'found an element for each playlist item'
);
});
QUnit.module('videojs-playlist-ui: Components', {beforeEach: setup, afterEach: teardown});
// --------------------
// Creation and Updates
// --------------------
QUnit.test('includes the video name if provided', function(assert) {
this.player.playlist(playlist);
this.player.playlistUi();
const items = this.fixture.querySelectorAll('.vjs-playlist-item');
assert.strictEqual(items[0].querySelector('.vjs-playlist-name').textContent,
playlist[0].name,
'wrote the name');
assert.strictEqual(items[1].querySelector('.vjs-playlist-name').textContent,
'Untitled Video',
'wrote a placeholder for the name');
});
QUnit.test('includes custom data attribute if provided', function(assert) {
this.player.playlist(playlist);
this.player.playlistUi();
const items = this.fixture.querySelectorAll('.vjs-playlist-item');
assert.strictEqual(items[0].dataset.id,
playlist[0].data.id,
'set a single data attribute');
assert.strictEqual(items[0].dataset.id,
'1',
'set a single data attribute (actual value)');
assert.strictEqual(items[0].dataset.foo,
playlist[0].data.foo,
'set an addtional data attribute');
assert.strictEqual(items[0].dataset.foo,
'bar',
'set an addtional data attribute');
});
QUnit.test('outputs a <picture> for simple thumbnails', function(assert) {
this.player.playlist(playlist);
this.player.playlistUi();
const pictures = this.fixture.querySelectorAll('.vjs-playlist-item picture');
assert.strictEqual(pictures.length, 1, 'output one picture');
const imgs = pictures[0].querySelectorAll('img');
assert.strictEqual(imgs.length, 1, 'output one img');
assert.strictEqual(imgs[0].src, window.location.protocol + playlist[1].thumbnail, 'set the src attribute');
});
QUnit.test('outputs a <picture> for responsive thumbnails', function(assert) {
const playlistOverride = [{
sources: [{
src: '//example.com/movie.mp4',
type: 'video/mp4'
}],
thumbnail: [{
srcset: '/test/example/oceans.jpg',
type: 'image/jpeg',
media: '(min-width: 400px;)'
}, {
src: '/test/example/oceans-low.jpg'
}]
}];
this.player.playlist(playlistOverride);
this.player.playlistUi();
const sources = this.fixture.querySelectorAll('.vjs-playlist-item picture source');
const imgs = this.fixture.querySelectorAll('.vjs-playlist-item picture img');
assert.strictEqual(sources.length, 1, 'output one source');
assert.strictEqual(sources[0].srcset,
playlistOverride[0].thumbnail[0].srcset,
'wrote the srcset attribute');
assert.strictEqual(sources[0].type,
playlistOverride[0].thumbnail[0].type,
'wrote the type attribute');
assert.strictEqual(sources[0].media,
playlistOverride[0].thumbnail[0].media,
'wrote the type attribute');
assert.strictEqual(imgs.length, 1, 'output one img');
assert.strictEqual(imgs[0].src,
resolveUrl(playlistOverride[0].thumbnail[1].src),
'output the img src attribute');
});
QUnit.test('outputs a placeholder for items without thumbnails', function(assert) {
this.player.playlist(playlist);
this.player.playlistUi();
const thumbnails = this.fixture.querySelectorAll('.vjs-playlist-item .vjs-playlist-thumbnail');
assert.strictEqual(thumbnails.length, playlist.length, 'output two thumbnails');
assert.strictEqual(thumbnails[0].nodeName.toLowerCase(), 'div', 'the second is a placeholder');
});
QUnit.test('includes the duration if one is provided', function(assert) {
this.player.playlist(playlist);
this.player.playlistUi();
const durations = this.fixture.querySelectorAll('.vjs-playlist-item .vjs-playlist-duration');
assert.strictEqual(durations.length, 1, 'skipped the item without a duration');
assert.strictEqual(durations[0].textContent,
'1:40',
'wrote the duration');
assert.strictEqual(durations[0].getAttribute('datetime'),
'PT0H0M' + playlist[0].duration + 'S',
'wrote a machine-readable datetime');
});
QUnit.test('marks the selected playlist item on startup', function(assert) {
this.player.playlist(playlist);
this.player.currentSrc = () => playlist[0].sources[0].src;
this.player.playlistUi();
const selectedItems = this.fixture.querySelectorAll('.vjs-playlist-item.vjs-selected');
assert.strictEqual(selectedItems.length, 1, 'marked one playlist item');
assert.strictEqual(selectedItems[0].querySelector('.vjs-playlist-name').textContent,
playlist[0].name,
'marked the first playlist item');
});
QUnit.test('updates the selected playlist item on loadstart', function(assert) {
this.player.playlist(playlist);
this.player.playlistUi();
this.player.playlist.currentItem(1);
this.player.currentSrc = () => playlist[1].sources[0].src;
this.player.trigger('loadstart');
const selectedItems = this.fixture.querySelectorAll('.vjs-playlist-item.vjs-selected');
assert.strictEqual(this.fixture.querySelectorAll('.vjs-playlist-item').length,
playlist.length,
'displayed the correct number of items');
assert.strictEqual(selectedItems.length, 1, 'marked one playlist item');
assert.strictEqual(selectedItems[0].querySelector('img').src,
resolveUrl(playlist[1].thumbnail),
'marked the second playlist item');
});
QUnit.test('selects no item if the playlist is not in use', function(assert) {
this.player.playlist(playlist);
this.player.playlist.currentItem = () => -1;
this.player.playlistUi();
this.player.trigger('loadstart');
assert.strictEqual(this.fixture.querySelectorAll('.vjs-playlist-item.vjs-selected').length,
0,
'no items selected');
});
QUnit.test('updates on "playlistchange", different lengths', function(assert) {
this.player.playlist([]);
this.player.playlistUi();
let items = this.fixture.querySelectorAll('.vjs-playlist-item');
assert.strictEqual(items.length, 0, 'no items initially');
this.player.playlist(playlist);
this.player.trigger('playlistchange');
items = this.fixture.querySelectorAll('.vjs-playlist-item');
assert.strictEqual(items.length, playlist.length, 'updated with the new items');
});
QUnit.test('updates on "playlistchange", equal lengths', function(assert) {
this.player.playlist([{sources: []}, {sources: []}]);
this.player.playlistUi();
let items = this.fixture.querySelectorAll('.vjs-playlist-item');
assert.strictEqual(items.length, 2, 'two items initially');
this.player.playlist(playlist);
this.player.trigger('playlistchange');
items = this.fixture.querySelectorAll('.vjs-playlist-item');
assert.strictEqual(items.length, playlist.length, 'updated with the new items');
assert.strictEqual(this.player.playlistMenu.items[0].item, playlist[0], 'we have updated items');
assert.strictEqual(this.player.playlistMenu.items[1].item, playlist[1], 'we have updated items');
});
QUnit.test('updates on "playlistchange", update selection', function(assert) {
this.player.playlist(playlist);
this.player.currentSrc = function() {
return playlist[0].sources[0].src;
};
this.player.playlistUi();
let items = this.fixture.querySelectorAll('.vjs-playlist-item');
assert.strictEqual(items.length, 2, 'two items initially');
assert.ok((/vjs-selected/).test(items[0].getAttribute('class')), 'first item is selected by default');
this.player.playlist.currentItem(1);
this.player.currentSrc = function() {
return playlist[1].sources[0].src;
};
this.player.trigger('playlistchange');
items = this.fixture.querySelectorAll('.vjs-playlist-item');
assert.strictEqual(items.length, playlist.length, 'updated with the new items');
assert.ok((/vjs-selected/).test(items[1].getAttribute('class')), 'second item is selected after update');
assert.ok(!(/vjs-selected/).test(items[0].getAttribute('class')), 'first item is not selected after update');
});
QUnit.test('updates on "playlistsorted", different lengths', function(assert) {
this.player.playlist([]);
this.player.playlistUi();
let items = this.fixture.querySelectorAll('.vjs-playlist-item');
assert.strictEqual(items.length, 0, 'no items initially');
this.player.playlist(playlist);
this.player.trigger('playlistsorted');
items = this.fixture.querySelectorAll('.vjs-playlist-item');
assert.strictEqual(items.length, playlist.length, 'updated with the new items');
});
QUnit.test('updates on "playlistsorted", equal lengths', function(assert) {
this.player.playlist([{sources: []}, {sources: []}]);
this.player.playlistUi();
let items = this.fixture.querySelectorAll('.vjs-playlist-item');
assert.strictEqual(items.length, 2, 'two items initially');
this.player.playlist(playlist);
this.player.trigger('playlistsorted');
items = this.fixture.querySelectorAll('.vjs-playlist-item');
assert.strictEqual(items.length, playlist.length, 'updated with the new items');
assert.strictEqual(this.player.playlistMenu.items[0].item, playlist[0], 'we have updated items');
assert.strictEqual(this.player.playlistMenu.items[1].item, playlist[1], 'we have updated items');
});
QUnit.test('updates on "playlistsorted", update selection', function(assert) {
this.player.playlist(playlist);
this.player.currentSrc = function() {
return playlist[0].sources[0].src;
};
this.player.playlistUi();
let items = this.fixture.querySelectorAll('.vjs-playlist-item');
assert.strictEqual(items.length, 2, 'two items initially');
assert.ok((/vjs-selected/).test(items[0].getAttribute('class')), 'first item is selected by default');
this.player.playlist.currentItem(1);
this.player.currentSrc = function() {
return playlist[1].sources[0].src;
};
this.player.trigger('playlistsorted');
items = this.fixture.querySelectorAll('.vjs-playlist-item');
assert.strictEqual(items.length, playlist.length, 'updated with the new items');
assert.ok((/vjs-selected/).test(items[1].getAttribute('class')), 'second item is selected after update');
assert.ok(!(/vjs-selected/).test(items[0].getAttribute('class')), 'first item is not selected after update');
});
QUnit.test('tracks when an ad is playing', function(assert) {
this.player.playlist([]);
this.player.playlistUi();
this.player.duration = () => 5;
const playlistMenu = this.player.playlistMenu;
assert.ok(!playlistMenu.hasClass('vjs-ad-playing'),
'does not have class vjs-ad-playing');
this.player.trigger('adstart');
assert.ok(playlistMenu.hasClass('vjs-ad-playing'),
'has class vjs-ad-playing');
this.player.trigger('adend');
assert.ok(!playlistMenu.hasClass('vjs-ad-playing'),
'does not have class vjs-ad-playing');
});
// -----------
// Interaction
// -----------
QUnit.test('changes the selection when tapped', function(assert) {
let playCalled = false;
this.player.playlist(playlist);
this.player.playlistUi({playOnSelect: true});
this.player.play = function() {
playCalled = true;
};
let sources;
this.player.src = (src) => {
if (src) {
sources = src;
}
return sources[0];
};
this.player.currentSrc = () => sources[0].src;
this.player.playlistMenu.items[1].trigger('tap');
// trigger a loadstart synchronously to simplify the test
this.player.trigger('loadstart');
assert.ok(this.player.playlistMenu.items[1].hasClass('vjs-selected'),
'selected the new item');
assert.ok(!this.player.playlistMenu.items[0].hasClass('vjs-selected'),
'deselected the old item');
assert.strictEqual(playCalled, true, 'play gets called if option is set');
});
QUnit.test('play should not get called by default upon selection of menu items ', function(assert) {
let playCalled = false;
this.player.playlist(playlist);
this.player.playlistUi();
this.player.play = function() {
playCalled = true;
};
let sources;
this.player.src = (src) => {
if (src) {
sources = src;
}
return sources[0];
};
this.player.currentSrc = () => sources[0].src;
this.player.playlistMenu.items[1].trigger('tap');
// trigger a loadstart synchronously to simplify the test
this.player.trigger('loadstart');
assert.strictEqual(playCalled, false, 'play should not get called by default');
});
QUnit.test('disposing the playlist menu nulls out the player\'s reference to it', function(assert) {
assert.strictEqual(this.fixture.querySelectorAll('.vjs-playlist').length, 2, 'there are two playlist containers at the start');
this.player.playlist(playlist);
this.player.playlistUi();
this.player.playlistMenu.dispose();
assert.strictEqual(this.fixture.querySelectorAll('.vjs-playlist').length, 1, 'only the unused playlist container is left');
assert.strictEqual(this.player.playlistMenu, null, 'the playlistMenu property is null');
});
QUnit.test('disposing the playlist menu removes playlist menu items', function(assert) {
assert.strictEqual(this.fixture.querySelectorAll('.vjs-playlist').length, 2, 'there are two playlist containers at the start');
this.player.playlist(playlist);
this.player.playlistUi();
// Cache some references so we can refer to them after disposal.
const items = [].concat(this.player.playlistMenu.items);
this.player.playlistMenu.dispose();
assert.strictEqual(this.fixture.querySelectorAll('.vjs-playlist').length, 1, 'only the unused playlist container is left');
assert.strictEqual(this.player.playlistMenu, null, 'the playlistMenu property is null');
items.forEach(i => {
assert.strictEqual(i.el_, null, `the item "${i.id_}" has been disposed`);
});
});
QUnit.test('disposing the player also disposes the playlist menu', function(assert) {
assert.strictEqual(this.fixture.querySelectorAll('.vjs-playlist').length, 2, 'there are two playlist containers at the start');
this.player.playlist(playlist);
this.player.playlistUi();
this.player.dispose();
assert.strictEqual(this.fixture.querySelectorAll('.vjs-playlist').length, 1, 'only the unused playlist container is left');
assert.strictEqual(this.player.playlistMenu, null, 'the playlistMenu property is null');
});

View File

@ -0,0 +1,149 @@
<a name="4.2.6"></a>
## [4.2.6](https://github.com/brightcove/videojs-playlist/compare/v4.2.5...v4.2.6) (2018-09-05)
### Bug Fixes
* Remove the postinstall script to prevent install issues ([#119](https://github.com/brightcove/videojs-playlist/issues/119)) ([159fafe](https://github.com/brightcove/videojs-playlist/commit/159fafe))
<a name="4.2.5"></a>
## [4.2.5](https://github.com/brightcove/videojs-playlist/compare/v4.2.4...v4.2.5) (2018-08-30)
### Chores
* update generator to v7.1.1 ([12c5d53](https://github.com/brightcove/videojs-playlist/commit/12c5d53))
* **package:** Update rollup to version 0.65.0 ([#116](https://github.com/brightcove/videojs-playlist/issues/116)) ([17d6a37](https://github.com/brightcove/videojs-playlist/commit/17d6a37))
* update to generator-videojs-plugin[@7](https://github.com/7).2.0 ([4b90483](https://github.com/brightcove/videojs-playlist/commit/4b90483))
<a name="4.2.4"></a>
## [4.2.4](https://github.com/brightcove/videojs-playlist/compare/v4.2.3...v4.2.4) (2018-08-23)
### Chores
* generator v7 ([#114](https://github.com/brightcove/videojs-playlist/issues/114)) ([e671236](https://github.com/brightcove/videojs-playlist/commit/e671236))
<a name="4.2.3"></a>
## [4.2.3](https://github.com/brightcove/videojs-playlist/compare/v4.2.2...v4.2.3) (2018-08-03)
### Bug Fixes
* babel the es dist, by updating the generator ([#107](https://github.com/brightcove/videojs-playlist/issues/107)) ([4f1fdb9](https://github.com/brightcove/videojs-playlist/commit/4f1fdb9))
### Chores
* **package:** update dependencies, enable greenkeeper ([#106](https://github.com/brightcove/videojs-playlist/issues/106)) ([5ed060e](https://github.com/brightcove/videojs-playlist/commit/5ed060e))
<a name="4.2.2"></a>
## [4.2.2](https://github.com/brightcove/videojs-playlist/compare/v4.2.1...v4.2.2) (2018-07-05)
### Chores
* generator v6 ([#102](https://github.com/brightcove/videojs-playlist/issues/102)) ([8c50798](https://github.com/brightcove/videojs-playlist/commit/8c50798))
<a name="4.2.1"></a>
## [4.2.1](https://github.com/brightcove/videojs-playlist/compare/v4.2.0...v4.2.1) (2018-06-13)
### Features
* Expose the version of the plugin at the `VERSION` property. ([#94](https://github.com/brightcove/videojs-playlist/issues/94)) ([d71dec1](https://github.com/brightcove/videojs-playlist/commit/d71dec1))
<a name="4.2.0"></a>
# [4.2.0](https://github.com/brightcove/videojs-playlist/compare/v4.1.1...v4.2.0) (2018-01-25)
### Features
* Add 'duringplaylistchange' event. ([#92](https://github.com/brightcove/videojs-playlist/issues/92)) ([eb80503](https://github.com/brightcove/videojs-playlist/commit/eb80503))
* Add 'rest' option to the shuffle method. ([#91](https://github.com/brightcove/videojs-playlist/issues/91)) ([57d5f0c](https://github.com/brightcove/videojs-playlist/commit/57d5f0c))
<a name="4.1.1"></a>
## [4.1.1](https://github.com/brightcove/videojs-playlist/compare/v4.1.0...v4.1.1) (2018-01-08)
### Bug Fixes
* Fix an issue where we could auto-advance even if the user restarted playback after an ended event. ([#88](https://github.com/brightcove/videojs-playlist/issues/88)) ([5d872d1](https://github.com/brightcove/videojs-playlist/commit/5d872d1))
<a name="4.1.0"></a>
# [4.1.0](https://github.com/brightcove/videojs-playlist/compare/v4.0.2...v4.1.0) (2017-11-28)
### Features
* Add new methods: `currentIndex`, `nextIndex`, `previousIndex`, `lastIndex`, `sort`, `reverse`, and `shuffle`. ([#87](https://github.com/brightcove/videojs-playlist/issues/87)) ([271a27b](https://github.com/brightcove/videojs-playlist/commit/271a27b))
### Documentation
* Fix missing call to playlist ([#86](https://github.com/brightcove/videojs-playlist/issues/86)) ([a7ffd57](https://github.com/brightcove/videojs-playlist/commit/a7ffd57))
<a name="4.0.2"></a>
## [4.0.2](https://github.com/brightcove/videojs-playlist/compare/v4.0.1...v4.0.2) (2017-11-13)
### Bug Fixes
* Fix item switching for asynchronous source setting in Video.js 6. ([#85](https://github.com/brightcove/videojs-playlist/issues/85)) ([8a77bf0](https://github.com/brightcove/videojs-playlist/commit/8a77bf0))
<a name="4.0.1"></a>
## [4.0.1](https://github.com/brightcove/videojs-playlist/compare/v4.0.0...v4.0.1) (2017-10-16)
### Chores
* depend on either vjs 5.x or 6.x ([#84](https://github.com/brightcove/videojs-playlist/issues/84)) ([3f3c946](https://github.com/brightcove/videojs-playlist/commit/3f3c946))
<a name="4.0.0"></a>
# [4.0.0](https://github.com/brightcove/videojs-playlist/compare/v2.0.0...v4.0.0) (2017-05-19)
### Chores
* Update tooling using generator v5 prerelease. ([#79](https://github.com/brightcove/videojs-playlist/issues/79)) ([0b53140](https://github.com/brightcove/videojs-playlist/commit/0b53140))
### BREAKING CHANGES
* Remove Bower support.
## 3.1.1 (2017-04-27)
_(none)_
## 3.1.0 (2017-04-03)
* @incompl Add repeat functionality to plugin [#71](https://github.com/brightcove/videojs-playlist/pull/71)
## 3.0.2 (2017-02-10)
* @misteroneill Suppress videojs.plugin deprecation warning in Video.js 6 [#68](https://github.com/brightcove/videojs-playlist/pull/68)
## 3.0.1 (2017-01-30)
* @misteroneill Update project to use latest version of plugin generator as well as ensure cross-version support between Video.js 5 and 6. [#63](https://github.com/brightcove/videojs-playlist/pull/63)
## 3.0.0 (2016-09-12)
* @misteroneill Remove Brightcove VideoCloud-specific Code [#51](https://github.com/brightcove/videojs-playlist/pull/51)
## 2.5.0 (2016-09-12)
* @mister-ben Load playlist with initial video at specified index or no starting video [#38](https://github.com/brightcove/videojs-playlist/pull/38)
## 2.4.1 (2016-04-21)
* @gkatsev fixed build scripts to only apply browserify-shim for dist files. Fixes [#36](https://github.com/brightcove/videojs-playlist/issues/36). [#44](https://github.com/brightcove/videojs-playlist/pull/44)
## 2.4.0 (2016-04-21)
* @vdeshpande Fixed an issue where incorrect end time value was used [#43](https://github.com/brightcove/videojs-playlist/pull/43)
## 2.3.0 (2016-04-19)
* @vdeshpande Support cue point intervals [#37](https://github.com/brightcove/videojs-playlist/pull/37)
## 2.2.0 (2016-01-29)
* @forbesjo Support turning a list of cue points into a TextTrack [#24](https://github.com/brightcove/videojs-playlist/pull/24)
## 2.1.0 (2015-12-30)
* @misteroneill Moved to the generator-videojs-plugin format and added `last()` method [#23](https://github.com/brightcove/videojs-playlist/pull/23)
## 2.0.0 (2015-11-25)
* @misteroneill Updates for video.js 5.x [#22](https://github.com/brightcove/videojs-playlist/pull/22)
* @saramartinez Fix typos in examples for `currentItem()` method [#18](https://github.com/brightcove/videojs-playlist/pull/18)
## 1.0.3 (2015-08-24)
* @forbesjo README update [#16](https://github.com/brightcove/videojs-playlist/pull/16)
* @forbesjo Fix for playlist items without a `src` [#14](https://github.com/brightcove/videojs-playlist/pull/14)
## 1.0.2 (2015-04-09)
* @gkatsev Explicitly define which files are included.
## 1.0.1 (2015-03-30)
* @gkatsev Added missing repository field to `package.json`.
## 1.0.0 (2015-03-30)
* @gkatsev Initial release.

View File

@ -0,0 +1,30 @@
# CONTRIBUTING
We welcome contributions from everyone!
## Getting Started
Make sure you have Node.js 4.8 or higher and npm installed.
1. Fork this repository and clone your fork
1. Install dependencies: `npm install`
1. Run a development server: `npm start`
### Making Changes
Refer to the [video.js plugin conventions][conventions] for more detail on best practices and tooling for video.js plugin authorship.
When you've made your changes, push your commit(s) to your fork and issue a pull request against the original repository.
### Running Tests
Testing is a crucial part of any software project. For all but the most trivial changes (typos, etc) test cases are expected. Tests are run in actual browsers using [Karma][karma].
- In all available and supported browsers: `npm test`
- In a specific browser: `npm run test:chrome`, `npm run test:firefox`, etc.
- While development server is running (`npm start`), navigate to [`http://localhost:9999/test/`][local]
[karma]: http://karma-runner.github.io/
[local]: http://localhost:9999/test/
[conventions]: https://github.com/videojs/generator-videojs-plugin/blob/master/docs/conventions.md

View File

@ -0,0 +1,13 @@
Copyright Brightcove, Inc.
Licensed 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.

View File

@ -0,0 +1,96 @@
# videojs-playlist
[![Build Status](https://travis-ci.org/brightcove/videojs-playlist.svg?branch=master)](https://travis-ci.org/brightcove/videojs-playlist)
[![Greenkeeper badge](https://badges.greenkeeper.io/brightcove/videojs-playlist.svg)](https://greenkeeper.io/)
[![Slack Status](http://slack.videojs.com/badge.svg)](http://slack.videojs.com)
[![NPM](https://nodei.co/npm/videojs-playlist.png?downloads=true&downloadRank=true)](https://nodei.co/npm/videojs-playlist/)
A plugin to enable playlists in video.js
Maintenance Status: Stable
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
- [Installation](#installation)
- [Inclusion](#inclusion)
- [Basic Usage](#basic-usage)
- [License](#license)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## Installation
Install videojs-playlist via npm (preferred):
```sh
$ npm install videojs-playlist
```
Or Bower:
```sh
$ bower install videojs-playlist
```
## Inclusion
Include videojs-playlist on your website using the tool(s) of your choice.
The simplest method of inclusion is a `<script>` tag after the video.js `<script>` tag:
```html
<script src="path/to/video.js/dist/video.js"></script>
<script src="path/to/videojs-playlist/dist/videojs-playlist.js"></script>
```
When installed via npm, videojs-playlist supports Browserify-based workflows out of the box.
## Basic Usage
For full details on how to use the playlist plugin can be found in [the API documentation](docs/api.md).
```js
var player = videojs('video');
player.playlist([{
sources: [{
src: 'http://media.w3.org/2010/05/sintel/trailer.mp4',
type: 'video/mp4'
}],
poster: 'http://media.w3.org/2010/05/sintel/poster.png'
}, {
sources: [{
src: 'http://media.w3.org/2010/05/bunny/trailer.mp4',
type: 'video/mp4'
}],
poster: 'http://media.w3.org/2010/05/bunny/poster.png'
}, {
sources: [{
src: 'http://vjs.zencdn.net/v/oceans.mp4',
type: 'video/mp4'
}],
poster: 'http://www.videojs.com/img/poster.jpg'
}, {
sources: [{
src: 'http://media.w3.org/2010/05/bunny/movie.mp4',
type: 'video/mp4'
}],
poster: 'http://media.w3.org/2010/05/bunny/poster.png'
}, {
sources: [{
src: 'http://media.w3.org/2010/05/video/movie_300.mp4',
type: 'video/mp4'
}],
poster: 'http://media.w3.org/2010/05/video/poster.png'
}]);
// Play through the playlist automatically.
player.playlist.autoadvance(0);
```
## License
Apache-2.0. Copyright (c) Brightcove, Inc.

View File

@ -0,0 +1,767 @@
/*! @name videojs-playlist @version 4.2.6 @license Apache-2.0 */
'use strict';
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var videojs = _interopDefault(require('video.js'));
/**
* Validates a number of seconds to use as the auto-advance delay.
*
* @private
* @param {number} s
* The number to check
*
* @return {boolean}
* Whether this is a valid second or not
*/
var validSeconds = function validSeconds(s) {
return typeof s === 'number' && !isNaN(s) && s >= 0 && s < Infinity;
};
/**
* Resets the auto-advance behavior of a player.
*
* @param {Player} player
* The player to reset the behavior on
*/
var reset = function reset(player) {
var aa = player.playlist.autoadvance_;
if (aa.timeout) {
player.clearTimeout(aa.timeout);
}
if (aa.trigger) {
player.off('ended', aa.trigger);
}
aa.timeout = null;
aa.trigger = null;
};
/**
* Sets up auto-advance behavior on a player.
*
* @param {Player} player
* the current player
*
* @param {number} delay
* The number of seconds to wait before each auto-advance.
*
* @return {undefined}
* Used to short circuit function logic
*/
var setup = function setup(player, delay) {
reset(player); // Before queuing up new auto-advance behavior, check if `seconds` was
// called with a valid value.
if (!validSeconds(delay)) {
player.playlist.autoadvance_.delay = null;
return;
}
player.playlist.autoadvance_.delay = delay;
player.playlist.autoadvance_.trigger = function () {
// This calls setup again, which will reset the existing auto-advance and
// set up another auto-advance for the next "ended" event.
var cancelOnPlay = function cancelOnPlay() {
return setup(player, delay);
}; // If there is a "play" event while we're waiting for an auto-advance,
// we need to cancel the auto-advance. This could mean the user seeked
// back into the content or restarted the content. This is reproducible
// with an auto-advance > 0.
player.one('play', cancelOnPlay);
player.playlist.autoadvance_.timeout = player.setTimeout(function () {
reset(player);
player.off('play', cancelOnPlay);
player.playlist.next();
}, delay * 1000);
};
player.one('ended', player.playlist.autoadvance_.trigger);
};
/**
* Removes all remote text tracks from a player.
*
* @param {Player} player
* The player to clear tracks on
*/
var clearTracks = function clearTracks(player) {
var tracks = player.remoteTextTracks();
var i = tracks && tracks.length || 0; // This uses a `while` loop rather than `forEach` because the
// `TextTrackList` object is a live DOM list (not an array).
while (i--) {
player.removeRemoteTextTrack(tracks[i]);
}
};
/**
* Plays an item on a player's playlist.
*
* @param {Player} player
* The player to play the item on
*
* @param {Object} item
* A source from the playlist.
*
* @return {Player}
* The player that is now playing the item
*/
var playItem = function playItem(player, item) {
var replay = !player.paused() || player.ended();
player.trigger('beforeplaylistitem', item);
player.poster(item.poster || '');
player.src(item.sources);
clearTracks(player);
player.ready(function () {
(item.textTracks || []).forEach(player.addRemoteTextTrack.bind(player));
player.trigger('playlistitem', item);
if (replay) {
var playPromise = player.play(); // silence error when a pause interrupts a play request
// on browsers which return a promise
if (typeof playPromise !== 'undefined' && typeof playPromise.then === 'function') {
playPromise.then(null, function (e) {});
}
}
setup(player, player.playlist.autoadvance_.delay);
});
return player;
};
/**
* Given two sources, check to see whether the two sources are equal.
* If both source urls have a protocol, the protocols must match, otherwise, protocols
* are ignored.
*
* @private
* @param {string|Object} source1
* The first source
*
* @param {string|Object} source2
* The second source
*
* @return {boolean}
* The result
*/
var sourceEquals = function sourceEquals(source1, source2) {
var src1 = source1;
var src2 = source2;
if (typeof source1 === 'object') {
src1 = source1.src;
}
if (typeof source2 === 'object') {
src2 = source2.src;
}
if (/^\/\//.test(src1)) {
src2 = src2.slice(src2.indexOf('//'));
}
if (/^\/\//.test(src2)) {
src1 = src1.slice(src1.indexOf('//'));
}
return src1 === src2;
};
/**
* Look through an array of playlist items for a specific `source`;
* checking both the value of elements and the value of their `src`
* property.
*
* @private
* @param {Array} arr
* An array of playlist items to look through
*
* @param {string} src
* The source to look for
*
* @return {number}
* The index of that source or -1
*/
var indexInSources = function indexInSources(arr, src) {
for (var i = 0; i < arr.length; i++) {
var sources = arr[i].sources;
if (Array.isArray(sources)) {
for (var j = 0; j < sources.length; j++) {
var source = sources[j];
if (source && sourceEquals(source, src)) {
return i;
}
}
}
}
return -1;
};
/**
* Randomize the contents of an array.
*
* @private
* @param {Array} arr
* An array.
*
* @return {Array}
* The same array that was passed in.
*/
var randomize = function randomize(arr) {
var index = -1;
var lastIndex = arr.length - 1;
while (++index < arr.length) {
var rand = index + Math.floor(Math.random() * (lastIndex - index + 1));
var value = arr[rand];
arr[rand] = arr[index];
arr[index] = value;
}
return arr;
};
/**
* Factory function for creating new playlist implementation on the given player.
*
* API summary:
*
* playlist(['a', 'b', 'c']) // setter
* playlist() // getter
* playlist.currentItem() // getter, 0
* playlist.currentItem(1) // setter, 1
* playlist.next() // 'c'
* playlist.previous() // 'b'
* playlist.first() // 'a'
* playlist.last() // 'c'
* playlist.autoadvance(5) // 5 second delay
* playlist.autoadvance() // cancel autoadvance
*
* @param {Player} player
* The current player
*
* @param {Array=} initialList
* If given, an initial list of sources with which to populate
* the playlist.
*
* @param {number=} initialIndex
* If given, the index of the item in the list that should
* be loaded first. If -1, no video is loaded. If omitted, The
* the first video is loaded.
*
* @return {Function}
* Returns the playlist function specific to the given player.
*/
function factory(player, initialList, initialIndex) {
if (initialIndex === void 0) {
initialIndex = 0;
}
var list = null;
var changing = false;
/**
* Get/set the playlist for a player.
*
* This function is added as an own property of the player and has its
* own methods which can be called to manipulate the internal state.
*
* @param {Array} [newList]
* If given, a new list of sources with which to populate the
* playlist. Without this, the function acts as a getter.
*
* @param {number} [newIndex]
* If given, the index of the item in the list that should
* be loaded first. If -1, no video is loaded. If omitted, The
* the first video is loaded.
*
* @return {Array}
* The playlist
*/
var playlist = player.playlist = function (newList, newIndex) {
if (newIndex === void 0) {
newIndex = 0;
}
if (changing) {
throw new Error('do not call playlist() during a playlist change');
}
if (Array.isArray(newList)) {
// @todo - Simplify this to `list.slice()` for v5.
var previousPlaylist = Array.isArray(list) ? list.slice() : null;
list = newList.slice(); // Mark the playlist as changing during the duringplaylistchange lifecycle.
changing = true;
player.trigger({
type: 'duringplaylistchange',
nextIndex: newIndex,
nextPlaylist: list,
previousIndex: playlist.currentIndex_,
// @todo - Simplify this to simply pass along `previousPlaylist` for v5.
previousPlaylist: previousPlaylist || []
});
changing = false;
if (newIndex !== -1) {
playlist.currentItem(newIndex);
} // The only time the previous playlist is null is the first call to this
// function. This allows us to fire the `duringplaylistchange` event
// every time the playlist is populated and to maintain backward
// compatibility by not firing the `playlistchange` event on the initial
// population of the list.
//
// @todo - Remove this condition in preparation for v5.
if (previousPlaylist) {
player.setTimeout(function () {
player.trigger('playlistchange');
}, 0);
}
} // Always return a shallow clone of the playlist list.
return list.slice();
}; // On a new source, if there is no current item, disable auto-advance.
player.on('loadstart', function () {
if (playlist.currentItem() === -1) {
reset(player);
}
});
playlist.currentIndex_ = -1;
playlist.player_ = player;
playlist.autoadvance_ = {};
playlist.repeat_ = false;
/**
* Get or set the current item in the playlist.
*
* During the duringplaylistchange event, acts only as a getter.
*
* @param {number} [index]
* If given as a valid value, plays the playlist item at that index.
*
* @return {number}
* The current item index.
*/
playlist.currentItem = function (index) {
// If the playlist is changing, only act as a getter.
if (changing) {
return playlist.currentIndex_;
}
if (typeof index === 'number' && playlist.currentIndex_ !== index && index >= 0 && index < list.length) {
playlist.currentIndex_ = index;
playItem(playlist.player_, list[playlist.currentIndex_]);
} else {
playlist.currentIndex_ = playlist.indexOf(playlist.player_.currentSrc() || '');
}
return playlist.currentIndex_;
};
/**
* Checks if the playlist contains a value.
*
* @param {string|Object|Array} value
* The value to check
*
* @return {boolean}
* The result
*/
playlist.contains = function (value) {
return playlist.indexOf(value) !== -1;
};
/**
* Gets the index of a value in the playlist or -1 if not found.
*
* @param {string|Object|Array} value
* The value to find the index of
*
* @return {number}
* The index or -1
*/
playlist.indexOf = function (value) {
if (typeof value === 'string') {
return indexInSources(list, value);
}
var sources = Array.isArray(value) ? value : value.sources;
for (var i = 0; i < sources.length; i++) {
var source = sources[i];
if (typeof source === 'string') {
return indexInSources(list, source);
} else if (source.src) {
return indexInSources(list, source.src);
}
}
return -1;
};
/**
* Get the index of the current item in the playlist. This is identical to
* calling `currentItem()` with no arguments.
*
* @return {number}
* The current item index.
*/
playlist.currentIndex = function () {
return playlist.currentItem();
};
/**
* Get the index of the last item in the playlist.
*
* @return {number}
* The index of the last item in the playlist or -1 if there are no
* items.
*/
playlist.lastIndex = function () {
return list.length - 1;
};
/**
* Get the index of the next item in the playlist.
*
* @return {number}
* The index of the next item in the playlist or -1 if there is no
* current item.
*/
playlist.nextIndex = function () {
var current = playlist.currentItem();
if (current === -1) {
return -1;
}
var lastIndex = playlist.lastIndex(); // When repeating, loop back to the beginning on the last item.
if (playlist.repeat_ && current === lastIndex) {
return 0;
} // Don't go past the end of the playlist.
return Math.min(current + 1, lastIndex);
};
/**
* Get the index of the previous item in the playlist.
*
* @return {number}
* The index of the previous item in the playlist or -1 if there is
* no current item.
*/
playlist.previousIndex = function () {
var current = playlist.currentItem();
if (current === -1) {
return -1;
} // When repeating, loop back to the end of the playlist.
if (playlist.repeat_ && current === 0) {
return playlist.lastIndex();
} // Don't go past the beginning of the playlist.
return Math.max(current - 1, 0);
};
/**
* Plays the first item in the playlist.
*
* @return {Object|undefined}
* Returns undefined and has no side effects if the list is empty.
*/
playlist.first = function () {
if (changing) {
return;
}
if (list.length) {
return list[playlist.currentItem(0)];
}
playlist.currentIndex_ = -1;
};
/**
* Plays the last item in the playlist.
*
* @return {Object|undefined}
* Returns undefined and has no side effects if the list is empty.
*/
playlist.last = function () {
if (changing) {
return;
}
if (list.length) {
return list[playlist.currentItem(playlist.lastIndex())];
}
playlist.currentIndex_ = -1;
};
/**
* Plays the next item in the playlist.
*
* @return {Object|undefined}
* Returns undefined and has no side effects if on last item.
*/
playlist.next = function () {
if (changing) {
return;
}
var index = playlist.nextIndex();
if (index !== playlist.currentIndex_) {
return list[playlist.currentItem(index)];
}
};
/**
* Plays the previous item in the playlist.
*
* @return {Object|undefined}
* Returns undefined and has no side effects if on first item.
*/
playlist.previous = function () {
if (changing) {
return;
}
var index = playlist.previousIndex();
if (index !== playlist.currentIndex_) {
return list[playlist.currentItem(index)];
}
};
/**
* Set up auto-advance on the playlist.
*
* @param {number} [delay]
* The number of seconds to wait before each auto-advance.
*/
playlist.autoadvance = function (delay) {
setup(playlist.player_, delay);
};
/**
* Sets `repeat` option, which makes the "next" video of the last video in
* the playlist be the first video in the playlist.
*
* @param {boolean} [val]
* The value to set repeat to
*
* @return {boolean}
* The current value of repeat
*/
playlist.repeat = function (val) {
if (val === undefined) {
return playlist.repeat_;
}
if (typeof val !== 'boolean') {
videojs.log.error('videojs-playlist: Invalid value for repeat', val);
return;
}
playlist.repeat_ = !!val;
return playlist.repeat_;
};
/**
* Sorts the playlist array.
*
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort}
* @fires playlistsorted
*
* @param {Function} compare
* A comparator function as per the native Array method.
*/
playlist.sort = function (compare) {
// Bail if the array is empty.
if (!list.length) {
return;
}
list.sort(compare); // If the playlist is changing, don't trigger events.
if (changing) {
return;
}
/**
* Triggered after the playlist is sorted internally.
*
* @event playlistsorted
* @type {Object}
*/
player.trigger('playlistsorted');
};
/**
* Reverses the playlist array.
*
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse}
* @fires playlistsorted
*/
playlist.reverse = function () {
// Bail if the array is empty.
if (!list.length) {
return;
}
list.reverse(); // If the playlist is changing, don't trigger events.
if (changing) {
return;
}
/**
* Triggered after the playlist is sorted internally.
*
* @event playlistsorted
* @type {Object}
*/
player.trigger('playlistsorted');
};
/**
* Shuffle the contents of the list randomly.
*
* @see {@link https://github.com/lodash/lodash/blob/40e096b6d5291a025e365a0f4c010d9a0efb9a69/shuffle.js}
* @fires playlistsorted
* @todo Make the `rest` option default to `true` in v5.0.0.
* @param {Object} [options]
* An object containing shuffle options.
*
* @param {boolean} [options.rest = false]
* By default, the entire playlist is randomized. However, this may
* not be desirable in all cases, such as when a user is already
* watching a video.
*
* When `true` is passed for this option, it will only shuffle
* playlist items after the current item. For example, when on the
* first item, will shuffle the second item and beyond.
*/
playlist.shuffle = function (_temp) {
var _ref = _temp === void 0 ? {} : _temp,
rest = _ref.rest;
var index = 0;
var arr = list; // When options.rest is true, start randomization at the item after the
// current item.
if (rest) {
index = playlist.currentIndex_ + 1;
arr = list.slice(index);
} // Bail if the array is empty or too short to shuffle.
if (arr.length <= 1) {
return;
}
randomize(arr); // When options.rest is true, splice the randomized sub-array back into
// the original array.
if (rest) {
var _list;
(_list = list).splice.apply(_list, [index, arr.length].concat(arr));
} // If the playlist is changing, don't trigger events.
if (changing) {
return;
}
/**
* Triggered after the playlist is sorted internally.
*
* @event playlistsorted
* @type {Object}
*/
player.trigger('playlistsorted');
}; // If an initial list was given, populate the playlist with it.
if (Array.isArray(initialList)) {
playlist(initialList.slice(), initialIndex); // If there is no initial list given, silently set an empty array.
} else {
list = [];
}
return playlist;
}
var version = "4.2.6";
var registerPlugin = videojs.registerPlugin || videojs.plugin;
/**
* The video.js playlist plugin. Invokes the playlist-maker to create a
* playlist function on the specific player.
*
* @param {Array} list
* a list of sources
*
* @param {number} item
* The index to start at
*/
var plugin = function plugin(list, item) {
factory(this, list, item);
};
registerPlugin('playlist', plugin);
plugin.VERSION = version;
module.exports = plugin;

View File

@ -0,0 +1,763 @@
/*! @name videojs-playlist @version 4.2.6 @license Apache-2.0 */
import videojs from 'video.js';
/**
* Validates a number of seconds to use as the auto-advance delay.
*
* @private
* @param {number} s
* The number to check
*
* @return {boolean}
* Whether this is a valid second or not
*/
var validSeconds = function validSeconds(s) {
return typeof s === 'number' && !isNaN(s) && s >= 0 && s < Infinity;
};
/**
* Resets the auto-advance behavior of a player.
*
* @param {Player} player
* The player to reset the behavior on
*/
var reset = function reset(player) {
var aa = player.playlist.autoadvance_;
if (aa.timeout) {
player.clearTimeout(aa.timeout);
}
if (aa.trigger) {
player.off('ended', aa.trigger);
}
aa.timeout = null;
aa.trigger = null;
};
/**
* Sets up auto-advance behavior on a player.
*
* @param {Player} player
* the current player
*
* @param {number} delay
* The number of seconds to wait before each auto-advance.
*
* @return {undefined}
* Used to short circuit function logic
*/
var setup = function setup(player, delay) {
reset(player); // Before queuing up new auto-advance behavior, check if `seconds` was
// called with a valid value.
if (!validSeconds(delay)) {
player.playlist.autoadvance_.delay = null;
return;
}
player.playlist.autoadvance_.delay = delay;
player.playlist.autoadvance_.trigger = function () {
// This calls setup again, which will reset the existing auto-advance and
// set up another auto-advance for the next "ended" event.
var cancelOnPlay = function cancelOnPlay() {
return setup(player, delay);
}; // If there is a "play" event while we're waiting for an auto-advance,
// we need to cancel the auto-advance. This could mean the user seeked
// back into the content or restarted the content. This is reproducible
// with an auto-advance > 0.
player.one('play', cancelOnPlay);
player.playlist.autoadvance_.timeout = player.setTimeout(function () {
reset(player);
player.off('play', cancelOnPlay);
player.playlist.next();
}, delay * 1000);
};
player.one('ended', player.playlist.autoadvance_.trigger);
};
/**
* Removes all remote text tracks from a player.
*
* @param {Player} player
* The player to clear tracks on
*/
var clearTracks = function clearTracks(player) {
var tracks = player.remoteTextTracks();
var i = tracks && tracks.length || 0; // This uses a `while` loop rather than `forEach` because the
// `TextTrackList` object is a live DOM list (not an array).
while (i--) {
player.removeRemoteTextTrack(tracks[i]);
}
};
/**
* Plays an item on a player's playlist.
*
* @param {Player} player
* The player to play the item on
*
* @param {Object} item
* A source from the playlist.
*
* @return {Player}
* The player that is now playing the item
*/
var playItem = function playItem(player, item) {
var replay = !player.paused() || player.ended();
player.trigger('beforeplaylistitem', item);
player.poster(item.poster || '');
player.src(item.sources);
clearTracks(player);
player.ready(function () {
(item.textTracks || []).forEach(player.addRemoteTextTrack.bind(player));
player.trigger('playlistitem', item);
if (replay) {
var playPromise = player.play(); // silence error when a pause interrupts a play request
// on browsers which return a promise
if (typeof playPromise !== 'undefined' && typeof playPromise.then === 'function') {
playPromise.then(null, function (e) {});
}
}
setup(player, player.playlist.autoadvance_.delay);
});
return player;
};
/**
* Given two sources, check to see whether the two sources are equal.
* If both source urls have a protocol, the protocols must match, otherwise, protocols
* are ignored.
*
* @private
* @param {string|Object} source1
* The first source
*
* @param {string|Object} source2
* The second source
*
* @return {boolean}
* The result
*/
var sourceEquals = function sourceEquals(source1, source2) {
var src1 = source1;
var src2 = source2;
if (typeof source1 === 'object') {
src1 = source1.src;
}
if (typeof source2 === 'object') {
src2 = source2.src;
}
if (/^\/\//.test(src1)) {
src2 = src2.slice(src2.indexOf('//'));
}
if (/^\/\//.test(src2)) {
src1 = src1.slice(src1.indexOf('//'));
}
return src1 === src2;
};
/**
* Look through an array of playlist items for a specific `source`;
* checking both the value of elements and the value of their `src`
* property.
*
* @private
* @param {Array} arr
* An array of playlist items to look through
*
* @param {string} src
* The source to look for
*
* @return {number}
* The index of that source or -1
*/
var indexInSources = function indexInSources(arr, src) {
for (var i = 0; i < arr.length; i++) {
var sources = arr[i].sources;
if (Array.isArray(sources)) {
for (var j = 0; j < sources.length; j++) {
var source = sources[j];
if (source && sourceEquals(source, src)) {
return i;
}
}
}
}
return -1;
};
/**
* Randomize the contents of an array.
*
* @private
* @param {Array} arr
* An array.
*
* @return {Array}
* The same array that was passed in.
*/
var randomize = function randomize(arr) {
var index = -1;
var lastIndex = arr.length - 1;
while (++index < arr.length) {
var rand = index + Math.floor(Math.random() * (lastIndex - index + 1));
var value = arr[rand];
arr[rand] = arr[index];
arr[index] = value;
}
return arr;
};
/**
* Factory function for creating new playlist implementation on the given player.
*
* API summary:
*
* playlist(['a', 'b', 'c']) // setter
* playlist() // getter
* playlist.currentItem() // getter, 0
* playlist.currentItem(1) // setter, 1
* playlist.next() // 'c'
* playlist.previous() // 'b'
* playlist.first() // 'a'
* playlist.last() // 'c'
* playlist.autoadvance(5) // 5 second delay
* playlist.autoadvance() // cancel autoadvance
*
* @param {Player} player
* The current player
*
* @param {Array=} initialList
* If given, an initial list of sources with which to populate
* the playlist.
*
* @param {number=} initialIndex
* If given, the index of the item in the list that should
* be loaded first. If -1, no video is loaded. If omitted, The
* the first video is loaded.
*
* @return {Function}
* Returns the playlist function specific to the given player.
*/
function factory(player, initialList, initialIndex) {
if (initialIndex === void 0) {
initialIndex = 0;
}
var list = null;
var changing = false;
/**
* Get/set the playlist for a player.
*
* This function is added as an own property of the player and has its
* own methods which can be called to manipulate the internal state.
*
* @param {Array} [newList]
* If given, a new list of sources with which to populate the
* playlist. Without this, the function acts as a getter.
*
* @param {number} [newIndex]
* If given, the index of the item in the list that should
* be loaded first. If -1, no video is loaded. If omitted, The
* the first video is loaded.
*
* @return {Array}
* The playlist
*/
var playlist = player.playlist = function (newList, newIndex) {
if (newIndex === void 0) {
newIndex = 0;
}
if (changing) {
throw new Error('do not call playlist() during a playlist change');
}
if (Array.isArray(newList)) {
// @todo - Simplify this to `list.slice()` for v5.
var previousPlaylist = Array.isArray(list) ? list.slice() : null;
list = newList.slice(); // Mark the playlist as changing during the duringplaylistchange lifecycle.
changing = true;
player.trigger({
type: 'duringplaylistchange',
nextIndex: newIndex,
nextPlaylist: list,
previousIndex: playlist.currentIndex_,
// @todo - Simplify this to simply pass along `previousPlaylist` for v5.
previousPlaylist: previousPlaylist || []
});
changing = false;
if (newIndex !== -1) {
playlist.currentItem(newIndex);
} // The only time the previous playlist is null is the first call to this
// function. This allows us to fire the `duringplaylistchange` event
// every time the playlist is populated and to maintain backward
// compatibility by not firing the `playlistchange` event on the initial
// population of the list.
//
// @todo - Remove this condition in preparation for v5.
if (previousPlaylist) {
player.setTimeout(function () {
player.trigger('playlistchange');
}, 0);
}
} // Always return a shallow clone of the playlist list.
return list.slice();
}; // On a new source, if there is no current item, disable auto-advance.
player.on('loadstart', function () {
if (playlist.currentItem() === -1) {
reset(player);
}
});
playlist.currentIndex_ = -1;
playlist.player_ = player;
playlist.autoadvance_ = {};
playlist.repeat_ = false;
/**
* Get or set the current item in the playlist.
*
* During the duringplaylistchange event, acts only as a getter.
*
* @param {number} [index]
* If given as a valid value, plays the playlist item at that index.
*
* @return {number}
* The current item index.
*/
playlist.currentItem = function (index) {
// If the playlist is changing, only act as a getter.
if (changing) {
return playlist.currentIndex_;
}
if (typeof index === 'number' && playlist.currentIndex_ !== index && index >= 0 && index < list.length) {
playlist.currentIndex_ = index;
playItem(playlist.player_, list[playlist.currentIndex_]);
} else {
playlist.currentIndex_ = playlist.indexOf(playlist.player_.currentSrc() || '');
}
return playlist.currentIndex_;
};
/**
* Checks if the playlist contains a value.
*
* @param {string|Object|Array} value
* The value to check
*
* @return {boolean}
* The result
*/
playlist.contains = function (value) {
return playlist.indexOf(value) !== -1;
};
/**
* Gets the index of a value in the playlist or -1 if not found.
*
* @param {string|Object|Array} value
* The value to find the index of
*
* @return {number}
* The index or -1
*/
playlist.indexOf = function (value) {
if (typeof value === 'string') {
return indexInSources(list, value);
}
var sources = Array.isArray(value) ? value : value.sources;
for (var i = 0; i < sources.length; i++) {
var source = sources[i];
if (typeof source === 'string') {
return indexInSources(list, source);
} else if (source.src) {
return indexInSources(list, source.src);
}
}
return -1;
};
/**
* Get the index of the current item in the playlist. This is identical to
* calling `currentItem()` with no arguments.
*
* @return {number}
* The current item index.
*/
playlist.currentIndex = function () {
return playlist.currentItem();
};
/**
* Get the index of the last item in the playlist.
*
* @return {number}
* The index of the last item in the playlist or -1 if there are no
* items.
*/
playlist.lastIndex = function () {
return list.length - 1;
};
/**
* Get the index of the next item in the playlist.
*
* @return {number}
* The index of the next item in the playlist or -1 if there is no
* current item.
*/
playlist.nextIndex = function () {
var current = playlist.currentItem();
if (current === -1) {
return -1;
}
var lastIndex = playlist.lastIndex(); // When repeating, loop back to the beginning on the last item.
if (playlist.repeat_ && current === lastIndex) {
return 0;
} // Don't go past the end of the playlist.
return Math.min(current + 1, lastIndex);
};
/**
* Get the index of the previous item in the playlist.
*
* @return {number}
* The index of the previous item in the playlist or -1 if there is
* no current item.
*/
playlist.previousIndex = function () {
var current = playlist.currentItem();
if (current === -1) {
return -1;
} // When repeating, loop back to the end of the playlist.
if (playlist.repeat_ && current === 0) {
return playlist.lastIndex();
} // Don't go past the beginning of the playlist.
return Math.max(current - 1, 0);
};
/**
* Plays the first item in the playlist.
*
* @return {Object|undefined}
* Returns undefined and has no side effects if the list is empty.
*/
playlist.first = function () {
if (changing) {
return;
}
if (list.length) {
return list[playlist.currentItem(0)];
}
playlist.currentIndex_ = -1;
};
/**
* Plays the last item in the playlist.
*
* @return {Object|undefined}
* Returns undefined and has no side effects if the list is empty.
*/
playlist.last = function () {
if (changing) {
return;
}
if (list.length) {
return list[playlist.currentItem(playlist.lastIndex())];
}
playlist.currentIndex_ = -1;
};
/**
* Plays the next item in the playlist.
*
* @return {Object|undefined}
* Returns undefined and has no side effects if on last item.
*/
playlist.next = function () {
if (changing) {
return;
}
var index = playlist.nextIndex();
if (index !== playlist.currentIndex_) {
return list[playlist.currentItem(index)];
}
};
/**
* Plays the previous item in the playlist.
*
* @return {Object|undefined}
* Returns undefined and has no side effects if on first item.
*/
playlist.previous = function () {
if (changing) {
return;
}
var index = playlist.previousIndex();
if (index !== playlist.currentIndex_) {
return list[playlist.currentItem(index)];
}
};
/**
* Set up auto-advance on the playlist.
*
* @param {number} [delay]
* The number of seconds to wait before each auto-advance.
*/
playlist.autoadvance = function (delay) {
setup(playlist.player_, delay);
};
/**
* Sets `repeat` option, which makes the "next" video of the last video in
* the playlist be the first video in the playlist.
*
* @param {boolean} [val]
* The value to set repeat to
*
* @return {boolean}
* The current value of repeat
*/
playlist.repeat = function (val) {
if (val === undefined) {
return playlist.repeat_;
}
if (typeof val !== 'boolean') {
videojs.log.error('videojs-playlist: Invalid value for repeat', val);
return;
}
playlist.repeat_ = !!val;
return playlist.repeat_;
};
/**
* Sorts the playlist array.
*
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort}
* @fires playlistsorted
*
* @param {Function} compare
* A comparator function as per the native Array method.
*/
playlist.sort = function (compare) {
// Bail if the array is empty.
if (!list.length) {
return;
}
list.sort(compare); // If the playlist is changing, don't trigger events.
if (changing) {
return;
}
/**
* Triggered after the playlist is sorted internally.
*
* @event playlistsorted
* @type {Object}
*/
player.trigger('playlistsorted');
};
/**
* Reverses the playlist array.
*
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse}
* @fires playlistsorted
*/
playlist.reverse = function () {
// Bail if the array is empty.
if (!list.length) {
return;
}
list.reverse(); // If the playlist is changing, don't trigger events.
if (changing) {
return;
}
/**
* Triggered after the playlist is sorted internally.
*
* @event playlistsorted
* @type {Object}
*/
player.trigger('playlistsorted');
};
/**
* Shuffle the contents of the list randomly.
*
* @see {@link https://github.com/lodash/lodash/blob/40e096b6d5291a025e365a0f4c010d9a0efb9a69/shuffle.js}
* @fires playlistsorted
* @todo Make the `rest` option default to `true` in v5.0.0.
* @param {Object} [options]
* An object containing shuffle options.
*
* @param {boolean} [options.rest = false]
* By default, the entire playlist is randomized. However, this may
* not be desirable in all cases, such as when a user is already
* watching a video.
*
* When `true` is passed for this option, it will only shuffle
* playlist items after the current item. For example, when on the
* first item, will shuffle the second item and beyond.
*/
playlist.shuffle = function (_temp) {
var _ref = _temp === void 0 ? {} : _temp,
rest = _ref.rest;
var index = 0;
var arr = list; // When options.rest is true, start randomization at the item after the
// current item.
if (rest) {
index = playlist.currentIndex_ + 1;
arr = list.slice(index);
} // Bail if the array is empty or too short to shuffle.
if (arr.length <= 1) {
return;
}
randomize(arr); // When options.rest is true, splice the randomized sub-array back into
// the original array.
if (rest) {
var _list;
(_list = list).splice.apply(_list, [index, arr.length].concat(arr));
} // If the playlist is changing, don't trigger events.
if (changing) {
return;
}
/**
* Triggered after the playlist is sorted internally.
*
* @event playlistsorted
* @type {Object}
*/
player.trigger('playlistsorted');
}; // If an initial list was given, populate the playlist with it.
if (Array.isArray(initialList)) {
playlist(initialList.slice(), initialIndex); // If there is no initial list given, silently set an empty array.
} else {
list = [];
}
return playlist;
}
var version = "4.2.6";
var registerPlugin = videojs.registerPlugin || videojs.plugin;
/**
* The video.js playlist plugin. Invokes the playlist-maker to create a
* playlist function on the specific player.
*
* @param {Array} list
* a list of sources
*
* @param {number} item
* The index to start at
*/
var plugin = function plugin(list, item) {
factory(this, list, item);
};
registerPlugin('playlist', plugin);
plugin.VERSION = version;
export default plugin;

View File

@ -0,0 +1,771 @@
/*! @name videojs-playlist @version 4.2.6 @license Apache-2.0 */
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('video.js')) :
typeof define === 'function' && define.amd ? define(['video.js'], factory) :
(global.videojsPlaylist = factory(global.videojs));
}(this, (function (videojs) { 'use strict';
videojs = videojs && videojs.hasOwnProperty('default') ? videojs['default'] : videojs;
/**
* Validates a number of seconds to use as the auto-advance delay.
*
* @private
* @param {number} s
* The number to check
*
* @return {boolean}
* Whether this is a valid second or not
*/
var validSeconds = function validSeconds(s) {
return typeof s === 'number' && !isNaN(s) && s >= 0 && s < Infinity;
};
/**
* Resets the auto-advance behavior of a player.
*
* @param {Player} player
* The player to reset the behavior on
*/
var reset = function reset(player) {
var aa = player.playlist.autoadvance_;
if (aa.timeout) {
player.clearTimeout(aa.timeout);
}
if (aa.trigger) {
player.off('ended', aa.trigger);
}
aa.timeout = null;
aa.trigger = null;
};
/**
* Sets up auto-advance behavior on a player.
*
* @param {Player} player
* the current player
*
* @param {number} delay
* The number of seconds to wait before each auto-advance.
*
* @return {undefined}
* Used to short circuit function logic
*/
var setup = function setup(player, delay) {
reset(player); // Before queuing up new auto-advance behavior, check if `seconds` was
// called with a valid value.
if (!validSeconds(delay)) {
player.playlist.autoadvance_.delay = null;
return;
}
player.playlist.autoadvance_.delay = delay;
player.playlist.autoadvance_.trigger = function () {
// This calls setup again, which will reset the existing auto-advance and
// set up another auto-advance for the next "ended" event.
var cancelOnPlay = function cancelOnPlay() {
return setup(player, delay);
}; // If there is a "play" event while we're waiting for an auto-advance,
// we need to cancel the auto-advance. This could mean the user seeked
// back into the content or restarted the content. This is reproducible
// with an auto-advance > 0.
player.one('play', cancelOnPlay);
player.playlist.autoadvance_.timeout = player.setTimeout(function () {
reset(player);
player.off('play', cancelOnPlay);
player.playlist.next();
}, delay * 1000);
};
player.one('ended', player.playlist.autoadvance_.trigger);
};
/**
* Removes all remote text tracks from a player.
*
* @param {Player} player
* The player to clear tracks on
*/
var clearTracks = function clearTracks(player) {
var tracks = player.remoteTextTracks();
var i = tracks && tracks.length || 0; // This uses a `while` loop rather than `forEach` because the
// `TextTrackList` object is a live DOM list (not an array).
while (i--) {
player.removeRemoteTextTrack(tracks[i]);
}
};
/**
* Plays an item on a player's playlist.
*
* @param {Player} player
* The player to play the item on
*
* @param {Object} item
* A source from the playlist.
*
* @return {Player}
* The player that is now playing the item
*/
var playItem = function playItem(player, item) {
var replay = !player.paused() || player.ended();
player.trigger('beforeplaylistitem', item);
player.poster(item.poster || '');
player.src(item.sources);
clearTracks(player);
player.ready(function () {
(item.textTracks || []).forEach(player.addRemoteTextTrack.bind(player));
player.trigger('playlistitem', item);
if (replay) {
var playPromise = player.play(); // silence error when a pause interrupts a play request
// on browsers which return a promise
if (typeof playPromise !== 'undefined' && typeof playPromise.then === 'function') {
playPromise.then(null, function (e) {});
}
}
setup(player, player.playlist.autoadvance_.delay);
});
return player;
};
/**
* Given two sources, check to see whether the two sources are equal.
* If both source urls have a protocol, the protocols must match, otherwise, protocols
* are ignored.
*
* @private
* @param {string|Object} source1
* The first source
*
* @param {string|Object} source2
* The second source
*
* @return {boolean}
* The result
*/
var sourceEquals = function sourceEquals(source1, source2) {
var src1 = source1;
var src2 = source2;
if (typeof source1 === 'object') {
src1 = source1.src;
}
if (typeof source2 === 'object') {
src2 = source2.src;
}
if (/^\/\//.test(src1)) {
src2 = src2.slice(src2.indexOf('//'));
}
if (/^\/\//.test(src2)) {
src1 = src1.slice(src1.indexOf('//'));
}
return src1 === src2;
};
/**
* Look through an array of playlist items for a specific `source`;
* checking both the value of elements and the value of their `src`
* property.
*
* @private
* @param {Array} arr
* An array of playlist items to look through
*
* @param {string} src
* The source to look for
*
* @return {number}
* The index of that source or -1
*/
var indexInSources = function indexInSources(arr, src) {
for (var i = 0; i < arr.length; i++) {
var sources = arr[i].sources;
if (Array.isArray(sources)) {
for (var j = 0; j < sources.length; j++) {
var source = sources[j];
if (source && sourceEquals(source, src)) {
return i;
}
}
}
}
return -1;
};
/**
* Randomize the contents of an array.
*
* @private
* @param {Array} arr
* An array.
*
* @return {Array}
* The same array that was passed in.
*/
var randomize = function randomize(arr) {
var index = -1;
var lastIndex = arr.length - 1;
while (++index < arr.length) {
var rand = index + Math.floor(Math.random() * (lastIndex - index + 1));
var value = arr[rand];
arr[rand] = arr[index];
arr[index] = value;
}
return arr;
};
/**
* Factory function for creating new playlist implementation on the given player.
*
* API summary:
*
* playlist(['a', 'b', 'c']) // setter
* playlist() // getter
* playlist.currentItem() // getter, 0
* playlist.currentItem(1) // setter, 1
* playlist.next() // 'c'
* playlist.previous() // 'b'
* playlist.first() // 'a'
* playlist.last() // 'c'
* playlist.autoadvance(5) // 5 second delay
* playlist.autoadvance() // cancel autoadvance
*
* @param {Player} player
* The current player
*
* @param {Array=} initialList
* If given, an initial list of sources with which to populate
* the playlist.
*
* @param {number=} initialIndex
* If given, the index of the item in the list that should
* be loaded first. If -1, no video is loaded. If omitted, The
* the first video is loaded.
*
* @return {Function}
* Returns the playlist function specific to the given player.
*/
function factory(player, initialList, initialIndex) {
if (initialIndex === void 0) {
initialIndex = 0;
}
var list = null;
var changing = false;
/**
* Get/set the playlist for a player.
*
* This function is added as an own property of the player and has its
* own methods which can be called to manipulate the internal state.
*
* @param {Array} [newList]
* If given, a new list of sources with which to populate the
* playlist. Without this, the function acts as a getter.
*
* @param {number} [newIndex]
* If given, the index of the item in the list that should
* be loaded first. If -1, no video is loaded. If omitted, The
* the first video is loaded.
*
* @return {Array}
* The playlist
*/
var playlist = player.playlist = function (newList, newIndex) {
if (newIndex === void 0) {
newIndex = 0;
}
if (changing) {
throw new Error('do not call playlist() during a playlist change');
}
if (Array.isArray(newList)) {
// @todo - Simplify this to `list.slice()` for v5.
var previousPlaylist = Array.isArray(list) ? list.slice() : null;
list = newList.slice(); // Mark the playlist as changing during the duringplaylistchange lifecycle.
changing = true;
player.trigger({
type: 'duringplaylistchange',
nextIndex: newIndex,
nextPlaylist: list,
previousIndex: playlist.currentIndex_,
// @todo - Simplify this to simply pass along `previousPlaylist` for v5.
previousPlaylist: previousPlaylist || []
});
changing = false;
if (newIndex !== -1) {
playlist.currentItem(newIndex);
} // The only time the previous playlist is null is the first call to this
// function. This allows us to fire the `duringplaylistchange` event
// every time the playlist is populated and to maintain backward
// compatibility by not firing the `playlistchange` event on the initial
// population of the list.
//
// @todo - Remove this condition in preparation for v5.
if (previousPlaylist) {
player.setTimeout(function () {
player.trigger('playlistchange');
}, 0);
}
} // Always return a shallow clone of the playlist list.
return list.slice();
}; // On a new source, if there is no current item, disable auto-advance.
player.on('loadstart', function () {
if (playlist.currentItem() === -1) {
reset(player);
}
});
playlist.currentIndex_ = -1;
playlist.player_ = player;
playlist.autoadvance_ = {};
playlist.repeat_ = false;
/**
* Get or set the current item in the playlist.
*
* During the duringplaylistchange event, acts only as a getter.
*
* @param {number} [index]
* If given as a valid value, plays the playlist item at that index.
*
* @return {number}
* The current item index.
*/
playlist.currentItem = function (index) {
// If the playlist is changing, only act as a getter.
if (changing) {
return playlist.currentIndex_;
}
if (typeof index === 'number' && playlist.currentIndex_ !== index && index >= 0 && index < list.length) {
playlist.currentIndex_ = index;
playItem(playlist.player_, list[playlist.currentIndex_]);
} else {
playlist.currentIndex_ = playlist.indexOf(playlist.player_.currentSrc() || '');
}
return playlist.currentIndex_;
};
/**
* Checks if the playlist contains a value.
*
* @param {string|Object|Array} value
* The value to check
*
* @return {boolean}
* The result
*/
playlist.contains = function (value) {
return playlist.indexOf(value) !== -1;
};
/**
* Gets the index of a value in the playlist or -1 if not found.
*
* @param {string|Object|Array} value
* The value to find the index of
*
* @return {number}
* The index or -1
*/
playlist.indexOf = function (value) {
if (typeof value === 'string') {
return indexInSources(list, value);
}
var sources = Array.isArray(value) ? value : value.sources;
for (var i = 0; i < sources.length; i++) {
var source = sources[i];
if (typeof source === 'string') {
return indexInSources(list, source);
} else if (source.src) {
return indexInSources(list, source.src);
}
}
return -1;
};
/**
* Get the index of the current item in the playlist. This is identical to
* calling `currentItem()` with no arguments.
*
* @return {number}
* The current item index.
*/
playlist.currentIndex = function () {
return playlist.currentItem();
};
/**
* Get the index of the last item in the playlist.
*
* @return {number}
* The index of the last item in the playlist or -1 if there are no
* items.
*/
playlist.lastIndex = function () {
return list.length - 1;
};
/**
* Get the index of the next item in the playlist.
*
* @return {number}
* The index of the next item in the playlist or -1 if there is no
* current item.
*/
playlist.nextIndex = function () {
var current = playlist.currentItem();
if (current === -1) {
return -1;
}
var lastIndex = playlist.lastIndex(); // When repeating, loop back to the beginning on the last item.
if (playlist.repeat_ && current === lastIndex) {
return 0;
} // Don't go past the end of the playlist.
return Math.min(current + 1, lastIndex);
};
/**
* Get the index of the previous item in the playlist.
*
* @return {number}
* The index of the previous item in the playlist or -1 if there is
* no current item.
*/
playlist.previousIndex = function () {
var current = playlist.currentItem();
if (current === -1) {
return -1;
} // When repeating, loop back to the end of the playlist.
if (playlist.repeat_ && current === 0) {
return playlist.lastIndex();
} // Don't go past the beginning of the playlist.
return Math.max(current - 1, 0);
};
/**
* Plays the first item in the playlist.
*
* @return {Object|undefined}
* Returns undefined and has no side effects if the list is empty.
*/
playlist.first = function () {
if (changing) {
return;
}
if (list.length) {
return list[playlist.currentItem(0)];
}
playlist.currentIndex_ = -1;
};
/**
* Plays the last item in the playlist.
*
* @return {Object|undefined}
* Returns undefined and has no side effects if the list is empty.
*/
playlist.last = function () {
if (changing) {
return;
}
if (list.length) {
return list[playlist.currentItem(playlist.lastIndex())];
}
playlist.currentIndex_ = -1;
};
/**
* Plays the next item in the playlist.
*
* @return {Object|undefined}
* Returns undefined and has no side effects if on last item.
*/
playlist.next = function () {
if (changing) {
return;
}
var index = playlist.nextIndex();
if (index !== playlist.currentIndex_) {
return list[playlist.currentItem(index)];
}
};
/**
* Plays the previous item in the playlist.
*
* @return {Object|undefined}
* Returns undefined and has no side effects if on first item.
*/
playlist.previous = function () {
if (changing) {
return;
}
var index = playlist.previousIndex();
if (index !== playlist.currentIndex_) {
return list[playlist.currentItem(index)];
}
};
/**
* Set up auto-advance on the playlist.
*
* @param {number} [delay]
* The number of seconds to wait before each auto-advance.
*/
playlist.autoadvance = function (delay) {
setup(playlist.player_, delay);
};
/**
* Sets `repeat` option, which makes the "next" video of the last video in
* the playlist be the first video in the playlist.
*
* @param {boolean} [val]
* The value to set repeat to
*
* @return {boolean}
* The current value of repeat
*/
playlist.repeat = function (val) {
if (val === undefined) {
return playlist.repeat_;
}
if (typeof val !== 'boolean') {
videojs.log.error('videojs-playlist: Invalid value for repeat', val);
return;
}
playlist.repeat_ = !!val;
return playlist.repeat_;
};
/**
* Sorts the playlist array.
*
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort}
* @fires playlistsorted
*
* @param {Function} compare
* A comparator function as per the native Array method.
*/
playlist.sort = function (compare) {
// Bail if the array is empty.
if (!list.length) {
return;
}
list.sort(compare); // If the playlist is changing, don't trigger events.
if (changing) {
return;
}
/**
* Triggered after the playlist is sorted internally.
*
* @event playlistsorted
* @type {Object}
*/
player.trigger('playlistsorted');
};
/**
* Reverses the playlist array.
*
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse}
* @fires playlistsorted
*/
playlist.reverse = function () {
// Bail if the array is empty.
if (!list.length) {
return;
}
list.reverse(); // If the playlist is changing, don't trigger events.
if (changing) {
return;
}
/**
* Triggered after the playlist is sorted internally.
*
* @event playlistsorted
* @type {Object}
*/
player.trigger('playlistsorted');
};
/**
* Shuffle the contents of the list randomly.
*
* @see {@link https://github.com/lodash/lodash/blob/40e096b6d5291a025e365a0f4c010d9a0efb9a69/shuffle.js}
* @fires playlistsorted
* @todo Make the `rest` option default to `true` in v5.0.0.
* @param {Object} [options]
* An object containing shuffle options.
*
* @param {boolean} [options.rest = false]
* By default, the entire playlist is randomized. However, this may
* not be desirable in all cases, such as when a user is already
* watching a video.
*
* When `true` is passed for this option, it will only shuffle
* playlist items after the current item. For example, when on the
* first item, will shuffle the second item and beyond.
*/
playlist.shuffle = function (_temp) {
var _ref = _temp === void 0 ? {} : _temp,
rest = _ref.rest;
var index = 0;
var arr = list; // When options.rest is true, start randomization at the item after the
// current item.
if (rest) {
index = playlist.currentIndex_ + 1;
arr = list.slice(index);
} // Bail if the array is empty or too short to shuffle.
if (arr.length <= 1) {
return;
}
randomize(arr); // When options.rest is true, splice the randomized sub-array back into
// the original array.
if (rest) {
var _list;
(_list = list).splice.apply(_list, [index, arr.length].concat(arr));
} // If the playlist is changing, don't trigger events.
if (changing) {
return;
}
/**
* Triggered after the playlist is sorted internally.
*
* @event playlistsorted
* @type {Object}
*/
player.trigger('playlistsorted');
}; // If an initial list was given, populate the playlist with it.
if (Array.isArray(initialList)) {
playlist(initialList.slice(), initialIndex); // If there is no initial list given, silently set an empty array.
} else {
list = [];
}
return playlist;
}
var version = "4.2.6";
var registerPlugin = videojs.registerPlugin || videojs.plugin;
/**
* The video.js playlist plugin. Invokes the playlist-maker to create a
* playlist function on the specific player.
*
* @param {Array} list
* a list of sources
*
* @param {number} item
* The index to start at
*/
var plugin = function plugin(list, item) {
factory(this, list, item);
};
registerPlugin('playlist', plugin);
plugin.VERSION = version;
return plugin;
})));

View File

@ -0,0 +1,2 @@
/*! @name videojs-playlist @version 4.2.6 @license Apache-2.0 */
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("video.js")):"function"==typeof define&&define.amd?define(["video.js"],t):e.videojsPlaylist=t(e.videojs)}(this,function(e){"use strict";var t=function(e){var t=e.playlist.autoadvance_;t.timeout&&e.clearTimeout(t.timeout),t.trigger&&e.off("ended",t.trigger),t.timeout=null,t.trigger=null},r=function e(r,n){var i;(t(r),"number"==typeof(i=n)&&!isNaN(i)&&i>=0&&i<1/0)?(r.playlist.autoadvance_.delay=n,r.playlist.autoadvance_.trigger=function(){var i=function(){return e(r,n)};r.one("play",i),r.playlist.autoadvance_.timeout=r.setTimeout(function(){t(r),r.off("play",i),r.playlist.next()},1e3*n)},r.one("ended",r.playlist.autoadvance_.trigger)):r.playlist.autoadvance_.delay=null},n=function(e,t){var n=!e.paused()||e.ended();return e.trigger("beforeplaylistitem",t),e.poster(t.poster||""),e.src(t.sources),function(e){for(var t=e.remoteTextTracks(),r=t&&t.length||0;r--;)e.removeRemoteTextTrack(t[r])}(e),e.ready(function(){if((t.textTracks||[]).forEach(e.addRemoteTextTrack.bind(e)),e.trigger("playlistitem",t),n){var i=e.play();void 0!==i&&"function"==typeof i.then&&i.then(null,function(e){})}r(e,e.playlist.autoadvance_.delay)}),e},i=function(e,t){for(var r=0;r<e.length;r++){var n=e[r].sources;if(Array.isArray(n))for(var i=0;i<n.length;i++){var a=n[i];if(a&&(l=void 0,c=void 0,l=o=a,c=u=t,"object"==typeof o&&(l=o.src),"object"==typeof u&&(c=u.src),/^\/\//.test(l)&&(c=c.slice(c.indexOf("//"))),/^\/\//.test(c)&&(l=l.slice(l.indexOf("//"))),l===c))return r}}var o,u,l,c;return-1},a=function(e){for(var t=-1,r=e.length-1;++t<e.length;){var n=t+Math.floor(Math.random()*(r-t+1)),i=e[n];e[n]=e[t],e[t]=i}return e};var o=function(o,u){!function(o,u,l){void 0===l&&(l=0);var c=null,s=!1,d=o.playlist=function(e,t){if(void 0===t&&(t=0),s)throw new Error("do not call playlist() during a playlist change");if(Array.isArray(e)){var r=Array.isArray(c)?c.slice():null;c=e.slice(),s=!0,o.trigger({type:"duringplaylistchange",nextIndex:t,nextPlaylist:c,previousIndex:d.currentIndex_,previousPlaylist:r||[]}),s=!1,-1!==t&&d.currentItem(t),r&&o.setTimeout(function(){o.trigger("playlistchange")},0)}return c.slice()};o.on("loadstart",function(){-1===d.currentItem()&&t(o)}),d.currentIndex_=-1,d.player_=o,d.autoadvance_={},d.repeat_=!1,d.currentItem=function(e){return s?d.currentIndex_:("number"==typeof e&&d.currentIndex_!==e&&e>=0&&e<c.length?(d.currentIndex_=e,n(d.player_,c[d.currentIndex_])):d.currentIndex_=d.indexOf(d.player_.currentSrc()||""),d.currentIndex_)},d.contains=function(e){return-1!==d.indexOf(e)},d.indexOf=function(e){if("string"==typeof e)return i(c,e);for(var t=Array.isArray(e)?e:e.sources,r=0;r<t.length;r++){var n=t[r];if("string"==typeof n)return i(c,n);if(n.src)return i(c,n.src)}return-1},d.currentIndex=function(){return d.currentItem()},d.lastIndex=function(){return c.length-1},d.nextIndex=function(){var e=d.currentItem();if(-1===e)return-1;var t=d.lastIndex();return d.repeat_&&e===t?0:Math.min(e+1,t)},d.previousIndex=function(){var e=d.currentItem();return-1===e?-1:d.repeat_&&0===e?d.lastIndex():Math.max(e-1,0)},d.first=function(){if(!s)return c.length?c[d.currentItem(0)]:void(d.currentIndex_=-1)},d.last=function(){if(!s)return c.length?c[d.currentItem(d.lastIndex())]:void(d.currentIndex_=-1)},d.next=function(){if(!s){var e=d.nextIndex();return e!==d.currentIndex_?c[d.currentItem(e)]:void 0}},d.previous=function(){if(!s){var e=d.previousIndex();return e!==d.currentIndex_?c[d.currentItem(e)]:void 0}},d.autoadvance=function(e){r(d.player_,e)},d.repeat=function(t){return void 0===t?d.repeat_:"boolean"==typeof t?(d.repeat_=!!t,d.repeat_):void e.log.error("videojs-playlist: Invalid value for repeat",t)},d.sort=function(e){c.length&&(c.sort(e),s||o.trigger("playlistsorted"))},d.reverse=function(){c.length&&(c.reverse(),s||o.trigger("playlistsorted"))},d.shuffle=function(e){var t,r=(void 0===e?{}:e).rest,n=0,i=c;(r&&(n=d.currentIndex_+1,i=c.slice(n)),i.length<=1)||(a(i),r&&(t=c).splice.apply(t,[n,i.length].concat(i)),s||o.trigger("playlistsorted"))},Array.isArray(u)?d(u.slice(),l):c=[]}(this,o,u)};return((e=e&&e.hasOwnProperty("default")?e.default:e).registerPlugin||e.plugin)("playlist",o),o.VERSION="4.2.6",o});

View File

@ -0,0 +1,507 @@
# video.js Playlist API
## Playlist Item Object
A playlist is an array of playlist items. A playlist item is an object with the following properties:
| Property | Type | Optional | Description |
| ------------ | ------ | -------- | -------------------------------------------------- |
| `sources` | Array | | An array of sources that video.js understands. |
| `poster` | String | ✓ | A poster image to display for these sources. |
| `textTracks` | Array | ✓ | An array of text tracks that Video.js understands. |
## Methods
### `player.playlist([Array newList], [Number newIndex]) -> Array`
Get or set the current playlist for a player.
If called without arguments, it is a getter. With an argument, it is a setter.
```js
player.playlist([{
sources: [{
src: 'http://media.w3.org/2010/05/sintel/trailer.mp4',
type: 'video/mp4'
}],
poster: 'http://media.w3.org/2010/05/sintel/poster.png'
}, {
sources: [{
src: 'http://media.w3.org/2010/05/bunny/trailer.mp4',
type: 'video/mp4'
}],
poster: 'http://media.w3.org/2010/05/bunny/poster.png'
}, {
sources: [{
src: 'http://vjs.zencdn.net/v/oceans.mp4',
type: 'video/mp4'
}],
poster: 'http://www.videojs.com/img/poster.jpg'
}, {
sources: [{
src: 'http://media.w3.org/2010/05/bunny/movie.mp4',
type: 'video/mp4'
}],
poster: 'http://media.w3.org/2010/05/bunny/poster.png'
}, {
sources: [{
src: 'http://media.w3.org/2010/05/video/movie_300.mp4',
type: 'video/mp4'
}],
poster: 'http://media.w3.org/2010/05/video/poster.png'
}]);
// [{ ... }, ... ]
player.playlist([{
sources: [{
src: 'http://media.w3.org/2010/05/video/movie_300.mp4',
type: 'video/mp4'
}],
poster: 'http://media.w3.org/2010/05/video/poster.png'
}]);
// [{ ... }]
```
If a setter, a second argument sets the video to be loaded. If omitted, the
first video is loaded. If `-1`, no video is loaded.
```js
player.playlist([{
sources: [{
src: 'http://media.w3.org/2010/05/sintel/trailer.mp4',
type: 'video/mp4'
}],
poster: 'http://media.w3.org/2010/05/sintel/poster.png'
}, {
sources: [{
src: 'http://media.w3.org/2010/05/bunny/trailer.mp4',
type: 'video/mp4'
}],
poster: 'http://media.w3.org/2010/05/bunny/poster.png'
}], 1);
// [{ ... }]
```
#### `player.playlist.currentItem([Number index]) -> Number`
Get or set the current item index.
If called without arguments, it is a getter. With an argument, it is a setter.
If the player is currently playing a non-playlist video, it will return `-1`.
```js
var samplePlaylist = [{
sources: [{
src: 'http://media.w3.org/2010/05/sintel/trailer.mp4',
type: 'video/mp4'
}],
poster: 'http://media.w3.org/2010/05/sintel/poster.png'
}, {
sources: [{
src: 'http://media.w3.org/2010/05/bunny/trailer.mp4',
type: 'video/mp4'
}],
poster: 'http://media.w3.org/2010/05/bunny/poster.png'
}];
player.playlist(samplePlaylist);
player.currentItem();
// 0
player.currentItem(2);
// 2
player.src('http://example.com/video.mp4');
player.playlist.currentItem();
// -1
```
#### `player.playlist.contains(String|Object|Array value) -> Boolean`
Determine whether a string, source object, or playlist item is contained within a playlist.
Assuming the playlist used above, consider the following example:
```js
player.playlist.contains('http://media.w3.org/2010/05/sintel/trailer.mp4');
// true
player.playlist.contains([{
src: 'http://media.w3.org/2010/05/sintel/poster.png',
type: 'image/png'
}]);
// false
player.playlist.contains({
sources: [{
src: 'http://media.w3.org/2010/05/sintel/trailer.mp4',
type: 'video/mp4'
}]
});
// true
```
#### `player.playlist.indexOf(String|Object|Array value) -> Number`
Get the index of a string, source object, or playlist item in the playlist. If not found, returns `-1`.
Assuming the playlist used above, consider the following example:
```js
player.playlist.indexOf('http://media.w3.org/2010/05/bunny/trailer.mp4');
// 1
player.playlist.contains([{
src: 'http://media.w3.org/2010/05/bunny/movie.mp4',
type: 'video/mp4'
}]);
// 3
player.playlist.contains({
sources: [{
src: 'http://media.w3.org/2010/05/video/movie_300.mp4',
type: 'video/mp4'
}]
});
// 4
```
#### `player.playlist.currentIndex() -> Number`
Get the index of the current item in the playlist. This is identical to calling `currentItem()` with no arguments.
```js
var samplePlaylist = [{
sources: [{
src: 'http://media.w3.org/2010/05/sintel/trailer.mp4',
type: 'video/mp4'
}],
poster: 'http://media.w3.org/2010/05/sintel/poster.png'
}, {
sources: [{
src: 'http://media.w3.org/2010/05/bunny/trailer.mp4',
type: 'video/mp4'
}],
poster: 'http://media.w3.org/2010/05/bunny/poster.png'
}];
player.currentIndex();
// 0
```
#### `player.playlist.nextIndex() -> Number`
Get the index of the next item in the playlist.
If the player is on the last item, returns the last item's index. However, if the playlist repeats and is on the last item, returns `0`.
If the player is currently playing a non-playlist video, it will return `-1`.
```js
var samplePlaylist = [{
sources: [{
src: 'http://media.w3.org/2010/05/sintel/trailer.mp4',
type: 'video/mp4'
}],
poster: 'http://media.w3.org/2010/05/sintel/poster.png'
}, {
sources: [{
src: 'http://media.w3.org/2010/05/bunny/trailer.mp4',
type: 'video/mp4'
}],
poster: 'http://media.w3.org/2010/05/bunny/poster.png'
}];
player.playlist(samplePlaylist);
player.nextIndex();
// 1
player.next();
player.nextIndex();
// 1
player.repeat(true);
player.nextIndex();
// 0
player.src('http://example.com/video.mp4');
player.playlist.nextIndex();
// -1
```
#### `player.playlist.previousIndex() -> Number`
Get the index of the previous item in the playlist.
If the player is on the first item, returns `0`. However, if the playlist repeats and is on the first item, returns the last item's index.
If the player is currently playing a non-playlist video, it will return `-1`.
```js
var samplePlaylist = [{
sources: [{
src: 'http://media.w3.org/2010/05/sintel/trailer.mp4',
type: 'video/mp4'
}],
poster: 'http://media.w3.org/2010/05/sintel/poster.png'
}, {
sources: [{
src: 'http://media.w3.org/2010/05/bunny/trailer.mp4',
type: 'video/mp4'
}],
poster: 'http://media.w3.org/2010/05/bunny/poster.png'
}];
player.playlist(samplePlaylist, 1);
player.previousIndex();
// 0
player.previous();
player.previousIndex();
// 0
player.repeat(true);
player.previousIndex();
// 1
player.src('http://example.com/video.mp4');
player.playlist.previousIndex();
// -1
```
#### `player.playlist.lastIndex() -> Number`
Get the index of the last item in the playlist.
```js
var samplePlaylist = [{
sources: [{
src: 'http://media.w3.org/2010/05/sintel/trailer.mp4',
type: 'video/mp4'
}],
poster: 'http://media.w3.org/2010/05/sintel/poster.png'
}, {
sources: [{
src: 'http://media.w3.org/2010/05/bunny/trailer.mp4',
type: 'video/mp4'
}],
poster: 'http://media.w3.org/2010/05/bunny/poster.png'
}];
player.lastIndex();
// 1
```
#### `player.playlist.first() -> Object|undefined`
Play the first item in the playlist.
Returns the activated playlist item unless the playlist is empty (in which case, returns `undefined`).
```js
player.playlist.first();
// { ... }
player.playlist([]);
player.playlist.first();
// undefined
```
#### `player.playlist.last() -> Object|undefined`
Play the last item in the playlist.
Returns the activated playlist item unless the playlist is empty (in which case, returns `undefined`).
```js
player.playlist.last();
// { ... }
player.playlist([]);
player.playlist.last();
// undefined
```
#### `player.playlist.next() -> Object`
Advance to the next item in the playlist.
Returns the activated playlist item unless the playlist is at the end (in which case, returns `undefined`).
```js
player.playlist.next();
// { ... }
player.playlist.last();
player.playlist.next();
// undefined
```
#### `player.playlist.previous() -> Object`
Go back to the previous item in the playlist.
Returns the activated playlist item unless the playlist is at the beginning (in which case, returns `undefined`).
```js
player.playlist.next();
// { ... }
player.playlist.previous();
// { ... }
player.playlist.first();
// { ... }
player.playlist.previous();
// undefined
```
#### `player.playlist.autoadvance([Number delay]) -> undefined`
Sets up playlist auto-advance behavior.
Once invoked, at the end of each video in the playlist, the plugin will wait `delay` seconds before proceeding automatically to the next video.
Any value which is not a positive, finite integer, will be treated as a request to cancel and reset the auto-advance behavior.
If you change auto-advance during a delay, the auto-advance will be canceled and it will not advance the next video, but it will use the new timeout value for the following videos.
```js
// no wait before loading in the next item
player.playlist.autoadvance(0);
// wait 5 seconds before loading in the next item
player.playlist.autoadvance(5);
// reset and cancel the auto-advance
player.playlist.autoadvance();
```
#### `player.playlist.repeat([Boolean val]) -> Boolean`
Enable or disable repeat by passing true or false as the argument.
When repeat is enabled, the "next" video after the final video in the playlist is the first video in the playlist. This affects the behavior of calling `next()`, of autoadvance, and so on.
This method returns the current value. Call with no argument to use as a getter.
Examples:
```js
player.playlist.repeat(true);
player.playlist.repeat();
// true
player.playlist.repeat(false);
player.playlist.repeat();
// false
```
#### `player.playlist.sort([Function compare]) -> undefined`
Sort the playlist in a manner identical to [`Array#sort`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort).
Fires the `playlistsorted` event after sorting.
#### `player.playlist.reverse() -> undefined`
Reverse the playlist in a manner identical to [`Array#reverse`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse).
Fires the `playlistsorted` event after reversing.
#### `player.playlist.shuffle() -> undefined`
Shuffles/randomizes the order of playlist items in a manner identical to [`lodash.shuffle`](https://lodash.com/docs/4.17.4#shuffle).
Fires the `playlistsorted` event after shuffling.
## Events
### `duringplaylistchange`
This event is fired _after_ the contents of the playlist are changed when calling `playlist()`, but _before_ the current playlist item is changed. The event object has several special properties:
- `nextIndex`: The index from the next playlist that will be played first.
- `nextPlaylist`: A shallow clone of the next playlist.
- `previousIndex`: The index from the previous playlist (will always match the current index when this event triggers, but is provided for completeness).
- `previousPlaylist`: A shallow clone of the previous playlist.
**NOTE**: This event fires every time `player.playlist()` is called - including the first time.
#### Caveats
During the firing of this event, the playlist is considered to be in a **changing state**, which has the following effects:
- Calling the main playlist method (i.e. `player.playlist([...])`) will throw an error.
- Playlist navigation methods - `first`, `last`, `next`, and `previous` - are rendered inoperable.
- The `currentItem()` method only acts as a getter.
- While the sorting methods - `sort`, `reverse`, and `shuffle` - will continue to work, they do not fire the `playlistsorted` event.
#### Why have this event?
This event provides an opportunity to intercept the playlist setting process before a new source is set on the player and before the `playlistchange` event fires, while providing a consistent playlist API.
One use-case might be shuffling a playlist that has just come from a server, but before its initial source is loaded into the player or the playlist UI is updated:
```js
player.on('duringplaylistchange', function() {
// Remember, this will not trigger a "playlistsorted" event!
player.playlist.shuffle();
});
player.on('playlistchange', function() {
videojs.log('The playlist was shuffled, so the UI can be updated.');
});
```
### `playlistchange`
This event is fired _asynchronously_ whenever the contents of the playlist are changed (i.e., when `player.playlist()` is called with an argument) - except the first time.
It is fired asynchronously to let the browser start loading the first video in the new playlist.
```js
player.on('playlistchange', function() {
player.playlist();
});
player.playlist([]);
// [ ... ]
player.playlist([]);
// [ ... ]
```
#### Backward Compatibility
This event _does not fire_ the first time `player.playlist()` is called. If you want it to fire on the first call to `player.playlist()`, you can call it without an argument before calling it with one:
```js
// This will fire no events.
player.playlist();
// This will fire both "duringplaylistchange" and "playlistchange"
player.playlist([...]);
```
This behavior will be removed in v5.0.0 and the event will fire in all cases.
### `beforeplaylistitem`
This event is fired before switching to a new content source within a playlist (i.e., when any of `currentItem()`, `first()`, or `last()` is called, but before the player's state has been changed).
### `playlistitem`
This event is fired when switching to a new content source within a playlist (i.e., when any of `currentItem()`, `first()`, or `last()` is called; after the player's state has been changed, but before playback has been resumed).
### `playlistsorted`
This event is fired when any method is called that changes the order of playlist items - `sort()`, `reverse()`, or `shuffle()`.

View File

@ -0,0 +1,148 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Source: auto-advance.js</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Source: auto-advance.js</h1>
<section>
<article>
<pre class="prettyprint source linenums"><code>
/**
* Validates a number of seconds to use as the auto-advance delay.
*
* @private
* @param {number} s
* The number to check
*
* @return {boolean}
* Whether this is a valid second or not
*/
const validSeconds = s =>
typeof s === 'number' &amp;&amp; !isNaN(s) &amp;&amp; s >= 0 &amp;&amp; s &lt; Infinity;
/**
* Resets the auto-advance behavior of a player.
*
* @param {Player} player
* The player to reset the behavior on
*/
let reset = (player) => {
const aa = player.playlist.autoadvance_;
if (aa.timeout) {
player.clearTimeout(aa.timeout);
}
if (aa.trigger) {
player.off('ended', aa.trigger);
}
aa.timeout = null;
aa.trigger = null;
};
/**
* Sets up auto-advance behavior on a player.
*
* @param {Player} player
* the current player
*
* @param {number} delay
* The number of seconds to wait before each auto-advance.
*
* @return {undefined}
* Used to short circuit function logic
*/
const setup = (player, delay) => {
reset(player);
// Before queuing up new auto-advance behavior, check if `seconds` was
// called with a valid value.
if (!validSeconds(delay)) {
player.playlist.autoadvance_.delay = null;
return;
}
player.playlist.autoadvance_.delay = delay;
player.playlist.autoadvance_.trigger = function() {
// This calls setup again, which will reset the existing auto-advance and
// set up another auto-advance for the next "ended" event.
const cancelOnPlay = () => setup(player, delay);
// If there is a "play" event while we're waiting for an auto-advance,
// we need to cancel the auto-advance. This could mean the user seeked
// back into the content or restarted the content. This is reproducible
// with an auto-advance > 0.
player.one('play', cancelOnPlay);
player.playlist.autoadvance_.timeout = player.setTimeout(() => {
reset(player);
player.off('play', cancelOnPlay);
player.playlist.next();
}, delay * 1000);
};
player.one('ended', player.playlist.autoadvance_.trigger);
};
/**
* Used to change the reset function in this module at runtime
* This should only be used in tests.
*
* @param {Function} fn
* The function to se the reset to
*/
const setReset_ = (fn) => {
reset = fn;
};
export {
setReset_,
reset,
setup
};
</code></pre>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Events</h3><ul><li><a href="global.html#event:playlistsorted">playlistsorted</a></li></ul><h3>Global</h3><ul><li><a href="global.html#clearTracks">clearTracks</a></li><li><a href="global.html#playItem">playItem</a></li><li><a href="global.html#plugin">plugin</a></li><li><a href="global.html#reset">reset</a></li><li><a href="global.html#setReset_">setReset_</a></li><li><a href="global.html#setup">setup</a></li></ul>
</nav>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Fri Jan 26 2018 12:37:44 GMT-0500 (EST)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

Some files were not shown because too many files have changed in this diff Show More