Playback error fix, downloading on windows crash fix, logging POC
This commit is contained in:
parent
736fa01161
commit
96db2c3753
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
|
|
||||||
<v-dialog v-model='show' max-width='420'>
|
<v-dialog v-model='dShow' max-width='420'>
|
||||||
<v-card>
|
<v-card>
|
||||||
|
|
||||||
<v-card-title class='headline'>
|
<v-card-title class='headline'>
|
||||||
|
@ -57,6 +57,7 @@ export default {
|
||||||
],
|
],
|
||||||
qualityString: 'Settings quality',
|
qualityString: 'Settings quality',
|
||||||
autostart: true,
|
autostart: true,
|
||||||
|
dShow: this.show
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -98,6 +99,15 @@ export default {
|
||||||
return duration * this.$root.settings.downloadsQuality;
|
return duration * this.$root.settings.downloadsQuality;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
//Prevent errors on closing with mouse
|
||||||
|
show() {
|
||||||
|
this.dShow = this.show;
|
||||||
|
},
|
||||||
|
dShow() {
|
||||||
|
if (!this.dShow) this.$emit('close');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
|
@ -49,7 +49,7 @@ export default {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
let res = await this.$axios.get(`/lyrics/${this.songId}`);
|
let res = await this.$axios.get(`/lyrics/${this.songId}`);
|
||||||
if (res.data) this.lyrics = res.data;
|
if (res.data && res.data.lyrics.length > 0) this.lyrics = res.data;
|
||||||
|
|
||||||
} catch (e) {true;}
|
} catch (e) {true;}
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
|
|
|
@ -94,7 +94,10 @@ new Vue({
|
||||||
source: 'none',
|
source: 'none',
|
||||||
data: 'none'
|
data: 'none'
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
|
//Used to prevent double listen logging
|
||||||
|
logListenId: null
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// PLAYBACK METHODS
|
// PLAYBACK METHODS
|
||||||
|
@ -106,6 +109,8 @@ new Vue({
|
||||||
if (!this.audio || this.state != 1) return;
|
if (!this.audio || this.state != 1) return;
|
||||||
this.audio.play();
|
this.audio.play();
|
||||||
this.state = 2;
|
this.state = 2;
|
||||||
|
|
||||||
|
this.logListen();
|
||||||
},
|
},
|
||||||
pause() {
|
pause() {
|
||||||
if (!this.audio || this.state != 2) return;
|
if (!this.audio || this.state != 2) return;
|
||||||
|
@ -217,6 +222,7 @@ new Vue({
|
||||||
//Play
|
//Play
|
||||||
this.state = 2;
|
this.state = 2;
|
||||||
this.audio.play();
|
this.audio.play();
|
||||||
|
this.logListen();
|
||||||
await this.savePlaybackInfo();
|
await this.savePlaybackInfo();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -326,6 +332,16 @@ new Vue({
|
||||||
async cacheLibrary() {
|
async cacheLibrary() {
|
||||||
let res = await this.$axios.get(`/playlist/${this.profile.favoritesPlaylist}?full=idk`);
|
let res = await this.$axios.get(`/playlist/${this.profile.favoritesPlaylist}?full=idk`);
|
||||||
this.libraryTracks = res.data.tracks.map((t) => t.id);
|
this.libraryTracks = res.data.tracks.map((t) => t.id);
|
||||||
|
},
|
||||||
|
|
||||||
|
//Log song listened to deezer, only if allowed
|
||||||
|
async logListen() {
|
||||||
|
if (!this.settings.logListen) return;
|
||||||
|
if (this.logListenId == this.track.id) return;
|
||||||
|
if (!this.track || !this.track.id) return;
|
||||||
|
|
||||||
|
this.logListenId = this.track.id;
|
||||||
|
await this.$axios.put(`/log/${this.track.id}`);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async created() {
|
async created() {
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
</v-card>
|
</v-card>
|
||||||
|
|
||||||
<h1 class='pb-2'>Queue:</h1>
|
<h1 class='pb-2'>Queue:</h1>
|
||||||
<div class='text-h6 pb-2 d-flex'>Total: {{$root.downloads.length}}
|
<div class='text-h6 mr-4 pb-2 d-flex'>Total: {{$root.downloads.length}}
|
||||||
<v-btn @click='$root.toggleDownload' class='ml-2' color='primary'>
|
<v-btn @click='$root.toggleDownload' class='ml-4' color='primary'>
|
||||||
<div v-if='$root.downloading'>
|
<div v-if='$root.downloading'>
|
||||||
<v-icon>mdi-stop</v-icon>
|
<v-icon>mdi-stop</v-icon>
|
||||||
Stop
|
Stop
|
||||||
|
@ -32,15 +32,20 @@
|
||||||
</div>
|
</div>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<!-- Open dir -->
|
<!-- Open dir -->
|
||||||
<v-btn @click='openDir' class='ml-2' v-if='$root.settings.electron'>
|
<v-btn @click='openDir' class='ml-4' v-if='$root.settings.electron'>
|
||||||
<v-icon>mdi-folder</v-icon>
|
<v-icon>mdi-folder</v-icon>
|
||||||
Show folder
|
Show folder
|
||||||
</v-btn>
|
</v-btn>
|
||||||
|
<!-- Delete all -->
|
||||||
|
<v-btn @click='deleteDownload(-1)' class='ml-4' color='red'>
|
||||||
|
<v-icon>mdi-delete</v-icon>
|
||||||
|
Clear queue
|
||||||
|
</v-btn>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Downloads -->
|
<!-- Downloads -->
|
||||||
<v-list dense>
|
<v-list dense>
|
||||||
<div v-for='download in $root.downloads' :key='download.id'>
|
<div v-for='(download, index) in $root.downloads' :key='download.id'>
|
||||||
<v-list-item dense>
|
<v-list-item dense>
|
||||||
<v-list-item-avatar>
|
<v-list-item-avatar>
|
||||||
<v-img :src='download.track.albumArt.thumb'></v-img>
|
<v-img :src='download.track.albumArt.thumb'></v-img>
|
||||||
|
@ -49,6 +54,11 @@
|
||||||
<v-list-item-title>{{download.track.title}}</v-list-item-title>
|
<v-list-item-title>{{download.track.title}}</v-list-item-title>
|
||||||
<v-list-item-subtitle>{{download.track.artistString}}</v-list-item-subtitle>
|
<v-list-item-subtitle>{{download.track.artistString}}</v-list-item-subtitle>
|
||||||
</v-list-item-content>
|
</v-list-item-content>
|
||||||
|
<v-liste-item-action>
|
||||||
|
<v-btn icon @click='deleteDownload(index)'>
|
||||||
|
<v-icon>mdi-delete</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
</v-liste-item-action>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
</div>
|
</div>
|
||||||
</v-list>
|
</v-list>
|
||||||
|
@ -65,6 +75,11 @@ export default {
|
||||||
openDir() {
|
openDir() {
|
||||||
const {ipcRenderer} = window.require('electron');
|
const {ipcRenderer} = window.require('electron');
|
||||||
ipcRenderer.send('openDownloadsDir');
|
ipcRenderer.send('openDownloadsDir');
|
||||||
|
},
|
||||||
|
//Remove download from queue
|
||||||
|
async deleteDownload(i) {
|
||||||
|
await this.$axios.delete(`/downloads/${i}`);
|
||||||
|
this.$root.getDownloads();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,17 @@
|
||||||
hint='Variables: %title%, %artists%, %artist%, %feats%, %trackNumber%, %0trackNumber%, %album%'
|
hint='Variables: %title%, %artists%, %artist%, %feats%, %trackNumber%, %0trackNumber%, %album%'
|
||||||
></v-text-field>
|
></v-text-field>
|
||||||
|
|
||||||
|
<!-- Log listening -->
|
||||||
|
<v-list-item>
|
||||||
|
<v-list-item-action>
|
||||||
|
<v-checkbox v-model='$root.settings.logListen'></v-checkbox>
|
||||||
|
</v-list-item-action>
|
||||||
|
<v-list-item-content>
|
||||||
|
<v-list-item-title>Log track listens to Deezer</v-list-item-title>
|
||||||
|
<v-list-item-subtitle>This allows listening history, flow and recommendations to work properly.</v-list-item-subtitle>
|
||||||
|
</v-list-item-content>
|
||||||
|
</v-list-item>
|
||||||
|
|
||||||
<!-- Minimize to tray -->
|
<!-- Minimize to tray -->
|
||||||
<v-list-item v-if='$root.settings.electron'>
|
<v-list-item v-if='$root.settings.electron'>
|
||||||
<v-list-item-action>
|
<v-list-item-action>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "freezer",
|
"name": "freezer",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "background.js",
|
"main": "background.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
@ -156,6 +156,27 @@ class Downloads {
|
||||||
fs.promises.mkdir(Settings.getTempDownloads(), {recursive: true});
|
fs.promises.mkdir(Settings.getTempDownloads(), {recursive: true});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Remove download
|
||||||
|
async delete(index) {
|
||||||
|
//Clear all
|
||||||
|
if (index == -1) {
|
||||||
|
this.downloads = [];
|
||||||
|
await new Promise((res, rej) => {
|
||||||
|
this.db.remove({state: 0}, {}, (e) => {});
|
||||||
|
res();
|
||||||
|
})
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Remove single
|
||||||
|
if (index >= this.downloads.length) return;
|
||||||
|
await new Promise((res, rej) => {
|
||||||
|
this.db.remove({_id: this.downloads[index].id}, {}, (e) => {});
|
||||||
|
res();
|
||||||
|
});
|
||||||
|
this.downloads.splice(index, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Download {
|
class Download {
|
||||||
|
@ -263,9 +284,11 @@ class Download {
|
||||||
} catch (e) {};
|
} catch (e) {};
|
||||||
|
|
||||||
//Decrypt
|
//Decrypt
|
||||||
decryptor.decryptFile(decryptor.getKey(this.track.id), tmp, this.path);
|
decryptor.decryptFile(decryptor.getKey(this.track.id), tmp, `${tmp}.DEC`);
|
||||||
|
fs.promises.copyFile(`${tmp}.DEC`, this.path);
|
||||||
//Delete encrypted
|
//Delete encrypted
|
||||||
await fs.promises.unlink(tmp);
|
await fs.promises.unlink(tmp);
|
||||||
|
await fs.promises.unlink(`${tmp}.DEC`);
|
||||||
|
|
||||||
//Tags
|
//Tags
|
||||||
await this.tagAudio(this.path, this.track);
|
await this.tagAudio(this.path, this.track);
|
||||||
|
|
|
@ -274,7 +274,7 @@ app.get('/stream/:info', (req, res) => {
|
||||||
let dStart = start - (start % 2048);
|
let dStart = start - (start % 2048);
|
||||||
|
|
||||||
//Make request to Deezer CDN
|
//Make request to Deezer CDN
|
||||||
https.get(url, {headers: {'Range': `bytes=${dStart}-${end}`}}, (r) => {
|
let _request = https.get(url, {headers: {'Range': `bytes=${dStart}-${end}`}}, (r) => {
|
||||||
//Error from Deezer
|
//Error from Deezer
|
||||||
//TODO: Quality fallback
|
//TODO: Quality fallback
|
||||||
if (r.statusCode < 200 || r.statusCode > 300) {
|
if (r.statusCode < 200 || r.statusCode > 300) {
|
||||||
|
@ -311,6 +311,13 @@ app.get('/stream/:info', (req, res) => {
|
||||||
//Pipe: Deezer -> Decryptor -> Response
|
//Pipe: Deezer -> Decryptor -> Response
|
||||||
decryptor.pipe(res);
|
decryptor.pipe(res);
|
||||||
r.pipe(decryptor);
|
r.pipe(decryptor);
|
||||||
|
|
||||||
|
});
|
||||||
|
//Internet/Request error
|
||||||
|
_request.on('error', (e) => {
|
||||||
|
//console.log('Streaming error: ' + e);
|
||||||
|
//HTML audio will restart automatically
|
||||||
|
res.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -400,6 +407,27 @@ app.get('/downloads', async (req, res) => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//Delete singel download
|
||||||
|
app.delete('/downloads/:index', async (req, res) => {
|
||||||
|
let index = parseInt(req.params.index, 10);
|
||||||
|
await downloads.delete(index);
|
||||||
|
res.status(200).end();
|
||||||
|
});
|
||||||
|
|
||||||
|
//Log listen to deezer
|
||||||
|
app.put('/log/:id', async (req, res) => {
|
||||||
|
await deezer.callApi('log.listen', {
|
||||||
|
params: {
|
||||||
|
timestamp: Math.floor(new Date() / 1000),
|
||||||
|
ts_listen: Math.floor(new Date() / 1000),
|
||||||
|
type: 1,
|
||||||
|
stat: {seek: 0, pause: 0, sync: 0},
|
||||||
|
media: {id: req.params.id.toString(), type: 'song', format: 'MP3_128'}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
res.status(200).end();
|
||||||
|
});
|
||||||
|
|
||||||
//Redirect to index on unknown path
|
//Redirect to index on unknown path
|
||||||
app.all('*', (req, res) => {
|
app.all('*', (req, res) => {
|
||||||
res.redirect('/');
|
res.redirect('/');
|
||||||
|
|
|
@ -22,6 +22,8 @@ class Settings {
|
||||||
this.createAlbumFolder = true;
|
this.createAlbumFolder = true;
|
||||||
this.createArtistFolder = true;
|
this.createArtistFolder = true;
|
||||||
this.downloadFilename = '%0trackNumber%. %artists% - %title%';
|
this.downloadFilename = '%0trackNumber%. %artists% - %title%';
|
||||||
|
|
||||||
|
this.logListen = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Based on electorn app.getPath
|
//Based on electorn app.getPath
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "freezer",
|
"name": "freezer",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.0.0",
|
"version": "1.0.2",
|
||||||
"description": "",
|
"description": "",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"pack": "electron-builder --dir",
|
"pack": "electron-builder --dir",
|
||||||
|
|
Loading…
Reference in New Issue