alpha player

This commit is contained in:
IrosTheBeggar 2021-12-02 16:46:21 -05:00
parent 800a915455
commit e8e2b306b6
5 changed files with 352 additions and 71 deletions

View File

@ -36,8 +36,14 @@
<script defer src="m.js"></script>
<script src="../assets/js/lib/vue2.js"></script>
<!-- Sortable JS -->
<script src="../assets/js/lib/sortable.js"></script>
<!-- https://github.com/SortableJS/Vue.Draggable - v2.14.1 -->
<script src="../assets/js/lib/vue-sortable.js"></script>
<script src="../assets/js/mstream.player.js"></script>
<script defer src="vp.js"></script>
</head>
<body>
@ -126,6 +132,9 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="#DDD" width="24" height="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M20.2 5.9l.8-.8C19.6 3.7 17.8 3 16 3s-3.6.7-5 2.1l.8.8C13 4.8 14.5 4.2 16 4.2s3 .6 4.2 1.7zm-.9.8c-.9-.9-2.1-1.4-3.3-1.4s-2.4.5-3.3 1.4l.8.8c.7-.7 1.6-1 2.5-1 .9 0 1.8.3 2.5 1l.8-.8zM19 13h-2V9h-2v4H5c-1.1 0-2 .9-2 2v4c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2v-4c0-1.1-.9-2-2-2zM8 18H6v-2h2v2zm3.5 0h-2v-2h2v2zm3.5 0h-2v-2h2v2z"/></svg>
<span>Servers</span>
</div>
<div class="side-nav-header">
<span>Navigation</span>
</div>
<div class="side-nav-item my-waves" onclick="window.open('./admin', '_blank');">
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24" viewBox="0 0 24 24" width="24"><g><rect fill="none" height="24" width="24"/></g><g><g><path d="M17,11c0.34,0,0.67,0.04,1,0.09V6.27L10.5,3L3,6.27v4.91c0,4.54,3.2,8.79,7.5,9.82c0.55-0.13,1.08-0.32,1.6-0.55 C11.41,19.47,11,18.28,11,17C11,13.69,13.69,11,17,11z"/><path d="M17,13c-2.21,0-4,1.79-4,4c0,2.21,1.79,4,4,4s4-1.79,4-4C21,14.79,19.21,13,17,13z M17,14.38c0.62,0,1.12,0.51,1.12,1.12 s-0.51,1.12-1.12,1.12s-1.12-0.51-1.12-1.12S16.38,14.38,17,14.38z M17,19.75c-0.93,0-1.74-0.46-2.24-1.17 c0.05-0.72,1.51-1.08,2.24-1.08s2.19,0.36,2.24,1.08C18.74,19.29,17.93,19.75,17,19.75z"/></g></g></svg>
<span>Admin Panel</span>
@ -207,7 +216,7 @@
<svg v-else class="pointer margin-lr" v-on:click="toggleMute" xmlns="http://www.w3.org/2000/svg" height="25" viewBox="0 0 24 24" width="25"><path d="M0 0h24v24H0z" fill="none"/><path d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z"/></svg>
<div v-on:click.stop="changeVol($event)" class="progress volume pointer" ref="volumeWrapper">
<div class="determinate" :style="volWidthCss"></div>
<div style="background-color:#657ee4 !important" class="determinate" :style="volWidthCss"></div>
</div>
</div>
</div>
@ -256,12 +265,13 @@
<div class="col col-y s12 m6">
<h5>Now Playing</h5>
<ul class="collection">
<li class="collection-item">Test Item</li>
<li class="collection-item">Test Item</li>
<li class="collection-item">Test Item</li>
<li class="collection-item">Test Item</li>
</ul>
<draggable class="collection" tag="ul" :list="playlist" :options="{handle:'.drag-handle'}" @end="checkMove" id="playlist">
<li v-for="(song, index) in playlist" is="playlist-item" :key="index" :index="index" :song="song">
</li>
</draggable>
<!-- <ul class="collection">
<li v-for="(song, index) in playlist" is="playlist-item" :key="index" :index="index" :song="song"></li>
</ul> -->
</div>
</div>
@ -283,6 +293,8 @@
</svg>
</a>
</div>
<script src="vp.js"></script>
</body>
</html>

