Delete webapp2. Poor thing never saw the light of day

This commit is contained in:
IrosTheBeggar 2017-08-29 21:10:16 -04:00
parent 5a05df6f74
commit 7b65fd759d
47 changed files with 0 additions and 10170 deletions

View File

@ -1,120 +0,0 @@
/* ==========================================================================
LET'S GET STARTED!
========================================================================== */
body, input, select, button {
font-size: 100%;
line-height: 1.5;
font-family: 'Montserrat', 'Proxima Nova', sans-serif;
color: #ccc;
}
/* ==========================================================================
=BASE
========================================================================== */
.hide {
/*display: none;*/
}
input {
padding: 1em;
background: #222;
border: none;
display: block;
width: 100%;
box-sizing: border-box;
transition: all .15s ease;
}
input:hover {
background: #252525;
}
input:focus {
border-color: #2962FF;
outline: none;
}
.label--magic {
position: relative;
margin: 0 0 1.5em;
display: block;
}
.label--magic > span {
position: absolute;
z-index: 2;
color: #555;
margin: 1em .625em;
padding: 0 .375em;
cursor: pointer;
top: 0;
transform-origin: 0 50%;
transition: all .3s ease;
border-radius: 2px;
}
.label--magic > input {
position: relative;
}
.label--magic input:focus {
background: #252525;
}
.label--magic input:focus + span,
.label--magic input:not(:focus):valid + span {
transform: scale(.8);
background: #252525;
top: -2em;
}
button {
display: block;
width: 100%;
padding: 1em;
border: none;
color: white;
background: #2962FF;
cursor: pointer;
transition: all .15s ease;
}
button:hover {
background: #2979FF;
}
/* ==========================================================================
=LOGIN OVERLAY
========================================================================== */
.login-overlay {
position: fixed;
padding: 0;
margin: 0;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(255, 255, 255, 0.2);
z-index: 9;
}
.login-panel {
width: 300px;
padding: 2em;
margin: 2em auto;
background: #111;
}
.login-icon {
max-width: 50%;
margin: 0 auto 1.5em;
display: block;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig><msapplication><tile><square70x70logo src="/ms-icon-70x70.png"/><square150x150logo src="/ms-icon-150x150.png"/><square310x310logo src="/ms-icon-310x310.png"/><TileColor>#ffffff</TileColor></tile></msapplication></browserconfig>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1,41 +0,0 @@
{
"name": "App",
"icons": [
{
"src": "\/android-icon-36x36.png",
"sizes": "36x36",
"type": "image\/png",
"density": "0.75"
},
{
"src": "\/android-icon-48x48.png",
"sizes": "48x48",
"type": "image\/png",
"density": "1.0"
},
{
"src": "\/android-icon-72x72.png",
"sizes": "72x72",
"type": "image\/png",
"density": "1.5"
},
{
"src": "\/android-icon-96x96.png",
"sizes": "96x96",
"type": "image\/png",
"density": "2.0"
},
{
"src": "\/android-icon-144x144.png",
"sizes": "144x144",
"type": "image\/png",
"density": "3.0"
},
{
"src": "\/android-icon-192x192.png",
"sizes": "192x192",
"type": "image\/png",
"density": "4.0"
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -1,32 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xml:space="preserve"
style="enable-background:new 0 0 218.6 220.5;"
viewBox="0 0 218.6 220.5"
y="0px"
x="0px"
id="Layer_1"
version="1.1"><metadata
id="metadata15"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
id="defs13" /><style
id="style2"
type="text/css">
.st0{fill-rule:evenodd;clip-rule:evenodd;fill:#6785B3;}
.st1{fill-rule:evenodd;clip-rule:evenodd;fill:#26487C;}
</style><polygon
id="polygon4"
points="8.4,211.7 8.4,9.9 68.9,41.5 68.9,211.7 "
class="st0" /><polygon
id="polygon6"
points="77.6,211.7 77.6,44 109.7,61 140.9,44 140.9,211.7 "
class="st1" /><polygon
id="polygon8"
points="149.6,211.7 149.6,41.5 210.1,9.9 210.1,211.7 "
class="st0" /></svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

View File

@ -1,34 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 612 153" style="enable-background:new 0 0 612 153;" xml:space="preserve">
<style type="text/css">
.st0{fill-rule:evenodd;clip-rule:evenodd;fill:#264679;}
.st1{fill-rule:evenodd;clip-rule:evenodd;fill:#6684B2;}
.st2{fill-rule:evenodd;clip-rule:evenodd;fill:#26477B;}
</style>
<g>
<path class="st0" d="M179.9,45.5c-6.2,0-11.5,1.7-15.9,5c-4.4,3.3-6.5,8.1-6.5,14.4c0,4.9,1.3,9.1,3.8,12.4
c2.5,3.4,5.7,5.8,9.3,7.3c3.7,1.5,7.3,2.8,11,3.8c3.7,1,6.8,2.3,9.3,3.9c2.5,1.5,3.8,3.5,3.8,5.8c0,4.8-4.4,7.2-13.1,7.2h-24.1V118
h24.1c17.1,0,25.6-6.7,25.6-20.2c0-1.9-0.2-3.8-0.6-5.8c-0.4-2-1.2-4-2.6-6c-1.3-2.1-3.3-3.7-5.8-4.9c-2.5-1.2-6.4-2.7-11.5-4.5
l-8.8-3.1c-0.7-0.2-1.7-0.7-2.9-1.3c-1.3-0.7-2.2-1.3-2.8-1.9c-0.6-0.6-1.1-1.4-1.6-2.3c-0.5-0.9-0.7-2-0.7-3.2c0-2,1-3.5,2.9-4.6
c1.9-1.1,4.3-1.6,7-1.6h24.6V45.5H179.9z"/>
<path class="st0" d="M226.4,58.3v31c0,10.2,2.5,17.6,7.6,22c5.1,4.4,13,6.6,23.7,6.6v-12.8c-2.7,0-4.9-0.2-6.8-0.4
c-1.8-0.3-3.7-0.9-5.8-1.9c-2-0.9-3.6-2.6-4.7-4.9c-1.1-2.3-1.6-5.2-1.6-8.7V58.3h18.8V45.5h-18.8V31.6L214,58.3H226.4z"/>
<path class="st0" d="M281.1,118V76.8c0-7.2,0.9-12,2.6-14.5c1-1.3,2.2-2.2,3.6-2.8c1.4-0.6,2.6-1,3.6-1.1c1-0.1,2.5-0.1,4.3-0.1
H310V45.5h-12.2c-3.6,0-6.5,0.1-8.6,0.3c-2.1,0.2-4.5,0.9-7.3,2c-2.8,1.1-5.1,2.8-7.1,5c-4,4.4-6,12.4-6,24V118H281.1z"/>
<path class="st0" d="M326.2,53.8c-6.2,7.4-9.3,17-9.3,28.9c0,10.7,3.2,19.4,9.5,26.2s14.7,10.1,25.3,10.1c8.7,0,16.3-2.7,22.7-8.1
L366,102c-3.7,2.1-8.5,3.2-14.3,3.2c-6.5,0-11.8-2.3-15.8-6.9c-4-4.6-6-10.5-6-17.9c0-7,1.9-12.9,5.6-17.9c3.8-5,8.9-7.5,15.5-7.5
c3.3,0,6.1,0.8,8.2,2.4c2.1,1.6,3.2,4,3.2,7.2c0,5-1.2,8.5-3.6,10.6c-2.4,2.1-6.7,3.2-12.9,3.2h-6.7v11.7h5.7
c20.3,0,30.5-8.5,30.5-25.4c0-13.6-7.9-20.7-23.7-21.5C340.9,43,332.4,46.5,326.2,53.8z"/>
<path class="st0" d="M412.3,73.2c-7.4,0-13.6,1.9-18.5,5.7c-4.9,3.8-7.4,9.4-7.4,16.7c0,7.3,2.3,12.9,7,16.7
c4.6,3.8,10.9,5.7,18.8,5.7h31V73.6c0-9.1-2.4-16-7.2-20.8c-4.8-4.8-11.7-7.2-20.7-7.2h-22.9v12.8h22.3c10.9,0,16.4,6.1,16.4,18.2
v28.7h-18.4c-9.1,0-13.6-3.2-13.6-9.8c0-3.3,1.2-5.9,3.6-7.8c2.4-1.8,5.8-2.7,10.2-2.7c5.1,0,9.4,1.4,12.9,4.3V75.3
C420.9,73.9,416.5,73.2,412.3,73.2z"/>
<path class="st0" d="M458.8,118H471V58.3h24.4V118h12.2V58.3h5.7c6.8,0,11.3,0.7,13.5,2c4.3,2.5,6.5,7.7,6.5,15.5V118h12.2V75.7
c0-6-0.6-11.2-1.9-15.5c-1.2-4.3-3.9-7.8-7.9-10.6c-3.9-2.7-9.1-4.1-15.7-4.1h-61.4V118z"/>
<polygon class="st1" points="75,118.5 75,35.5 96,48.5 96,118.5 "/>
<polygon class="st2" points="99,118.5 99,49.5 110.5,56.5 121,49.5 121,118.5 "/>
<polygon class="st1" points="124,118.5 124,48.5 145,35.5 145,118.5 "/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -1,156 +0,0 @@
/*!
* JavaScript Cookie v2.1.3
* https://github.com/js-cookie/js-cookie
*
* Copyright 2006, 2015 Klaus Hartl & Fagner Brack
* Released under the MIT license
*/
;(function (factory) {
var registeredInModuleLoader = false;
if (typeof define === 'function' && define.amd) {
define(factory);
registeredInModuleLoader = true;
}
if (typeof exports === 'object') {
module.exports = factory();
registeredInModuleLoader = true;
}
if (!registeredInModuleLoader) {
var OldCookies = window.Cookies;
var api = window.Cookies = factory();
api.noConflict = function () {
window.Cookies = OldCookies;
return api;
};
}
}(function () {
function extend () {
var i = 0;
var result = {};
for (; i < arguments.length; i++) {
var attributes = arguments[ i ];
for (var key in attributes) {
result[key] = attributes[key];
}
}
return result;
}
function init (converter) {
function api (key, value, attributes) {
var result;
if (typeof document === 'undefined') {
return;
}
// Write
if (arguments.length > 1) {
attributes = extend({
path: '/'
}, api.defaults, attributes);
if (typeof attributes.expires === 'number') {
var expires = new Date();
expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5);
attributes.expires = expires;
}
try {
result = JSON.stringify(value);
if (/^[\{\[]/.test(result)) {
value = result;
}
} catch (e) {}
if (!converter.write) {
value = encodeURIComponent(String(value))
.replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);
} else {
value = converter.write(value, key);
}
key = encodeURIComponent(String(key));
key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent);
key = key.replace(/[\(\)]/g, escape);
return (document.cookie = [
key, '=', value,
attributes.expires ? '; expires=' + attributes.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
attributes.path ? '; path=' + attributes.path : '',
attributes.domain ? '; domain=' + attributes.domain : '',
attributes.secure ? '; secure' : ''
].join(''));
}
// Read
if (!key) {
result = {};
}
// To prevent the for loop in the first place assign an empty array
// in case there are no cookies at all. Also prevents odd result when
// calling "get()"
var cookies = document.cookie ? document.cookie.split('; ') : [];
var rdecode = /(%[0-9A-Z]{2})+/g;
var i = 0;
for (; i < cookies.length; i++) {
var parts = cookies[i].split('=');
var cookie = parts.slice(1).join('=');
if (cookie.charAt(0) === '"') {
cookie = cookie.slice(1, -1);
}
try {
var name = parts[0].replace(rdecode, decodeURIComponent);
cookie = converter.read ?
converter.read(cookie, name) : converter(cookie, name) ||
cookie.replace(rdecode, decodeURIComponent);
if (this.json) {
try {
cookie = JSON.parse(cookie);
} catch (e) {}
}
if (key === name) {
result = cookie;
break;
}
if (!key) {
result[name] = cookie;
}
} catch (e) {}
}
return result;
}
api.set = api;
api.get = function (key) {
return api.call(api, key);
};
api.getJSON = function () {
return api.apply({
json: true
}, [].slice.call(arguments));
};
api.defaults = {};
api.remove = function (key, attributes) {
api(key, '', extend(attributes, {
expires: -1
}));
};
api.withConverter = init;
return api;
}
return init(function () {});
}));

View File

@ -1,799 +0,0 @@
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
exports.FLACDemuxer = require('./src/demuxer');
exports.FLACDecoder = require('./src/decoder');
require('./src/ogg');
},{"./src/decoder":2,"./src/demuxer":3,"./src/ogg":4}],2:[function(require,module,exports){
(function (global){
/*
* FLAC.js - Free Lossless Audio Codec decoder in JavaScript
* Original C version from FFmpeg (c) 2003 Alex Beregszaszi
* JavaScript port by Devon Govett and Jens Nockert of Official.fm Labs
*
* Licensed under the same terms as the original. The original
* license follows.
*
* FLAC.js is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FLAC.js is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
*/
var AV = (typeof window !== "undefined" ? window['AV'] : typeof global !== "undefined" ? global['AV'] : null);
var FLACDecoder = AV.Decoder.extend(function() {
AV.Decoder.register('flac', this);
this.prototype.setCookie = function(cookie) {
this.cookie = cookie;
// initialize arrays
this.decoded = [];
for (var i = 0; i < this.format.channelsPerFrame; i++) {
this.decoded[i] = new Int32Array(cookie.maxBlockSize);
}
// for 24 bit lpc frames, this is used to simulate a 64 bit int
this.lpc_total = new Int32Array(2);
};
const BLOCK_SIZES = new Int16Array([
0, 192, 576 << 0, 576 << 1, 576 << 2, 576 << 3, 0, 0,
256 << 0, 256 << 1, 256 << 2, 256 << 3, 256 << 4, 256 << 5, 256 << 6, 256 << 7
]);
const SAMPLE_RATES = new Int32Array([
0, 88200, 176400, 192000,
8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000,
0, 0, 0, 0
]);
const SAMPLE_SIZES = new Int8Array([
0, 8, 12, 0, 16, 20, 24, 0
]);
const MAX_CHANNELS = 8,
CHMODE_INDEPENDENT = 0,
CHMODE_LEFT_SIDE = 8,
CHMODE_RIGHT_SIDE = 9,
CHMODE_MID_SIDE = 10;
this.prototype.readChunk = function() {
var stream = this.bitstream;
if (!stream.available(32))
return;
// frame sync code
if ((stream.read(15) & 0x7FFF) !== 0x7FFC)
throw new Error('Invalid sync code');
var isVarSize = stream.read(1), // variable block size stream code
bsCode = stream.read(4), // block size
srCode = stream.read(4), // sample rate code
chMode = stream.read(4), // channel mode
bpsCode = stream.read(3); // bits per sample
stream.advance(1); // reserved bit
// channels
this.chMode = chMode;
var channels;
if (chMode < MAX_CHANNELS) {
channels = chMode + 1;
this.chMode = CHMODE_INDEPENDENT;
} else if (chMode <= CHMODE_MID_SIDE) {
channels = 2;
} else {
throw new Error('Invalid channel mode');
}
if (channels !== this.format.channelsPerFrame)
throw new Error('Switching channel layout mid-stream not supported.');
// bits per sample
if (bpsCode === 3 || bpsCode === 7)
throw new Error('Invalid sample size code');
this.bps = SAMPLE_SIZES[bpsCode];
if (this.bps !== this.format.bitsPerChannel)
throw new Error('Switching bits per sample mid-stream not supported.');
// sample number or frame number
// see http://www.hydrogenaudio.org/forums/index.php?s=ea7085ffe6d57132c36e6105c0d434c9&showtopic=88390&pid=754269&st=0&#entry754269
var ones = 0;
while (stream.read(1) === 1)
ones++;
var frame_or_sample_num = stream.read(7 - ones);
for (; ones > 1; ones--) {
stream.advance(2); // == 2
frame_or_sample_num = (frame_or_sample_num << 6) | stream.read(6);
}
// block size
if (bsCode === 0)
throw new Error('Reserved blocksize code');
else if (bsCode === 6)
this.blockSize = stream.read(8) + 1;
else if (bsCode === 7)
this.blockSize = stream.read(16) + 1;
else
this.blockSize = BLOCK_SIZES[bsCode];
// sample rate
var sampleRate;
if (srCode < 12)
sampleRate = SAMPLE_RATES[srCode];
else if (srCode === 12)
sampleRate = stream.read(8) * 1000;
else if (srCode === 13)
sampleRate = stream.read(16);
else if (srCode === 14)
sampleRate = stream.read(16) * 10;
else
throw new Error('Invalid sample rate code');
stream.advance(8); // skip CRC check
// subframes
for (var i = 0; i < channels; i++)
this.decodeSubframe(i);
stream.align();
stream.advance(16); // skip CRC frame footer
var is32 = this.bps > 16,
output = new ArrayBuffer(this.blockSize * channels * (is32 ? 4 : 2)),
buf = is32 ? new Int32Array(output) : new Int16Array(output),
blockSize = this.blockSize,
decoded = this.decoded,
j = 0;
switch (this.chMode) {
case CHMODE_INDEPENDENT:
for (var k = 0; k < blockSize; k++) {
for (var i = 0; i < channels; i++) {
buf[j++] = decoded[i][k];
}
}
break;
case CHMODE_LEFT_SIDE:
for (var i = 0; i < blockSize; i++) {
var left = decoded[0][i],
right = decoded[1][i];
buf[j++] = left;
buf[j++] = (left - right);
}
break;
case CHMODE_RIGHT_SIDE:
for (var i = 0; i < blockSize; i++) {
var left = decoded[0][i],
right = decoded[1][i];
buf[j++] = (left + right);
buf[j++] = right;
}
break;
case CHMODE_MID_SIDE:
for (var i = 0; i < blockSize; i++) {
var left = decoded[0][i],
right = decoded[1][i];
left -= right >> 1;
buf[j++] = (left + right);
buf[j++] = left;
}
break;
}
return buf;
};
this.prototype.decodeSubframe = function(channel) {
var wasted = 0,
stream = this.bitstream,
blockSize = this.blockSize,
decoded = this.decoded;
this.curr_bps = this.bps;
if (channel === 0) {
if (this.chMode === CHMODE_RIGHT_SIDE)
this.curr_bps++;
} else {
if (this.chMode === CHMODE_LEFT_SIDE || this.chMode === CHMODE_MID_SIDE)
this.curr_bps++;
}
if (stream.read(1))
throw new Error("Invalid subframe padding");
var type = stream.read(6);
if (stream.read(1)) {
wasted = 1;
while (!stream.read(1))
wasted++;
this.curr_bps -= wasted;
}
if (this.curr_bps > 32)
throw new Error("decorrelated bit depth > 32 (" + this.curr_bps + ")");
if (type === 0) {
var tmp = stream.read(this.curr_bps, true);
for (var i = 0; i < blockSize; i++)
decoded[channel][i] = tmp;
} else if (type === 1) {
var bps = this.curr_bps;
for (var i = 0; i < blockSize; i++)
decoded[channel][i] = stream.read(bps, true);
} else if ((type >= 8) && (type <= 12)) {
this.decode_subframe_fixed(channel, type & ~0x8);
} else if (type >= 32) {
this.decode_subframe_lpc(channel, (type & ~0x20) + 1);
} else {
throw new Error("Invalid coding type");
}
if (wasted) {
for (var i = 0; i < blockSize; i++)
decoded[channel][i] <<= wasted;
}
};
this.prototype.decode_subframe_fixed = function(channel, predictor_order) {
var decoded = this.decoded[channel],
stream = this.bitstream,
bps = this.curr_bps;
// warm up samples
for (var i = 0; i < predictor_order; i++)
decoded[i] = stream.read(bps, true);
this.decode_residuals(channel, predictor_order);
var a = 0, b = 0, c = 0, d = 0;
if (predictor_order > 0)
a = decoded[predictor_order - 1];
if (predictor_order > 1)
b = a - decoded[predictor_order - 2];
if (predictor_order > 2)
c = b - decoded[predictor_order - 2] + decoded[predictor_order - 3];
if (predictor_order > 3)
d = c - decoded[predictor_order - 2] + 2 * decoded[predictor_order - 3] - decoded[predictor_order - 4];
switch (predictor_order) {
case 0:
break;
case 1:
case 2:
case 3:
case 4:
var abcd = new Int32Array([a, b, c, d]),
blockSize = this.blockSize;
for (var i = predictor_order; i < blockSize; i++) {
abcd[predictor_order - 1] += decoded[i];
for (var j = predictor_order - 2; j >= 0; j--) {
abcd[j] += abcd[j + 1];
}
decoded[i] = abcd[0];
}
break;
default:
throw new Error("Invalid Predictor Order " + predictor_order);
}
};
this.prototype.decode_subframe_lpc = function(channel, predictor_order) {
var stream = this.bitstream,
decoded = this.decoded[channel],
bps = this.curr_bps,
blockSize = this.blockSize;
// warm up samples
for (var i = 0; i < predictor_order; i++) {
decoded[i] = stream.read(bps, true);
}
var coeff_prec = stream.read(4) + 1;
if (coeff_prec === 16)
throw new Error("Invalid coefficient precision");
var qlevel = stream.read(5, true);
if (qlevel < 0)
throw new Error("Negative qlevel, maybe buggy stream");
var coeffs = new Int32Array(32);
for (var i = 0; i < predictor_order; i++) {
coeffs[i] = stream.read(coeff_prec, true);
}
this.decode_residuals(channel, predictor_order);
if (this.bps <= 16) {
for (var i = predictor_order; i < blockSize - 1; i += 2) {
var d = decoded[i - predictor_order],
s0 = 0, s1 = 0, c = 0;
for (var j = predictor_order - 1; j > 0; j--) {
c = coeffs[j];
s0 += c * d;
d = decoded[i - j];
s1 += c * d;
}
c = coeffs[0];
s0 += c * d;
d = decoded[i] += (s0 >> qlevel);
s1 += c * d;
decoded[i + 1] += (s1 >> qlevel);
}
if (i < blockSize) {
var sum = 0;
for (var j = 0; j < predictor_order; j++)
sum += coeffs[j] * decoded[i - j - 1];
decoded[i] += (sum >> qlevel);
}
} else {
// simulate 64 bit integer using an array of two 32 bit ints
var total = this.lpc_total;
for (var i = predictor_order; i < blockSize; i++) {
// reset total to 0
total[0] = 0;
total[1] = 0;
for (j = 0; j < predictor_order; j++) {
// simulate `total += coeffs[j] * decoded[i - j - 1]`
multiply_add(total, coeffs[j], decoded[i - j - 1]);
}
// simulate `decoded[i] += total >> qlevel`
// we know that qlevel < 32 since it is a 5 bit field (see above)
decoded[i] += (total[0] >>> qlevel) | (total[1] << (32 - qlevel));
}
}
};
const TWO_PWR_32_DBL = Math.pow(2, 32);
// performs `total += a * b` on a simulated 64 bit int
// total is an Int32Array(2)
// a and b are JS numbers (32 bit ints)
function multiply_add(total, a, b) {
// multiply a * b (we can use normal JS multiplication for this)
var r = a * b;
var n = r < 0;
if (n)
r = -r;
var r_low = (r % TWO_PWR_32_DBL) | 0;
var r_high = (r / TWO_PWR_32_DBL) | 0;
if (n) {
r_low = ~r_low + 1;
r_high = ~r_high;
}
// add result to total
var a48 = total[1] >>> 16;
var a32 = total[1] & 0xFFFF;
var a16 = total[0] >>> 16;
var a00 = total[0] & 0xFFFF;
var b48 = r_high >>> 16;
var b32 = r_high & 0xFFFF;
var b16 = r_low >>> 16;
var b00 = r_low & 0xFFFF;
var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
c00 += a00 + b00;
c16 += c00 >>> 16;
c00 &= 0xFFFF;
c16 += a16 + b16;
c32 += c16 >>> 16;
c16 &= 0xFFFF;
c32 += a32 + b32;
c48 += c32 >>> 16;
c32 &= 0xFFFF;
c48 += a48 + b48;
c48 &= 0xFFFF;
// store result back in total
total[0] = (c16 << 16) | c00;
total[1] = (c48 << 16) | c32;
}
const INT_MAX = 32767;
this.prototype.decode_residuals = function(channel, predictor_order) {
var stream = this.bitstream,
method_type = stream.read(2);
if (method_type > 1)
throw new Error('Illegal residual coding method ' + method_type);
var rice_order = stream.read(4),
samples = (this.blockSize >>> rice_order);
if (predictor_order > samples)
throw new Error('Invalid predictor order ' + predictor_order + ' > ' + samples);
var decoded = this.decoded[channel],
sample = predictor_order,
i = predictor_order;
for (var partition = 0; partition < (1 << rice_order); partition++) {
var tmp = stream.read(method_type === 0 ? 4 : 5);
if (tmp === (method_type === 0 ? 15 : 31)) {
tmp = stream.read(5);
for (; i < samples; i++)
decoded[sample++] = stream.read(tmp, true);
} else {
for (; i < samples; i++)
decoded[sample++] = this.golomb(tmp, INT_MAX, 0);
}
i = 0;
}
};
const MIN_CACHE_BITS = 25;
this.prototype.golomb = function(k, limit, esc_len) {
var data = this.bitstream,
offset = data.bitPosition,
buf = data.peek(32 - offset) << offset,
v = 0;
var log = 31 - clz(buf | 1); // log2(buf)
if (log - k >= 32 - MIN_CACHE_BITS && 32 - log < limit) {
buf >>>= log - k;
buf += (30 - log) << k;
data.advance(32 + k - log);
v = buf;
} else {
for (var i = 0; data.read(1) === 0; i++)
buf = data.peek(32 - offset) << offset;
if (i < limit - 1) {
if (k)
buf = data.read(k);
else
buf = 0;
v = buf + (i << k);
} else if (i === limit - 1) {
buf = data.read(esc_len);
v = buf + 1;
} else {
v = -1;
}
}
return (v >> 1) ^ -(v & 1);
};
// Should be in the damned standard library...
function clz(input) {
var output = 0,
curbyte = 0;
while(true) { // emulate goto in JS using the break statement :D
curbyte = input >>> 24;
if (curbyte) break;
output += 8;
curbyte = input >>> 16;
if (curbyte & 0xff) break;
output += 8;
curbyte = input >>> 8;
if (curbyte & 0xff) break;
output += 8;
curbyte = input;
if (curbyte & 0xff) break;
output += 8;
return output;
}
if (!(curbyte & 0xf0))
output += 4;
else
curbyte >>>= 4;
if (curbyte & 0x8)
return output;
if (curbyte & 0x4)
return output + 1;
if (curbyte & 0x2)
return output + 2;
if (curbyte & 0x1)
return output + 3;
// shouldn't get here
return output + 4;
}
});
module.exports = FLACDecoder;
}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],3:[function(require,module,exports){
(function (global){
/*
* FLAC.js - Free Lossless Audio Codec decoder in JavaScript
* By Devon Govett and Jens Nockert of Official.fm Labs
*
* FLAC.js is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FLAC.js is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
*/
var AV = (typeof window !== "undefined" ? window['AV'] : typeof global !== "undefined" ? global['AV'] : null);
var FLACDemuxer = AV.Demuxer.extend(function() {
AV.Demuxer.register(this);
this.probe = function(buffer) {
return buffer.peekString(0, 4) === 'fLaC';
}
const STREAMINFO = 0,
PADDING = 1,
APPLICATION = 2,
SEEKTABLE = 3,
VORBIS_COMMENT = 4,
CUESHEET = 5,
PICTURE = 6,
INVALID = 127,
STREAMINFO_SIZE = 34;
this.prototype.readChunk = function() {
var stream = this.stream;
if (!this.readHeader && stream.available(4)) {
if (stream.readString(4) !== 'fLaC')
return this.emit('error', 'Invalid FLAC file.');
this.readHeader = true;
}
while (stream.available(1) && !this.last) {
if (!this.readBlockHeaders) {
var tmp = stream.readUInt8();
this.last = (tmp & 0x80) === 0x80,
this.type = tmp & 0x7F,
this.size = stream.readUInt24();
}
if (!this.foundStreamInfo && this.type !== STREAMINFO)
return this.emit('error', 'STREAMINFO must be the first block');
if (!stream.available(this.size))
return;
switch (this.type) {
case STREAMINFO:
if (this.foundStreamInfo)
return this.emit('error', 'STREAMINFO can only occur once.');
if (this.size !== STREAMINFO_SIZE)
return this.emit('error', 'STREAMINFO size is wrong.');
this.foundStreamInfo = true;
var bitstream = new AV.Bitstream(stream);
var cookie = {
minBlockSize: bitstream.read(16),
maxBlockSize: bitstream.read(16),
minFrameSize: bitstream.read(24),
maxFrameSize: bitstream.read(24)
};
this.format = {
formatID: 'flac',
sampleRate: bitstream.read(20),
channelsPerFrame: bitstream.read(3) + 1,
bitsPerChannel: bitstream.read(5) + 1
};
this.emit('format', this.format);
this.emit('cookie', cookie);
var sampleCount = bitstream.read(36);
this.emit('duration', sampleCount / this.format.sampleRate * 1000 | 0);
stream.advance(16); // skip MD5 hashes
this.readBlockHeaders = false;
break;
/*
I am only looking at the least significant 32 bits of sample number and offset data
This is more than sufficient for the longest flac file I have (~50 mins 2-channel 16-bit 44.1k which uses about 7.5% of the UInt32 space for the largest offset)
Can certainly be improved by storing sample numbers and offests as doubles, but would require additional overriding of the searchTimestamp and seek functions (possibly more?)
Also the flac faq suggests it would be possible to find frame lengths and thus create seek points on the fly via decoding but I assume this would be slow
I may look into these thigns though as my project progresses
*/
case SEEKTABLE:
for(var s=0; s<this.size/18; s++)
{
if(stream.peekUInt32(0) == 0xFFFFFFFF && stream.peekUInt32(1) == 0xFFFFFFFF)
{
//placeholder, ignore
stream.advance(18);
} else {
if(stream.readUInt32() > 0)
{
this.emit('error', 'Seek points with sample number >UInt32 not supported');
}
var samplenum = stream.readUInt32();
if(stream.readUInt32() > 0)
{
this.emit('error', 'Seek points with stream offset >UInt32 not supported');
}
var offset = stream.readUInt32();
stream.advance(2);
this.addSeekPoint(offset, samplenum);
}
}
break;
case VORBIS_COMMENT:
// see http://www.xiph.org/vorbis/doc/v-comment.html
this.metadata || (this.metadata = {});
var len = stream.readUInt32(true);
this.metadata.vendor = stream.readString(len);
var length = stream.readUInt32(true);
for (var i = 0; i < length; i++) {
len = stream.readUInt32(true);
var str = stream.readString(len, 'utf8'),
idx = str.indexOf('=');
this.metadata[str.slice(0, idx).toLowerCase()] = str.slice(idx + 1);
}
// TODO: standardize field names across formats
break;
case PICTURE:
var type = stream.readUInt32();
if (type !== 3) { // make sure this is album art (type 3)
stream.advance(this.size - 4);
} else {
var mimeLen = stream.readUInt32(),
mime = stream.readString(mimeLen),
descLen = stream.readUInt32(),
description = stream.readString(descLen),
width = stream.readUInt32(),
height = stream.readUInt32(),
depth = stream.readUInt32(),
colors = stream.readUInt32(),
length = stream.readUInt32(),
picture = stream.readBuffer(length);
this.metadata || (this.metadata = {});
this.metadata.coverArt = picture;
}
// does anyone want the rest of the info?
break;
default:
stream.advance(this.size);
this.readBlockHeaders = false;
}
if (this.last && this.metadata)
this.emit('metadata', this.metadata);
}
while (stream.available(1) && this.last) {
var buffer = stream.readSingleBuffer(stream.remainingBytes());
this.emit('data', buffer);
}
}
});
module.exports = FLACDemuxer;
}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],4:[function(require,module,exports){
(function (global){
var AV = (typeof window !== "undefined" ? window['AV'] : typeof global !== "undefined" ? global['AV'] : null);
// if ogg.js exists, register a plugin
try {
var OggDemuxer = (typeof window !== "undefined" ? window['AV']['OggDemuxer'] : typeof global !== "undefined" ? global['AV']['OggDemuxer'] : null);
} catch (e) {};
if (!OggDemuxer) return;
OggDemuxer.plugins.push({
magic: "\177FLAC",
init: function() {
this.list = new AV.BufferList();
this.stream = new AV.Stream(this.list);
},
readHeaders: function(packet) {
var stream = this.stream;
this.list.append(new AV.Buffer(packet));
stream.advance(5); // magic
if (stream.readUInt8() != 1)
throw new Error('Unsupported FLAC version');
stream.advance(3);
if (stream.peekString(0, 4) != 'fLaC')
throw new Error('Not flac');
this.flac = AV.Demuxer.find(stream.peekSingleBuffer(0, stream.remainingBytes()));
if (!this.flac)
throw new Error('Flac demuxer not found');
this.flac.prototype.readChunk.call(this);
return true;
},
readPacket: function(packet) {
this.list.append(new AV.Buffer(packet));
this.flac.prototype.readChunk.call(this);
}
});
}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}]},{},[1])
//# sourceMappingURL=flac.js.map

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -1,326 +0,0 @@
'use strict';
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
(function () {
"use strict";
function buildDraggable(Sortable) {
function removeNode(node) {
node.parentElement.removeChild(node);
}
function insertNodeAt(fatherNode, node, position) {
if (position < fatherNode.children.length) {
fatherNode.insertBefore(node, fatherNode.children[position]);
} else {
fatherNode.appendChild(node);
}
}
function computeVmIndex(vnodes, element) {
return vnodes.map(function (elt) {
return elt.elm;
}).indexOf(element);
}
function _computeIndexes(slots, children) {
if (!slots) {
return [];
}
var elmFromNodes = slots.map(function (elt) {
return elt.elm;
});
return [].concat(_toConsumableArray(children)).map(function (elt) {
return elmFromNodes.indexOf(elt);
});
}
function emit(evtName, evtData) {
var _this = this;
this.$nextTick(function () {
return _this.$emit(evtName.toLowerCase(), evtData);
});
}
function delegateAndEmit(evtName) {
var _this2 = this;
return function (evtData) {
if (_this2.realList !== null) {
_this2['onDrag' + evtName](evtData);
}
emit.call(_this2, evtName, evtData);
};
}
var eventsListened = ['Start', 'Add', 'Remove', 'Update', 'End'];
var eventsToEmit = ['Choose', 'Sort', 'Filter', 'Clone'];
var readonlyProperties = ['Move'].concat(eventsListened, eventsToEmit).map(function (evt) {
return 'on' + evt;
});
var draggingElement = null;
var props = {
options: Object,
list: {
type: Array,
required: false,
default: null
},
value: {
type: Array,
required: false,
default: null
},
clone: {
type: Function,
default: function _default(original) {
return original;
}
},
element: {
type: String,
default: 'div'
},
move: {
type: Function,
default: null
}
};
var draggableComponent = {
props: props,
data: function data() {
return {
transitionMode: false,
componentMode: false
};
},
render: function render(h) {
if (this.$slots.default && this.$slots.default.length === 1) {
var child = this.$slots.default[0];
if (child.componentOptions && child.componentOptions.tag === "transition-group") {
this.transitionMode = true;
}
}
return h(this.element, null, this.$slots.default);
},
mounted: function mounted() {
var _this3 = this;
this.componentMode = this.element.toLowerCase() !== this.$el.nodeName.toLowerCase();
if (this.componentMode && this.transitionMode) {
throw new Error('Transition-group inside component is not suppported. Please alter element value or remove transition-group. Current element value: ' + this.element);
}
var optionsAdded = {};
eventsListened.forEach(function (elt) {
optionsAdded['on' + elt] = delegateAndEmit.call(_this3, elt);
});
eventsToEmit.forEach(function (elt) {
optionsAdded['on' + elt] = emit.bind(_this3, elt);
});
var options = _extends({}, this.options, optionsAdded, { onMove: function onMove(evt) {
return _this3.onDragMove(evt);
} });
this._sortable = new Sortable(this.rootContainer, options);
this.computeIndexes();
},
beforeDestroy: function beforeDestroy() {
this._sortable.destroy();
},
computed: {
rootContainer: function rootContainer() {
return this.transitionMode ? this.$el.children[0] : this.$el;
},
isCloning: function isCloning() {
return !!this.options && !!this.options.group && this.options.group.pull === 'clone';
},
realList: function realList() {
return !!this.list ? this.list : this.value;
}
},
watch: {
options: function options(newOptionValue) {
for (var property in newOptionValue) {
if (readonlyProperties.indexOf(property) == -1) {
this._sortable.option(property, newOptionValue[property]);
}
}
},
realList: function realList() {
this.computeIndexes();
}
},
methods: {
getChildrenNodes: function getChildrenNodes() {
if (this.componentMode) {
return this.$children[0].$slots.default;
}
var rawNodes = this.$slots.default;
return this.transitionMode ? rawNodes[0].child.$slots.default : rawNodes;
},
computeIndexes: function computeIndexes() {
var _this4 = this;
this.$nextTick(function () {
_this4.visibleIndexes = _computeIndexes(_this4.getChildrenNodes(), _this4.rootContainer.children);
});
},
getUnderlyingVm: function getUnderlyingVm(htmlElt) {
var index = computeVmIndex(this.getChildrenNodes(), htmlElt);
var element = this.realList[index];
return { index: index, element: element };
},
getUnderlyingPotencialDraggableComponent: function getUnderlyingPotencialDraggableComponent(_ref) {
var __vue__ = _ref.__vue__;
if (!__vue__ || !__vue__.$options || __vue__.$options._componentTag !== "transition-group") {
return __vue__;
}
return __vue__.$parent;
},
emitChanges: function emitChanges(evt) {
var _this5 = this;
this.$nextTick(function () {
_this5.$emit('change', evt);
});
},
alterList: function alterList(onList) {
if (!!this.list) {
onList(this.list);
} else {
var newList = [].concat(_toConsumableArray(this.value));
onList(newList);
this.$emit('input', newList);
}
},
spliceList: function spliceList() {
var _arguments = arguments;
var spliceList = function spliceList(list) {
return list.splice.apply(list, _arguments);
};
this.alterList(spliceList);
},
updatePosition: function updatePosition(oldIndex, newIndex) {
var updatePosition = function updatePosition(list) {
return list.splice(newIndex, 0, list.splice(oldIndex, 1)[0]);
};
this.alterList(updatePosition);
},
getRelatedContextFromMoveEvent: function getRelatedContextFromMoveEvent(_ref2) {
var to = _ref2.to,
related = _ref2.related;
var component = this.getUnderlyingPotencialDraggableComponent(to);
if (!component) {
return { component: component };
}
var list = component.realList;
var context = { list: list, component: component };
if (to !== related && list && component.getUnderlyingVm) {
var destination = component.getUnderlyingVm(related);
return _extends(destination, context);
}
return context;
},
getVmIndex: function getVmIndex(domIndex) {
var indexes = this.visibleIndexes;
var numberIndexes = indexes.length;
return domIndex > numberIndexes - 1 ? numberIndexes : indexes[domIndex];
},
onDragStart: function onDragStart(evt) {
this.context = this.getUnderlyingVm(evt.item);
evt.item._underlying_vm_ = this.clone(this.context.element);
draggingElement = evt.item;
},
onDragAdd: function onDragAdd(evt) {
var element = evt.item._underlying_vm_;
if (element === undefined) {
return;
}
removeNode(evt.item);
var newIndex = this.getVmIndex(evt.newIndex);
this.spliceList(newIndex, 0, element);
this.computeIndexes();
var added = { element: element, newIndex: newIndex };
this.emitChanges({ added: added });
},
onDragRemove: function onDragRemove(evt) {
insertNodeAt(this.rootContainer, evt.item, evt.oldIndex);
if (this.isCloning) {
removeNode(evt.clone);
return;
}
var oldIndex = this.context.index;
this.spliceList(oldIndex, 1);
var removed = { element: this.context.element, oldIndex: oldIndex };
this.emitChanges({ removed: removed });
},
onDragUpdate: function onDragUpdate(evt) {
removeNode(evt.item);
insertNodeAt(evt.from, evt.item, evt.oldIndex);
var oldIndex = this.context.index;
var newIndex = this.getVmIndex(evt.newIndex);
this.updatePosition(oldIndex, newIndex);
var moved = { element: this.context.element, oldIndex: oldIndex, newIndex: newIndex };
this.emitChanges({ moved: moved });
},
computeFutureIndex: function computeFutureIndex(relatedContext, evt) {
if (!relatedContext.element) {
return 0;
}
var domChildren = [].concat(_toConsumableArray(evt.to.children));
var currentDOMIndex = domChildren.indexOf(evt.related);
var currentIndex = relatedContext.component.getVmIndex(currentDOMIndex);
var draggedInList = domChildren.indexOf(draggingElement) != -1;
return draggedInList ? currentIndex : currentIndex + 1;
},
onDragMove: function onDragMove(evt) {
var onMove = this.move;
if (!onMove || !this.realList) {
return true;
}
var relatedContext = this.getRelatedContextFromMoveEvent(evt);
var draggedContext = this.context;
var futureIndex = this.computeFutureIndex(relatedContext, evt);
_extends(draggedContext, { futureIndex: futureIndex });
_extends(evt, { relatedContext: relatedContext, draggedContext: draggedContext });
return onMove(evt);
},
onDragEnd: function onDragEnd(evt) {
this.computeIndexes();
draggingElement = null;
}
}
};
return draggableComponent;
}
if (typeof exports == "object") {
var Sortable = require("sortablejs");
module.exports = buildDraggable(Sortable);
} else if (typeof define == "function" && define.amd) {
define(['sortablejs'], function (Sortable) {
return buildDraggable(Sortable);
});
} else if (window && window.Vue && window.Sortable) {
var draggable = buildDraggable(window.Sortable);
Vue.component('draggable', draggable);
}
})();

View File

@ -1,180 +0,0 @@
// TODO: MOVE THIS ALL TO PROMISES
var MSTREAMAPI = (function () {
let mstreamModule = {};
mstreamModule.listOfServers = [];
mstreamModule.currentServer = {
host:"",
username:"",
token: "",
vPath: ""
}
$.ajaxPrefilter(function( options ) {
options.beforeSend = function (xhr) {
xhr.setRequestHeader('x-access-token', MSTREAMAPI.currentServer.token);
}
});
// TODO: Special functions for handling multiple servers
// Add Server
// Delete Server
// Select Server
// Edit Server
// Test Sever
// Login server and save credentials
function makeRequest(url, type, dataObject, callback){
var request = $.ajax({
url: url,
type: type,
contentType: "application/json",
dataType: "json",
data: JSON.stringify(dataObject)
});
request.done(function( response ) {
callback(response, false);
});
// TODO: AHandle errors
request.fail(function( jqXHR, textStatus ) {
callback(textStatus, jqXHR);
});
}
function makePOSTRequest(url, dataObject, callback){
makeRequest(url, "POST", dataObject, callback);
}
function makeGETRequest(url, dataObject, callback){
makeRequest(url, "GET", dataObject, callback);
}
mstreamModule.dirparser = function(directory, filetypes, callback){
makePOSTRequest('/dirparser', {dir: directory}, callback);
}
mstreamModule.savePlaylist = function(title, songs, callback){
makePOSTRequest('/playlist/save', { title: title, songs: songs }, callback);
}
mstreamModule.deletePlaylist = function(playlistname, callback){
makePOSTRequest('/playlist/delete', {playlistname: playlistname}, callback);
}
mstreamModule.loadPlaylist = function(playlistname, callback){
makePOSTRequest('/playlist/load', {playlistname: playlistname}, callback);
}
mstreamModule.getAllPlaylists = function(callback){
makeGETRequest('/playlist/getall', false, callback);
}
mstreamModule.search = function(searchTerm, callback){
makePOSTRequest('/db/search', {search: searchTerm}, callback);
}
mstreamModule.artists = function(callback){
makeGETRequest('/db/artists', false, callback);
}
mstreamModule.albums = function(callback){
makeGETRequest('/db/albums', false, callback);
}
mstreamModule.artistAlbums = function(artist, callback){
makePOSTRequest("/db/artists-albums", {artist: artist}, callback);
}
mstreamModule.albumSongs = function(album, callback){
makePOSTRequest("/db/album-songs", {album: album}, callback);
}
mstreamModule.dbStatus = function(callback){
makeGETRequest("/db/status", false, callback);
}
mstreamModule.dbScan = function(callback){
makeGETRequest("/db/recursive-scan", false, callback);
}
mstreamModule.makeShared = function(playlist, shareTimeInDays, callback){
makePOSTRequest("/shared/make-shared", { time: shareTimeInDays, playlist: playlist}, callback);
}
mstreamModule.lookupMetadata = function(filepath, callback){
makePOSTRequest("/db/metadata", {filepath: filepath}, callback);
}
// LOGIN
mstreamModule.login = function(username, password, callback){
makePOSTRequest("/login", { username: username, password: password}, callback);
}
mstreamModule.updateCurrentServer = function(username, token, vPath){
mstreamModule.currentServer.user = username;
mstreamModule.currentServer.token = token;
mstreamModule.currentServer.vPath = vPath;
}
mstreamModule.ping = function(callback){
makeGETRequest("/ping", false, callback);
}
// Special helper function
// TODO: handle metadata
MSTREAMPLAYER.addSongWizard = function(filepath, metadata, lookupMetadata){
var url = mstreamModule.currentServer.host + filepath;
if(mstreamModule.currentServer.vPath){
url = mstreamModule.currentServer.vPath + '/' + url;
}
if(mstreamModule.currentServer.token){
url = url + '?token=' + mstreamModule.currentServer.token;
}
var newSong = {
url: url,
filepath: filepath,
metadata: metadata
};
MSTREAMPLAYER.addSong(newSong);
// perform lookup
if(lookupMetadata === true){
mstreamModule.lookupMetadata(filepath, function(response, error){
if(error !== false){
return;
}
console.log(response);
if(response.metadata){
newSong.metadata = Object.create(response.metadata);
MSTREAMPLAYER.resetCurrentMetadata();
}
});
}
}
return mstreamModule;
}());

View File

@ -1,293 +0,0 @@
var MSTREAMGEN = (function () {
let mstreamModule = {};
// TODO: Functions to change current server and save servers
// Not needed until express port
mstreamModule.currentProperties = {
currentList: false
// Can be anything in the title array
}
var currentListTypes = {
'filebrowser': {displayName: 'File Browser'},
'albums': {displayName: 'Albums'},
'artists': {displayName: 'Artists'},
'search': {displayName: 'Search'},
'playlists': {displayname: 'Playlists'}
};
mstreamModule.dataList = [];
// TODO: Modify prototype functions for dataList to verify all items
// dataItem = {
// type: '',
// data:'',
//}
function clearAndSetDataList(type){
if(!(type in currentListTypes) || type !== false){
// TODO: Throw Error
}
mstreamModule.currentProperties.currentList = type;
// Loop through and pop so Vue doesn't throw a fit
while(mstreamModule.dataList.length > 0){
mstreamModule.dataList.pop();
}
}
mstreamModule.clearDataList = function(){
clearAndSetDataList(false);
}
// TODO: TURN THIS INTO MAP
mstreamModule.fileExplorerArray = [
{name:'/', position:0}
];
function getDirectoryContents(){
// Construct the directory string
var directoryString = "";
for (var i = 0; i < mstreamModule.fileExplorerArray.length; i++) {
// Ignore root directory
if(mstreamModule.fileExplorerArray[i].name !== '/'){
directoryString += mstreamModule.fileExplorerArray[i].name + "/";
}
}
MSTREAMAPI.dirparser(directoryString, false, function(response, error){
if(error !== false){
boilerplateFailure(response, error);
}
clearAndSetDataList('filebrowser');
$.each(response.contents, function() {
mstreamModule.dataList.push(
{
type: (this.type === 'directory' ? "directory" : "file"),
metadata: {}, // TODO: Move all metadata to here
path: response.path + this.name,
name: this.name,
artist: false, // TODO:
title: false // TODO:
}
);
});
});
}
mstreamModule.getCurrentDirectoryContents = function(){
getDirectoryContents();
}
mstreamModule.goToNextDirectory = function(folder, currentScrollPosition = 0){
if(currentScrollPosition != 0 ){
// TODO: Save Scroll Position
}
mstreamModule.fileExplorerArray.push({name:folder, position:0});
getDirectoryContents();
}
mstreamModule.goBackDirectory = function(){
// Make sure it's not the root directory
// TODO: TEST THAT THIS ALL WORKS
if(mstreamModule.dataList[mstreamModule.dataList.length-1].name === '/'){
return false;
}
mstreamModule.fileExplorerArray.pop();
getDirectoryContents();
// TODO: Return Current Scroll Position
}
mstreamModule.getCurrentScrollPosition = function(){
return mstreamModule.dataList[mstreamModule.dataList.length-1].position;
}
// TODO:
mstreamModule.goToExactDirectory = function(directory){
// Clear Out fileExplorerArray
// loop and pop
// Setup new fileExplorerArray
// splice
// loop
getDirectoryContents();
}
// TODO Move this to a secondary module that's initiated when it's assured the MSTREAM module is looded
mstreamModule.savePlaylist = function(saveThis){
// TODO: Verify all data in saveThis
if(saveThis.length == 0){
return;
}
// Get playlist from MSTREAM
// var playlist = MSTREAMPLAYER.whatever
// Get user entered title
// var title = '';
// Check for special characters
if(/^[a-zA-Z0-9-_ ]*$/.test(title) == false) {
// TODO: Warn User
return false;
}
// loop through array and add each file to the playlist
// $.each( playlistArray, function() {
// // TODO:
// });
$.ajax({
type: "POST",
url: "saveplaylist",
contentType: "application/json",
dataType: "json",
data: {
title:title,
stuff:saveThis // TODO: Change this on server end
},
})
.done(function( msg ) {
if(msg == 1){
// ???
}
if(msg == 0){
// .. ???
}
});
// TODO: error handeling
}
mstreamModule.getAllPlaylists = function(){
var request = $.ajax({
url: "getallplaylists",
type: "GET"
});
request.done(function( msg ) {
clearAndSetDataList('playlists');
var parsedResponse = $.parseJSON(msg);
//parse through the json array and make an array of corresponding divs
var playlists = [];
$.each(parsedResponse, function() {
mstreamModule.dataList.push(
{
type: 'playlist',
name: this.name
}
);
});
});
request.fail(function( jqXHR, textStatus ) {
// TODO:
});
}
mstreamModule.deletePlaylist = function(playlistNameString){
}
mstreamModule.getPlaylistContents = function(playlistNameString){
// Make an AJAX call to get the contents of the playlist
$.ajax({
type: "GET",
url: "loadplaylist",
data: {playlistname: playlistNameString},
dataType: 'json',
})
.done(function( msg ) {
// Add the playlist name to the modal
// Clear the playlist
// Append the playlist items to the playlist
$.each( msg, function(i ,item) {
});
});
}
// TODO:
function boilerplateFailure(response, error){
return;
}
mstreamModule.getSharedPlaylist = function(){
// Get the URL parameters
console.log(window.location.pathname);
// Call the api with the the short token
// Add songs to MSTREAM
}
// Return an object that is assigned to Module
return mstreamModule;
}());

View File

@ -1,673 +0,0 @@
$(document).ready(function(){
// Auto Focus
Vue.directive('focus', {
// When the bound element is inserted into the DOM...
inserted: function (el) {
// Focus the element
el.focus()
}
});
var loginPanel = new Vue({
el: '#login-overlay',
data: {
needToLogin: false,
error: false,
errorMessage: 'Login Failed',
pending: false
},
methods: {
submitCode: function(e){
// Get Code
this.pending = true;
var that = this;
MSTREAMAPI.login($('#login-username').val(), $('#login-password').val(), function(response, error){
if(error !== false){
// Alert the user
that.pending = false;
that.error = true;
return;
}
// Eye-candy: change the error color and essage
$('#login-alert').toggleClass('alert');
$('#login-alert').toggleClass('success');
that.errorMessage = "Welcome To mStream!";
// Add the token to the cookies
Cookies.set('token', response.token);
// Add the token the URL calls
MSTREAMAPI.updateCurrentServer($('#login-username').val(), response.token, response.vPath)
loadFileExplorer();
// MSTREAMGEN.getCurrentDirectoryContents();
// Remove the overlay
$('.login-overlay').fadeOut( "slow" );
that.pending = false;
that.needToLogin = false;
});
}
}
});
function testIt(token){
if(token){
MSTREAMAPI.currentServer.token = token;
}
MSTREAMAPI.ping( function(response, error){
if(error !== false){
// NOTE: There needs to be a split here
// For the webapp we simply display the login panel
loginPanel.needToLogin = true;
// TODO: Move this transitionstuff to vue
$('.login-overlay').fadeIn( "slow" );
console.log(loginPanel);
// For electron we need to alert the user that user it failed and guide them to the login form
return;
}
// set vPath
MSTREAMAPI.currentServer.vPath = response.vPath;
// Setup the filebrowser
loadFileExplorer();
});
}
// NOTE: There needs to be a split here
// For the normal webap we just get the token
// var token = Cookies.get('token');
testIt(Cookies.get('token'));
// For electron we need to pull it from wherever electron stores things
////////////////////////////// Global Variables
// These vars track your position within the file explorer
var fileExplorerArray = [];
var fileExplorerScrollPosition = [];
// Stores an array of searchable ojects
var currentBrowsingList = [];
//////////////////////////////// Administrative stuff
// when you click an mp3, add it to the now playling playlist
$("#filelist").on('click', 'div.filez', function() {
MSTREAMPLAYER.addSongWizard($(this).data("file_location"), {}, true);
});
// Handle panel stuff
function resetPanel(panelName, className){
$('#filelist').empty();
$('.directoryTitle').hide();
$('#filelist').removeClass('scrollBoxHeight1');
$('#filelist').removeClass('scrollBoxHeight2');
$('#filelist').addClass(className);
$('.panel_one_name').html(panelName);
}
function boilerplateFailure(response, error){
$('#filelist').empty();
$('#filelist').html('<p>Call Failed</p>');
}
// clear the playlist
$("#clear").on('click', function() {
MSTREAMPLAYER.clearPlaylist();
});
/////////////////////////////////////// File Explorer
function loadFileExplorer(){
resetPanel('File Explorer', 'scrollBoxHeight1');
$('#directory_bar').show();
// Reset file explorer vars
fileExplorerArray = [];
fileExplorerScrollPosition = [];
//send this directory to be parsed and displayed
senddir(0);
}
// Load up the file explorer
$('.get_file_explorer').on('click', loadFileExplorer);
// when you click on a directory, go to that directory
$("#filelist").on('click', 'div.dirz', function() {
//get the id of that class
var nextDir = $(this).attr("id");
fileExplorerArray.push(nextDir);
// Save the scroll position
var scrollPosition = $('#filelist').scrollTop();
fileExplorerScrollPosition.push(scrollPosition);
// pass this value along
senddir(0);
});
// when you click the back directory
$(".backButton").on('click', function() {
if(fileExplorerArray.length != 0){
// remove the last item in the array
fileExplorerArray.pop();
// Get the scroll postion
var scrollPosition = fileExplorerScrollPosition.pop();
senddir(scrollPosition);
}
});
// send a new directory to be parsed.
function senddir(scrollPosition){
// Construct the directory string
var directoryString = "";
for (var i = 0; i < fileExplorerArray.length; i++) {
directoryString += fileExplorerArray[i] + "/";
}
MSTREAMAPI.dirparser(directoryString, false, function(response, error){
if(error !== false){
boilerplateFailure(response, error);
}
// Set any directory views
$('.directoryName').html('/' + directoryString);
// hand this data off to be printed on the page
printdir(response);
// Set scroll postion
$('#filelist').scrollTop(scrollPosition);
});
}
// function that will recieve JSON array of a directory listing. It will then make a list of the directory and tack on classes for functionality
function printdir(response){
currentBrowsingList = response.contents;
// clear the list
$('#filelist').empty();
$('#search_folders').val('');
// TODO: create an object of everything that the user can easily sort through
var searchObject = [];
//parse through the json array and make an array of corresponding divs
var filelist = [];
$.each(currentBrowsingList, function() {
if(this.type=='directory'){
filelist.push('<div id="'+this.name+'" class="dirz">'+this.name+'</div>');
}else{
if(this.artist!=null || this.title!=null){
filelist.push('<div data-filetype="'+this.type+'" data-file_location="'+response.path+this.name+'" class="filez"><span class="pre-char">&#9836;</span> <span class="title">'+this.artist+' - '+this.title+'</span></div>');
}else{
filelist.push('<div data-filetype="'+this.type+'" data-file_location="'+response.path+this.name+'" class="filez"><span class="pre-char">&#9835;</span> <span class="title">'+this.name+'</span></div>');
}
}
});
// Post the html to the filelist div
$('#filelist').html(filelist);
}
// when you click 'add directory', add entire directory to the playlist
$("#addall").on('click', function() {
//make an array of all the mp3 files in the curent directory
var elems = document.getElementsByClassName('filez');
var arr = jQuery.makeArray(elems);
//loop through array and add each file to the playlist
$.each( arr, function() {
MSTREAMPLAYER.addSongWizard($(this).data("file_location"), {}, true);
});
});
// Search Files
$('#search_folders').on('keyup', function(){
if($(this).val().length>1){
var searchVal = $(this).val();
var path = ""; // Construct the directory string
for (var i = 0; i < fileExplorerArray.length; i++) {
path += fileExplorerArray[i] + "/";
}
var filelist = [];
$.each(currentBrowsingList, function() {
var lowerCase = this.name.toLowerCase();
if (lowerCase.indexOf( searchVal.toLowerCase() ) !== -1) {
if(this.type=='directory'){
filelist.push('<div id="'+this.name+'" class="dirz">'+this.name+'</div>');
}else{
if(this.artist!=null || this.title!=null){
filelist.push('<div data-filetype="'+this.type+'" data-file_location="'+path+this.name+'" class="filez"><span class="pre-char">&#9836;</span> <span class="title">'+this.artist+' - '+this.title+'</span></div>');
}else{
filelist.push('<div data-filetype="'+this.type+'" data-file_location="'+path+this.name+'" class="filez"><span class="pre-char">&#9835;</span> <span class="title">'+this.name+'</span></div>');
}
}
}
});
}
// Post the html to the filelist div
$('#filelist').html(filelist);
});
$('#search-explorer').on('click', function(){
// Hide Filepath
$('#search_folders').toggleClass( 'hide' );
// Show Search Input
$('.directoryName').toggleClass( 'hide' );
if(!$('#search_folders').hasClass('hide')){
$( "#search_folders" ).focus();
}
});
////////////////////////////////////// Share playlists
$('#share_playlist_form').on('submit', function(e){
e.preventDefault();
$('#share_it').prop("disabled",true);
var shareTimeInDays = $('#share_time').val();
// Check for special characters
if(/^[0-9]*$/.test(shareTimeInDays) == false) {
console.log('don\'t do that');
$('#share_it').prop("disabled",false);
return false;
}
//loop through array and add each file to the playlist
var stuff = [];
for (let i = 0; i < MSTREAMPLAYER.playlist.length; i++) {
//Do something
stuff.push(MSTREAMPLAYER.playlist[i].filepath);
}
if(stuff.length == 0){
$('#share_it').prop("disabled",false);
return;
}
MSTREAMAPI.makeShared(stuff, shareTimeInDays, function(response, error){
if(error !== false){
return boilerplateFailure(response, error);
}
$('#share_it').prop("disabled",false);
var adrs = window.location.protocol + '//' + window.location.host + '/shared/playlist/' + response.id;
$('.share-textarea').val(adrs);
});
});
////////////////////////////////////// Save/Load playlists
// Save a new playlist
$('#save_playlist_form').on('submit', function(e){
e.preventDefault();
// Check for special characters
if(/^[a-zA-Z0-9-_ ]*$/.test(title) == false) {
console.log('don\'t do that');
return false;
}
if(MSTREAMPLAYER.playlist.length == 0){
// TODO: Alert user nothing was saved
return;
}
$('#save_playlist').prop("disabled",true);
var title = $('#playlist_name').val();
//loop through array and add each file to the playlist
var songs = [];
for (let i = 0; i < MSTREAMPLAYER.playlist.length; i++) {
songs.push(MSTREAMPLAYER.playlist[i].filepath);
}
MSTREAMAPI.savePlaylist(title, songs, function(response, error){
if(error !== false){
return boilerplateFailure(response, error);
}
$('#save_playlist').prop("disabled",false);
$('#close_save_playlist').trigger("click");
});
});
// Get all playlists
$('.get_all_playlists').on('click', function(){
resetPanel('Playlists', 'scrollBoxHeight2');
MSTREAMAPI.getAllPlaylists( function(response, error){
if(error !== false){
return boilerplateFailure(response, error);
}
// loop through the json array and make an array of corresponding divs
var playlists = [];
$.each(response, function() {
playlists.push('<div data-playlistname="'+this.name+'" class="playlist_row_container"><span data-playlistname="'+this.name+'" class="playlistz force-width">'+this.name+'</span><span data-playlistname="'+this.name+'" class="deletePlaylist">x</span></div>');
});
// Add playlists to the left panel
$('#filelist').html(playlists);
});
});
// delete playlist
$("#filelist").on('click', '.deletePlaylist', function(){
// Get Playlist ID
var playlistname = $(this).data('playlistname');
var that = this;
MSTREAMAPI.deletePlaylist(playlistname, function(response, error){
if(error !== false){
return boilerplateFailure(response, error);
}
$(that).parent().remove();
});
});
// load up a playlist
$("#filelist").on('click', '.playlistz', function() {
var playlistname = $(this).data('playlistname');
var name = $(this).html();
MSTREAMAPI.loadPlaylist(playlistname, function(response, error){
if(error !== false){
return boilerplateFailure(response, error);
}
// Add the playlist name to the modal
$('#playlist_name').val(name);
// Clear the playlist
MSTREAMPLAYER.clearPlaylist();
// Append the playlist items to the playlist
$.each( response, function(i ,item) {
MSTREAMPLAYER.addSongWizard(item.filepath , {}, true);
});
});
});
/////////////// Download Playlist
$('#downloadPlaylist').click(function(){
// Loop through array and add each file to the playlist
var downloadFiles = [];
for (let i = 0; i < MSTREAMPLAYER.playlist.length; i++) {
downloadFiles.push(MSTREAMPLAYER.playlist[i].filepath);
}
// Use key if necessary
if( MSTREAMAPI.currentServer.token){
$("#downform").attr("action", "download?token=" + MSTREAMAPI.currentServer.token);
}
$('<input>').attr({
type: 'hidden',
name: 'fileArray',
value: JSON.stringify(downloadFiles),
}).appendTo('#downform');
//submit form
$('#downform').submit();
// clear the form
$('#downform').empty();
});
///////////////////////////// Database Management
// The Manage DB panel
$('#manage_database').on('click', function(){
resetPanel('Database Management', 'scrollBoxHeight2');
MSTREAMAPI.dbStatus( function(response, error){
if(error !== false){
return boilerplateFailure(response, error);
}
// If there is an error
if(response.error){
$('#filelist').html('<p>The database returned the following error:</p><p>' + response.error + '</p>');
return;
}
// Add Beets Msg
if(response.dbType == 'beets' || response.dbType == 'beets-default' ){
$('#filelist').append('<h3><img style="height:40px;" src="img/database-icon.svg" >Powered by Beets DB</h3>');
}
// if the DB is locked
if(response.locked){
$('#filelist').append('<p>The database is currently being built. Currently ' + response.totalFileCount + ' files are in the DB</p><input type="button" value="Check Progress" class="button secondary small" id="check_db_progress" >');
return;
}
// If you got this far the db is made and working
$('#filelist').append('<p>Your DB has ' + response.totalFileCount + ' files</p><input type="button" class="button secondary rounded small" value="Build Database" id="build_database">');
});
});
// Build the database
$('body').on('click', '#build_database', function(){
$(this).prop("disabled", true);
MSTREAMAPI.dbScan( function(response, error){
if(error !== false){
return boilerplateFailure(response, error);
}
// Append the check db button so the user can start checking right away
$('#filelist').append('<input type="button" value="Check Progress" id="check_db_progress" >');
});
});
// Check DB build progress
$('body').on('click', '#check_db_progress', function(){
MSTREAMAPI.dbStatus( function(response, error){
if(error !== false){
return boilerplateFailure(response, error);
}
$( "#db_progress_report" ).remove();
// if file_count is 0, report that the the build script is not done counting files
if(response.file_count == 0){
$('#filelist').append('<p id="db_progress_report">The create database script is still counting the files in the music collection. This operation can take some time. Try again in a bit</p>');
return;
}
// Append new <p> tag with id of "db_progress_report"
$('#filelist').append('<p id="db_progress_report">Progress: '+ response.files_in_db +'/'+ response.file_count +'</p>');
});
});
//////////////////////////////////// Sort by Albums
//Load up album explorer
$('.get_all_albums').on('click', function(){
resetPanel('Albums', 'scrollBoxHeight2');
MSTREAMAPI.albums( function(response, error){
if(error !== false){
return boilerplateFailure(response, error);
}
//parse through the json array and make an array of corresponding divs
var albums = [];
$.each(response.albums, function(index, value) {
albums.push('<div data-album="'+value+'" class="albumz">'+value+' </div>');
});
$('#filelist').html(albums);
});
});
// Load up album-songs
$("#filelist").on('click', '.albumz', function() {
var album = $(this).data('album');
MSTREAMAPI.albumSongs(album, function(response, error){
if(error !== false){
return boilerplateFailure(response, error);
}
//clear the list
$('#filelist').empty();
//parse through the json array and make an array of corresponding divs
var filelist = [];
$.each(response, function() {
if(this.metadata.title){
filelist.push('<div data-file_location="'+this.filepath+'" class="filez"><span class="pre-char">&#9835;</span> <span class="title">'+this.metadata.title+'</span></div>');
}
else{
filelist.push('<div data-file_location="'+this.filepath+'" class="filez"><span class="pre-char">&#9836;</span> <span class="title">'+this.metadata.filename+'</span></div>');
}
});
$('#filelist').html(filelist);
});
});
/////////////////////////////////////// Artists
// Load up album-songs
$('.get_all_artists').on('click', function(){
resetPanel('Artists', 'scrollBoxHeight2');
MSTREAMAPI.artists( function(response, error){
if(error !== false){
return boilerplateFailure(response, error);
}
//parse through the json array and make an array of corresponding divs
var artists = [];
$.each(response.artists, function(index,value) {
artists.push('<div data-artist="'+value+'" class="artistz">'+value+' </div>');
});
$('#filelist').html(artists);
});
});
$("#filelist").on('click', '.artistz', function() {
var artist = $(this).data('artist');
MSTREAMAPI.artistAlbums(artist, function(response, error){
if(error !== false){
return boilerplateFailure(response, error);
}
//clear the list
$('#filelist').empty();
var albums = [];
$.each(response.albums, function(index, value) {
albums.push('<div data-album="'+value+'" class="albumz">'+value+' </div>');
});
$('#filelist').html(albums);
$('.panel_one_name').html('Artists->Albums');
});
});
///////////////////////////// Search Function
// Setup the search interface
$('#search_database').on('click', function(){
resetPanel('Search', 'scrollBoxHeight1');
$('#search_container').show();
});
// Auto Search
$('#search_it').on('keyup', function(){
// TODO: Put this on some kind of time delay. That way rapid keystrokes won't spam the server
if($(this).val().length>1){
MSTREAMAPI.search($(this).val(), function(response, error){
if(error !== false){
return boilerplateFailure(response, error);
}
var htmlString = '';
if(response.artists.length > 0){
htmlString += '<h2 class="search_subtitle"><strong>Artists</strong></h2>';
$.each(response.artists, function(index, value) {
htmlString += '<div data-artist="'+value+'" class="artistz">'+value+' </div>';
});
}
if(response.albums.length > 0){
htmlString += '<h2 class="search_subtitle"><strong>Albums</strong></h2>';
$.each(response.albums, function(index, value) {
htmlString += '<div data-album="'+value+'" class="albumz">'+value+' </div>';
});
}
$('#filelist').html(htmlString);
});
}
});
//////////////////////// Jukebox Mode
function setupJukeboxPanel(){
// Hide the directory bar
resetPanel('Jukebox Mode', 'scrollBoxHeight2');
var newHtml;
if(JUKEBOX.stats.live !== false && JUKEBOX.connection !== false){
newHtml = createJukeboxPanel();
}else{
newHtml = '\
<p class="jukebox-panel">\
<br><br>\
<h3>Jukebox Mode allows you to control this page remotely<h3> <br><br>\
<div class="jukebox_connect button"> CONNECT IT!</div>\
</p>\
<img src="public/img/loading.gif" class="hide jukebox-loading">';
}
// Add the content
$('#filelist').html(newHtml);
}
// The jukebox panel
$('#jukebox_mode').on('click', function(){
setupJukeboxPanel();
});
// Setup Jukebox
$('body').on('click', '.jukebox_connect', function(){
$(this).prop("disabled", true);
$(this).hide();
$('.jukebox-loading').toggleClass('hide');
JUKEBOX.createWebsocket( MSTREAMAPI.currentServer.token, function(){
// Wait a while and display the status
setTimeout(function(){
// TODO: Check that status has changed
setupJukeboxPanel();
},1800);
});
});
function createJukeboxPanel(){
var returnHtml = '<p class="jukebox-panel">';
if(JUKEBOX.stats.error !== false){
return returnHtml + 'An error occurred. Please refresh the page and try again</p>';
}
if(JUKEBOX.stats.adminCode){
returnHtml += '<h1>Code: ' + JUKEBOX.stats.adminCode + '</h1>';
}
if(JUKEBOX.stats.guestCode){
returnHtml += '<h2>Guest Code: ' + JUKEBOX.stats.guestCode + '</h2>';
}
var adrs = window.location.protocol + '//' + window.location.host + '/remote';
returnHtml += '<br><h4>Remote Jukebox Controls: <a target="_blank" href="' + adrs + '"> ' + adrs + '</a><h4>';
return returnHtml + '</p>';
}
});

View File

@ -1,102 +0,0 @@
var JUKEBOX = (function () {
let mstreamModule = {};
mstreamModule.connection = false;
// jukebox global variable
mstreamModule.stats = {
// connection: false,
live: false,
guestCode: false,
adminCode: false,
error: false,
accessAddress: false
};
// TODO: Move token to the api library
mstreamModule.createWebsocket = function(accessKey, callback){
if(mstreamModule.stats.live ===true ){
return false;
}
mstreamModule.stats.live = true;
// if user is running mozilla then use it's built-in WebSocket
window.WebSocket = window.WebSocket || window.MozWebSocket;
// if browser doesn't support WebSocket, just show some notification and exit
if (!window.WebSocket) {
// TODO: Make a warning
return;
}
// TODO: Check if websocket has already been created
// open connection
var l = window.location;
var wsLink = ((l.protocol === "https:") ? "wss://" : "ws://") + l.host + l.pathname;
mstreamModule.connection = new WebSocket(wsLink + 'jukebox/open-connection?token=' + accessKey);
mstreamModule.connection.onopen = function () {
callback();
};
mstreamModule.connection.onerror = function (error) {
// TODO: Error Code
console.log('CONNECTION ERROR!!!!!!!!!!!!');
};
// most important part - incoming messages
mstreamModule.connection.onmessage = function (message) {
// try to parse JSON message. Because we know that the server always returns
// JSON this should work without any problem but we should make sure that
// the message is not chunked or otherwise damaged.
try {
var json = JSON.parse(message.data);
} catch (e) {
return;
}
// Handle Code
if(json.code){
mstreamModule.stats.adminCode = json.code;
}
if(json.guestCode){
mstreamModule.stats.guestCode = json.guestCode;
}
if(!json.command){
return;
}
if(json.command === 'next'){
MSTREAMPLAYER.nextSong();
return;
}
if( json.command === 'playPause'){
MSTREAMPLAYER.playPause();
}
if( json.command === 'previous'){
MSTREAMPLAYER.previousSong();
return;
}
if( json.command === 'addSong' && json.file){
MSTREAMPLAYER.addSongWizard(json.file, {}, true);
}
};
}
// TODO: Finish this at some point
// mstreamModule.commandList = {
// 'next': MSTREAMPLAYER.nextSong(),
// 'playPause': MSTREAMPLAYER.playPause(),
// 'previous': MSTREAMPLAYER.previousSong(),
// }
return mstreamModule;
}());

View File

@ -1,765 +0,0 @@
var MSTREAMPLAYER = (function () {
let mstreamModule = {};
// Playlist variables
mstreamModule.positionCache = {val:-1};
// var currentSong;
mstreamModule.playlist = [];
// The audioData looks like this
// var song = {
// "url":"vPath/path/to/song.mp3?token=xxx",
// "filepath": "path/to/song.mp3"
// }
mstreamModule.addSong = function(audioData){
if(!audioData.url || audioData.url == false){
return false;
}
// Handle shuffle
if(mstreamModule.playerStats.shuffle === true){
var pos = Math.floor(Math.random() * (shuffleCache.length + 1));
shuffleCache.splice(pos, 0, song);
}
return addSongToPlaylist(audioData);
}
function addSongToPlaylist(song){
mstreamModule.playlist.push(song);
// If this the first song in the list
if(mstreamModule.playlist.length === 1){
mstreamModule.positionCache.val = 0;
return goToSong(mstreamModule.positionCache.val);
}
// TODO: Check if we are at the end of the playlist and nothing is playing.
// Start playing if this condition is met
// Cache song if appropriate
var oPlayer = getOtherPlayer();
if(oPlayer.playerObject === false && mstreamModule.playlist[mstreamModule.positionCache.val + 1]){
// setCachedSong(mstreamModule.positionCache.val + 1);
clearTimeout(cacheTimer);
cacheTimer = setTimeout(function(){ setCachedSong(mstreamModule.positionCache.val + 1) } , 3000);
}
return true;
}
mstreamModule.clearAndPlay = function(song){
// Clear playlist
mstreamModule.playlist = [];
return addSong(song);
}
mstreamModule.clearPlaylist = function(){
while(mstreamModule.playlist.length > 0) {mstreamModule.playlist.pop();}
mstreamModule.positionCache.val = -1;
clearEnd();
// Clear shuffle as well
if(mstreamModule.playerStats.shuffle === true){
// Clear Shuffle Cache
while(shuffleCache.length > 0) {shuffleCache.pop();}
}
return true;
}
mstreamModule.nextSong = function(){
// Stop the current song
return goToNextSong();
}
mstreamModule.previousSong = function(){
return goToPreviousSong();
}
mstreamModule.goToSongAtPosition = function(position){
if(!mstreamModule.playlist[position]){
return false;
}
clearEnd();
mstreamModule.positionCache.val = position;
return goToSong(mstreamModule.positionCache.val);
}
// TODO: Log Failures
mstreamModule.removeSongAtPosition = function(position, sanityCheckUrl){
// Check that position is filled
if (position > mstreamModule.playlist.length || position < 0) {
return false;
}
// If sanityCheckUrl, check that url are the same
if(sanityCheckUrl && sanityCheckUrl != mstreamModule.playlist[position].url){
return false;
}
var removedSong = mstreamModule.playlist[position];
// Remove song
mstreamModule.playlist.splice(position, 1);
if(mstreamModule.playerStats.shuffle === true){
// Remove song from shuffle Cache
for(var i=0, len=shuffleCache.length; i < len; i++){
// Check if this is the current song
if(removedSong === shuffleCache[i]){
shuffleCache.splice(i, 1);
}
}
for(var i=0, len=shufflePrevious.length; i < len; i++){
// Check if this is the current song
if(removedSong === shufflePrevious[i]){
shufflePrevious.splice(i, 1);
}
}
}
// Handle case where user removes current song and it's the last song in the playlist
if(position === mstreamModule.positionCache.val && position === mstreamModule.playlist.length ){
clearEnd();
// Go to random song if random is set
if(mstreamModule.playerStats.shuffle === true){
goToNextSong();
}else if(mstreamModule.playerStats.shouldLoop === true){ // Loop is loop is set
mstreamModule.positionCache.val = 0;
goToSong(mstreamModule.positionCache.val);
}else{ // Reset to start is nothing is set
mstreamModule.positionCache.val = -1;
}
}else if(position === mstreamModule.positionCache.val){ // User removes currently playing song
// Go to next song
clearEnd();
// If random is set, go to random song
if(mstreamModule.playerStats.shuffle === true){
goToNextSong();
}else{
goToSong(mstreamModule.positionCache.val);
}
}else if( position < mstreamModule.positionCache.val){
// Lower positioncache by 1 if necessary
mstreamModule.positionCache.val--;
}else if( position === (mstreamModule.positionCache.val + 1) ){
// setCachedSong(mstreamModule.positionCache.val + 1);
clearTimeout(cacheTimer);
cacheTimer = setTimeout(function(){ setCachedSong(mstreamModule.positionCache.val + 1) } , 3000);
}
}
mstreamModule.getCurrentSong = function(){
var lPlayer = getCurrentPlayer();
return lPlayer.songObject;
}
function goToPreviousSong(){
// TODO: If random is set, go to previous song from cache
if(mstreamModule.playerStats.shuffle === true){
// TODO: Check that there is a previous song to go back to
if(shufflePrevious.length <= 1){
return;
}
// Pop a song and go to the last song
var nextSong = shufflePrevious.pop();
shuffleCache.push(nextSong);
var currentSong = shufflePrevious[shufflePrevious.length-1];
// Reset position cache
for(var i=0, len=mstreamModule.playlist.length; i < len; i++){
// Check if this is the current song
if(currentSong === mstreamModule.playlist[i]){
mstreamModule.positionCache.val = i;
}
}
clearEnd();
goToSong(mstreamModule.positionCache.val );
return;
}
// Make sure there is a previous song
if(mstreamModule.positionCache.val === 0 || mstreamModule.positionCache.val === -1){
return false;
}
// Set previous song and play
clearEnd();
mstreamModule.positionCache.val--;
return goToSong(mstreamModule.positionCache.val);
}
function goToNextSong(){
// If random is set, go to random song
if(mstreamModule.playerStats.shuffle === true){
// Chose a random value
var nextSong = shuffleCache.pop();
// Prevent same song from playing twice after a re-shuffle
if(nextSong === mstreamModule.getCurrentSong()){
console.log('DUPEEEEE');
shuffleCache.unshift(nextSong);
nextSong = shuffleCache.pop();
}
if(shuffleCache.length === 0){
newShuffle();
}
// Reset position cache
for(var i=0, len=mstreamModule.playlist.length; i < len; i++){
// Check if this is the current song
if(nextSong === mstreamModule.playlist[i]){
mstreamModule.positionCache.val = i;
}
}
clearEnd();
goToSong(mstreamModule.positionCache.val );
// Remove duplicates from shuffle previous
for(var i=0, len=shufflePrevious.length; i < len; i++){
// Check if this is the current song
if(nextSong === shufflePrevious[i]){
shufflePrevious.splice(i, 1);
}
}
shufflePrevious.push(nextSong);
// Load selected song
return;
}
// Check if the next song exists
if(!mstreamModule.playlist[mstreamModule.positionCache.val + 1]){
// If loop is set and no other song, go back to first song
if(mstreamModule.playerStats.shouldLoop === true && mstreamModule.playlist.length > 0){
mstreamModule.positionCache.val = 0;
clearEnd();
return goToSong(mstreamModule.positionCache.val);
}
return false;
}
// Load up next song
mstreamModule.positionCache.val++;
clearEnd();
return goToSong(mstreamModule.positionCache.val);
}
function getCurrentPlayer(){
if(curP === 'A'){
return playerA;
}else if(curP === 'B'){
return playerB;
}
return false;
}
function getOtherPlayer(){
if(curP === 'A'){
return playerB;
}else if(curP === 'B'){
return playerA;
}
return false;
}
function flipFlop(){
if(curP === 'A'){
curP = 'B';
}else if(curP === 'B'){
curP = 'A';
}
return curP;
}
function goToSong(position){
if(!mstreamModule.playlist[position]){
return false;
}
var localPlayerObject = getCurrentPlayer();
var otherPlayerObject = getOtherPlayer();
// Stop the current song
if(localPlayerObject.playerType === 'aurora' ){
localPlayerObject.playerObject.stop();
}else if(localPlayerObject.playerType === 'howler'){
localPlayerObject.playerObject.unload();
}
// Reset Duration
mstreamModule.playerStats.duration = 0;
mstreamModule.playerStats.currentTime = 0;
// TODO: Handle situation where next song is same as current song
// Song is cached
if(otherPlayerObject.songObject === mstreamModule.playlist[position]){
// console.log('USING CACHED SONG');
flipFlop();
// Play
mstreamModule.playPause();
}else{
// console.log('DID NOT USE CACHE');
setMedia(mstreamModule.playlist[position], localPlayerObject, true);
}
var lPlayer = getCurrentPlayer();
var curSong = lPlayer.songObject;
// TODO: Handle instace where metadata is empty
// mstreamModule.playerStats.metadata = curSong.metadata;
if(curSong.metadata){
mstreamModule.resetCurrentMetadata();
}
// TODO: This is a mess, figure out a better way
var newOtherPlayerObject = getOtherPlayer();
newOtherPlayerObject.playerType = false;
newOtherPlayerObject.playerObject = false;
newOtherPlayerObject.songObject= false;
// Cache next song
// The timer prevents excessive cachign when the user starts button mashing
// setCachedSong(position + 1);
clearTimeout(cacheTimer);
cacheTimer = setTimeout(function(){ setCachedSong(position + 1) } , 3000);
return true;
}
mstreamModule.resetCurrentMetadata = function() {
var lPlayer = getCurrentPlayer();
var curSong = lPlayer.songObject;
// TODO: Handle instace where metadata is empty
// mstreamModule.playerStats.metadata = curSong.metadata;
if(curSong.metadata){
mstreamModule.playerStats.metadata.artist = curSong.metadata.artist;
mstreamModule.playerStats.metadata.album = curSong.metadata.album;
mstreamModule.playerStats.metadata.track = curSong.metadata.track;
mstreamModule.playerStats.metadata.title = curSong.metadata.title;
mstreamModule.playerStats.metadata.year = curSong.metadata.year;
mstreamModule.playerStats.metadata['album-art'] = curSong.metadata['album-art'];
}
console.log( mstreamModule.playerStats.metadata)
}
mstreamModule.resetPositionCache = function(){
var len;
var lPlayer = getCurrentPlayer();
var curSong = lPlayer.songObject;
for(var i=0, len=mstreamModule.playlist.length; i < len; i++){
// Check if this is the current song
if(curSong === mstreamModule.playlist[i]){
mstreamModule.positionCache.val = i;
return;
}
}
// No song found, reset
mstreamModule.positionCache.val = -1;
}
// ========================= Aurora Player ===============
// Shell for interacting with Aurora
function AVPlayerPlay(){
var localPlayer = getCurrentPlayer();
if(localPlayer.playerObject.playing){
return;
}
localPlayer.playerObject.play();
mstreamModule.playerStats.playing = true;
}
function AVPlayerPause(){
var localPlayer = getCurrentPlayer();
localPlayer.playerObject.pause();
mstreamModule.playerStats.playing = false;
}
function AVPlayerPlayPause(){
var localPlayer = getCurrentPlayer();
// TODO: Check that media is loaded
if(localPlayer.playerObject.playing){
localPlayer.playerObject.pause();
mstreamModule.playerStats.playing = false;
}else{
localPlayer.playerObject.play();
mstreamModule.playerStats.playing = true;
}
}
// ========================================================
// ========================= Howler Player ===============
function howlPlayerPlay(){
var localPlayer = getCurrentPlayer();
mstreamModule.playerStats.playing = true;
localPlayer.playerObject.play();
}
function howlPlayerPause(){
var localPlayer = getCurrentPlayer();
mstreamModule.playerStats.playing = false;
localPlayer.playerObject.pause();
}
function howlPlayerPlayPause(){
var localPlayer = getCurrentPlayer();
// TODO: Check that media is loaded
if(localPlayer.playerObject.playing()){
mstreamModule.playerStats.playing = false;
localPlayer.playerObject.pause();
}else{
localPlayer.playerObject.play();
mstreamModule.playerStats.playing = true;
}
}
// ========================================================
// ========================= Youtube Player ===============
var YTPlayer;
// TODO:
// ========================================================
function clearEnd(){
var localPlayer = getCurrentPlayer();
if(localPlayer.playerType === 'aurora' ){
localPlayer.playerObject.on("end", function() {
return
}, false);
}else if(localPlayer.playerType === 'howler'){
localPlayer.playerObject.off('end');
}
}
// Player
// Event: On Song end
// Set Media
// Play, pause, skip, etc
mstreamModule.playPause = function(){
var localPlayer = getCurrentPlayer();
if(localPlayer.playerType === 'aurora' ){
return AVPlayerPlayPause();
}else if(localPlayer.playerType === 'howler'){
return howlPlayerPlayPause();
}
}
mstreamModule.playerStats = {
duration:0,
currentTime:0,
playing: false,
repeat: false,
shuffle:false,
metadata: {
"artist": false,
"album": false,
"track": false,
"title": false,
"year": false,
"album-art": false,
"filepath": false,
}
}
var playerA = {
playerType: false,
playerObject: false,
songObject: false
}
var playerB = {
playerType: false,
playerObject: false,
songObject: false
}
var curP = 'A';
function setMedia(song, player, play){
if(song.url.indexOf('.flac') !== -1 && Howler.codecs('flac') === false ){
// Set via aurora
player.playerType = 'aurora';
player.playerObject = AV.Player.fromURL(song.url);
player.playerObject.on("end", function() {
callMeOnStreamEnd();
}, false);
// Handle error event
player.playerObject.on("error", function(e) {
// TODO: GO TO NEXT SONG
}, false);
player.playerObject.on("metadata", function() {
// Move this to metadata ???
if(play == true){
AVPlayerPlay();
}
}, false);
player.playerObject.preload();
}else{
player.playerType = 'howler';
player.playerObject = new Howl({
src: [song.url],
html5: true, // Force to HTML5. Otherwise streaming will suck
// onplay: function() { },
onload: function() {
},
onend: function() {
callMeOnStreamEnd();
},
onpause: function() {
},
onstop: function() {
},
onplay: function(){
}
});
if(play == true){
howlPlayerPlay();
}
}
player.songObject = song;
}
function callMeOnStreamEnd(){
mstreamModule.playerStats.playing= false;
// Go to next song
goToNextSong();
}
// NOTE: Seektime is in seconds
mstreamModule.seek = function(seekTime){
var lPlayer = getCurrentPlayer();
if(lPlayer.playerType === 'aurora' ){
// Do nothing, auroradoesn't support seeking right now
return false;
}else if(lPlayer.playerType === 'howler'){
// Check that the seek number is less than the duration
if(seekTime < 0 || seekTime > lPlayer.playerObject._duration){
return false;
}
lPlayer.playerObject.seek(seektime)
}
}
mstreamModule.seekByPercentage = function(percentage){
if(percentage < 0 || percentage > 99){
return false;
}
var lPlayer = getCurrentPlayer();
if(lPlayer.playerType === 'aurora' ){
// Do nothing, auroradoesn't support seeking
return false;
}else if(lPlayer.playerType === 'howler'){
var seektime = (percentage * lPlayer.playerObject._duration)/ 100;
lPlayer.playerObject.seek(seektime)
}
}
var timers = {};
function startTime(interval) {
if (timers.sliderUpdateInterval) { clearInterval(timers.sliderUpdateInterval); }
timers.sliderUpdateInterval = setInterval( function(){
var lPlayer = getCurrentPlayer();
if(lPlayer.playerType === 'aurora' ){
mstreamModule.playerStats.duration = lPlayer.playerObject.duration / 1000;
mstreamModule.playerStats.currentTime = lPlayer.playerObject.currentTime / 1000;
}else if(lPlayer.playerType === 'howler'){
mstreamModule.playerStats.currentTime = lPlayer.playerObject.seek();
mstreamModule.playerStats.duration = lPlayer.playerObject._duration;
}else{
// NO PLAYER, set default values
mstreamModule.playerStats.currentTime = 0;
mstreamModule.playerStats.duration = 0;
}
}, interval);
}
startTime(100);
function clearTimer(){
clearInterval(timers.sliderUpdateInterval);
}
// Timer for caching. Helps prevent excess cahing due to button mashing
var cacheTimer;
function setCachedSong(position){
console.log(' ATTEMPTING TO CACHE');
if(!mstreamModule.playlist[position]){
console.log(' FAILED TO CACHE');
return false;
}
var oPlayer = getOtherPlayer();
setMedia(mstreamModule.playlist[position], oPlayer, false);
console.log(' IT CACHED!!!!!!');
console.log(mstreamModule.playlist[position]);
return true;
}
// Loop
mstreamModule.playerStats.shouldLoop = false;
mstreamModule.setRepeat = function(newValue){
if(typeof(newValue) != "boolean"){
return false;
}
mstreamModule.playerStats.shouldLoop = newValue;
return newValue;
}
mstreamModule.toggleRepeat = function(){
mstreamModule.playerStats.shouldLoop = !mstreamModule.playerStats.shouldLoop;
return mstreamModule.playerStats.shouldLoop;
}
// Random Song
mstreamModule.playerStats.shuffle = false;
shuffleCache = []; // Cache the last 5 songs played to avoid repeats
shufflePrevious = [];
mstreamModule.setShuffle = function(newValue){
if(typeof(newValue) != "boolean"){
return false;
}
if(newValue===true){
newShuffle();
}else{
turnShuffleOff();
}
mstreamModule.playerStats.shuffle = newValue;
return true;
}
mstreamModule.toggleShuffle = function(){
mstreamModule.playerStats.shuffle = !mstreamModule.playerStats.shuffle;
if(mstreamModule.playerStats.shuffle === true){
newShuffle();
}else{
turnShuffleOff();
}
return mstreamModule.playerStats.shuffle;
}
function newShuffle(){
shuffleCache = shuffle(mstreamModule.playlist.slice(0));
}
function turnShuffleOff(){
shufflePrevious = [];
shuffleCache = [];
}
function shuffle(array) {
var currentIndex = array.length
, temporaryValue
, randomIndex
;
// While there remain elements to shuffle...
while (0 !== currentIndex) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
// And swap it with the current element.
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
}
// Return an object that is assigned to Module
return mstreamModule;
}());

View File

@ -1,86 +0,0 @@
var VUEBROWSER = function() {
// Auto Focus
Vue.directive('focus', {
// When the bound element is inserted into the DOM...
inserted: function (el) {
// Focus the element
el.focus()
}
});
var loginPanel = new Vue({
el: '#login-overlay',
data: {
needToLogin: false,
error: false,
errorMessage: 'Login Failed',
pending: false
},
methods: {
submitCode: function(e){
// Get Code
this.pending = true;
var that = this;
MSTREAMAPI.login($('#login-username').val(), $('#login-password').val(), function(response, error){
if(error !== false){
// Alert the user
that.pending = false;
that.error = true;
return;
}
// Eye-candy: change the error message
that.errorMessage = "Welcome To mStream!";
// Add the token to the cookies
Cookies.set('token', response.token);
// Add the token the URL calls
MSTREAMAPI.updateCurrentServer($('#login-username').val(), response.token, response.vPath)
// TODO: Add function to load up either the file browser or artist panel
// Remove the overlay
$('.login-overlay').fadeOut( "slow" ); // TDO: Figure out how to use Vue to fade the modal in and out
that.pending = false;
that.needToLogin = false;
});
}
}
});
function testIt(token){
if(token){
MSTREAMAPI.currentServer.token = token;
}
MSTREAMAPI.ping( function(response, error){
if(error !== false){
// NOTE: There needs to be a split here
// For the webapp we simply display the login panel
loginPanel.needToLogin = true;
// TODO: Move this transitionstuff to vue
$('.login-overlay').fadeIn( "slow" );
// For electron we need to alert the user that user it failed and guide them to the login form
return;
}
// set vPath
MSTREAMAPI.currentServer.vPath = response.vPath;
// TODO: Add function to load up either the file browser or artist panel
});
}
// NOTE: There needs to be a split here
// For the normal webap we just get the token
// var token = Cookies.get('token');
testIt(Cookies.get('token'));
// For electron we need to pull it from wherever electron stores things
};

View File

@ -1,235 +0,0 @@
var VUEPLAYER = function() {
// Template for playlist items
Vue.component('playlist-item', {
template: '\
<div class="playlist-item" v-bind:class="{ playing: (this.index == positionCache.val) }" >\
<span v-on:click="goToSong($event)" class="song-area">{{ comtext }}</span> <span v-on:click="removeSong($event)" class="removeSong">X</span>\
</div>\
',
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: {
// Go to a song on item click
goToSong: function(event){
MSTREAMPLAYER.goToSongAtPosition(this.index);
},
// Remove song
removeSong: function(event){
MSTREAMPLAYER.removeSongAtPosition(this.index, false);
}
},
computed: {
comtext: function() {
var returnThis = this.song.filepath;
if(this.song.metadata.title){
returnThis = this.song.metadata.title;
if(this.song.metadata.artist){
returnThis = this.song.metadata.artist + ' - ' + returnThis;
}
}
return returnThis;
}
}
});
// Code to update playlist
var playlistElement = new Vue({
el: '#playlist',
data: {
playlist: MSTREAMPLAYER.playlist,
},
methods: {
// checkMove is called when a drag-and-drop action happens
checkMove: function (event) {
MSTREAMPLAYER.resetPositionCache();
}
}
});
var progressBar = new Vue({
el: '#mstream-player',
data: {
playerStats: MSTREAMPLAYER.playerStats,
playlist: MSTREAMPLAYER.playlist,
positionCache: MSTREAMPLAYER.positionCache,
met: MSTREAMPLAYER.playerStats.metadata
},
computed: {
imgsrc: function () {
return "/public/img/"+(this.playerStats.playing ? 'pause' : 'play')+"-white.svg";
},
widthcss: function ( ) {
if(this.playerStats.duration === 0){
return "width:0";
}
var percentage = 100 - (( this.playerStats.currentTime / this.playerStats.duration) * 100);
return "width:calc(100% - "+percentage+"%)";
},
showTime: function(){
if (this.playerStats.duration === 0) {
return '';
}
var curr = this.playerStats.duration - this.playerStats.currentTime;
var minutes = Math.floor(curr / 60);
var secondsToCalc = Math.floor(curr % 60) + '';
var currentText = minutes + ':' + (secondsToCalc.length < 2 ? '0' + secondsToCalc : secondsToCalc);
return currentText;
},
currentSongText: function(){
// TODO: Handle metadata
// Call these vars so updates cahnge whenever they do
var posit = this.positionCache.val;
var plist = this.playlist;
var playerStats = this.playerStats;
var titleX = this.met.title;
var metx = this.met;
var currentSong = MSTREAMPLAYER.getCurrentSong();
if(currentSong === false){
return '\u00A0\u00A0\u00A0Welcome To mStream!\u00A0\u00A0\u00A0';
}
// Get current song straight from the source
var returnText = '';
if(playerStats.metadata && titleX){
returnText = titleX;
if(playerStats.metadata.artist){
returnText = playerStats.metadata.artist + ' - ' + returnText;
}
}else{
// Use filepath instead
var filepathArray = currentSong.filepath.split("/");
returnText = filepathArray[filepathArray.length-1]
}
console.log(MSTREAMPLAYER.playerStats.metadata);
return '\u00A0\u00A0\u00A0' + returnText + '\u00A0\u00A0\u00A0';
}
},
methods: {
toggleRepeat: function(){
MSTREAMPLAYER.toggleRepeat();
},
toggleShuffle: function(){
MSTREAMPLAYER.toggleShuffle();
}
}
});
var metadataPanel = new Vue({
el: '#metadata-panel',
data: {
meta: MSTREAMPLAYER.playerStats.metadata
},
computed: {
albumArtPath: function(){
if(!this.meta['album-art']){
return '/public/img/default.png';
}
return '/album-art/' + this.meta['album-art'];
}
}
});
// Button Events
document.getElementById( "progress-bar" ).addEventListener("click",function(event) {
var relativeClickPosition = event.clientX - this.getBoundingClientRect().left;
var totalWidth = this.getBoundingClientRect().width;
var percentage = (relativeClickPosition / totalWidth) * 100;
// Set Player time
MSTREAMPLAYER.seekByPercentage(percentage);
});
// Button Events
document.getElementById( "next-button" ).addEventListener("click",function() {
MSTREAMPLAYER.nextSong();
});
document.getElementById( "play-pause-button" ).addEventListener("click", function() {
MSTREAMPLAYER.playPause();
});
document.getElementById("previous-button").addEventListener("click", function(){
MSTREAMPLAYER.previousSong();
});
// This makes the title text scroll back and forth
var scrollTimer;
var scrollRight = true; //Track Scroll Direction
function startTime(interval) {
if (scrollTimer) { clearInterval(scrollTimer); }
scrollTimer = setInterval( function(){
// Get the max scroll distance
var maxScrollLeft = document.getElementById('title-text').scrollWidth - document.getElementById('title-text').clientWidth;
// Change the scroll direction if necessary
// TODO: Pause for a second when these conditions are hit
if(document.getElementById('title-text').scrollLeft > (maxScrollLeft - 1)){
scrollRight = false;
}
if(document.getElementById('title-text').scrollLeft === 0){
scrollRight = true;
}
// Do the scroll
if(scrollRight === true){
document.getElementById('title-text').scrollLeft = document.getElementById('title-text').scrollLeft + 2;
}else{
document.getElementById('title-text').scrollLeft = document.getElementById('title-text').scrollLeft - 2;
}
}, interval);
}
startTime(50);
// Change spacebar behviour to Play/PauseListen to every key press user makes
// Useful for adding media functionality to certain keys
window.addEventListener("keydown", function(event){
// Use default behavior if user is in a form
var element = event.target.tagName.toLowerCase();
if(element == 'input' || element == 'textarea'){
return;
}
// Check the key
switch (event.keyCode) {
case 32: //SpaceBar
event.preventDefault();
MSTREAMPLAYER.playPause();
break;
}
return false;
}, false);
};

View File

@ -1,127 +0,0 @@
<!doctype html>
<html class="no-js" lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta content="yes" name="mobile-web-app-capable">
<meta content="yes" name="apple-mobile-web-app-capable">
<meta content="black" name="apple-mobile-web-app-status-bar-style">
<title>mStream Media Player - All your media. Everywhere you go.</title>
<!-- Favicon -->
<link rel="apple-touch-icon" sizes="57x57" href="/public/favicon/apple-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/public/favicon/apple-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="/public/favicon/apple-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="/public/favicon/apple-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="/public/favicon/apple-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="/public/favicon/apple-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/public/favicon/apple-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/public/favicon/apple-icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/public/favicon/apple-icon-180x180.png">
<link rel="icon" type="image/png" sizes="192x192" href="/public/favicon/android-icon-192x192.png">
<link rel="icon" type="image/png" sizes="32x32" href="/public/favicon/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="96x96" href="/public/favicon/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16" href="/public/favicon/favicon-16x16.png">
<link rel="manifest" href="/public/favicon/manifest.json">
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="msapplication-TileImage" content="/public/favicon/ms-icon-144x144.png">
<meta name="theme-color" content="#ffffff">
<!-- GOAL: Remove jquery dependancy
Currently mstream.js and mstream.api.js use it -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<!-- Cookie Library -->
<script type="text/javascript" src="/public/js/lib/cookie.js"></script>
<!-- Vue JS -->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<!-- Sortable JS
Used to add drag and drop re-arranging to queue -->
<script src="https://unpkg.com/sortablejs@latest"></script>
<!-- https://github.com/SortableJS/Vue.Draggable - v2.6 -->
<script src="/public/js/lib/vue-sortable.js"></script>
<!--
This is the mStream Player and Queue code
It must be loaded before all aother mstream libraries because it's a dependancy of those libraries
DO NOT Change to order these are loaded in
-->
<script src="/public/js/lib/aurora.js"></script>
<script src="/public/js/lib/flac.js"></script>
<script src="/public/js/lib/howler.core.js"></script>
<script src="/public/js/mstream.player.js"></script>
<!-- END PLAYE AND QUEUE CODE -->
<!-- This API library must be loaded after the player
This library provides a convenient way to call the server's API -->
<script src="/public/js/mstream.api.js"></script>
<!-- Jukebox Control Code -- >
<script src="/public/js/mstream.jukebox.js"></script>
<!-- This file is a bunch of jquery that handles the browser -->
<!-- It needs to be replaced with vue code.
I'm keeping it here for a reference. A lot of code for parsing AJAX responses can be recycled -->
<!-- <script type="text/javascript" src="/public/js/mstream.js"></script> -->
<!-- This is the file that will replace mstream.js -->
<script type="text/javascript" src="/public/js/mstream.vue-browser.js"></script>
<!-- Vue Player and Queue controls
NOTE: This file is what wires up the MSTREAMPLAYER object to the html
Uncomment it once the html has been contructed -->
<!-- <script src="/public/js/mstream.vue-player-controls.js"></script> -->
<!-- Styles -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/6.0.0/normalize.min.css">
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,400i,800" rel="stylesheet">
<link rel="stylesheet" href="/public/css/style.css">
<script>
// Run Vue code once the page has been loaded
$(document).ready(function(){
// // invoke vueplayer
// Uncomment once player html is constructed
// VUEPLAYER();
VUEBROWSER();
});
</script>
</head>
<body>
<!-- Login Overlay -->
<div id="login-overlay" class="login-overlay hide">
<div class="login-panel">
<img class="login-icon" src="/public/img/mstream-icon.svg">
<form id="login-form" v-on:submit.prevent="submitCode($event)">
<label class="label--magic">
<input v-focus type="text" required id="login-username">
<span>Username</span>
</label>
<label class="label--magic">
<input required type="password" required id="login-password">
<span>Password</span>
</label>
<button id="login-submit" type="submit" :disabled="pending === true ? true : false">Login</button>
</form>
<div v-show="error" id="login-alert" class="">{{errorMessage}}</div>
</div>
</div>
<div>
The rest of the webapp goes here
</div>
</body>

Binary file not shown.