611 lines
14 KiB
HTML
611 lines
14 KiB
HTML
<html>
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/>
|
|
<title>dtam music playlist - HTML5 Player</title>
|
|
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
|
|
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
|
|
<script src="//code.jquery.com/ui/1.11.2/jquery-ui.min.js"></script>
|
|
<script>
|
|
var g_playlist = null;
|
|
var g_previous = [];
|
|
var g_previous_idx = 0;
|
|
var g_looping = false;
|
|
var MAX_HISTORY = 10;
|
|
|
|
var scrubp = 0;
|
|
var is_dragging_scrubber = false;
|
|
|
|
var PLAYLISTS = {
|
|
'weeb': '//dtam.pw/music/main_parsed.xml',
|
|
'VIP': '//vip.aersia.net/roster.xml',
|
|
};
|
|
|
|
var DEFAULT_PLAYLIST = 'weeb';
|
|
|
|
function formatTimecode (seconds) {
|
|
seconds = Math.floor (seconds);
|
|
minutes = Math.floor (seconds / 60);
|
|
seconds = seconds - (minutes * 60);
|
|
minutes = "" + minutes;
|
|
seconds = "" + seconds;
|
|
|
|
if (minutes.length == 1)
|
|
minutes = "0" + minutes;
|
|
if (seconds.length == 1)
|
|
seconds = "0" + seconds;
|
|
|
|
return minutes + ":" + seconds;
|
|
}
|
|
|
|
// Creates an id for a track used in the location hash
|
|
function createTrackId (track) {
|
|
var playlist = $('#select-playlist').val ();
|
|
var track = track.creator + ' - ' + track.title;
|
|
track = track.replace(/[^a-zA-Z0-9-]/g, '_');
|
|
|
|
return encodeURIComponent (playlist) + ':' + track;
|
|
}
|
|
|
|
function parseTrackId (trackId) {
|
|
var pieces = trackId.split (':');
|
|
var playlist = '';
|
|
var track = '';
|
|
|
|
if (pieces.length < 2) {
|
|
playlist = decodeURIComponent (trackId);
|
|
track = '';
|
|
} else {
|
|
pieces.pop ();
|
|
playlist = decodeURIComponent (pieces.join (':'));
|
|
track = trackId;
|
|
}
|
|
|
|
if (!(playlist in PLAYLISTS))
|
|
return null;
|
|
|
|
return {
|
|
playlist: playlist,
|
|
track: track
|
|
};
|
|
}
|
|
|
|
function parsePlaylist (playlistXML) {
|
|
result = [];
|
|
|
|
$(playlistXML).find ('playlist trackList > track').each (function () {
|
|
track = {
|
|
creator: $(this).find ('creator').text (),
|
|
title: $(this).find ('title').text (),
|
|
location: $(this).find ('location').text ()
|
|
};
|
|
|
|
result.push (track);
|
|
});
|
|
|
|
return result;
|
|
}
|
|
|
|
function playPreviousTrack () {
|
|
if (g_playlist === null)
|
|
return;
|
|
|
|
if (g_previous_idx <= 0)
|
|
g_previous_idx = 0;
|
|
else
|
|
g_previous_idx -= 1;
|
|
|
|
playTrack (g_previous[g_previous_idx]);
|
|
}
|
|
|
|
function playNextTrack () {
|
|
if (g_playlist === null)
|
|
return;
|
|
|
|
if (g_previous_idx >= (g_previous.length - 1)) {
|
|
g_previous.push (Math.floor (Math.random () * g_playlist.length));
|
|
g_previous_idx = g_previous.length - 1;
|
|
}
|
|
else {
|
|
g_previous_idx += 1;
|
|
}
|
|
|
|
while (g_previous.length > MAX_HISTORY) {
|
|
g_previous.shift ();
|
|
g_previous_idx -= 1;
|
|
}
|
|
|
|
playTrack (g_previous[g_previous_idx]);
|
|
}
|
|
|
|
|
|
function playTrack (trackid) {
|
|
var track = g_playlist[trackid];
|
|
|
|
$('#tracks-table .selected').removeClass ('selected');
|
|
var trackelem = $('#tracks-table div').eq (trackid);
|
|
trackelem.addClass ('selected');
|
|
|
|
window.location.hash = createTrackId (track);
|
|
$('audio').attr ('src', track.location);
|
|
$('audio').trigger ('play');
|
|
|
|
$('html, body').stop ().animate ({
|
|
scrollTop: trackelem.offset ().top - $('.control-bar').height ()
|
|
}, 1000);
|
|
}
|
|
|
|
function loadNewPlaylist (playlist, track) {
|
|
var playlistURL = PLAYLISTS[playlist];
|
|
var selected_track = track;
|
|
|
|
localStorage['playlist'] = playlist;
|
|
$('#select-playlist').val (playlist);
|
|
|
|
// Clear
|
|
$('#tracks-table div').remove ();
|
|
g_previous = [];
|
|
g_previous_idx = 0;
|
|
g_playlist = null;
|
|
|
|
$.ajax({
|
|
url: playlistURL,
|
|
success: function (data) {
|
|
// Parse track list
|
|
g_playlist = parsePlaylist (data);
|
|
|
|
// Build HTML table for track listing
|
|
for (var i = 0; i < g_playlist.length; ++i) {
|
|
var track = g_playlist[i];
|
|
|
|
var row = $('<div>');
|
|
row.text (track.creator + ' - ' + track.title);
|
|
row.attr ('id', createTrackId (track));
|
|
|
|
row.appendTo ('#tracks-table');
|
|
(function (i) {
|
|
row.click (function () {
|
|
playTrack (i);
|
|
});
|
|
}) (i);
|
|
}
|
|
|
|
// Select specified track if possible, or play random track if not.
|
|
var elements = $('#tracks-table div').filter (function (idx, elem) {
|
|
return elem.id == selected_track;
|
|
});
|
|
|
|
if (elements.length > 0) {
|
|
elements[0].click ();
|
|
} else {
|
|
playNextTrack ();
|
|
}
|
|
}
|
|
});
|
|
};
|
|
|
|
function playpause () {
|
|
if ($('audio').get (0).paused)
|
|
$('audio').trigger ('play');
|
|
else
|
|
$('audio').trigger ('pause');
|
|
}
|
|
|
|
function toggleLooping () {
|
|
g_looping = !g_looping;
|
|
$('audio').attr ('loop', g_looping);
|
|
$('#btn-loop i').toggleClass('fa-times', g_looping);
|
|
$('#btn-loop i').toggleClass('fa-repeat', !g_looping);
|
|
}
|
|
|
|
function populatePlaylistOptions () {
|
|
for (var name in PLAYLISTS) {
|
|
var option = $("<option>");
|
|
option.val (name);
|
|
option.text (name);
|
|
|
|
$('#select-playlist').append (option);
|
|
}
|
|
}
|
|
|
|
$(function () {
|
|
// Register Events
|
|
$('audio').on ('pause', function () {
|
|
$('#btn-play i').removeClass ('fa-pause');
|
|
$('#btn-play i').addClass ('fa-play');
|
|
});
|
|
|
|
$('audio').on ('play', function () {
|
|
$('#btn-play i').removeClass ('fa-play');
|
|
$('#btn-play i').addClass ('fa-pause');
|
|
});
|
|
|
|
$('audio').on ('error', function () {
|
|
playNextTrack ();
|
|
});
|
|
|
|
$('audio').on ('timeupdate', function () {
|
|
if (isNaN (this.duration))
|
|
return;
|
|
if (!is_dragging_scrubber)
|
|
$('#scrubber-progress').css('width', (this.currentTime / this.duration) * 100+'%');
|
|
$('#time-current').text (formatTimecode (this.currentTime));
|
|
$('#time-remaining').text (formatTimecode (this.duration - this.currentTime));
|
|
});
|
|
|
|
$('#time-bar').on('mousedown mouseup', function(e) {
|
|
if (e.which == 1) {
|
|
is_dragging_scrubber = true;
|
|
var sc_w = $('#scrubber-track').outerWidth();
|
|
var p = ((e.pageX - $('#scrubber-track').offset().left) / sc_w) * 100;
|
|
$('#scrubber-progress').css('width', p+'%');
|
|
scrubp = p;
|
|
$(document).on('mousemove.scrubber-track', function(e) {
|
|
sc_w = $('#scrubber-track').outerWidth();
|
|
p = ((e.pageX - $('#scrubber-track').offset().left) / sc_w) * 100;
|
|
$('#scrubber-progress').css('width', p+'%');
|
|
scrubp = p;
|
|
});
|
|
}
|
|
});
|
|
|
|
$(document).on('mouseup.scrubber-track', function(e) {
|
|
if (is_dragging_scrubber) {
|
|
$('audio').get(0).currentTime = (scrubp / 100) * $('audio').get(0).duration;
|
|
$(this).off('mousemove.scrubber-track');
|
|
is_dragging_scrubber = false;
|
|
}
|
|
});
|
|
|
|
$('audio').on ('ended', function () {
|
|
if (!g_looping)
|
|
playNextTrack ();
|
|
});
|
|
|
|
$('#btn-play').click (playpause);
|
|
|
|
$(document).keypress (function (e) {
|
|
if (e.which == 32) {
|
|
e.preventDefault ();
|
|
playpause ();
|
|
}
|
|
});
|
|
|
|
$('#btn-next').click (function () {
|
|
playNextTrack (true);
|
|
});
|
|
|
|
$('#btn-previous').click (function () {
|
|
playPreviousTrack ();
|
|
});
|
|
|
|
$('#btn-loop').click (function () {
|
|
toggleLooping ();
|
|
});
|
|
|
|
$('#select-playlist').on ('change', function () {
|
|
var playlist = $('#select-playlist').val ();
|
|
loadNewPlaylist (playlist, '');
|
|
});
|
|
|
|
$('#volume-slider').slider({
|
|
orientation: "vertical",
|
|
range: "min",
|
|
min: 0,
|
|
max: 100,
|
|
value: $('audio').get (0).volume * 100,
|
|
slide: function(event, ui) {
|
|
//change volume here
|
|
$('audio').get(0).volume = (ui.value / 100);
|
|
if (ui.value > 50) {
|
|
$('#btn-volume i').removeClass($('#btn-volume i').attr('class').split(' ')[1]).addClass('fa-volume-up');
|
|
}
|
|
else if (ui.value > 0) {
|
|
$('#btn-volume i').removeClass($('#btn-volume i').attr('class').split(' ')[1]).addClass('fa-volume-down');
|
|
}
|
|
else {
|
|
$('#btn-volume i').removeClass($('#btn-volume i').attr('class').split(' ')[1]).addClass('fa-volume-off');
|
|
}
|
|
|
|
localStorage['volume'] = $('audio').get (0).volume;
|
|
}
|
|
});
|
|
|
|
$('#btn-volume').on('click', function() {
|
|
$('#volume-slider').slideToggle(200);
|
|
});
|
|
|
|
populatePlaylistOptions ();
|
|
|
|
// Default playlist, random track
|
|
var playlist = DEFAULT_PLAYLIST;
|
|
var track = '';
|
|
|
|
/* Load settings */
|
|
if (localStorage.getItem ('volume') !== null)
|
|
$('audio').get (0).volume = localStorage.getItem('volume');
|
|
|
|
if (localStorage.getItem ('playlist') !== null) {
|
|
if (localStorage.getItem ('playlist') in PLAYLISTS)
|
|
playlist = localStorage.getItem ('playlist');
|
|
}
|
|
|
|
// If hash is set, override playlist and track
|
|
var url_track = parseTrackId (window.location.hash.substr (1));
|
|
|
|
if (url_track !== null) {
|
|
playlist = url_track.playlist;
|
|
track = url_track.track;
|
|
}
|
|
|
|
// Load playlist and track
|
|
loadNewPlaylist (playlist, track);
|
|
});
|
|
</script>
|
|
|
|
<style>
|
|
html, body, div, span, applet, object, iframe,
|
|
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
|
a, abbr, acronym, address, big, cite, code,
|
|
del, dfn, em, img, ins, kbd, q, s, samp,
|
|
small, strike, strong, sub, sup, tt, var,
|
|
b, u, i, center,
|
|
dl, dt, dd, ol, ul, li,
|
|
fieldset, form, label, legend,
|
|
table, caption, tbody, tfoot, thead, tr, th, td,
|
|
article, aside, canvas, details, embed,
|
|
figure, figcaption, footer, header, hgroup,
|
|
menu, nav, output, ruby, section, summary,
|
|
time, mark, audio, video {
|
|
margin: 0;
|
|
padding: 0;
|
|
border: 0;
|
|
font-size: 100%;
|
|
font: inherit;
|
|
vertical-align: baseline;
|
|
}
|
|
/* HTML5 display-role reset for older browsers */
|
|
article, aside, details, figcaption, figure,
|
|
footer, header, hgroup, menu, nav, section {
|
|
display: block;
|
|
}
|
|
body {
|
|
line-height: 1;
|
|
}
|
|
ol, ul {
|
|
list-style: none;
|
|
}
|
|
blockquote, q {
|
|
quotes: none;
|
|
}
|
|
blockquote:before, blockquote:after,
|
|
q:before, q:after {
|
|
content: '';
|
|
content: none;
|
|
}
|
|
|
|
body {
|
|
background-color: #183c63;
|
|
}
|
|
|
|
#tracks-table {
|
|
width: 100%;
|
|
margin-top: 18px;
|
|
}
|
|
|
|
#tracks-table div {
|
|
background-color: #183c63;
|
|
border: 1px solid #003366;
|
|
color: #FF9148;
|
|
padding: 5px;
|
|
font-family: Helvetica, Arial, sans-serif;
|
|
font-size: 8pt;
|
|
cursor: pointer;
|
|
}
|
|
|
|
#tracks-table div.selected {
|
|
background-color: #e5874a;
|
|
color: #183c63;
|
|
}
|
|
|
|
#tracks-table div:hover {
|
|
background-color: #4e91ff;
|
|
color: #183c63;
|
|
}
|
|
|
|
.control-bar {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 18px;
|
|
background: linear-gradient(to bottom, rgba(192,204,217,1) 0%, rgba(0,12,25,1) 100%);
|
|
}
|
|
|
|
.control-buttons {
|
|
width: 100%;
|
|
height: 100%;
|
|
border-spacing: 1px;
|
|
border-collapse: separate;
|
|
}
|
|
|
|
.control-buttons td {
|
|
font-family: Helvetica, Arial, sans-serif;
|
|
font-size: 7pt;
|
|
color: #FF9148;
|
|
border-width: 0px;
|
|
background: linear-gradient(to bottom, rgba(61,99,137,1) 0%, rgba(3,41,79,1) 100%);
|
|
text-align: center;
|
|
cursor: pointer;
|
|
vertical-align: middle;
|
|
}
|
|
|
|
.control-buttons td:hover {
|
|
color: #4e91ff;
|
|
}
|
|
|
|
.control-button {
|
|
width: 20px;
|
|
}
|
|
|
|
.control-volume {
|
|
width: 60px;
|
|
font-size: 9pt;
|
|
}
|
|
|
|
.control-playlist {
|
|
width: 80px;
|
|
}
|
|
|
|
.control-playlist select {
|
|
height: 16px;
|
|
font-family: Helvetica, Arial, sans-serif;
|
|
font-size: 7pt;
|
|
padding: 0;
|
|
color: #FF9148;
|
|
border: 0;
|
|
background: transparent;
|
|
}
|
|
|
|
.credits {
|
|
position: fixed;
|
|
bottom: 0;
|
|
right: 0;
|
|
width: 100px;
|
|
background-color: #000;
|
|
background-color: rgba(0,0,0,0.5);
|
|
color: #FF9148;
|
|
padding: 5px;
|
|
font-family: Helvetica, Arial, sans-serif;
|
|
font-size: 8pt;
|
|
text-align: center;
|
|
}
|
|
|
|
.credits a {
|
|
color: #a96030;
|
|
font-family: Helvetica, Arial, sans-serif;
|
|
font-size: 8pt;
|
|
text-decoration: none;
|
|
}
|
|
|
|
#time-current, #time-remaining {
|
|
width: 60px;
|
|
}
|
|
|
|
#time-bar:hover #scrubber {
|
|
background: rgb(78,145,255);
|
|
}
|
|
|
|
#scrubber-track {
|
|
width: 100%;
|
|
height: 5px;
|
|
background: #7f6157;
|
|
}
|
|
|
|
#scrubber-progress {
|
|
background: #FF9148;
|
|
height: 100%;
|
|
position: relative;
|
|
}
|
|
|
|
#scrubber {
|
|
position: absolute;
|
|
right: 0;
|
|
height: 8px;
|
|
width: 3px;
|
|
display: inline-block;
|
|
border: 1px solid #7f6157;
|
|
background: #FF9148;
|
|
-ms-transform: translateY(-25%);
|
|
-webkit-transform: translateY(-25%);
|
|
transform: translateY(-25%);
|
|
}
|
|
|
|
::-webkit-scrollbar {
|
|
width: 8px;
|
|
}
|
|
|
|
::-webkit-scrollbar-track {
|
|
background-color: #7f6157;
|
|
}
|
|
|
|
::-webkit-scrollbar-thumb {
|
|
background-color: #FF9148;
|
|
border-radius: 2px;
|
|
}
|
|
|
|
::-webkit-scrollbar-thumb:hover {
|
|
background-color: rgb(78,145,255);
|
|
}
|
|
|
|
#volume-slider {
|
|
width: 10px;
|
|
height: 65px;
|
|
position: absolute;
|
|
background: linear-gradient(to bottom, rgba(61,99,137,1) 0%, rgba(3,41,79,1) 100%);
|
|
border: 1px solid gray;
|
|
top: 19px;
|
|
margin-left: -1px;
|
|
display: none;
|
|
padding: 0 5px;
|
|
}
|
|
.ui-slider-range-min {
|
|
background-color: #FF9148;
|
|
position: absolute;
|
|
width: 8px;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
margin: auto;
|
|
}
|
|
@media(max-device-width: 700px) {
|
|
.control-bar {
|
|
height: 70px;
|
|
}
|
|
.control-buttons {
|
|
height: 50px;
|
|
}
|
|
.control-button {
|
|
width: 30px;
|
|
}
|
|
#time-bar {
|
|
position: absolute;
|
|
bottom: 10px;
|
|
left: 0;
|
|
width: 100%;
|
|
}
|
|
#tracks-table {
|
|
margin-top: 70px;
|
|
}
|
|
#tracks-table div {
|
|
font-size: 11pt;
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class='control-bar'>
|
|
<table class='control-buttons' cellpadding="0" cellspacing="0">
|
|
<tr>
|
|
<td id='btn-play' class='control-button'><i class="fa fa-play"></i></td>
|
|
<td id='btn-previous' class='control-button'><i class="fa fa-step-backward"></i></td>
|
|
<td id='btn-next' class='control-button'><i class="fa fa-step-forward"></i></td>
|
|
<td id='btn-loop' class='control-button'><i class="fa fa-repeat"></i></td>
|
|
<td id='time-current'></td>
|
|
<td id='time-bar'><div id="scrubber-track"><div id="scrubber-progress"><div id="scrubber"></div></div></div></td>
|
|
<td id='time-remaining'></td>
|
|
<td id='btn-volume' class='control-button'><i class="fa fa-volume-up"></i><div id="volume-slider"></div></td>
|
|
<td class='control-playlist'>
|
|
<select id='select-playlist'></select>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
|
|
<audio></audio>
|
|
|
|
<div id='tracks-table'></div>
|
|
|
|
</body>
|
|
</html>
|