View File

@ -37,7 +37,7 @@ function renderAlbum(id, artist, name, albumArtFile, year) {
}
function renderFileWithMetadataHtml(filepath, lokiId, metadata) {
return `<div data-lokiid="${lokiId}" class="clear relative">
return `<div data-lokiid="${lokiId}" class="relative">
<div data-file_location="${filepath}" class="filez left flex" onclick="onFileClick(this);">
<img class="album-art-box" ${metadata['album-art'] ? `data-original="/album-art/${metadata['album-art']}?token=${MSTREAMAPI.currentServer.token}"` : 'src="assets/img/default.png"'}>
<div>
@ -55,8 +55,8 @@ function renderFileWithMetadataHtml(filepath, lokiId, metadata) {
}
function createMusicFileHtml(fileLocation, title, aa, rating, subtitle) {
return `<li class="clear relative collection-item">
<div data-file_location="${fileLocation}" class="filez left flex" onclick="onFileClick(this);">
return `<li class="collection-item">
<div data-file_location="${fileLocation}" class="filez flex" onclick="onFileClick(this);">
${aa ? `<img class="album-art-box" ${aa}>` : '<svg class="music-image" height="18" width="18" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40"><path d="M9 37.5c-3.584 0-6.5-2.916-6.5-6.5s2.916-6.5 6.5-6.5a6.43 6.43 0 012.785.634l.715.34V5.429l25-3.846V29c0 3.584-2.916 6.5-6.5 6.5s-6.5-2.916-6.5-6.5 2.916-6.5 6.5-6.5a6.43 6.43 0 012.785.634l.715.34V11.023l-19 2.931V31c0 3.584-2.916 6.5-6.5 6.5z" fill="#8bb7f0"/><path d="M37 2.166V29c0 3.308-2.692 6-6 6s-6-2.692-6-6 2.692-6 6-6a5.93 5.93 0 012.57.586l1.43.68V10.441l-1.152.178-18 2.776-.848.13V31c0 3.308-2.692 6-6 6s-6-2.692-6-6 2.692-6 6-6a5.93 5.93 0 012.57.586l1.43.68V5.858l24-3.692M38 1L12 5v19.683A6.962 6.962 0 009 24a7 7 0 107 7V14.383l18-2.776v11.076A6.962 6.962 0 0031 22a7 7 0 107 7V1z" fill="#4e7ab5"/></svg>'}
<div>
${subtitle ? `<b>` : ''}
@ -76,7 +76,7 @@ function createMusicFileHtml(fileLocation, title, aa, rating, subtitle) {
}
function renderDirHtml(name) {
return `<li class="clear relative collection-item">
return `<li class="collection-item">
<div data-directory="${name}" class="dirz" onclick="handleDirClick(this);">
<svg class="folder-image" viewBox="0 0 48 48" version="1.0" xmlns="http://www.w3.org/2000/svg"><path fill="#FFA000" d="M38 12H22l-4-4H8c-2.2 0-4 1.8-4 4v24c0 2.2 1.8 4 4 4h31c1.7 0 3-1.3 3-3V16c0-2.2-1.8-4-4-4z"/><path fill="#FFCA28" d="M42.2 18H15.3c-1.9 0-3.6 1.4-3.9 3.3L8 40h31.7c1.9 0 3.6-1.4 3.9-3.3l2.5-14c.5-2.4-1.4-4.7-3.9-4.7z"/></svg>
<span class="item-text">${name}</span>
@ -93,7 +93,7 @@ function renderDirHtml(name) {
}
function createFileplaylistHtml(dataDirectory) {
return `<li class="clear relative collection-item">
return `<li class="relative collection-item">
<div data-directory="${dataDirectory}" class="fileplaylistz" onclick="onFilePlaylistClick(this);">
<svg class="fileplaylist-image" xmlns="http://www.w3.org/2000/svg" viewBox="24 0 303.188 303.188"><path fill="#e8e8e8" d="M219.821 0H32.842v303.188h237.504V50.525z"/><g fill="#333"><path d="M99.324 273.871l-9.813-34.557h-.295c.459 5.885.689 10.458.689 13.717v20.84H78.419v-47.979h17.262l10.009 34.065h.263l9.813-34.065h17.295v47.979h-11.913v-21.036c0-1.094.017-2.308.049-3.643.033-1.335.181-4.605.443-9.813h-.295l-9.681 34.491h-12.34v.001zM173.426 236.295c0 2.976-.908 5.529-2.724 7.663-1.816 2.133-4.441 3.681-7.876 4.644v.197c8.008 1.006 12.011 4.791 12.011 11.354 0 4.464-1.767 7.975-5.3 10.534-3.533 2.56-8.439 3.84-14.719 3.84-2.582 0-4.972-.186-7.171-.558-2.198-.372-4.577-1.05-7.138-2.034V261.17a28.545 28.545 0 006.416 2.379c2.177.515 4.185.771 6.023.771 2.844 0 4.917-.399 6.219-1.198 1.302-.799 1.952-2.051 1.952-3.758 0-1.313-.339-2.324-1.017-3.035-.679-.711-1.773-1.247-3.282-1.607-1.51-.361-3.479-.542-5.907-.542h-2.953v-9.747h3.018c6.586 0 9.879-1.684 9.879-5.054 0-1.269-.487-2.21-1.461-2.822s-2.28-.919-3.922-.919c-3.063 0-6.235 1.029-9.517 3.085l-5.382-8.664c2.537-1.75 5.136-2.997 7.794-3.741s5.704-1.115 9.14-1.115c4.966 0 8.86.984 11.683 2.953 2.823 1.969 4.234 4.682 4.234 8.139zM223.571 225.892v28.88c0 6.279-1.778 11.141-5.333 14.588-3.556 3.445-8.681 5.168-15.375 5.168-6.542 0-11.568-1.674-15.08-5.022-3.511-3.347-5.267-8.16-5.267-14.439v-29.175h13.028v28.157c0 3.393.635 5.854 1.903 7.385s3.14 2.297 5.612 2.297c2.647 0 4.566-.76 5.759-2.281 1.192-1.52 1.789-4.008 1.789-7.465v-28.093h12.964z"/></g><path fill="#004a94" d="M227.64 25.263H32.842V0h186.979z"/><path fill="#d1d3d3" d="M219.821 50.525h50.525L219.821 0z"/><circle cx="150.304" cy="122.143" r="59.401" fill="#004a94"/><path d="M130.903 91.176v47.938c-1.681-.198-3.551-.154-5.529.195-7.212 1.271-13.057 5.968-13.057 10.49s5.845 7.157 13.057 5.886c7.211-1.271 13.056-5.968 13.056-10.49v-38.703l32.749-5.775v31.295c-1.68-.199-3.549-.153-5.529.196-7.213 1.271-13.057 5.968-13.057 10.49 0 4.523 5.844 7.157 13.057 5.886 7.21-1.271 13.056-5.968 13.056-10.49V82.748l-47.803 8.428z" fill="#fff"/></svg>
<span class="item-text">${dataDirectory}</span>
@ -171,8 +171,8 @@ async function senddir(root) {
try {
const response = await MSTREAMAPI.dirparser(directoryString);
if(response.path.length > 1) {
fileExplorerArray.push(response.path.replace('/', ''));
if(root === true && response.path.length > 1) {
fileExplorerArray.push(response.path.replaceAll('/', ''));
programState.push({
state: 'fileExplorer',
previousScroll: 0,
@ -235,6 +235,17 @@ if (typeof(Storage) !== "undefined" && localStorage.getItem("token")) {
MSTREAMAPI.currentServer.token = localStorage.getItem("token");
}
function handleDirClick(el){
fileExplorerArray.push(el.getAttribute('data-directory'));
programState.push({
state: 'fileExplorer',
previousScroll: document.getElementById('filelist').scrollTop,
previousSearch: ''
// previousSearch: document.getElementById('search_folders').value
});
senddir();
}
loadFileExplorer();
function boilerplateFailure(err) {
@ -250,4 +261,28 @@ function boilerplateFailure(err) {
position: 'topCenter',
timeout: 3500
});
}
}
function onFileClick(el) {
VUEPLAYERCORE.addSongWizard(el.getAttribute("data-file_location"), {}, true);
}
async function recursiveAddDir(el) {
try {
const directoryString = getDirectoryString2(el);
const res = await MSTREAMAPI.recursiveScan(directoryString);
addAllSongs(res);
} catch(err) {
boilerplateFailure(err);
}
}
function addAllSongs(res) {
for (var i = 0; i < res.length; i++) {
VUEPLAYERCORE.addSongWizard(res[i], {}, true);
}
}
function playNow(el) {
VUEPLAYERCORE.addSongWizard(el.getAttribute("data-file_location"), {}, true, MSTREAMPLAYER.positionCache.val + 1);
}

View File

@ -38,7 +38,12 @@ body {
}
.progress {
padding-top: 10px
padding-top: 10px;
background-color: #CCC !important;
}
.determinate {
background-color: #fa832b !important;
}
#media-player-button-bar {
@ -306,11 +311,16 @@ body {
cursor: pointer;
}
/* Note: maybe move things below this line elsewhere */
.collection-item {
/* background-color: #22272e !important; */
background-color: #2d333b !important;
border-bottom: 1px solid #444c56 !important;
color: #FFF;
padding: 0 !important;
position: relative;
}
.collection {
@ -383,7 +393,7 @@ body {
}
.playing {
background-color: #E6EBFA !important;
background-color: #4a463e !important;
}
.aa-card {
@ -453,6 +463,10 @@ body {
bottom: auto !important;
}
#mstream-player {
max-width: 1800px;
}
#mstream-player svg {
fill:#FFF;
color: #FFF;
@ -462,20 +476,82 @@ body {
display: flex;
}
.dirz, .filez {
.dirz, .filez, .playlist-item {
width: 100%;
padding-top: 12px;
padding-bottom: 12px;
padding-left: 10px;
padding-right: 10px;
cursor: pointer;
}
.song-button-box{
position: absolute;
right: 0;
z-index: 9999;
top: 0;
}
.clear {
clear: both; }
.clear:after {
content: "";
display: block;
clear: both;
.folder-image{
height: 20px;
margin-right: 5px;
}
.music-image{
min-height: 20px;
min-width: 20px;
margin-right: 5px;
}
.item-text {
vertical-align: top;
}
.songDropdown:hover, .downloadPlaylistSong:hover, .recursiveAddDir:hover, .addFileplaylist:hover {
background-color: #9E9E9E;
}
.songDropdown, .downloadPlaylistSong, .recursiveAddDir, .addFileplaylist {
height: 14px;
background-color: #B5B5B5;
float: right;
text-align: center;
font-size: 12px;
font-family: "Arial Black", Gadget, sans-serif;
padding-left: 3px;
padding-right: 3px;
cursor: pointer;
}
.songDropdown {
min-width: 38px !important;
}
.popperMenu:hover, .downloadDir:hover, .downloadFileplaylist:hover, .fileAddToPlaylist:hover {
background-color: #9E9E9E;
}
.popperMenu, .downloadDir, .downloadFileplaylist, .fileAddToPlaylist {
min-width: 28px !important;
height: 14px;
background-color: #B5B5B5;
float: right;
text-align: center;
font-size: 12px;
font-family: "Arial Black", Gadget, sans-serif;
border-bottom-left-radius: 3px;
padding-left: 3px;
padding-right: 3px;
border-right: 1px solid #9E9E9E;
cursor: pointer;
}
.song-button-box svg {
vertical-align: text-top !important;
}
.drag-handle{
cursor: move;
float: left;
padding-right: 6px;
}

View File

@ -1,6 +1,159 @@
const VUEPLAYERCORE = (() => {
const mstreamModule = {};
new Vue({
el: '#playlist',
data: {
playlist: MSTREAMPLAYER.playlist,
// playlists: mstreamModule.playlists,
// showClear: showClearLink
},
methods: {
checkMove: function (event) {
},
clearRating: function () {
},
},
});
// Template for playlist items
Vue.component('playlist-item', {
template: `
<li class="noselect collection-item" v-bind:class="{ playing: (this.index === positionCache.val), playError: (this.songError && this.songError === true) }" >
<div v-on:click="goToSong($event)" class="playlist-item">
<span onclick="event.stopPropagation()" class="drag-handle">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="24" height="24"><path fill="#FFF" d="M4 7v2h24V7Zm0 8v2h24v-2Zm0 8v2h24v-2Z"/></svg>
</span>
<span class="song-area">{{ comtext }}</span>
</div>
</li>`,
props: ['index', 'song'],
// We need the positionCache to track the currently playing song
data: function () {
return {
positionCache: MSTREAMPLAYER.positionCache
}
},
// Methods used by playlist item events
methods: {
goToSong: function (event) {
MSTREAMPLAYER.goToSongAtPosition(this.index);
},
removeSong: function (event) {
MSTREAMPLAYER.removeSongAtPosition(this.index, false);
},
downloadSong: function (event) {
// document.getElementById("download-file").href = "/media/" + this.song.filepath + "?token=" + MSTREAMAPI.currentServer.token;
// document.getElementById('download-file').click();
},
createPopper: function (event) {
// if (currentPopperSongIndex === this.index) {
// currentPopperSongIndex = false;
// document.getElementById("pop").style.visibility = "hidden";
// return;
// }
// var ref = event.target;
// currentPopperSongIndex = this.index;
// currentPopperSongIndex2 = this.index;
// currentPopperSong = this.song;
// showClearLink.val = false;
// if (typeof MSTREAMPLAYER.playlist[currentPopperSongIndex2].metadata.rating === 'number'){
// showClearLink.val = true
// }
// myRater.setRating(this.song.metadata.rating / 2);
// const pop = document.getElementById('pop');
// Popper.createPopper(ref, pop, {
// placement: 'bottom-end',
// onFirstUpdate: function (data) {
// document.getElementById("pop").style.visibility = "visible";
// },
// modifiers: [
// {
// name: 'flip',
// options: {
// boundariesElement: 'scrollParent',
// },
// },
// {
// name: 'preventOverflow',
// options: {
// boundariesElement: 'scrollParent',
// },
// },
// ]
// });
},
createPopper2: function (event) {
// if (cpsi === this.index) {
// cpsi = false;
// document.getElementById("pop-d").style.visibility = "hidden";
// return;
// }
// var ref = event.target;
// cpsi = this.index;
// cps = this.song;
// const pop = document.getElementById('pop-d');
// Popper.createPopper(ref, pop, {
// placement: 'bottom-end',
// onFirstUpdate: function (data) {
// document.getElementById("pop-d").style.visibility = "visible";
// },
// modifiers: [
// {
// name: 'flip',
// options: {
// boundariesElement: 'scrollParent',
// },
// },
// {
// name: 'preventOverflow',
// options: {
// boundariesElement: 'scrollParent',
// },
// },
// ]
// });
},
},
computed: {
comtext: function () {
let returnThis = this.song.filepath.split('/').pop();
if (this.song.metadata.title) {
returnThis = this.song.metadata.title;
if (this.song.metadata.artist) {
returnThis = this.song.metadata.artist + ' - ' + returnThis;
}
}
return returnThis;
},
songError: function () {
return this.song.error;
},
ratingNumber: function () {
if (!this.song.metadata.rating) {
return '';
}
var returnThis = this.song.metadata.rating / 2;
if (!Number.isInteger(returnThis)) {
returnThis = returnThis.toFixed(1);
}
return returnThis;
}
}
});
new Vue({
el: '#mstream-player',
data: {
@ -94,50 +247,6 @@ const VUEPLAYERCORE = (() => {
}
});
Vue.component('playlist-item', {
// We need the positionCache to track the currently playing song
data: function () {
return {
positionCache: MSTREAMPLAYER.positionCache,
}
},
template: `
<li v-on:click="goToSong($event)" class="pointer collection-item" v-bind:class="{ playing: (this.index === positionCache.val), playError: (this.songError && this.songError === true) }" >
<div class="playlist-text">{{ comtext }}</div>
<a v-on:click.stop="downloadSong($event)" class="secondary-content">
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M19 12v7H5v-7H3v7c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2v-7h-2zm-6 .67l2.59-2.58L17 11.5l-5 5-5-5 1.41-1.41L11 12.67V3h2z"/></svg>
</a>
</li>`,
props: ['index', 'song'],
methods: {
goToSong: function () {
MSTREAMPLAYER.goToSongAtPosition(this.index);
},
// removeSong: function (event) {
// MSTREAMPLAYER.removeSongAtPosition(this.index, false);
// },
downloadSong: function () {
const link = document.createElement("a");
link.download = '';
link.href = this.song.url;
link.dispatchEvent(new MouseEvent('click', {bubbles: true, cancelable: true, view: window}));
}
},
computed: {
comtext: function () {
let returnThis = this.song.metadata.title ? this.song.metadata.title : this.song.filepath.split('/').pop();
if (this.song.metadata.artist) {
returnThis = this.song.metadata.artist + ' - ' + returnThis;
}
return returnThis;
},
songError: function () {
return this.song.error;
}
}
});
// Change spacebar behavior to Play/Pause
window.addEventListener("keydown", (event) => {
// Use default behavior if user is in a form
@ -155,5 +264,55 @@ const VUEPLAYERCORE = (() => {
}
}, false);
mstreamModule.transcodeOptions = {
serverEnabled: false,
frontendEnabled: false,
bitrate: '128k',
codec: 'mp3'
};
mstreamModule.addSongWizard = async (filepath, metadata, lookupMetadata, position) => {
// Escape filepath
var rawFilepath = filepath;
filepath = filepath.replace(/\%/g, "%25");
filepath = filepath.replace(/\#/g, "%23");
if (filepath.charAt(0) === '/') {
filepath = filepath.substr(1);
}
var defaultPathString = 'media/';
if (mstreamModule.transcodeOptions.serverEnabled && mstreamModule.transcodeOptions.frontendEnabled) {
defaultPathString = 'transcode/';
}
var url = '../' + MSTREAMAPI.currentServer.host + defaultPathString + filepath;
if (MSTREAMAPI.currentServer.token) {
url = url + '?token=' + MSTREAMAPI.currentServer.token;
}
const newSong = {
url: url,
rawFilePath: rawFilepath,
filepath: filepath,
metadata: metadata
};
if (position) {
MSTREAMPLAYER.insertSongAt(newSong, position, true);
} else {
MSTREAMPLAYER.addSong(newSong);
}
// perform lookup
if (lookupMetadata === true) {
const response = await MSTREAMAPI.lookupMetadata(rawFilepath);
if (response.metadata) {
newSong.metadata = response.metadata;
MSTREAMPLAYER.resetCurrentMetadata();
}
}
};
return mstreamModule;
})()

View File

@ -53,7 +53,6 @@
<!-- Star Rating System -->
<script src="assets/js/lib/star-rating.js"></script>
<!-- <script src="assets/js/lib/star.js"></script> -->
<script src="assets/js/lib/popper.js"></script>
<script async src="assets/js/lib/butterchurn.min.js"></script>