mirror of
https://github.com/janishutz/MusicPlayerV2.git
synced 2025-11-25 13:04:23 +00:00
get it running again
This commit is contained in:
@@ -138,8 +138,8 @@ app.get( '/indexDirs', ( req, res ) => {
|
|||||||
|
|
||||||
app.get( '/getSongCover', ( req, res ) => {
|
app.get( '/getSongCover', ( req, res ) => {
|
||||||
if ( req.query.filename ) {
|
if ( req.query.filename ) {
|
||||||
if ( coverArtIndex[ req.query.filename ] ) {
|
if ( indexer.getImages( req.query.filename ) ) {
|
||||||
res.send( coverArtIndex[ req.query.filename ] );
|
res.send( indexer.getImages( req.query.filename ) );
|
||||||
} else {
|
} else {
|
||||||
res.status( 404 ).send( 'No cover image for this file' );
|
res.status( 404 ).send( 'No cover image for this file' );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
<div v-if="hasLoaded" style="width: 100%">
|
<div v-if="hasLoaded" style="width: 100%">
|
||||||
<div class="current-song-wrapper">
|
<div class="current-song-wrapper">
|
||||||
<span class="material-symbols-outlined fancy-view-song-art" v-if="!playingSong.hasCoverArt">music_note</span>
|
<span class="material-symbols-outlined fancy-view-song-art" v-if="!playingSong.hasCoverArt">music_note</span>
|
||||||
|
<img v-else-if="playingSong.hasCoverArt && playingSong.coverArtOrigin === 'api'" :src="playingSong.coverArtURL" class="fancy-view-song-art" id="current-image" crossorigin="anonymous">
|
||||||
<img v-else :src="'/getSongCover?filename=' + playingSong.filename" class="fancy-view-song-art" id="current-image">
|
<img v-else :src="'/getSongCover?filename=' + playingSong.filename" class="fancy-view-song-art" id="current-image">
|
||||||
<div class="current-song">
|
<div class="current-song">
|
||||||
<progress max="1000" id="progress" :value="progressBar"></progress>
|
<progress max="1000" id="progress" :value="progressBar"></progress>
|
||||||
@@ -33,7 +34,8 @@
|
|||||||
<div class="song-list-wrapper">
|
<div class="song-list-wrapper">
|
||||||
<div v-for="song in songQueue" class="song-list">
|
<div v-for="song in songQueue" class="song-list">
|
||||||
<span class="material-symbols-outlined song-image" v-if="!song.hasCoverArt && ( playingSong.filename !== song.filename || isPlaying )">music_note</span>
|
<span class="material-symbols-outlined song-image" v-if="!song.hasCoverArt && ( playingSong.filename !== song.filename || isPlaying )">music_note</span>
|
||||||
<img v-else-if="song.hasCoverArt && ( playingSong.filename !== song.filename || isPlaying )" :src="'/getSongCover?filename=' + song.filename" class="song-image">
|
<img v-else-if="song.hasCoverArt && ( playingSong.filename !== song.filename || isPlaying ) && song.coverArtOrigin === 'api'" :src="song.coverArtURL" class="song-image">
|
||||||
|
<img v-else-if="song.hasCoverArt && ( playingSong.filename !== song.filename || isPlaying ) && song.coverArtOrigin !== 'api'" :src="'/getSongCover?filename=' + song.filename" class="song-image">
|
||||||
<div v-if="playingSong.filename === song.filename && isPlaying" class="playing-symbols">
|
<div v-if="playingSong.filename === song.filename && isPlaying" class="playing-symbols">
|
||||||
<div class="playing-symbols-wrapper">
|
<div class="playing-symbols-wrapper">
|
||||||
<div class="playing-bar" id="bar-1"></div>
|
<div class="playing-bar" id="bar-1"></div>
|
||||||
|
|||||||
@@ -148,7 +148,6 @@ createApp( {
|
|||||||
}, false );
|
}, false );
|
||||||
},
|
},
|
||||||
handleBackground() {
|
handleBackground() {
|
||||||
// TODO: Add hotkeys
|
|
||||||
let colourDetails = [];
|
let colourDetails = [];
|
||||||
let colours = [];
|
let colours = [];
|
||||||
let differentEnough = true;
|
let differentEnough = true;
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
<div class="media-pool" :style="isShowingFancyView ? 'overflow: hidden;' : ''">
|
<div class="media-pool" :style="isShowingFancyView ? 'overflow: hidden;' : ''">
|
||||||
<div v-if="hasLoadedSongs" style="width: 100%;" class="song-list-wrapper">
|
<div v-if="hasLoadedSongs" style="width: 100%;" class="song-list-wrapper">
|
||||||
<div v-for="song in songQueue" class="song-list" :class="[ isPlaying ? ( currentlyPlaying === song.filename ? 'playing': 'not-playing' ) : 'not-playing', !isPlaying && currentlyPlaying === song.filename ? 'active-song': undefined ]">
|
<div v-for="song in songQueue" class="song-list" :class="[ isPlaying ? ( currentlyPlaying === song.filename ? 'playing': 'not-playing' ) : 'not-playing', !isPlaying && currentlyPlaying === song.filename ? 'active-song': undefined ]">
|
||||||
<span class="material-symbols-outlined song-image" v-if="!loadCoverArtPreview || !song.hasCoverArt">music_note</span>
|
<span class="material-symbols-outlined song-image" v-if="!song.hasCoverArt">music_note</span>
|
||||||
|
<img v-else-if="song.hasCoverArt && song.coverArtOrigin === 'api'" :src="song.coverArtURL" class="song-image">
|
||||||
<img v-else :src="'http://localhost:8081/getSongCover?filename=' + song.filename" class="song-image">
|
<img v-else :src="'http://localhost:8081/getSongCover?filename=' + song.filename" class="song-image">
|
||||||
<div v-if="currentlyPlaying === song.filename && isPlaying" class="playing-symbols">
|
<div v-if="currentlyPlaying === song.filename && isPlaying" class="playing-symbols">
|
||||||
<div class="playing-symbols-wrapper">
|
<div class="playing-symbols-wrapper">
|
||||||
@@ -195,7 +196,6 @@
|
|||||||
return {
|
return {
|
||||||
hasLoadedSongs: false,
|
hasLoadedSongs: false,
|
||||||
isLoadingSongs: false,
|
isLoadingSongs: false,
|
||||||
loadCoverArtPreview: true,
|
|
||||||
allSongs: [],
|
allSongs: [],
|
||||||
songQueue: [],
|
songQueue: [],
|
||||||
loadedDirs: [],
|
loadedDirs: [],
|
||||||
@@ -206,7 +206,8 @@
|
|||||||
repeat: false,
|
repeat: false,
|
||||||
isShowingFancyView: false,
|
isShowingFancyView: false,
|
||||||
errorOccurredLoading: false,
|
errorOccurredLoading: false,
|
||||||
coverArtSetting: 'api'
|
coverArtSetting: 'api',
|
||||||
|
doOverride: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -292,7 +293,7 @@
|
|||||||
},
|
},
|
||||||
indexFiles () {
|
indexFiles () {
|
||||||
for ( let dir in this.loadedDirs ) {
|
for ( let dir in this.loadedDirs ) {
|
||||||
fetch( 'http://localhost:8081/indexDirs?dir=' + this.loadedDirs[ dir ] + ( this.loadCoverArtPreview ? '&coverart=' + this.coverArtSetting : '' ) ).then( res => {
|
fetch( 'http://localhost:8081/indexDirs?dir=' + this.loadedDirs[ dir ] + '&coverart=' + this.coverArtSetting + '&doOverride=' + this.doOverride ).then( res => {
|
||||||
if ( res.status === 200 ) {
|
if ( res.status === 200 ) {
|
||||||
this.errorOccurredLoading = false;
|
this.errorOccurredLoading = false;
|
||||||
res.json().then( json => {
|
res.json().then( json => {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
<div class="song-info-wrapper">
|
<div class="song-info-wrapper">
|
||||||
<div v-if="audioLoaded" @click="showFancyView()" style="cursor: pointer;">
|
<div v-if="audioLoaded" @click="showFancyView()" style="cursor: pointer;">
|
||||||
<span class="material-symbols-outlined image" v-if="!playingSong.hasCoverArt">music_note</span>
|
<span class="material-symbols-outlined image" v-if="!playingSong.hasCoverArt">music_note</span>
|
||||||
|
<img v-else-if="playingSong.hasCoverArt && playingSong.coverArtOrigin === 'api'" :src="playingSong.coverArtURL" class="image">
|
||||||
<img v-else :src="'http://localhost:8081/getSongCover?filename=' + playingSong.filename" class="image">
|
<img v-else :src="'http://localhost:8081/getSongCover?filename=' + playingSong.filename" class="image">
|
||||||
</div>
|
</div>
|
||||||
<span class="material-symbols-outlined image" v-else>music_note</span>
|
<span class="material-symbols-outlined image" v-else>music_note</span>
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ const allowedFileTypes = [ '.mp3', '.wav', '.flac' ];
|
|||||||
const csv = require( 'csv-parser' );
|
const csv = require( 'csv-parser' );
|
||||||
const path = require( 'path' );
|
const path = require( 'path' );
|
||||||
|
|
||||||
let indexedData = {};
|
|
||||||
let coverArtIndex = {};
|
let coverArtIndex = {};
|
||||||
|
|
||||||
module.exports.index = ( req ) => {
|
module.exports.index = ( req ) => {
|
||||||
@@ -25,19 +24,21 @@ module.exports.index = ( req ) => {
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
( async() => {
|
( async() => {
|
||||||
// TODO: Check for songlist.csv or songlist.json file and use the data provided there for each song to override
|
// Check for songlist.csv or songlist.json file and use the data provided there for each song to override
|
||||||
// what was found automatically. If no song title was found in songlist or metadata, use filename
|
// what was found automatically. If no song title was found in songlist or metadata, use filename
|
||||||
// TODO: Also save found information to those files and don't rerun checks if data is present
|
// additionally check if dir has been indexed (songs.json file)
|
||||||
if ( dat.includes( 'songlist.csv' ) || dat.includes( 'songlist.json' ) ) {
|
if ( dat.includes( 'songs.json' ) ) {
|
||||||
parseExistingData( dat, req.query.dir ).then( data => {
|
|
||||||
parseDir( dat, req, data );
|
|
||||||
} );
|
|
||||||
} else if ( dat.includes( 'songs.json' ) ) {
|
|
||||||
parseExistingData( dat, req.query.dir ).then( data => {
|
parseExistingData( dat, req.query.dir ).then( data => {
|
||||||
resolve( data );
|
resolve( data );
|
||||||
} ).catch( err => {
|
} ).catch( err => {
|
||||||
reject( err );
|
reject( err );
|
||||||
} );
|
} );
|
||||||
|
} else if ( dat.includes( 'songlist.csv' ) || dat.includes( 'songlist.json' ) ) {
|
||||||
|
parseExistingData( dat, req.query.dir ).then( data => {
|
||||||
|
parseDir( dat, req, data ).then( indexedDir => {
|
||||||
|
resolve( indexedDir );
|
||||||
|
} );
|
||||||
|
} );
|
||||||
} else {
|
} else {
|
||||||
resolve( await parseDir( dat, req ) );
|
resolve( await parseDir( dat, req ) );
|
||||||
}
|
}
|
||||||
@@ -46,6 +47,10 @@ module.exports.index = ( req ) => {
|
|||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports.getImages = ( filename ) => {
|
||||||
|
return coverArtIndex[ filename ];
|
||||||
|
};
|
||||||
|
|
||||||
const parseExistingData = ( dat, dir ) => {
|
const parseExistingData = ( dat, dir ) => {
|
||||||
return new Promise( ( resolve, reject ) => {
|
return new Promise( ( resolve, reject ) => {
|
||||||
if ( dat.includes( 'songs.json' ) ) {
|
if ( dat.includes( 'songs.json' ) ) {
|
||||||
@@ -56,12 +61,11 @@ const parseExistingData = ( dat, dir ) => {
|
|||||||
let results = {};
|
let results = {};
|
||||||
let pos = 0;
|
let pos = 0;
|
||||||
fs.createReadStream( path.join( dir + '/songlist.csv' ) )
|
fs.createReadStream( path.join( dir + '/songlist.csv' ) )
|
||||||
.pipe( csv( [ 'name', 'artist', 'dancingStyle', 'tempo' ] ) )
|
.pipe( csv() )
|
||||||
.on( 'data', ( data ) => {
|
.on( 'data', ( data ) => {
|
||||||
results[ dir + '/' + dat[ pos ] ] = data;
|
results[ dir + '/' + dat[ pos ] ] = data;
|
||||||
pos += 1;
|
pos += 1;
|
||||||
} ).on( 'end', () => {
|
} ).on( 'end', () => {
|
||||||
console.log( results );
|
|
||||||
resolve( results );
|
resolve( results );
|
||||||
} );
|
} );
|
||||||
} else if ( dat.includes( 'songlist.json' ) ) {
|
} else if ( dat.includes( 'songlist.json' ) ) {
|
||||||
@@ -71,12 +75,11 @@ const parseExistingData = ( dat, dir ) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hasCompletedFetching = {};
|
hasCompletedFetching = {};
|
||||||
|
let files = {};
|
||||||
const parseDir = ( dat, req, existingData ) => {
|
const parseDir = ( dat, req, existingData ) => {
|
||||||
console.log( existingData );
|
|
||||||
return new Promise( ( resolve, reject ) => {
|
return new Promise( ( resolve, reject ) => {
|
||||||
( async() => {
|
( async() => {
|
||||||
let files = {};
|
files = {};
|
||||||
for ( let file in dat ) {
|
for ( let file in dat ) {
|
||||||
if ( allowedFileTypes.includes( dat[ file ].slice( dat[ file ].indexOf( '.' ), dat[ file ].length ) ) ) {
|
if ( allowedFileTypes.includes( dat[ file ].slice( dat[ file ].indexOf( '.' ), dat[ file ].length ) ) ) {
|
||||||
try {
|
try {
|
||||||
@@ -94,7 +97,9 @@ const parseDir = ( dat, req, existingData ) => {
|
|||||||
'numberOfChannels': metadata[ 'format' ][ 'numberOfChannels' ],
|
'numberOfChannels': metadata[ 'format' ][ 'numberOfChannels' ],
|
||||||
'container': metadata[ 'format' ][ 'container' ],
|
'container': metadata[ 'format' ][ 'container' ],
|
||||||
'filename': req.query.dir + '/' + dat[ file ],
|
'filename': req.query.dir + '/' + dat[ file ],
|
||||||
|
'coverArtOrigin': req.query.coverart ?? 'none',
|
||||||
}
|
}
|
||||||
|
runReplace( existingData, req.query.dir + '/' + dat[ file ], req.query.doOverride ?? false );
|
||||||
if ( req.query.coverart == 'meta' ) {
|
if ( req.query.coverart == 'meta' ) {
|
||||||
if ( metadata[ 'common' ][ 'picture' ] ) {
|
if ( metadata[ 'common' ][ 'picture' ] ) {
|
||||||
files[ req.query.dir + '/' + dat[ file ] ][ 'hasCoverArt' ] = true;
|
files[ req.query.dir + '/' + dat[ file ] ][ 'hasCoverArt' ] = true;
|
||||||
@@ -102,28 +107,10 @@ const parseDir = ( dat, req, existingData ) => {
|
|||||||
} else {
|
} else {
|
||||||
files[ req.query.dir + '/' + dat[ file ] ][ 'hasCoverArt' ] = false;
|
files[ req.query.dir + '/' + dat[ file ] ][ 'hasCoverArt' ] = false;
|
||||||
}
|
}
|
||||||
|
hasCompletedFetching[ req.query.dir + '/' + dat[ file ] ] = true;
|
||||||
} else if ( req.query.coverart == 'api' ) {
|
} else if ( req.query.coverart == 'api' ) {
|
||||||
hasCompletedFetching[ req.query.dir + '/' + dat[ file ] ] = false;
|
hasCompletedFetching[ req.query.dir + '/' + dat[ file ] ] = false;
|
||||||
imageFetcher.fetch( 'songs', metadata[ 'common' ][ 'artist' ] + ' ' + metadata[ 'common' ][ 'title' ], ( err, data ) => {
|
fetchImages( metadata[ 'common' ][ 'title' ], metadata[ 'common' ][ 'artist' ], metadata[ 'common' ][ 'year' ], req.query.dir, dat[ file ] );
|
||||||
if ( err ) {
|
|
||||||
files[ req.query.dir + '/' + dat[ file ] ][ 'hasCoverArt' ] = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ( data.results.songs ) {
|
|
||||||
if ( data.results.songs.data ) {
|
|
||||||
let url = data.results.songs.data[ 0 ].attributes.artwork.url;
|
|
||||||
url = url.replace( '{w}', data.results.songs.data[ 0 ].attributes.artwork.width );
|
|
||||||
url = url.replace( '{h}', data.results.songs.data[ 0 ].attributes.artwork.height );
|
|
||||||
console.log( url );
|
|
||||||
} else {
|
|
||||||
files[ req.query.dir + '/' + dat[ file ] ][ 'hasCoverArt' ] = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
files[ req.query.dir + '/' + dat[ file ] ][ 'hasCoverArt' ] = false;
|
|
||||||
}
|
|
||||||
hasCompletedFetching[ req.query.dir + '/' + dat[ file ] ] = true;
|
|
||||||
} );
|
|
||||||
files[ req.query.dir + '/' + dat[ file ] ][ 'hasCoverArt' ] = true;
|
|
||||||
} else {
|
} else {
|
||||||
files[ req.query.dir + '/' + dat[ file ] ][ 'hasCoverArt' ] = false;
|
files[ req.query.dir + '/' + dat[ file ] ][ 'hasCoverArt' ] = false;
|
||||||
}
|
}
|
||||||
@@ -134,14 +121,15 @@ const parseDir = ( dat, req, existingData ) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let ok = false;
|
let ok = false;
|
||||||
setInterval( () => {
|
let waiter = setInterval( () => {
|
||||||
for ( let song in hasCompletedFetching ) {
|
for ( let song in hasCompletedFetching ) {
|
||||||
if ( !hasCompletedFetching[ song ] ) {
|
if ( !hasCompletedFetching[ song ] ) {
|
||||||
ok = false;
|
ok = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( ok ) {
|
if ( ok ) {
|
||||||
indexedData[ req.query.dir ] = files;
|
saveToDisk( req.query.dir );
|
||||||
|
clearInterval( waiter );
|
||||||
resolve( files );
|
resolve( files );
|
||||||
}
|
}
|
||||||
ok = true;
|
ok = true;
|
||||||
@@ -150,7 +138,59 @@ const parseDir = ( dat, req, existingData ) => {
|
|||||||
} )
|
} )
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const runReplace = ( existingData, currentFile, doOverride ) => {
|
||||||
|
for ( let param in existingData[ currentFile ] ) {
|
||||||
|
if ( !files[ currentFile ][ param ] || doOverride ) {
|
||||||
|
files[ currentFile ][ param ] = existingData[ currentFile ][ param ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const saveToDisk = () => {
|
let imageQueue = [];
|
||||||
|
let runInterval = null;
|
||||||
|
const fetchImages = ( title, artist, year, dir, filename ) => {
|
||||||
|
imageQueue.push( { 'title': title, 'artist': artist, 'year': year, 'dir': dir, 'filename': filename } );
|
||||||
|
if ( runInterval === null ) {
|
||||||
|
runInterval = setInterval( () => {
|
||||||
|
if ( imageQueue.length > 0 ) {
|
||||||
|
const cur = imageQueue.reverse().pop();
|
||||||
|
imageQueue.reverse();
|
||||||
|
runFetch( cur.title, cur.artist, cur.year, cur.dir, cur.filename );
|
||||||
|
} else {
|
||||||
|
clearInterval( runInterval );
|
||||||
|
runInterval = null;
|
||||||
|
}
|
||||||
|
}, 100 );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const runFetch = ( title, artist, year, dir, filename ) => {
|
||||||
|
imageFetcher.fetch( 'songs', ( artist ?? '' ) + ' ' + ( title ?? '' ) + ' ' + ( year ?? '' ), ( err, data ) => {
|
||||||
|
if ( err ) {
|
||||||
|
files[ dir + '/' + filename ][ 'hasCoverArt' ] = false;
|
||||||
|
console.error( dir + '/' + filename );
|
||||||
|
console.error( err );
|
||||||
|
hasCompletedFetching[ dir + '/' + filename ] = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( data.results.songs ) {
|
||||||
|
if ( data.results.songs.data ) {
|
||||||
|
let url = data.results.songs.data[ 0 ].attributes.artwork.url;
|
||||||
|
url = url.replace( '{w}', data.results.songs.data[ 0 ].attributes.artwork.width );
|
||||||
|
url = url.replace( '{h}', data.results.songs.data[ 0 ].attributes.artwork.height );
|
||||||
|
files[ dir + '/' + filename ][ 'coverArtURL' ] = url;
|
||||||
|
files[ dir + '/' + filename ][ 'hasCoverArt' ] = true;
|
||||||
|
} else {
|
||||||
|
files[ dir + '/' + filename ][ 'hasCoverArt' ] = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
files[ dir + '/' + filename ][ 'hasCoverArt' ] = false;
|
||||||
|
}
|
||||||
|
hasCompletedFetching[ dir + '/' + filename ] = true;
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const saveToDisk = ( dir ) => {
|
||||||
|
fs.writeFileSync( path.join( dir + '/songs.json' ), JSON.stringify( files ) );
|
||||||
};
|
};
|
||||||
Reference in New Issue
Block a user