mirror of
https://github.com/janishutz/MusicPlayerV2.git
synced 2025-11-25 21:14:22 +00:00
almost finished
This commit is contained in:
@@ -19,13 +19,14 @@ app.use( session( {
|
||||
resave: false,
|
||||
} ) );
|
||||
|
||||
const conf = JSON.parse( fs.readFileSync( path.join( __dirname + '/config/config.json' ) ) );
|
||||
|
||||
// TODO: Import from config
|
||||
const remoteURL = 'http://localhost:3000';
|
||||
const remoteURL = conf.connectionURL ?? 'http://localhost:3000';
|
||||
let hasConnected = false;
|
||||
|
||||
const connect = () => {
|
||||
if ( authKey !== '' ) {
|
||||
if ( authKey !== '' && conf.doConnect ) {
|
||||
axios.post( remoteURL + '/connect', { 'authKey': authKey } ).then( res => {
|
||||
if ( res.status === 200 ) {
|
||||
console.log( '[ BACKEND INTEGRATION ] Connection successful' );
|
||||
@@ -42,10 +43,7 @@ const connect = () => {
|
||||
}
|
||||
};
|
||||
|
||||
let authKey = '';
|
||||
try {
|
||||
authKey = '' + fs.readFileSync( path.join( __dirname + '/config/authKey.txt' ) );
|
||||
} catch( err ) {};
|
||||
let authKey = conf.authKey ?? '';
|
||||
|
||||
connect();
|
||||
|
||||
@@ -69,8 +67,8 @@ app.get( '/', ( request, response ) => {
|
||||
} );
|
||||
|
||||
app.get( '/openSongs', ( req, res ) => {
|
||||
res.send( '{ "data": [ "/home/janis/Music/KB2022" ] }' );
|
||||
// res.send( '{ "data": [ "/mnt/storage/SORTED/Music/audio/KB2022" ] }' );
|
||||
// res.send( '{ "data": [ "/home/janis/Music/KB2022" ] }' );
|
||||
res.send( '{ "data": [ "/mnt/storage/SORTED/Music/audio/KB2022" ] }' );
|
||||
// res.send( { 'data': dialog.showOpenDialogSync( { properties: [ 'openDirectory' ], title: 'Open music library folder' } ) } );
|
||||
} );
|
||||
|
||||
@@ -119,6 +117,24 @@ app.get( '/mainNotifier', ( req, res ) => {
|
||||
} );
|
||||
|
||||
const sendUpdate = ( update ) => {
|
||||
if ( update === 'pos' ) {
|
||||
currentDetails[ 'playingSong' ][ 'startTime' ] = new Date().getTime();
|
||||
for ( let client in connectedClients ) {
|
||||
connectedClients[ client ].write( 'data: ' + JSON.stringify( { 'type': 'playingSong', 'data': currentDetails[ 'playingSong' ] } ) + '\n\n' );
|
||||
}
|
||||
} else if ( update === 'playingSong' ) {
|
||||
currentDetails[ update ][ 'startTime' ] = new Date().getTime();
|
||||
} else if ( update === 'isPlaying' ) {
|
||||
currentDetails[ 'playingSong' ][ 'startTime' ] = new Date().getTime();
|
||||
for ( let client in connectedClients ) {
|
||||
connectedClients[ client ].write( 'data: ' + JSON.stringify( { 'type': 'playingSong', 'data': currentDetails[ 'playingSong' ] } ) + '\n\n' );
|
||||
}
|
||||
|
||||
for ( let client in connectedClients ) {
|
||||
connectedClients[ client ].write( 'data: ' + JSON.stringify( { 'type': 'pos', 'data': currentDetails[ 'pos' ] } ) + '\n\n' );
|
||||
}
|
||||
}
|
||||
|
||||
for ( let client in connectedClients ) {
|
||||
connectedClients[ client ].write( 'data: ' + JSON.stringify( { 'type': update, 'data': currentDetails[ update ] } ) + '\n\n' );
|
||||
}
|
||||
@@ -126,16 +142,20 @@ const sendUpdate = ( update ) => {
|
||||
// Check if connected and if not, try to authenticate with data from authKey file
|
||||
|
||||
if ( hasConnected ) {
|
||||
if ( update === 'pos' ) {
|
||||
return;
|
||||
} else if ( update === 'playingSong' ) {
|
||||
currentDetails[ update ][ 'startTime' ] === new Date().getTime();
|
||||
if ( update === 'isPlaying' ) {
|
||||
axios.post( remoteURL + '/statusUpdate', { 'type': 'playingSong', 'data': currentDetails[ 'playingSong' ], 'authKey': authKey } ).catch( err => {
|
||||
console.error( err );
|
||||
} );
|
||||
|
||||
axios.post( remoteURL + '/statusUpdate', { 'type': 'pos', 'data': currentDetails[ 'pos' ], 'authKey': authKey } ).catch( err => {
|
||||
console.error( err );
|
||||
} );
|
||||
} else if ( update === 'pos' ) {
|
||||
axios.post( remoteURL + '/statusUpdate', { 'type': 'playingSong', 'data': currentDetails[ 'playingSong' ], 'authKey': authKey } ).catch( err => {
|
||||
console.error( err );
|
||||
} );
|
||||
}
|
||||
axios.post( remoteURL + '/statusUpdate', { 'type': update, 'data': currentDetails[ update ], 'authKey': authKey } ).then( res => {
|
||||
if ( res.status !== 200 ) {
|
||||
console.log( res );
|
||||
}
|
||||
} ).catch( err => {
|
||||
axios.post( remoteURL + '/statusUpdate', { 'type': update, 'data': currentDetails[ update ], 'authKey': authKey } ).catch( err => {
|
||||
console.error( err );
|
||||
} );
|
||||
} else {
|
||||
|
||||
@@ -156,19 +156,27 @@ body {
|
||||
font-size: 30vh !important;
|
||||
}
|
||||
|
||||
#canvas {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#app {
|
||||
background-color: rgba( 0, 0, 0, 0 );
|
||||
}
|
||||
|
||||
#progress {
|
||||
#progress, #progress::-webkit-progress-bar {
|
||||
background-color: rgba(45, 28, 145);
|
||||
color: rgba(45, 28, 145);
|
||||
width: 30vw;
|
||||
border: none;
|
||||
border-radius: 50px;
|
||||
border-radius: 0px;
|
||||
accent-color: white;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
#progress::-moz-progress-bar {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
#progress::-webkit-progress-value {
|
||||
background-color: white !important;
|
||||
}
|
||||
|
||||
.mode-selector-wrapper {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="info">Designed and developed by Janis Hutz https://janishutz.com</div>
|
||||
<div class="info">Designed and developed by Janis Hutz <a href="https://janishutz.com" target="_blank" style="text-decoration: none; color: white;">https://janishutz.com</a></div>
|
||||
<div class="content" id="app">
|
||||
<div v-if="hasLoaded" style="width: 100%">
|
||||
<div class="current-song-wrapper">
|
||||
@@ -64,7 +64,6 @@
|
||||
<div class="beat"></div>
|
||||
<div class="beat-manual"></div>
|
||||
</div>
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
|
||||
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
|
||||
|
||||
@@ -11,11 +11,8 @@ createApp( {
|
||||
pos: 0,
|
||||
queuePos: 0,
|
||||
colourPalette: [],
|
||||
startTime: 0,
|
||||
offsetTime: 0,
|
||||
progressBar: 0,
|
||||
timeTracker: null,
|
||||
timeCorrector: null,
|
||||
visualizationSettings: 'mic',
|
||||
micAnalyzer: null,
|
||||
beatDetected: false,
|
||||
@@ -59,20 +56,16 @@ createApp( {
|
||||
},
|
||||
methods: {
|
||||
startTimeTracker () {
|
||||
this.startTime = new Date().getTime();
|
||||
this.timeTracker = setInterval( () => {
|
||||
this.pos += 0.075;
|
||||
this.pos = ( new Date().getTime() - this.playingSong.startTime ) / 1000 + this.oldPos;
|
||||
this.progressBar = ( this.pos / this.playingSong.duration ) * 1000;
|
||||
}, 75 );
|
||||
|
||||
this.timeCorrector = setInterval( () => {
|
||||
this.pos = this.oldPos + ( new Date().getTime() - this.startTime ) / 1000;
|
||||
this.progressBar = ( this.pos / this.playingSong.duration ) * 1000;
|
||||
}, 5000 );
|
||||
if ( isNaN( this.progressBar ) ) {
|
||||
this.progressBar = 0;
|
||||
}
|
||||
}, 100 );
|
||||
},
|
||||
stopTimeTracker () {
|
||||
clearInterval( this.timeTracker );
|
||||
clearInterval( this.timeCorrector );
|
||||
this.oldPos = this.pos;
|
||||
},
|
||||
getImageData() {
|
||||
@@ -109,7 +102,6 @@ createApp( {
|
||||
this.songs = data.data.songQueue ?? [];
|
||||
this.pos = data.data.pos ?? 0;
|
||||
this.oldPos = data.data.pos ?? 0;
|
||||
this.startTime = new Date().getTime();
|
||||
this.progressBar = this.pos / this.playingSong.duration * 1000;
|
||||
this.queuePos = data.data.queuePos ?? 0;
|
||||
this.getImageData().then( palette => {
|
||||
@@ -122,7 +114,6 @@ createApp( {
|
||||
} else if ( data.type === 'pos' ) {
|
||||
this.pos = data.data;
|
||||
this.oldPos = data.data;
|
||||
this.startTime = new Date().getTime();
|
||||
this.progressBar = data.data / this.playingSong.duration * 1000;
|
||||
} else if ( data.type === 'isPlaying' ) {
|
||||
this.isPlaying = data.data;
|
||||
@@ -146,6 +137,8 @@ createApp( {
|
||||
source.onopen = () => {
|
||||
this.hasLoaded = true;
|
||||
};
|
||||
|
||||
let self = this;
|
||||
|
||||
source.addEventListener( 'error', function( e ) {
|
||||
if ( e.eventPhase == EventSource.CLOSED ) source.close();
|
||||
@@ -153,6 +146,11 @@ createApp( {
|
||||
if ( e.target.readyState == EventSource.CLOSED ) {
|
||||
console.log( 'disconnected' );
|
||||
}
|
||||
|
||||
// TODO: Notify about disconnect
|
||||
setTimeout( () => {
|
||||
self.connect();
|
||||
}, 1000 );
|
||||
}, false );
|
||||
},
|
||||
handleBackground() {
|
||||
@@ -206,28 +204,32 @@ createApp( {
|
||||
this.setVisualization();
|
||||
},
|
||||
setVisualization () {
|
||||
if ( this.visualizationSettings === 'bpm' ) {
|
||||
if ( this.playingSong.bpm && this.isPlaying ) {
|
||||
$( '.beat' ).show();
|
||||
$( '.beat' ).css( 'animation-duration', 60 / this.playingSong.bpm );
|
||||
$( '.beat' ).css( 'animation-delay', this.pos % ( 60 / this.playingSong.bpm * this.pos ) + this.playingSong.bpmOffset - ( 60 / this.playingSong.bpm * this.pos / 2 ) );
|
||||
} else {
|
||||
if ( Object.keys( this.playingSong ).length > 0 ) {
|
||||
if ( this.visualizationSettings === 'bpm' ) {
|
||||
if ( this.playingSong.bpm && this.isPlaying ) {
|
||||
$( '.beat' ).show();
|
||||
$( '.beat' ).css( 'animation-duration', 60 / this.playingSong.bpm );
|
||||
$( '.beat' ).css( 'animation-delay', this.pos % ( 60 / this.playingSong.bpm * this.pos ) + this.playingSong.bpmOffset - ( 60 / this.playingSong.bpm * this.pos / 2 ) );
|
||||
} else {
|
||||
$( '.beat' ).hide();
|
||||
}
|
||||
try {
|
||||
clearInterval( this.micAnalyzer );
|
||||
} catch ( err ) {}
|
||||
} else if ( this.visualizationSettings === 'off' ) {
|
||||
$( '.beat' ).hide();
|
||||
try {
|
||||
clearInterval( this.micAnalyzer );
|
||||
} catch ( err ) {}
|
||||
} else if ( this.visualizationSettings === 'mic' ) {
|
||||
$( '.beat-manual' ).hide();
|
||||
try {
|
||||
clearInterval( this.micAnalyzer );
|
||||
} catch ( err ) {}
|
||||
this.micAudioHandler();
|
||||
}
|
||||
try {
|
||||
clearInterval( this.micAnalyzer );
|
||||
} catch ( err ) {}
|
||||
} else if ( this.visualizationSettings === 'off' ) {
|
||||
$( '.beat' ).hide();
|
||||
try {
|
||||
clearInterval( this.micAnalyzer );
|
||||
} catch ( err ) {}
|
||||
} else if ( this.visualizationSettings === 'mic' ) {
|
||||
$( '.beat-manual' ).hide();
|
||||
try {
|
||||
clearInterval( this.micAnalyzer );
|
||||
} catch ( err ) {}
|
||||
this.micAudioHandler();
|
||||
} else {
|
||||
console.log( 'not playing yet' );
|
||||
}
|
||||
},
|
||||
micAudioHandler () {
|
||||
@@ -288,9 +290,9 @@ createApp( {
|
||||
},
|
||||
mounted() {
|
||||
this.connect();
|
||||
if ( this.visualizationSettings === 'mic' ) {
|
||||
this.micAudioHandler();
|
||||
}
|
||||
// if ( this.visualizationSettings === 'mic' ) {
|
||||
// this.micAudioHandler();
|
||||
// }
|
||||
},
|
||||
watch: {
|
||||
isPlaying( value ) {
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
</div>
|
||||
<div class="playback-pos-info">
|
||||
<div style="margin-right: auto;">{{ playbackPosBeautified }}</div>
|
||||
<div>{{ durationBeautified }}</div>
|
||||
<div @click="toggleShowMode()" style="cursor: pointer;">{{ durationBeautified }}</div>
|
||||
</div>
|
||||
<sliderView :active="audioLoaded" :position="playbackPos" :duration="playingSong.duration" @pos="( p ) => { setPos( p ) }"
|
||||
name="player"></sliderView>
|
||||
@@ -142,6 +142,7 @@ export default {
|
||||
hasLoadedSongs: false,
|
||||
isShowingFancyView: false,
|
||||
notifier: null,
|
||||
isShowingRemainingTime: false,
|
||||
}
|
||||
},
|
||||
components: {
|
||||
@@ -208,6 +209,22 @@ export default {
|
||||
}
|
||||
}, 300 );
|
||||
},
|
||||
toggleShowMode() {
|
||||
this.isShowingRemainingTime = !this.isShowingRemainingTime;
|
||||
if ( !this.isShowingRemainingTime ) {
|
||||
const minuteCounts = Math.floor( this.playingSong.duration / 60 );
|
||||
this.durationBeautified = String( minuteCounts ) + ':';
|
||||
if ( ( '' + minuteCounts ).length === 1 ) {
|
||||
this.durationBeautified = '0' + minuteCounts + ':';
|
||||
}
|
||||
const secondCounts = Math.floor( this.playingSong.duration - minuteCounts * 60 );
|
||||
if ( ( '' + secondCounts ).length === 1 ) {
|
||||
this.durationBeautified += '0' + secondCounts;
|
||||
} else {
|
||||
this.durationBeautified += secondCounts;
|
||||
}
|
||||
}
|
||||
},
|
||||
sendUpdate( update ) {
|
||||
let data = {};
|
||||
if ( update === 'pos' ) {
|
||||
@@ -250,14 +267,27 @@ export default {
|
||||
} else {
|
||||
this.playbackPosBeautified += secondCount;
|
||||
}
|
||||
}, 0.02 );
|
||||
this.progressTracker = setInterval( () => {
|
||||
this.sendUpdate( 'pos' );
|
||||
}, 5000 );
|
||||
|
||||
if ( this.isShowingRemainingTime ) {
|
||||
const minuteCounts = Math.floor( ( this.playingSong.duration - this.playbackPos ) / 60 );
|
||||
this.durationBeautified = '-' + String( minuteCounts ) + ':';
|
||||
if ( ( '' + minuteCounts ).length === 1 ) {
|
||||
this.durationBeautified = '-0' + minuteCounts + ':';
|
||||
}
|
||||
const secondCounts = Math.floor( ( this.playingSong.duration - this.playbackPos ) - minuteCounts * 60 );
|
||||
if ( ( '' + secondCounts ).length === 1 ) {
|
||||
this.durationBeautified += '0' + secondCounts;
|
||||
} else {
|
||||
this.durationBeautified += secondCounts;
|
||||
}
|
||||
}
|
||||
}, 20 );
|
||||
this.sendUpdate( 'pos' );
|
||||
this.sendUpdate( 'isPlaying' );
|
||||
} else if ( action === 'pause' ) {
|
||||
this.$emit( 'update', { 'type': 'playback', 'status': false } );
|
||||
musicPlayer.pause();
|
||||
this.sendUpdate( 'pos' );
|
||||
try {
|
||||
clearInterval( this.progressTracker );
|
||||
clearInterval( this.notifier );
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
gaöwovwef89voawö8p9 odövefw8öoaewpf89wec
|
||||
5
frontend/src/config/config.json
Normal file
5
frontend/src/config/config.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"connectionURL": "http://localhost:3000",
|
||||
"authKey": "gaöwovwef89voawö8p9 odövefw8öoaewpf89wec",
|
||||
"doConnect": true
|
||||
}
|
||||
Reference in New Issue
Block a user