Partial Progress with rewriting parts of Song.js

Also started work on Writing Storage.js

Storage.js manages info across sessions of melodii
This commit is contained in:
Paoda 2019-03-22 22:01:44 -07:00
parent dd58f5512f
commit 152ef58e41
6 changed files with 230 additions and 17 deletions

View File

@ -24,17 +24,16 @@ const filepath = new Filepath("C:\\Users\\Paoda\\Downloads\\Music");
(async () => {
let list = await filepath.getValidFiles();
let song = new Song(list[~~(Math.random() * list.length)]);
song = await Song.getMetadata(song);
Song.setAlbumArt(song.metadata);
let song = new Song(list[~~(Math.random() * list.length)], true);
await song.getMetadata();
mp.loadSong(song);
// mp.play();
mp.element.onended = async () => {
let song = new Song(list[~~(Math.random() * list.length)]);
song = await Song.getMetadata(song);
Song.setAlbumArt(song.metadata);
let song = new Song(list[~~(Math.random() * list.length)], true);
await song.getMetadata();
mp.loadSong(song);
mp.play();
};

View File

@ -152,7 +152,7 @@ export default class Body extends React.Component {
term = parseInt(term, 10);
temp.tbody = table.tbody.filter(obj => obj.year === term);
} else {
// type == time
// type === time
term = term.toLowerCase();
temp.tbody = table.tbody.filter(obj =>
obj.time.toLowerCase().includes(term)

View File

@ -262,7 +262,7 @@ export function sortTable(table, term) {
return a.year - b.year;
});
} else if (term === "time") {
//term == time convert the time into seconds
//term === time convert the time into seconds
//The messy else if + else is becomes a.inSeconds || b.inSeconds can be undefined.
tbody.sort((a, b) => {
if (a.inSeconds && b.inSeconds) {

View File

@ -49,21 +49,27 @@ export default class MusicPlayer {
*/
load(playlist) {
const song = playlist.next();
let path = song.location;
try {
this.element.src = this.getURICompatible(path);
this.element.load();
console.log("'" + path + "'" + " from " + playlist.title + " was succesfully loaded");
} catch(e) {
console.error(path + " failed to load " + e.name + " from " + playlist.title);
}
song.getMetadata().then(() => {
let path = song.location;
try {
this.element.src = this.getURICompatible(path);
this.element.load();
console.log("'" + path + "'" + " from " + playlist.title + " was succesfully loaded");
} catch(e) {
console.error(path + " failed to load " + e.name + " from " + playlist.title);
}
})
}
/** Loads Song
* @param {Song} song
*/
loadSong(song) {
song.displayAlbumArt();
if (archive.getCurrentSong() !== undefined)
archive.add(archive.getCurrentSong());
let path = song.location;

View File

@ -9,10 +9,85 @@ export default class Song {
* @param {String} path
* @param {Boolean} ShouldAlbumArtExist
*/
constructor(path, ShouldAlbumArtExist) { //whether album art should exist
constructor(path, shouldCreateAlbumArt = false) { //whether album art should exist
this.location = path;
this.title = "";
this.unf_time = 0;
this.album = "";
this.year = 0;
this.genres = [];
this.genre = "";
this.albumArt = "";
this.albumArtPresent = false;
this.shouldCreateAlbumArt = shouldCreateAlbumArt;
}
/**
* Gets Metadata from File.
*/
getMetadata() {
return new Promise((res, rej) => {
mm.parseFile(this.location, { native: true, duration: true }).then((metadata) => {
this.metadata = metadata;
console.log(metadata);
const format = metadata.format;
const common = metadata.common;
this.title = common.title || "";
this.unf_time = format.duration || 0;
this.album = common.album || "";
this.year = common.year || 0;
this.genre = common.genre ? common.genre.toString() : "";
if (this.shouldCreateAlbumArt) this.getAlbumArt(common.picture);
res();
}).catch((err) => rej(err));
});
}
/**
* Finds and Loads Album Art. Saves it to Song instance.
* TODO: Move the Event emission to only occur when the song is played.
* @param {*} picture
*/
getAlbumArt(picture) {
if (picture) {
if (picture.length > 0) {
console.log(picture);
const pic = picture[0];
this.albumArt = URL.createObjectURL(new Blob([pic.data], {
'type': pic.format
}));
this.albumArtPresent = true;
} else console.error(this.title + ' Has Album Art, however, no data was found.');
} else console.warn(this.title, + ' does not have Album Art.');
}
displayAlbumArt() {
console.log("Album Art", this.albumArt);
console.log("Album Art is Present: ", this.albumArtPresent)
if (this.albumArtPresent) Emitter.emit('updateAlbumArt', this.albumart);
else Emitter.emit('updateAlbumArt', noalbumart);
}
get time() {
let min = ~~((format.duration % 3600) / 60);
let sec = ~~(format.duration % 60);
if (sec < 10) sec = "0" + sec;
return min + ":" + sec;
}
/**
* Gets Metadata from Song
* @param {Song} song

133
src/melodii/Storage.js Normal file
View File

@ -0,0 +1,133 @@
import Song from './Song';
import Filepath from './Filepath'
/**
* This classs Manages:
* - User Settings
* - Metadata Saving
* - Passing of Metadata to Table Generation
*
* The Goal of This function is to remove the complete dependence of electron-settings
* and the fact that melodii (2019.03.22) relies on Tabe.js for Saving metadata as well as table configurations.
*/
class Storage {
constructor(path) {
this.path = path;
this.ready = false; // Async Actions still need to happen
/** @type {Array<Albums>} */
this.albums = [];
this.init();
}
/**
* Initialize the Storage Instance.
* @async
* @private
*/
async init() {
const filepath = new Filepath(path);
this.knownFiles = await filepath.getValidFiles();
this.ready = true; // All prerequisite Async has been done.
}
/**
* Goes Through all Known Songs and
* Creates Object Representatinos of all of them.
*
*/
parseSongList() {
const files = this.knownFiles;
// Need to Iterate over every song, find the name of the album and create an album with that instance.
// Store the album in some array so we know what albums exist and have a method to check whether the album has been
// created or not. Once that is done we can then create a Song based of that, and add it to the album.
// The end result should be an album class with all the properties filled in
// with attention put towards this.songs which would be an array of Song classes.
files.forEach(async path => {
const song = new Song(path, true);
const albumName = song.metadata.common.album;
if (!albumExists(albumName)) {
const album = new Album(albumName);
album.addSong(song);
this.albums.push(album)
}
});
const self = this;
/**
* Returns true if album is already present in List of known Albums.
* @param {*} name
*/
function albumExists(name) {
/// Please Write a Better version of this later.
let exists = false;
for (let i = 0; i < self.albums.length; i++) {
if (self.albums[i].name === name) {
exists = true;
break;
}
}
return exists;
}
}
}
/**
* Class Representation of an Album of Songs
*
*/
class Album {
/** @param {String} name */
constructor(name) {
// Properties Here are based off what is commonly found within Mp3 Tags.
/** @type {String} */
this.name
/** @type {Array<Song>} */
this.songs = [];
/** Album Artist */
this.artist = ""
}
/**
* Adds Class Representation of a Song to an Album Class
* @param {Song} song
*/
addSong(song) {
this.songs.push(song);
}
/**
* Removes a Song Class from the Album
* @param {String} path
*/
removeSong(path) {
console.error("This feature is unimplimented.")
}
}