Release 4.1.2 4.1.2
authorRemixDev <DeezloaderRemix@gmail.com>
Sat, 25 Aug 2018 20:34:30 +0000 (22:34 +0200)
committerRemixDev <DeezloaderRemix@gmail.com>
Sat, 25 Aug 2018 20:34:30 +0000 (22:34 +0200)
README.md
app/app.js
app/deezer-api.js
app/default.json
app/package.json
app/public/css/style.css
app/public/index.html
app/public/js/main.js
package.json

index 0d906bb15757bb356bdf1622e3ef92d860a6bde1..1038d6079693066641d76f06dcf1c03d8289e637 100644 (file)
--- a/README.md
+++ b/README.md
@@ -1,9 +1,9 @@
 # Deezloader Remix
-### Latest Version: 4.1.1
+### Latest Version: 4.1.2
 Deezloader Remix is an improved version of Deezloader based on the Reborn branch.<br/>
 With this app you can download songs, playlists and albums directly from Deezers Server in a single and well packaged app.
 
-![](https://i.imgur.com/GbouYCB.png)
+![](https://i.imgur.com/7Qbvu1f.png)
 ## Features
 ### Base Features
 * Download MP3s and FLACs directly from Deezer Servers
index 4f38fa6317a44e5060ff6c35f4b45fc1e593d81a..522dd2b1a2bd525b3f31c9c8dedbf90205bd70d6 100644 (file)
@@ -181,7 +181,9 @@ io.sockets.on('connection', function (socket) {
                        if (!track.trackSocket.currentItem.percentage) {
                                track.trackSocket.currentItem.percentage = 0;
                        }
-                       if(track.format == 9){
+                       if (parseInt(track.SNG_ID)<0){
+                               complete = track.FILESIZE;
+                       }else if(track.format == 9){
                                complete = track.FILESIZE_FLAC;
                        }else{
                                if (track.FILESIZE_MP3_320) {
@@ -221,32 +223,58 @@ io.sockets.on('connection', function (socket) {
        }
 
        function socketDownloadTrack(data){
-               Deezer.getTrack(data.id, data.settings.maxBitrate, function (track, err) {
-                       if (err) {
-                               return;
-                       }
-                       let queueId = "id" + Math.random().toString(36).substring(2);
-                       let _track = {
-                               name: track["SNG_TITLE"],
-                               artist: track["ART_NAME"],
-                               size: 1,
-                               downloaded: 0,
-                               failed: 0,
-                               queueId: queueId,
-                               id: track["SNG_ID"],
-                               type: "track"
-                       };
-                       data.settings.trackInfo= slimDownTrackInfo(track);
-                       if (track["VERSION"]) _track.name = _track.name + " " + track["VERSION"];
-                       _track.settings = data.settings || {};
-                       addToQueue(JSON.parse(JSON.stringify(_track)));
-               });
+               if(parseInt(data.id)>0){
+                       Deezer.getTrack(data.id, data.settings.maxBitrate, function (track, err) {
+                               if (err) {
+                                       logger.error(err)
+                                       return;
+                               }
+                               let queueId = "id" + Math.random().toString(36).substring(2);
+                               let _track = {
+                                       name: track["SNG_TITLE"],
+                                       artist: track["ART_NAME"],
+                                       size: 1,
+                                       downloaded: 0,
+                                       failed: 0,
+                                       queueId: queueId,
+                                       id: track["SNG_ID"],
+                                       type: "track"
+                               };
+                               data.settings.trackInfo= slimDownTrackInfo(track);
+                               if (track["VERSION"]) _track.name = _track.name + " " + track["VERSION"];
+                               _track.settings = data.settings || {};
+                               addToQueue(JSON.parse(JSON.stringify(_track)));
+                       });
+               }else{
+                       Deezer.getLocalTrack(data.id, function (track, err) {
+                               if (err) {
+                                       logger.error(err)
+                                       return;
+                               }
+                               let queueId = "id" + Math.random().toString(36).substring(2);
+                               let _track = {
+                                       name: track["SNG_TITLE"],
+                                       artist: track["ART_NAME"],
+                                       size: 1,
+                                       downloaded: 0,
+                                       failed: 0,
+                                       queueId: queueId,
+                                       id: track["SNG_ID"],
+                                       type: "track"
+                               };
+                               data.settings.trackInfo= slimDownTrackInfo(track);
+                               if (track["VERSION"]) _track.name = _track.name + " " + track["VERSION"];
+                               _track.settings = data.settings || {};
+                               addToQueue(JSON.parse(JSON.stringify(_track)));
+                       });
+               }
        }
        socket.on("downloadtrack", data=>{socketDownloadTrack(data)});
 
        function socketDownloadPlaylist(data){
                Deezer.getPlaylist(data.id, function (playlist, err) {
                        if (err) {
+                               logger.error(err)
                                return;
                        }
                        let queueId = "id" + Math.random().toString(36).substring(2);
@@ -265,6 +293,10 @@ io.sockets.on('connection', function (socket) {
                        _playlist.settings = data.settings || {};
                        if (_playlist.size>400){
                                Deezer.getPlaylistTracks(data.id, function (playlist, err) {
+                                       if (err){
+                                               logger.error(err)
+                                               return;
+                                       }
                                        _playlist.size = playlist.data.length
                                        _playlist.tracks = playlist.data
                                        addToQueue(JSON.parse(JSON.stringify(_playlist)));
@@ -279,6 +311,7 @@ io.sockets.on('connection', function (socket) {
        function socketDownloadAlbum(data){
                Deezer.getAlbum(data.id, function (album, err) {
                        if (err) {
+                               logger.error(err)
                                return;
                        }
                        let queueId = "id" + Math.random().toString(36).substring(2);
@@ -304,6 +337,7 @@ io.sockets.on('connection', function (socket) {
        function socketDownloadArtist(data){
                Deezer.getArtistAlbums(data.id, function (albums, err) {
                        if (err) {
+                               logger.error(err)
                                return;
                        }
                        (function sendAllAlbums(i) {
@@ -337,6 +371,9 @@ io.sockets.on('connection', function (socket) {
                        };
                        _playlist.settings = data.settings || {};
                        addToQueue(JSON.parse(JSON.stringify(_playlist)));
+               }).catch(err=>{
+                       logger.error(err)
+                       return;
                })
        });
 
@@ -354,7 +391,7 @@ io.sockets.on('connection', function (socket) {
                        }
                        socket.lastQueueId = downloading.queueId;
                }
-
+               let filePath;
                logger.info(`Registered ${downloading.type}: ${downloading.id} | ${downloading.artist} - ${downloading.name}`);
                switch(downloading.type){
                        case "track":
@@ -391,7 +428,19 @@ io.sockets.on('connection', function (socket) {
                                downloading.settings.albName = downloading.name;
                                downloading.settings.artName = downloading.artist;
                                downloading.errorLog = "";
+                               downloading.searchedLog = "";
                                downloading.playlistArr = Array(downloading.size);
+                               filePath = mainFolder;
+                               if (downloading.settings.createArtistFolder || downloading.settings.createAlbumFolder) {
+                                       if (downloading.settings.createArtistFolder) {
+                                               filePath += antiDot(fixName(downloading.settings.artName)) + path.sep;
+                                       }
+                                       if (downloading.settings.createAlbumFolder) {
+                                               filePath += antiDot(fixName(settingsRegexAlbum(downloading.settings.foldername,downloading.settings.artName,downloading.settings.albName,downloading.settings.albumInfo.release_date.slice(0, 4),downloading.settings.albumInfo.record_type,downloading.settings.albumInfo.label))) + path.sep;
+                                       }
+                               } else if (downloading.settings.artName) {
+                                       filePath += antiDot(fixName(settingsRegexAlbum(downloading.settings.foldername,downloading.settings.artName,downloading.settings.albName,downloading.settings.albumInfo.release_date.slice(0, 4),downloading.settings.albumInfo.record_type,downloading.settings.albumInfo.label))) + path.sep;
+                               }
                                downloading.finished = new Promise((resolve,reject)=>{
                                        downloading.playlistContent.every(function (t) {
                                                socket.trackQueue.push(cb=>{
@@ -403,10 +452,11 @@ io.sockets.on('connection', function (socket) {
                                                        downloadTrack(t, downloading.settings, null, function (err, track) {
                                                                if (!err) {
                                                                        downloading.downloaded++;
-                                                                       downloading.playlistArr[track[0]] = track[1];
+                                                                       downloading.playlistArr[track.playlistData[0]] = track.playlistData[1].split(filePath)[1];
+                                                                       if (track.searched) downloading.searchedLog += `${t.artist} - ${t.name}\r\n`
                                                                } else {
                                                                        downloading.failed++;
-                                                                       downloading.errorLog += track+"\r\n";
+                                                                       downloading.errorLog += `${t.id} | ${t.artist} - ${t.name}\r\n`;
                                                                }
                                                                socket.emit("downloadProgress", {
                                                                        queueId: downloading.queueId,
@@ -433,17 +483,6 @@ io.sockets.on('connection', function (socket) {
                                                queueId: downloading.queueId,
                                                percentage: 100
                                        });
-                                       let filePath = mainFolder;
-                                       if (downloading.settings.createArtistFolder || downloading.settings.createAlbumFolder) {
-                                               if (downloading.settings.createArtistFolder) {
-                                                       filePath += antiDot(fixName(downloading.settings.artName)) + path.sep;
-                                               }
-                                               if (downloading.settings.createAlbumFolder) {
-                                                       filePath += antiDot(fixName(settingsRegexAlbum(downloading.settings.foldername,downloading.settings.artName,downloading.settings.albName,downloading.settings.albumInfo.release_date.slice(0, 4),downloading.settings.albumInfo.record_type))) + path.sep;
-                                               }
-                                       } else if (downloading.settings.artName) {
-                                               filePath += antiDot(fixName(settingsRegexAlbum(downloading.settings.foldername,downloading.settings.artName,downloading.settings.albName,downloading.settings.albumInfo.release_date.slice(0, 4),downloading.settings.albumInfo.record_type))) + path.sep;
-                                       }
                                        if (downloading.settings.logErrors){
                                                if (downloading.errorLog != ""){
                                                        if (!fs.existsSync(filePath)) fs.mkdirSync(filePath);
@@ -452,6 +491,14 @@ io.sockets.on('connection', function (socket) {
                                                        if (fs.existsSync(filePath+"notFound.txt")) fs.unlinkSync(filePath+"notFound.txt");
                                                }
                                        }
+                                       if (downloading.settings.logSearched){
+                                               if (downloading.searchedLog != ""){
+                                                       if (!fs.existsSync(filePath)) fs.mkdirSync(filePath);
+                                                       fs.writeFileSync(filePath+"alternativeSongs.txt",downloading.searchedLog)
+                                               }else{
+                                                       if (fs.existsSync(filePath+"alternativeSongs.txt")) fs.unlinkSync(filePath+"alternativeSongs.txt");
+                                               }
+                                       }
                                        if (downloading.settings.createM3UFile){
                                                fs.writeFileSync(filePath + "playlist.m3u", downloading.playlistArr.join("\r\n"));
                                        }
@@ -472,15 +519,17 @@ io.sockets.on('connection', function (socket) {
                                                if (t.FALLBACK.SNG_ID)
                                                        return {id: t.id, fallback: t.FALLBACK.SNG_ID, name: t.title, artist: t.artist.name, index: i, queueId: downloading.queueId}
                                        }else{
-                                               return {id: t.id, name: t.title, artist: t.artist.name, index: i, queueId: downloading.queueId}
+                                               return {id: t.id, name: t.title, artist: t.artist.name, index: i+"", queueId: downloading.queueId}
                                        }
                                })
                                downloading.settings.plName = downloading.name;
                                downloading.errorLog = ""
+                               downloading.searchedLog = "";
                                downloading.playlistArr = Array(downloading.size);
                                downloading.settings.playlist = {
                                        fullSize: downloading.playlistContent.length
                                };
+                               filePath = mainFolder+antiDot(fixName(downloading.settings.plName)) + path.sep
                                downloading.finished = new Promise((resolve,reject)=>{
                                        downloading.playlistContent.every(function (t) {
                                                socket.trackQueue.push(cb=>{
@@ -492,10 +541,11 @@ io.sockets.on('connection', function (socket) {
                                                        downloadTrack(t, downloading.settings, null, function (err, track) {
                                                                if (!err) {
                                                                        downloading.downloaded++;
-                                                                       downloading.playlistArr[track[0]] = track[1];
+                                                                       downloading.playlistArr[track.playlistData[0]] = track.playlistData[1].split(filePath)[1];
+                                                                       if (track.searched) downloading.searchedLog += `${t.artist} - ${t.name}\r\n`
                                                                } else {
                                                                        downloading.failed++;
-                                                                       downloading.errorLog += track+"\r\n"
+                                                                       downloading.errorLog += `${t.id} | ${t.artist} - ${t.name}\r\n`
                                                                }
                                                                socket.emit("downloadProgress", {
                                                                        queueId: downloading.queueId,
@@ -516,7 +566,6 @@ io.sockets.on('connection', function (socket) {
                                                queueId: downloading.queueId,
                                                percentage: 100
                                        });
-                                       let filePath = mainFolder+antiDot(fixName(downloading.settings.plName)) + path.sep
                                        if (downloading.settings.logErrors){
                                                if (downloading.errorLog != ""){
                                                        if (!fs.existsSync(filePath)) fs.mkdirSync(filePath);
@@ -525,12 +574,20 @@ io.sockets.on('connection', function (socket) {
                                                        if (fs.existsSync(filePath+"notFound.txt")) fs.unlinkSync(filePath+"notFound.txt");
                                                }
                                        }
+                                       if (downloading.settings.logSearched){
+                                               if (downloading.searchedLog != ""){
+                                                       if (!fs.existsSync(filePath)) fs.mkdirSync(filePath);
+                                                       fs.writeFileSync(filePath+"alternativeSongs.txt",downloading.searchedLog)
+                                               }else{
+                                                       if (fs.existsSync(filePath+"alternativeSongs.txt")) fs.unlinkSync(filePath+"alternativeSongs.txt");
+                                               }
+                                       }
                                        if (downloading.settings.createM3UFile){
                                                fs.writeFileSync(filePath + "playlist.m3u", downloading.playlistArr.join("\r\n"));
                                        }
                                        if (downloading.settings.saveArtwork){
                                                if (!fs.existsSync(filePath)) fs.mkdirSync(filePath);
-                                               let imgPath = filePath + "folder"+(settings.PNGcovers ? ".png" : ".jpg");
+                                               let imgPath = filePath + antiDot(fixName(settingsRegexCover(downloading.settings.coverImageTemplate,downloading.artist,downloading.name)))+(downloading.settings.PNGcovers ? ".png" : ".jpg");
                                                if (downloading.cover){
                                                        downloading.cover = downloading.cover.replace("56x56",`${downloading.settings.artworkSize}x${downloading.settings.artworkSize}`)
                                                        request.get(downloading.cover, {encoding: 'binary'}, function(error,response,body){
@@ -605,12 +662,14 @@ io.sockets.on('connection', function (socket) {
                                        logger.info("All tracks converted, starting download");
                                        socket.emit("downloadStarted", {queueId: downloading.queueId});
                                        downloading.errorLog = "";
+                                       downloading.searchedLog = "";
                                        downloading.settings.playlist = {
                                                fullSize: values.length
                                        };
+                                       filePath = mainFolder+antiDot(fixName(downloading.settings.plName)) + path.sep
                                        downloading.finished = new Promise((resolve,reject)=>{
                                                values.every(function (t) {
-                                                       t.index = values.indexOf(t)
+                                                       t.index = values.indexOf(t)+""
                                                        t.queueId = downloading.queueId
                                                        socket.trackQueue.push(cb=>{
                                                                if (!socket.downloadQueue[downloading.queueId]) {
@@ -621,10 +680,11 @@ io.sockets.on('connection', function (socket) {
                                                                downloadTrack(t, downloading.settings, null, function (err, track) {
                                                                        if (!err) {
                                                                                downloading.downloaded++;
-                                                                               downloading.playlistArr[track[0]] = track[1];
+                                                                               downloading.playlistArr[track.playlistData[0]] = track.playlistData[1].split(filePath)[1];
+                                                                               if (track.searched) downloading.searchedLog += `${t.artist} - ${t.name}\r\n`
                                                                        } else {
                                                                                downloading.failed++;
-                                                                               downloading.errorLog += track+"\r\n"
+                                                                               downloading.errorLog += `${t.id} | ${t.artist} - ${t.name}\r\n`
                                                                        }
                                                                        socket.emit("downloadProgress", {
                                                                                queueId: downloading.queueId,
@@ -645,7 +705,6 @@ io.sockets.on('connection', function (socket) {
                                                        queueId: downloading.queueId,
                                                        percentage: 100
                                                });
-                                               let filePath = mainFolder+antiDot(fixName(downloading.settings.plName)) + path.sep
                                                if (downloading.settings.logErrors){
                                                        if (downloading.errorLog != ""){
                                                                if (!fs.existsSync(filePath)) fs.mkdirSync(filePath);
@@ -654,12 +713,20 @@ io.sockets.on('connection', function (socket) {
                                                                if (fs.existsSync(filePath+"notFound.txt")) fs.unlinkSync(filePath+"notFound.txt");
                                                        }
                                                }
+                                               if (downloading.settings.logSearched){
+                                                       if (downloading.searchedLog != ""){
+                                                               if (!fs.existsSync(filePath)) fs.mkdirSync(filePath);
+                                                               fs.writeFileSync(filePath+"alternativeSongs.txt",downloading.searchedLog)
+                                                       }else{
+                                                               if (fs.existsSync(filePath+"alternativeSongs.txt")) fs.unlinkSync(filePath+"alternativeSongs.txt");
+                                                       }
+                                               }
                                                if (downloading.settings.createM3UFile){
                                                        fs.writeFileSync(filePath + "playlist.m3u", downloading.playlistArr.join("\r\n"));
                                                }
                                                if (downloading.settings.saveArtwork){
                                                        if (!fs.existsSync(filePath)) fs.mkdirSync(filePath);
-                                                       let imgPath = filePath + "folder"+(settings.PNGcovers ? ".png" : ".jpg");
+                                                       let imgPath = filePath + antiDot(fixName(settingsRegexCover(downloading.settings.coverImageTemplate,downloading.artist,downloading.name)))+(downloading.settings.PNGcovers ? ".png" : ".jpg");
                                                        if (downloading.cover){
                                                                request.get(downloading.cover, {encoding: 'binary'}, function(error,response,body){
                                                                        if(error){
@@ -992,64 +1059,47 @@ io.sockets.on('connection', function (socket) {
        function downloadTrack(t, settings, altmetadata, callback) {
                if (!socket.downloadQueue[t.queueId]) {
                        logger.error("Not in queue");
-                       callback(new Error("Not in queue"), `${t.id} | ${t.artist} - ${t.name}`);
+                       callback(new Error("Not in queue"));
                        return;
                }
                if (t.id == 0){
                        logger.error("Failed to download track: Wrong ID");
-                       callback(new Error("Failed to download track: Wrong ID"), `${t.id} | ${t.artist} - ${t.name}`);
+                       callback(new Error("Failed to download track: Wrong ID"));
                        return;
                }
-               let temp1 = new Promise((resolve, reject)=>{
+               settings = settings || {};
+               let temp;
+               temp = new Promise((resolve, reject)=>{
                        if (!settings.trackInfo){
                                logger.info("Getting track data");
-                               Deezer.getTrack(t.id, settings.maxBitrate, function (trackInfo, err) {
-                                       if (err) {
-                                               if(t.fallback){
-                                                       logger.warn("Failed to download track, falling on alternative");
-                                                       t.id = t.fallback
-                                                       t.fallback = 0
-                                                       downloadTrack(t, settings, null, function(err){
-                                                               callback(err, `${t.id} | ${t.artist} - ${t.name}`);
-                                                       });
-                                               }else if(!t.searched){
-                                                       logger.warn("Failed to download track, searching for alternative");
-                                                       Deezer.track2ID(t.artist, t.name, null, data=>{
-                                                               t.searched = true;
-                                                               t.id = data.id;
-                                                               t.artist = data.artist;
-                                                               t.name = data.name;
-                                                               downloadTrack(t, settings, null, function(err){
-                                                                       callback(err, `${t.id} | ${t.artist} - ${t.name}`);
+                               if (parseInt(t.id)<0){
+                                       Deezer.getLocalTrack(t.id, function (trackInfo, err) {
+                                               if (err) {
+                                                       if(!t.searched){
+                                                               logger.warn("Failed to download track, searching for alternative");
+                                                               Deezer.track2ID(t.artist, t.name, null, data=>{
+                                                                       t.searched = true;
+                                                                       t.id = data.id;
+                                                                       t.artist = data.artist;
+                                                                       t.name = data.name;
+                                                                       downloadTrack(t, settings, null, callback);
                                                                });
-                                                       });
-                                               }else{
-                                                       logger.error("Failed to download track: "+ err);
-                                                       callback(err, `${t.id} | ${t.artist} - ${t.name}`);
+                                                       }else{
+                                                               logger.error("Failed to download track: "+ err);
+                                                               callback(err, `${t.id} | ${t.artist} - ${t.name}`);
+                                                       }
+                                                       return;
                                                }
-                                               return;
-                                       }
-                                       resolve(trackInfo);
-                               });
-                       }else{
-                               resolve(settings.trackInfo);
-                       }
-               })
-               temp1.then(data=>{
-                       let track = data;
-                       track.trackSocket = socket;
-                       logger.info("Getting album data");
-                       let temp2 = new Promise((resolve, reject)=>{
-                               if (!settings.albumInfo){
-                                       Deezer.getAlbum(track["ALB_ID"], function(res, err){
-                                               if(err){
+                                               resolve(trackInfo);
+                                       });
+                               }else{
+                                       Deezer.getTrack(t.id, settings.maxBitrate, function (trackInfo, err) {
+                                               if (err) {
                                                        if(t.fallback){
                                                                logger.warn("Failed to download track, falling on alternative");
                                                                t.id = t.fallback
                                                                t.fallback = 0
-                                                               downloadTrack(t, settings, null, function(err){
-                                                                       callback(err, `${t.id} | ${t.artist} - ${t.name}`);
-                                                               });
+                                                               downloadTrack(t, settings, null, callback);
                                                        }else if(!t.searched){
                                                                logger.warn("Failed to download track, searching for alternative");
                                                                Deezer.track2ID(t.artist, t.name, null, data=>{
@@ -1057,363 +1107,476 @@ io.sockets.on('connection', function (socket) {
                                                                        t.id = data.id;
                                                                        t.artist = data.artist;
                                                                        t.name = data.name;
-                                                                       downloadTrack(t, settings, null, function(err){
-                                                                               callback(err, `${t.id} | ${t.artist} - ${t.name}`);
-                                                                       });
+                                                                       downloadTrack(t, settings, null, callback);
                                                                });
                                                        }else{
                                                                logger.error("Failed to download track: "+ err);
-                                                               callback(new Error("Album does not exists."), `${t.id} | ${t.artist} - ${t.name}`);
+                                                               callback(err, `${t.id} | ${t.artist} - ${t.name}`);
                                                        }
                                                        return;
                                                }
+                                               resolve(trackInfo);
+                                       });
+                               }
+                       }else{
+                               resolve(settings.trackInfo);
+                       }
+               })
+               temp.then(data=>{
+               let track = data;
+               track.trackSocket = socket;
+               temp = new Promise((resolve, reject)=>{
+                       if (parseInt(t.id)>0){
+                               if (!settings.albumInfo){
+                                       logger.info("Getting album data");
+                                       Deezer.getAlbum(track["ALB_ID"], function(res, err){
+                                               if(err){
+                                                       logger.warn("Album not found, trying to reach deeper");
+                                                       Deezer.getAAlbum(track["ALB_ID"], function(res, err){
+                                                               if(err){
+                                                                       if(t.fallback){
+                                                                               logger.warn("Failed to download track, falling on alternative");
+                                                                               t.id = t.fallback
+                                                                               t.fallback = 0
+                                                                               settings.trackInfo = null;
+                                                                               downloadTrack(t, settings, null, callback);
+                                                                       }else if(!t.searched){
+                                                                               logger.warn("Failed to download track, searching for alternative");
+                                                                               Deezer.track2ID(t.artist, t.name, null, data=>{
+                                                                                       t.searched = true;
+                                                                                       t.id = data.id;
+                                                                                       t.artist = data.artist;
+                                                                                       t.name = data.name;
+                                                                                       downloadTrack(t, settings, null, callback);
+                                                                               });
+                                                                       }else{
+                                                                               logger.error("Failed to download track: "+ err);
+                                                                               callback(new Error("Album does not exists."));
+                                                                       }
+                                                                       return;
+                                                               }
+                                                               resolve(res);
+                                                       })
+                                                       return;
+                                               }
                                                resolve(res);
                                        })
                                }else{
                                        resolve(settings.albumInfo)
                                }
-                       });
-                       temp2.then(res=>{
-                               settings = settings || {};
-                               let ajson = res;
-                               let totalDiskNumber;
-                               let temp3;
-                               if (settings.partOfSet){
-                                       logger.info("Getting total disk number data");
-                                       temp3 = new Promise((resolve, reject) =>{
-                                               Deezer.getATrack(ajson.tracks.data[ajson.tracks.data.length-1].id, function(tres){
-                                                       totalDiskNumber = tres.disk_number;
-                                                       resolve();
-                                               });
-                                       })
+                       }else{
+                               resolve({artist:{}})
+                       }
+
+               });
+               temp.then(albumres=>{
+               let ajson = albumres;
+               if (ajson.totalDiskNumber){
+                       temp = new Promise((resolve, reject) =>{
+                               resolve(ajson.totalDiskNumber)
+                       })
+               }else{
+                       if ((settings.tags.discTotal || settings.createCDFolder) && parseInt(t.id)>0){
+                               logger.info("Getting total disc number");
+                               temp = new Promise((resolve, reject) =>{
+                                       Deezer.getATrack(ajson.tracks.data[ajson.tracks.data.length-1].id, function(tres){
+                                               resolve(tres.disk_number);
+                                       });
+                               })
+                       }else{
+                               temp = new Promise((resolve, reject) =>{
+                                       resolve(null)
+                               })
+                       }
+               }
+               temp.then(discTotal=>{
+               let totalDiskNumber = discTotal;
+               if (settings.tags.bpm && parseInt(t.id)>0){
+                       logger.info("Getting BPM");
+                       temp = new Promise((resolve, reject) =>{
+                               Deezer.getATrack(t.id, function(tres, err){
+                                       if (err) resolve(0);
+                                       resolve(tres.bpm);
+                               });
+                       })
+               }else{
+                       temp = new Promise((resolve, reject) =>{
+                               resolve(0);
+                       })
+               }
+               temp.then(bpm=>{
+               track.BPM = bpm;
+               let metadata = parseMetadata(track, ajson, totalDiskNumber, settings, parseInt(t.index), altmetadata);
+               let filename = fixName(`${metadata.artist} - ${metadata.title}`);
+               if (settings.filename) {
+                       filename = fixName(settingsRegex(metadata, settings.filename, settings.playlist));
+               }
+               let filepath = mainFolder;
+               let artistPath;
+               if (settings.createArtistFolder || settings.createAlbumFolder) {
+                       if(settings.plName){
+                               filepath += antiDot(fixName(settings.plName)) + path.sep;
+                       }
+                       if (settings.createArtistFolder) {
+                               if(settings.artName){
+                                       filepath += antiDot(fixName(settings.artName)) + path.sep;
                                }else{
-                                       temp3 = new Promise((resolve, reject) =>{
-                                               resolve()
-                                       })
+                                       filepath += antiDot(fixName(metadata.albumArtist)) + path.sep;
                                }
-                               temp3.then(()=>{
-                                       let metadata = parseMetadata(track, ajson, totalDiskNumber, settings, t.index, altmetadata);
-                                       let filename = fixName(`${metadata.artist} - ${metadata.title}`);
-                                       if (settings.filename) {
-                                               filename = fixName(settingsRegex(metadata, settings.filename, settings.playlist));
-                                       }
-                                       let filepath = mainFolder;
-                                       if (settings.createArtistFolder || settings.createAlbumFolder) {
-                                               if(settings.plName){
-                                                       filepath += antiDot(fixName(settings.plName)) + path.sep;
+                               artistPath = filepath;
+                       }
+
+                       if (settings.createAlbumFolder) {
+                               if(settings.artName){
+                                       filepath += antiDot(fixName(settingsRegexAlbum(settings.foldername,settings.artName,settings.albName,metadata.year,metadata.rtype,metadata.publisher))) + path.sep;
+                               }else{
+                                       filepath += antiDot(fixName(settingsRegexAlbum(settings.foldername,metadata.albumArtist,metadata.album,metadata.year,metadata.rtype,metadata.publisher))) + path.sep;
+                               }
+                       }
+               } else if (settings.plName) {
+                       filepath += antiDot(fixName(settings.plName)) + path.sep;
+               } else if (settings.artName) {
+                       filepath += antiDot(fixName(settingsRegexAlbum(settings.foldername,settings.artName,settings.albName,metadata.year,metadata.rtype,metadata.publisher))) + path.sep;
+               }
+               let coverpath = filepath;
+               if (metadata.discTotal > 1 && (settings.artName || settings.createAlbumFolder) && settings.createCDFolder){
+                       filepath += `CD${metadata.discNumber +  path.sep}`
+               }
+               let writePath;
+               if(track.format == 9){
+                       writePath = filepath + filename + '.flac';
+               }else{
+                       writePath = filepath + filename + '.mp3';
+               }
+               if(track["LYRICS_SYNC_JSON"] && settings.syncedlyrics){
+                       let lyricsbuffer = "";
+                       for(let i=0;i<track["LYRICS_SYNC_JSON"].length;i++){
+                               if(track["LYRICS_SYNC_JSON"][i].lrc_timestamp){
+                                       lyricsbuffer += track["LYRICS_SYNC_JSON"][i].lrc_timestamp+track["LYRICS_SYNC_JSON"][i].line+"\r\n";
+                               }else if(i+1 < track["LYRICS_SYNC_JSON"].length){
+                                       lyricsbuffer += track["LYRICS_SYNC_JSON"][i+1].lrc_timestamp+track["LYRICS_SYNC_JSON"][i].line+"\r\n";
+                               }
+                       }
+                       fs.outputFile(writePath.substring(0,writePath.lastIndexOf('.'))+".lrc",lyricsbuffer,function(){});
+               }
+               let playlistData = [0,""]
+               if (settings.createM3UFile && (settings.plName || settings.albName)) {
+                       if (settings.numplaylistbyalbum && t.index){
+                               playlistData = [parseInt(t.index), writePath];
+                       }else{
+                               playlistData = [metadata.trackNumber-1, writePath];
+                       }
+               }
+               if (fs.existsSync(writePath)) {
+                       logger.info("Already downloaded: " + metadata.artist + ' - ' + metadata.title);
+                       callback(null, {playlistData: playlistData, searched: t.searched});
+                       return;
+               }else{
+                       logger.info('Downloading file to ' + writePath);
+               }
+               //Get image
+               temp = new Promise((resolve, reject)=>{
+                       if (metadata.image) {
+                               let imgPath;
+                               //If its not from an album but a playlist.
+                               if(!(settings.albName || settings.createAlbumFolder)){
+                                       imgPath = coverArtFolder + (metadata.barcode ? fixName(metadata.barcode) : fixName(`${metadata.albumArtist - metadata.album}`))+(settings.PNGcovers ? ".png" : ".jpg");
+                               }else{
+                                       if (settings.saveArtwork)
+                                               imgPath = coverpath + antiDot(fixName(settingsRegexCover(settings.coverImageTemplate,settings.artName,settings.albName)))+(settings.PNGcovers ? ".png" : ".jpg");
+                                       else
+                                               imgPath = coverArtFolder + fixName(metadata.barcode)+(settings.PNGcovers ? ".png" : ".jpg");
+                               }
+
+                               if(fs.existsSync(imgPath)){
+                                       metadata.imagePath = (imgPath).replace(/\\/g, "/");
+                                       logger.info("Starting the download process CODE:1");
+                                       resolve();
+                               }else{
+                                       request.get(metadata.image, {encoding: 'binary'}, function(error,response,body){
+                                               if(error){
+                                                       logger.error(error.stack);
+                                                       metadata.image = undefined;
+                                                       metadata.imagePath = undefined;
+                                                       return;
                                                }
-                                               if (settings.createArtistFolder) {
-                                                       if(settings.artName){
-                                                               filepath += antiDot(fixName(settings.artName)) + path.sep;
-                                                       }else{
-                                                               filepath += antiDot(fixName(metadata.artist)) + path.sep;
+                                               fs.outputFile(imgPath,body,'binary',function(err){
+                                                       if(err){
+                                                               logger.error(err.stack);
+                                                       metadata.image = undefined;
+                                                       metadata.imagePath = undefined;
+                                                               return;
                                                        }
-                                               }
-
-                                               if (settings.createAlbumFolder) {
-                                                       if(settings.artName){
-                                                               filepath += antiDot(fixName(settingsRegexAlbum(settings.foldername,settings.artName,settings.albName,metadata.year,metadata.rtype))) + path.sep;
-                                                       }else{
-                                                               filepath += antiDot(fixName(settingsRegexAlbum(settings.foldername,metadata.performerInfo,metadata.album,metadata.year,metadata.rtype))) + path.sep;
+                                                       metadata.imagePath = (imgPath).replace(/\\/g, "/");
+                                                       logger.info("Starting the download process CODE:2");
+                                                       resolve();
+                                               })
+                                       });
+                               }
+                       }else{
+                               metadata.image = undefined;
+                               logger.info("Starting the download process CODE:3");
+                               resolve();
+                       }
+               })
+               temp.then(()=>{
+               temp = new Promise((resolve, reject)=>{
+                       if (metadata.artistImage && settings.saveArtworkArtist) {
+                               let imgPath;
+                               if(settings.createArtistFolder){
+                                       imgPath = artistPath + antiDot(fixName(settingsRegexArtistCover(settings.artistImageTemplate,metadata.albumArtist)))+(settings.PNGcovers ? ".png" : ".jpg");
+                                       if(fs.existsSync(imgPath)){
+                                               resolve();
+                                       }else{
+                                               request.get(metadata.artistImage, {encoding: 'binary'}, function(error,response,body){
+                                                       if(error){
+                                                               logger.error(error.stack);
+                                                               return;
                                                        }
-                                               }
-                                       } else if (settings.plName) {
-                                               filepath += antiDot(fixName(settings.plName)) + path.sep;
-                                       } else if (settings.artName) {
-                                               filepath += antiDot(fixName(settingsRegexAlbum(settings.foldername,settings.artName,settings.albName,metadata.year,metadata.rtype))) + path.sep;
+                                                       fs.outputFile(imgPath,body,'binary',function(err){
+                                                               if(err){
+                                                                       logger.error(err.stack);
+                                                                       return;
+                                                               }
+                                                               logger.info("Saved Artist Image");
+                                                               resolve();
+                                                       })
+                                               });
                                        }
-                                       let writePath;
-                                       if(track.format == 9){
-                                               writePath = filepath + filename + '.flac';
-                                       }else{
-                                               writePath = filepath + filename + '.mp3';
+                               }else{
+                                       resolve();
+                               }
+                       }else{
+                               resolve();
+                       }
+               })
+               temp.then(()=>{
+               let tempPath
+               if(parseInt(t.id)>0)
+                       tempPath = writePath+".temp"
+               else
+                       tempPath = writePath;
+               logger.info("Downloading and decrypting");
+               Deezer.decryptTrack(tempPath, track, t.queueId, function (err) {
+                       if (err && err.message == "aborted") {
+                               logger.info("Track got aborted");
+                               t.trackSocket = null
+                               callback(null, {playlistData: playlistData, searched: t.searched});
+                               return;
+                       }
+                       if (err) {
+                               if (t.fallback){
+                                       logger.warn("Failed to download: " + metadata.artist + " - " + metadata.title+", falling on alternative");
+                                       t.id = t.fallback
+                                       t.fallback = 0
+                                       settings.trackInfo = null;
+                                       downloadTrack(t, settings, metadata, callback);
+                               }else if(!t.searched){
+                                       logger.warn("Failed to download track, searching for alternative");
+                                       Deezer.track2ID(t.artist, t.name, null, data=>{
+                                               t.searched = true;
+                                               t.id = data.id;
+                                               t.artist = data.artist;
+                                               t.name = data.name;
+                                               downloadTrack(t, settings, null, callback);
+                                       });
+                               }else{
+                                       logger.error("Failed to download: " + metadata.artist + " - " + metadata.title);
+                                       callback(err, `${t.id} | ${t.artist} - ${t.name}`)
+                               }
+                               return;
+                       }
+                       logger.info("Downloaded: " + metadata.artist + " - " + metadata.title);
+                       if (parseInt(t.id)>0){
+                               if(track.format == 9){
+                                       let flacComments = [];
+                                       if (settings.tags.title)
+                                               flacComments.push('TITLE=' + metadata.title);
+                                       if (settings.tags.album)
+                                               flacComments.push('ALBUM=' + metadata.album);
+                                       if (settings.tags.albumArtist)
+                                               flacComments.push('ALBUMARTIST=' + metadata.albumArtist);
+                                       if (settings.tags.trackNumber)
+                                               flacComments.push('TRACKNUMBER=' + metadata.trackNumber);
+                                       if (settings.tags.discNumber)
+                                               flacComments.push('DISCNUMBER=' + metadata.discNumber);
+                                       if (settings.tags.trackTotal)
+                                               flacComments.push('TRACKTOTAL=' + metadata.trackTotal);
+                                       if (settings.tags.explicit)
+                                               flacComments.push('ITUNESADVISORY=' + metadata.explicit);
+                                       if (settings.tags.isrc)
+                                               flacComments.push('ISRC=' + metadata.ISRC);
+                                       if (settings.tags.artist)
+                                               metadata.artists.forEach(x=>{
+                                                       flacComments.push('ARTIST=' + x);
+                                               });
+                                       if (settings.tags.discTotal)
+                                               flacComments.push('DISCTOTAL='+splitNumber(metadata.discTotal,true));
+                                       if (settings.tags.length)
+                                               flacComments.push('LENGTH=' + metadata.length);
+                                       if (settings.tags.barcode && metadata.barcode)
+                                               flacComments.push('BARCODE=' + metadata.barcode);
+                                       if (metadata.unsynchronisedLyrics && settings.tags.unsynchronisedLyrics)
+                                               flacComments.push('LYRICS='+metadata.unsynchronisedLyrics.lyrics);
+                                       if (metadata.genre && settings.tags.genre)
+                                               metadata.genre.forEach(x=>{
+                                                       flacComments.push('GENRE=' + x);
+                                               });
+                                       if (metadata.copyright && settings.tags.copyright)
+                                               flacComments.push('COPYRIGHT=' + metadata.copyright);
+                                       if (0 < parseInt(metadata.year)){
+                                               if (settings.tags.year)
+                                                       flacComments.push('YEAR=' + metadata.year);
+                                               if (settings.tags.date)
+                                               flacComments.push('DATE=' + metadata.date);
                                        }
-                                       if(track["LYRICS_SYNC_JSON"] && settings.syncedlyrics){
-                                               let lyricsbuffer = "";
-                                               for(let i=0;i<track["LYRICS_SYNC_JSON"].length;i++){
-                                                       if(track["LYRICS_SYNC_JSON"][i].lrc_timestamp){
-                                                               lyricsbuffer += track["LYRICS_SYNC_JSON"][i].lrc_timestamp+track["LYRICS_SYNC_JSON"][i].line+"\r\n";
-                                                       }else if(i+1 < track["LYRICS_SYNC_JSON"].length){
-                                                               lyricsbuffer += track["LYRICS_SYNC_JSON"][i+1].lrc_timestamp+track["LYRICS_SYNC_JSON"][i].line+"\r\n";
+                                       if (0 < parseInt(metadata.bpm) && settings.tags.bpm)
+                                               flacComments.push('BPM=' + metadata.bpm);
+                                       if(metadata.publisher && settings.tags.publisher)
+                                               flacComments.push('PUBLISHER=' + metadata.publisher);
+                                       if(metadata.composer && settings.tags.composer)
+                                               metadata.composer.forEach(x=>{
+                                                       flacComments.push('COMPOSER=' + x);
+                                               });
+                                       if(metadata.musicpublisher && settings.tags.musicpublisher)
+                                               metadata.musicpublisher.forEach(x=>{
+                                                       flacComments.push('ORGANIZATION=' + x);
+                                               });
+                                       if(metadata.mixer && settings.tags.mixer)
+                                               metadata.mixer.forEach(x=>{
+                                                       flacComments.push('MIXER=' + x);
+                                               });
+                                       if(metadata.author && settings.tags.author)
+                                               metadata.author.forEach(x=>{
+                                                       flacComments.push('AUTHOR=' + x);
+                                               });
+                                       if(metadata.writer && settings.tags.writer)
+                                               metadata.writer.forEach(x=>{
+                                                       flacComments.push('WRITER=' + x);
+                                               });
+                                       if(metadata.engineer && settings.tags.engineer)
+                                               metadata.engineer.forEach(x=>{
+                                                       flacComments.push('ENGINEER=' + x);
+                                               });
+                                       if(metadata.producer && settings.tags.producer)
+                                               metadata.producer.forEach(x=>{
+                                                       flacComments.push('PRODUCER=' + x);
+                                               });
+                                       if(metadata.replayGain && settings.tags.replayGain)
+                                               flacComments.push('REPLAYGAIN_TRACK_GAIN=' + metadata.replayGain);
+
+                                       const reader = fs.createReadStream(tempPath);
+                                       const writer = fs.createWriteStream(writePath);
+                                       let processor = new mflac.Processor({parseMetaDataBlocks: true});
+                                       let vendor = 'reference libFLAC 1.2.1 20070917';
+                                       let cover = null;
+                                       if(metadata.imagePath && settings.tags.cover){
+                                               cover = fs.readFileSync(metadata.imagePath);
+                                       }
+                                       let mdbVorbisPicture;
+                                       let mdbVorbisComment;
+                                       processor.on('preprocess', (mdb) => {
+                                               // Remove existing VORBIS_COMMENT and PICTURE blocks, if any.
+                                               if (mflac.Processor.MDB_TYPE_VORBIS_COMMENT === mdb.type) {
+                                                       mdb.remove();
+                                               } else if (mflac.Processor.MDB_TYPE_PICTURE === mdb.type) {
+                                                       mdb.remove();
+                                               }
+                                               if (mdb.isLast) {
+                                                       res = settings.artworkSize;
+                                                       if(cover){
+                                                               mdbVorbisPicture = mflac.data.MetaDataBlockPicture.create(true, 3, `image/${(settings.PNGcovers) ? "png" : "jpeg"}`, '', res, res, 24, 0, cover);
                                                        }
+                                                       mdbVorbisComment = mflac.data.MetaDataBlockVorbisComment.create(false, vendor, flacComments);
+                                                       mdb.isLast = false;
                                                }
-                                               fs.outputFile(writePath.substring(0,writePath.lastIndexOf('.'))+".lrc",lyricsbuffer,function(){});
-                                       }
-                                       if (settings.createM3UFile && (settings.plName || settings.albName)) {
-                                               if (settings.numplaylistbyalbum && t.index){
-                                                       t.playlistData = [t.index, filename + (track.format == 9 ? ".flac" : ".mp3")];
-                                               }else{
-                                                       t.playlistData = [splitNumber(metadata.trackNumber,false)-1, filename + (track.format == 9 ? ".flac" : ".mp3")];
+                                       });
+                                       processor.on('postprocess', (mdb) => {
+                                               if (mflac.Processor.MDB_TYPE_VORBIS_COMMENT === mdb.type && null !== mdb.vendor) {
+                                                       vendor = mdb.vendor;
                                                }
-                                       }else{
-                                               t.playlistData = [0,""];
+                                               if (mdbVorbisPicture && mdbVorbisComment) {
+                                                       processor.push(mdbVorbisComment.publish());
+                                                       processor.push(mdbVorbisPicture.publish());
+                                               }else if(mdbVorbisComment){
+                                                       processor.push(mdbVorbisComment.publish());
+                                               }
+                                       });
+                                       reader.on('end', () => {
+                                               fs.remove(tempPath);
+                                       });
+                                       reader.pipe(processor).pipe(writer);
+                               }else{
+                                       const songBuffer = fs.readFileSync(tempPath);
+                                       const writer = new ID3Writer(songBuffer);
+                                       if (settings.tags.title)
+                                               writer.setFrame('TIT2', metadata.title);
+                                       if (settings.tags.artist)
+                                               writer.setFrame('TPE1', [metadata.artists]);
+                                       if (settings.tags.album)
+                                               writer.setFrame('TALB', metadata.album)
+                                       if (settings.tags.albumArtist && metadata.albumArtist)
+                                               writer.setFrame('TPE2', metadata.albumArtist)
+                                       if (settings.tags.trackNumber)
+                                               writer.setFrame('TRCK', (settings.tags.trackTotal ? metadata.trackNumber+"/"+metadata.trackTotal : metadata.trackNumber))
+                                       if (settings.tags.discNumber)
+                                               writer.setFrame('TPOS', (settings.tags.discTotal ? metadata.discNumber+"/"+metadata.discTotal : metadata.discNumber))
+                                       if (settings.tags.isrc)
+                                               writer.setFrame('TSRC', metadata.ISRC);
+
+                                       if (settings.tags.length)
+                                               writer.setFrame('TLEN', metadata.length);
+                                       if (settings.tags.barcode && metadata.barcode)
+                                               writer.setFrame('TXXX', {
+                                                       description: 'BARCODE',
+                                                       value: metadata.barcode
+                                               });
+                                       if(metadata.imagePath && settings.tags.cover){
+                                               const coverBuffer = fs.readFileSync(metadata.imagePath);
+                                               writer.setFrame('APIC', {
+                                                       type: 3,
+                                                       data: coverBuffer,
+                                                       description: ''
+                                               });
                                        }
-                                       if (fs.existsSync(writePath)) {
-                                               logger.info("Already downloaded: " + metadata.artist + ' - ' + metadata.title);
-                                               callback(null, t.playlistData);
-                                               return;
-                                       }else{
-                                               logger.info('Downloading file to ' + writePath);
+                                       if(metadata.unsynchronisedLyrics && settings.tags.cover)
+                                               writer.setFrame('USLT', metadata.unsynchronisedLyrics);
+                                       if(metadata.publisher && settings.tags.publisher)
+                                               writer.setFrame('TPUB', metadata.publisher);
+                                       if(metadata.genre && settings.tags.genre)
+                                               writer.setFrame('TCON', [metadata.genre]);
+                                       if(metadata.copyright && settings.tags.copyright)
+                                               writer.setFrame('TCOP', metadata.copyright);
+                                       if (0 < parseInt(metadata.year)) {
+                                               if (settings.tags.date)
+                                                       writer.setFrame('TDAT', metadata.date);
+                                               if (settings.tags.year)
+                                                       writer.setFrame('TYER', metadata.year);
                                        }
-                                       //Get image
-                                       let temp4 = new Promise((resolve, reject)=>{
-                                               if (metadata.image) {
-                                                       let imgPath;
-                                                       //If its not from an album but a playlist.
-                                                       if(!(settings.albName || settings.createAlbumFolder)){
-                                                               imgPath = coverArtFolder + fixName(metadata.BARCODE)+(settings.PNGcovers ? ".png" : ".jpg");
-                                                       }else{
-                                                               if (settings.saveArtwork)
-                                                                       imgPath = filepath + "folder"+(settings.PNGcovers ? ".png" : ".jpg");
-                                                               else
-                                                                       imgPath = coverArtFolder + fixName(metadata.BARCODE)+(settings.PNGcovers ? ".png" : ".jpg");
-                                                       }
-                                                       if(fs.existsSync(imgPath)){
-                                                               metadata.imagePath = (imgPath).replace(/\\/g, "/");
-                                                               logger.info("Starting the download process CODE:1");
-                                                               resolve();
-                                                       }else{
-                                                               request.get(metadata.image, {encoding: 'binary'}, function(error,response,body){
-                                                                       if(error){
-                                                                               logger.error(error.stack);
-                                                                               metadata.image = undefined;
-                                                                               metadata.imagePath = undefined;
-                                                                               return;
-                                                                       }
-                                                                       fs.outputFile(imgPath,body,'binary',function(err){
-                                                                               if(err){
-                                                                                       logger.error(err.stack);
-                                                                               metadata.image = undefined;
-                                                                               metadata.imagePath = undefined;
-                                                                                       return;
-                                                                               }
-                                                                               metadata.imagePath = (imgPath).replace(/\\/g, "/");
-                                                                               logger.info("Starting the download process CODE:2");
-                                                                               resolve();
-                                                                       })
-                                                               });
-                                                       }
-                                               }else{
-                                                       metadata.image = undefined;
-                                                       logger.info("Starting the download process CODE:3");
-                                                       resolve();
-                                               }
-                                       })
-                                       temp4.then(()=>{
-                                               let tempPath = writePath+".temp";
-                                               logger.info("Downloading and decrypting");
-                                               Deezer.decryptTrack(tempPath, track, t.queueId, function (err) {
-                                                       if (err && err.message == "aborted") {
-                                                               logger.info("Track got aborted");
-                                                               callback(null, t.playlistData);
-                                                               return;
-                                                       }
-                                                       if (err) {
-                                                               if (t.fallback){
-                                                                       logger.error("Failed to download: " + metadata.artist + " - " + metadata.title+", falling on alternative");
-                                                                       t.id = t.fallback
-                                                                       t.fallback = 0
-                                                                       downloadTrack(t, settings, metadata, callback);
-                                                               }else if(!t.searched){
-                                                                       logger.warn("Failed to download track, searching for alternative");
-                                                                       Deezer.track2ID(t.artist, t.name, null, data=>{
-                                                                               t.searched = true;
-                                                                               t.id = data.id;
-                                                                               t.artist = data.artist;
-                                                                               t.name = data.name;
-                                                                               downloadTrack(t, settings, null, function(err){
-                                                                                       callback(err, `${t.id} | ${t.artist} - ${t.name}`);
-                                                                               });
-                                                                       });
-                                                               }else{
-                                                                       logger.error("Failed to download: " + metadata.artist + " - " + metadata.title);
-                                                                       callback(err, `${t.id} | ${t.artist} - ${t.name}`)
-                                                               }
-                                                               return;
-                                                       }
-                                                       logger.info("Downloaded: " + metadata.artist + " - " + metadata.title);
-                                                       metadata.artist = [];
-                                                       artistArray = []
-                                                       track['ARTISTS'].forEach(function(artist){
-                                                               artistArray.push(artist['ART_NAME']);
-                                                       });
-                                                       Array.from(new Set(artistArray)).forEach(function(artist){
-                                                               if(metadata.artist.indexOf(artist) == -1)
-                                                                       metadata.artist.push(artist);
-                                                       });
-                                                       let separator = settings.multitagSeparator;
-                                                       if (separator == "null") separator = String.fromCharCode(parseInt("\u0000",16));
-                                                       if (track.format != 9) metadata.artist = metadata.artist.join(separator);
-
-                                                       if(track.format == 9){
-                                                               let flacComments = [
-                                                                       'TITLE=' + metadata.title,
-                                                                       'ALBUM=' + metadata.album,
-                                                                       'ALBUMARTIST=' + metadata.performerInfo,
-                                                                       'TRACKNUMBER=' + splitNumber(metadata.trackNumber,false),
-                                                                       'DISCNUMBER=' + splitNumber(metadata.partOfSet,false),
-                                                                       'TRACKTOTAL=' + splitNumber(metadata.trackNumber,true),
-                                                                       'ITUNESADVISORY=' + metadata.explicit,
-                                                                       'ISRC=' + metadata.ISRC
-                                                               ];
-                                                               metadata.artist.forEach(x=>{
-                                                                       flacComments.push('ARTIST=' + x);
-                                                               })
-                                                               if (settings.partOfSet)
-                                                                       flacComments.push('DISCTOTAL='+splitNumber(metadata.partOfSet,true))
-                                                               if(settings.extendedTags){
-                                                                       flacComments.push(
-                                                                               'LENGTH=' + metadata.length,
-                                                                               'BARCODE=' + metadata.BARCODE
-                                                                       );
-                                                               }
-                                                               if(metadata.unsynchronisedLyrics){
-                                                                       flacComments.push('LYRICS='+metadata.unsynchronisedLyrics.lyrics);
-                                                               }
-                                                               if(metadata.genre){
-                                                                       metadata.genre.forEach(x=>{
-                                                                               flacComments.push('GENRE=' + x);
-                                                                       })
-                                                               }
-                                                               if(metadata.copyright){
-                                                                       flacComments.push('COPYRIGHT=' + metadata.copyright);
-                                                               }
-                                                               if (0 < parseInt(metadata.year)) {
-                                                                       flacComments.push('YEAR=' + metadata.year);
-                                                                       flacComments.push('DATE=' + metadata.date);
-                                                               }
-                                                               if (0 < parseInt(metadata.bpm)) {
-                                                                       flacComments.push('BPM=' + metadata.bpm);
-                                                               }
-                                                               if(metadata.composer){
-                                                                       flacComments.push('COMPOSER=' + metadata.composer);
-                                                               }
-                                                               if(metadata.publisher){
-                                                                       flacComments.push('ORGANIZATION=' + metadata.publisher);
-                                                               }
-                                                               if(metadata.mixer){
-                                                                       flacComments.push('MIXER=' + metadata.mixer);
-                                                               }
-                                                               if(metadata.author){
-                                                                       flacComments.push('AUTHOR=' + metadata.author);
-                                                               }
-                                                               if(metadata.writer){
-                                                                       flacComments.push('WRITER=' + metadata.writer);
-                                                               }
-                                                               if(metadata.engineer){
-                                                                       flacComments.push('ENGINEER=' + metadata.engineer);
-                                                               }
-                                                               if(metadata.producer){
-                                                                       flacComments.push('PRODUCER=' + metadata.producer);
-                                                               }
-                                                               if(metadata.trackgain){
-                                                                       flacComments.push('REPLAYGAIN_TRACK_GAIN=' + metadata.trackgain);
-                                                               }
-                                                               const reader = fs.createReadStream(tempPath);
-                                                               const writer = fs.createWriteStream(writePath);
-                                                               let processor = new mflac.Processor({parseMetaDataBlocks: true});
-                                                               let vendor = 'reference libFLAC 1.2.1 20070917';
-                                                               let cover = null;
-                                                               if(metadata.imagePath){
-                                                                       cover = fs.readFileSync(metadata.imagePath);
-                                                               }
-                                                               let mdbVorbisPicture;
-                                                               let mdbVorbisComment;
-                                                               processor.on('preprocess', (mdb) => {
-                                                                       // Remove existing VORBIS_COMMENT and PICTURE blocks, if any.
-                                                                       if (mflac.Processor.MDB_TYPE_VORBIS_COMMENT === mdb.type) {
-                                                                               mdb.remove();
-                                                                       } else if (mflac.Processor.MDB_TYPE_PICTURE === mdb.type) {
-                                                                               mdb.remove();
-                                                                       }
-                                                                       if (mdb.isLast) {
-                                                                               res = settings.artworkSize;
-                                                                               if(cover){
-                                                                                       mdbVorbisPicture = mflac.data.MetaDataBlockPicture.create(true, 3, 'image/jpeg', '', res, res, 24, 0, cover);
-                                                                               }
-                                                                               mdbVorbisComment = mflac.data.MetaDataBlockVorbisComment.create(false, vendor, flacComments);
-                                                                               mdb.isLast = false;
-                                                                       }
-                                                               });
-                                                               processor.on('postprocess', (mdb) => {
-                                                                       if (mflac.Processor.MDB_TYPE_VORBIS_COMMENT === mdb.type && null !== mdb.vendor) {
-                                                                               vendor = mdb.vendor;
-                                                                       }
-                                                                       if (mdbVorbisPicture && mdbVorbisComment) {
-                                                                               processor.push(mdbVorbisComment.publish());
-                                                                               processor.push(mdbVorbisPicture.publish());
-                                                                       }else if(mdbVorbisComment){
-                                                                               processor.push(mdbVorbisComment.publish());
-                                                                       }
-                                                               });
-                                                               reader.on('end', () => {
-                                                                       fs.remove(tempPath);
-                                                               });
-                                                               reader.pipe(processor).pipe(writer);
-                                                       }else{
-                                                               const songBuffer = fs.readFileSync(tempPath);
-                                                               const writer = new ID3Writer(songBuffer);
-                                                               writer.setFrame('TIT2', metadata.title)
-                                                               .setFrame('TPE1', [metadata.artist])
-                                                               .setFrame('TALB', metadata.album)
-                                                               .setFrame('TPE2', metadata.performerInfo)
-                                                               .setFrame('TRCK', (settings.partOfSet ? metadata.trackNumber : splitNumber(metadata.trackNumber,false)))
-                                                               .setFrame('TPOS', (settings.partOfSet ? metadata.partOfSet : splitNumber(metadata.partOfSet,false)))
-                                                               .setFrame('TSRC', metadata.ISRC);
-                                                               if (settings.extendedTags){
-                                                                       writer.setFrame('TLEN', metadata.length)
-                                                                       .setFrame('TXXX', {
-                                                                               description: 'BARCODE',
-                                                                               value: metadata.BARCODE
-                                                                       })
-                                                               }
-                                                               if(metadata.imagePath){
-                                                                       const coverBuffer = fs.readFileSync(metadata.imagePath);
-                                                                       writer.setFrame('APIC', {
-                                                                               type: 3,
-                                                                               data: coverBuffer,
-                                                                               description: ''
-                                                                       });
-                                                               }
-                                                               if(metadata.unsynchronisedLyrics){
-                                                                       writer.setFrame('USLT', metadata.unsynchronisedLyrics);
-                                                               }
-                                                               if(metadata.publisher){
-                                                                       writer.setFrame('TPUB', metadata.publisher);
-                                                               }
-                                                               if(metadata.genre){
-                                                                       writer.setFrame('TCON', [metadata.genre]);
-                                                               }
-                                                               if(metadata.copyright){
-                                                                       writer.setFrame('TCOP', metadata.copyright);
-                                                               }
-                                                               if (0 < parseInt(metadata.year)) {
-                                                                       writer.setFrame('TDAT', metadata.date);
-                                                                       writer.setFrame('TYER', metadata.year);
-                                                               }
-                                                               if (0 < parseInt(metadata.bpm)) {
-                                                                       writer.setFrame('TBPM', metadata.bpm);
-                                                               }
-                                                               if(metadata.composer){
-                                                                       writer.setFrame('TCOM', [metadata.composer]);
-                                                               }
-                                                               if(metadata.trackgain){
-                                                                       writer.setFrame('TXXX', {
-                                                                               description: 'REPLAYGAIN_TRACK_GAIN',
-                                                                               value: metadata.trackgain
-                                                                       });
-                                                               }
-                                                               writer.addTag();
-                                                               const taggedSongBuffer = Buffer.from(writer.arrayBuffer);
-                                                               fs.writeFileSync(writePath, taggedSongBuffer);
-                                                               fs.remove(tempPath);
-                                                       }
-                                                       callback(null, t.playlistData);
-                                               })
-                                       })
-                               })
-                       })
+                                       if (0 < parseInt(metadata.bpm) && settings.tags.bpm)
+                                               writer.setFrame('TBPM', metadata.bpm);
+                                       if(metadata.composer && settings.tags.composer)
+                                               writer.setFrame('TCOM', [metadata.composer]);
+                                       if(metadata.replayGain && settings.tags.replayGain)
+                                               writer.setFrame('TXXX', {
+                                                       description: 'REPLAYGAIN_TRACK_GAIN',
+                                                       value: metadata.replayGain
+                                               });
+                                       writer.addTag();
+                                       const taggedSongBuffer = Buffer.from(writer.arrayBuffer);
+                                       fs.writeFileSync(writePath, taggedSongBuffer);
+                                       fs.remove(tempPath);
+                               }
+                       }
+                       t.trackSocket = null;
+                       callback(null, {playlistData: playlistData, searched: t.searched});
                })
+       })
+       })
+       })
+       })
+       })
+       })
        }
 
        function checkIfAlreadyInQueue(id) {
@@ -1489,11 +1652,12 @@ function settingsRegex(metadata, filename, playlist) {
        filename = filename.replace(/%album%/g, metadata.album);
        filename = filename.replace(/%artist%/g, metadata.artist);
        filename = filename.replace(/%year%/g, metadata.year);
+       filename = filename.replace(/%label%/g, metadata.publisher);
        if(typeof metadata.trackNumber != 'undefined'){
                if(configFile.userDefined.padtrck){
-                        filename = filename.replace(/%number%/g, pad(splitNumber(metadata.trackNumber, false), splitNumber(metadata.trackNumber, true)));
+                        filename = filename.replace(/%number%/g, pad(metadata.trackNumber, metadata.trackTotal));
                }else{
-                       filename = filename.replace(/%number%/g, splitNumber(metadata.trackNumber, false));
+                       filename = filename.replace(/%number%/g, metadata.trackNumber);
                }
        } else {
                filename = filename.replace(/%number%/g, '');
@@ -1507,11 +1671,27 @@ function settingsRegex(metadata, filename, playlist) {
  * @param foldername
  * @returns {XML|string|*}
  */
-function settingsRegexAlbum(foldername, artist, album, year, rtype) {
+function settingsRegexAlbum(foldername, artist, album, year, rtype, publisher) {
        foldername = foldername.replace(/%album%/g, album);
        foldername = foldername.replace(/%artist%/g, artist);
        foldername = foldername.replace(/%year%/g, year);
-       foldername = foldername.replace(/%type%/g, rtype);
+       if (rtype){
+               foldername = foldername.replace(/%type%/g, rtype[0].toUpperCase() + rtype.substring(1));
+       }else{
+               foldername = foldername.replace(/%type%/g, "");
+       }
+       foldername = foldername.replace(/%label%/g, publisher);
+       return foldername;
+}
+
+function settingsRegexCover(foldername, artist, name) {
+       foldername = foldername.replace(/%name%/g, name);
+       foldername = foldername.replace(/%artist%/g, artist);
+       return foldername;
+}
+
+function settingsRegexArtistCover(foldername, artist) {
+       foldername = foldername.replace(/%artist%/g, artist);
        return foldername;
 }
 
@@ -1551,6 +1731,7 @@ function slimDownTrackInfo(trackOld){
        track['ARTISTS'] = trackOld["ARTISTS"]
        track["ALB_ID"] = trackOld["ALB_ID"]
        track["ALB_PICTURE"] = trackOld["ALB_PICTURE"]
+       track["ART_PICTURE"] = trackOld["ART_PICTURE"]
        track["ALB_TITLE"] = trackOld["ALB_TITLE"]
        track["ART_NAME"] = trackOld["ART_NAME"]
        track["BPM"] = trackOld["BPM"]
@@ -1560,6 +1741,7 @@ function slimDownTrackInfo(trackOld){
        track["EXPLICIT_LYRICS"] = trackOld["EXPLICIT_LYRICS"]
        track["GAIN"] = trackOld["GAIN"]
        track["ISRC"] = trackOld["ISRC"]
+       track["TYPE"] = trackOld["TYPE"]
        track["LYRICS_SYNC_JSON"] = trackOld["LYRICS_SYNC_JSON"]
        track["LYRICS_TEXT"] = trackOld["LYRICS_TEXT"]
        track["PHYSICAL_RELEASE_DATE"] = trackOld["PHYSICAL_RELEASE_DATE"]
@@ -1571,6 +1753,7 @@ function slimDownTrackInfo(trackOld){
        track["FILESIZE_MP3_320"] = trackOld["FILESIZE_MP3_320"]
        track["FILESIZE_MP3_256"] = trackOld["FILESIZE_MP3_256"]
        track["FILESIZE_MP3_128"] = trackOld["FILESIZE_MP3_128"]
+       track.FILESIZE = trackOld.FILESIZE
        track["FALLBACK"] = trackOld["FALLBACK"]
        track.downloadUrl = trackOld.downloadUrl
        track.format = trackOld.format
@@ -1581,6 +1764,7 @@ function slimDownAlbumInfo(ajsonOld){
        let ajson = {};
        ajson.artist = {}
        ajson.artist.name = ajsonOld.artist.name
+       ajson.artist.picture_small = ajsonOld.artist.picture_small
        ajson.nb_tracks = ajsonOld.nb_tracks
        ajson.upc = ajsonOld.upc
        ajson.record_type = ajsonOld.record_type
@@ -1596,6 +1780,19 @@ function slimDownAlbumInfo(ajsonOld){
        return ajson
 }
 
+function swichReleaseType(id){
+       switch (id) {
+               case "0":
+                       return "Album";
+               case "1":
+                       return "Single";
+               case "3":
+                       return "Ep";
+               default:
+                       return id;
+       }
+}
+
 function parseMetadata(track, ajson, totalDiskNumber, settings, position, altmetadata){
        let metadata;
        if (track["VERSION"]) track["SNG_TITLE"] += " " + track["VERSION"];
@@ -1612,86 +1809,123 @@ function parseMetadata(track, ajson, totalDiskNumber, settings, position, altmet
                        title: track["SNG_TITLE"],
                        artist: track["ART_NAME"],
                        album: track["ALB_TITLE"],
-                       performerInfo: ajson.artist.name,
-                       trackNumber: track["TRACK_NUMBER"] + "/" + ajson.nb_tracks,
-                       partOfSet: track["DISK_NUMBER"],
+                       trackNumber: track["TRACK_NUMBER"],
+                       discNumber: track["DISK_NUMBER"],
                        explicit: track["EXPLICIT_LYRICS"],
                        ISRC: track["ISRC"],
+                       albumArtist: ajson.artist.name,
+                       trackTotal: ajson.nb_tracks,
                        rtype: ajson.record_type,
-                       BARCODE: ajson.upc,
+                       barcode: ajson.upc,
+                       length: track["DURATION"]
                };
-               if (settings.extendedTags){
-                       metadata.length = track["DURATION"];
-                       if(track["COPYRIGHT"]){
-                               metadata.copyright = track["COPYRIGHT"];
+               if(track["COPYRIGHT"]){
+                       metadata.copyright = track["COPYRIGHT"];
+               }
+               if (!metadata.rtype){
+                       metadata.rtype = swichReleaseType(track["TYPE"])
+               }
+               if(track["SNG_CONTRIBUTORS"]){
+                       if(track["SNG_CONTRIBUTORS"].composer){
+                               metadata.composer = [];
+                               Array.from(new Set(track["SNG_CONTRIBUTORS"].composer)).forEach(function(x){
+                                       if(metadata.composer.indexOf(x) == -1)
+                                               metadata.composer.push(x);
+                               });
+                               let separator = settings.multitagSeparator;
+                               if (separator == "null") separator = String.fromCharCode(parseInt("\u0000",16));
+                               if (track.format != 9) metadata.composer = metadata.composer.join(separator);
                        }
-                       if(track["SNG_CONTRIBUTORS"]){
-                               if(track["SNG_CONTRIBUTORS"].composer){
-                                       let composertag = "";
-                                       for (let i = 0; i < track["SNG_CONTRIBUTORS"].composer.length; i++) {
-                                               composertag += track["SNG_CONTRIBUTORS"].composer[i] + ", ";
-                                       }
-                                       metadata.composer = composertag.substring(0,composertag.length-2);
-                               }
-                               if(track["SNG_CONTRIBUTORS"].musicpublisher){
-                                       let publishertag = "";
-                                       for (let i = 0; i < track["SNG_CONTRIBUTORS"].musicpublisher.length; i++) {
-                                               publishertag += track["SNG_CONTRIBUTORS"].musicpublisher[i] + ", ";
-                                       }
-                                       metadata.publisher = publishertag.substring(0,publishertag.length-2);
-                               }
-                               if(track["SNG_CONTRIBUTORS"].producer){
-                                       let producertag = "";
-                                       for (let i = 0; i < track["SNG_CONTRIBUTORS"].producer.length; i++) {
-                                               producertag += track["SNG_CONTRIBUTORS"].producer[i] + ", ";
-                                       }
-                                       metadata.producer = producertag.substring(0,producertag.length-2);
-                               }
-                               if(track["SNG_CONTRIBUTORS"].engineer){
-                                       let engineertag = "";
-                                       for (let i = 0; i < track["SNG_CONTRIBUTORS"].engineer.length; i++) {
-                                               engineertag += track["SNG_CONTRIBUTORS"].engineer[i] + ", ";
-                                       }
-                                       metadata.engineer = engineertag.substring(0,engineertag.length-2);
-                               }
-                               if(track["SNG_CONTRIBUTORS"].writer){
-                                       let writertag = "";
-                                       for (let i = 0; i < track["SNG_CONTRIBUTORS"].writer.length; i++) {
-                                               writertag += track["SNG_CONTRIBUTORS"].writer[i] + ", ";
-                                       }
-                                       metadata.writer = writertag.substring(0,writertag.length-2);
-                               }
-                               if(track["SNG_CONTRIBUTORS"].author){
-                                       let authortag = "";
-                                       for (let i = 0; i < track["SNG_CONTRIBUTORS"].author.length; i++) {
-                                               authortag += track["SNG_CONTRIBUTORS"].author[i] + ", ";
-                                       }
-                                       metadata.author = authortag.substring(0,authortag.length-2);
-                               }
-                               if(track["SNG_CONTRIBUTORS"].mixer){
-                                       let mixertag = "";
-                                       for (let i = 0; i < track["SNG_CONTRIBUTORS"].mixer.length; i++) {
-                                               mixertag += track["SNG_CONTRIBUTORS"].mixer[i] + ", ";
-                                       }
-                                       metadata.mixer = mixertag.substring(0,mixertag.length-2);
-                               }
+                       if(track["SNG_CONTRIBUTORS"].musicpublisher){
+                               metadata.musicpublisher = [];
+                               Array.from(new Set(track["SNG_CONTRIBUTORS"].musicpublisher)).forEach(function(x){
+                                       if(metadata.musicpublisher.indexOf(x) == -1)
+                                               metadata.musicpublisher.push(x);
+                               });
+                               let separator = settings.multitagSeparator;
+                               if (separator == "null") separator = String.fromCharCode(parseInt("\u0000",16));
+                               if (track.format != 9) metadata.musicpublisher = metadata.musicpublisher.join(separator);
                        }
-                       if(track["LYRICS_TEXT"]){
-                               metadata.unsynchronisedLyrics = {
-                                       description: "",
-                                       lyrics: track["LYRICS_TEXT"]
-                               };
+                       if(track["SNG_CONTRIBUTORS"].producer){
+                               metadata.producer = [];
+                               Array.from(new Set(track["SNG_CONTRIBUTORS"].producer)).forEach(function(x){
+                                       if(metadata.producer.indexOf(x) == -1)
+                                               metadata.producer.push(x);
+                               });
+                               let separator = settings.multitagSeparator;
+                               if (separator == "null") separator = String.fromCharCode(parseInt("\u0000",16));
+                               if (track.format != 9) metadata.producer = metadata.producer.join(separator);
+                       }
+                       if(track["SNG_CONTRIBUTORS"].engineer){
+                               metadata.engineer = [];
+                               Array.from(new Set(track["SNG_CONTRIBUTORS"].engineer)).forEach(function(x){
+                                       if(metadata.engineer.indexOf(x) == -1)
+                                               metadata.engineer.push(x);
+                               });
+                               let separator = settings.multitagSeparator;
+                               if (separator == "null") separator = String.fromCharCode(parseInt("\u0000",16));
+                               if (track.format != 9) metadata.engineer = metadata.engineer.join(separator);
                        }
-                       if (track["GAIN"]) {
-                               metadata.trackgain = track["GAIN"];
+                       if(track["SNG_CONTRIBUTORS"].writer){
+                               metadata.writer = [];
+                               Array.from(new Set(track["SNG_CONTRIBUTORS"].writer)).forEach(function(x){
+                                       if(metadata.writer.indexOf(x) == -1)
+                                               metadata.writer.push(x);
+                               });
+                               let separator = settings.multitagSeparator;
+                               if (separator == "null") separator = String.fromCharCode(parseInt("\u0000",16));
+                               if (track.format != 9) metadata.writer = metadata.writer.join(separator);
+                       }
+                       if(track["SNG_CONTRIBUTORS"].author){
+                               metadata.author = [];
+                               Array.from(new Set(track["SNG_CONTRIBUTORS"].author)).forEach(function(x){
+                                       if(metadata.author.indexOf(x) == -1)
+                                               metadata.author.push(x);
+                               });
+                               let separator = settings.multitagSeparator;
+                               if (separator == "null") separator = String.fromCharCode(parseInt("\u0000",16));
+                               if (track.format != 9) metadata.author = metadata.author.join(separator);
+                       }
+                       if(track["SNG_CONTRIBUTORS"].mixer){
+                               metadata.mixer = [];
+                               Array.from(new Set(track["SNG_CONTRIBUTORS"].mixer)).forEach(function(x){
+                                       if(metadata.mixer.indexOf(x) == -1)
+                                               metadata.mixer.push(x);
+                               });
+                               let separator = settings.multitagSeparator;
+                               if (separator == "null") separator = String.fromCharCode(parseInt("\u0000",16));
+                               if (track.format != 9) metadata.mixer = metadata.mixer.join(separator);
                        }
                }
-               if(ajson.label && !metadata.publisher){
+               if(track["LYRICS_TEXT"]){
+                       metadata.unsynchronisedLyrics = {
+                               description: "",
+                               lyrics: track["LYRICS_TEXT"]
+                       };
+               }
+               if (track["GAIN"]) {
+                       metadata.replayGain = track["GAIN"];
+               }
+               if(ajson.label){
                        metadata.publisher = ajson.label;
                }
                if (0 < parseInt(track["BPM"])) {
                        metadata.bpm = track["BPM"];
                }
+               let separator = settings.multitagSeparator;
+               if (separator == "null") separator = String.fromCharCode(parseInt("\u0000",16))
+               if(track['ARTISTS']){
+                       metadata.artists = [];
+                       artistArray = []
+                       track['ARTISTS'].forEach(function(artist){
+                               artistArray.push(artist['ART_NAME']);
+                       });
+                       Array.from(new Set(artistArray)).forEach(function(artist){
+                               if(metadata.artists.indexOf(artist) == -1)
+                                       metadata.artists.push(artist);
+                       });
+                       if (track.format != 9) metadata.artists = metadata.artists.join(separator);
+               }
                if(ajson.genres && ajson.genres.data[0] && ajson.genres.data[0].name){
                        metadata.genre = [];
                        genreArray = [];
@@ -1702,13 +1936,14 @@ function parseMetadata(track, ajson, totalDiskNumber, settings, position, altmet
                                if(metadata.genre.indexOf(genre) == -1)
                                        metadata.genre.push(genre);
                        });
-                       let separator = settings.multitagSeparator;
-                       if (separator == "null") separator = String.fromCharCode(parseInt("\u0000",16))
                        if (track.format != 9) metadata.genre = metadata.genre.join(separator);
                }
                if (track["ALB_PICTURE"]) {
                        metadata.image = Deezer.albumPicturesHost + track["ALB_PICTURE"]+"/"+settings.artworkSize+"x"+settings.artworkSize+"-000000-80-0-0"+(settings.PNGcovers ? ".png" : ".jpg");
                }
+               if (ajson.artist.picture_small) {
+                       metadata.artistImage = ajson.artist.picture_small.split("56x56-000000-80-0-0.jpg")[0]+settings.artworkSize+"x"+settings.artworkSize+"-000000-80-0-0"+(settings.PNGcovers ? ".png" : ".jpg");
+               }
                if (ajson.release_date) {
                        metadata.year = ajson.release_date.slice(0, 4);
                        metadata.date = ajson.release_date;
@@ -1717,11 +1952,13 @@ function parseMetadata(track, ajson, totalDiskNumber, settings, position, altmet
                        metadata.date = track["PHYSICAL_RELEASE_DATE"];
                }
                if(settings.plName && !(settings.createArtistFolder || settings.createAlbumFolder) && !settings.numplaylistbyalbum){
-                       metadata.trackNumber = (position+1).toString() + "/" + settings.playlist.fullSize;
-                       metadata.partOfSet = "1/1";
+                       metadata.trackNumber = (position+1).toString();
+                       metadata.trackTotal = settings.playlist.fullSize;
+                       metadata.discNumber = "1";
+                       metadata.discTotal = "1";
                }
                if (totalDiskNumber){
-                       metadata.partOfSet += "/"+totalDiskNumber
+                       metadata.discTotal = totalDiskNumber;
                }
        }
        return metadata;
index 6f962cdd1ae4da0e0c8290eb71405df456b9371c..54f796ab528e38128953d4fcdc219c214a19ff21 100644 (file)
@@ -7,18 +7,13 @@ module.exports = new Deezer();
 
 function Deezer() {
        this.apiUrl = "http://www.deezer.com/ajax/gw-light.php";
-       this.apiQueries = {
-               api_version: "1.0",
-               api_token: "null",
-               input: "3"
-       };
        this.httpHeaders = {
-               "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36",
+               "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36",
                "Content-Language": "en-US",
                "Cache-Control": "max-age=0",
                "Accept": "*/*",
                "Accept-Charset": "utf-8,ISO-8859-1;q=0.7,*;q=0.3",
-               "Accept-Language": "de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4"
+               "Accept-Language": "en-US,en;q=0.9,en-US;q=0.8,en;q=0.7"
        }
        this.albumPicturesHost = "https://e-cdns-images.dzcdn.net/images/cover/";
        this.reqStream = {}
@@ -30,14 +25,20 @@ Deezer.prototype.init = function(username, password, callback) {
        request.post({
                url: self.apiUrl,
                qs: {
-                       ...self.apiQueries,
+                       api_version: "1.0",
+                       api_token: "null",
+                       input: "3",
                        method: 'deezer.getUserData'
                },
                headers: self.httpHeaders,
                jar: true,
                json:true,
        }, function(err, res, body) {
-               self.apiQueries.api_token = body.results.checkForm;
+               if(body.results.USER.USER_ID !== 0){
+                       // login already done
+                       callback(null, null);
+                       return;
+               }
                request.post({
                        url: "https://www.deezer.com/ajax/action.php",
                        headers: this.httpHeaders,
@@ -55,7 +56,9 @@ Deezer.prototype.init = function(username, password, callback) {
                                request.post({
                                        url: self.apiUrl,
                                        qs: {
-                                               ...self.apiQueries,
+                                               api_version: "1.0",
+                                               api_token: "null",
+                                               input: "3",
                                                method: 'deezer.getUserData'
                                        },
                                        headers: self.httpHeaders,
@@ -82,88 +85,87 @@ Deezer.prototype.init = function(username, password, callback) {
 
 
 Deezer.prototype.getPlaylist = function(id, callback) {
-       getJSON("https://api.deezer.com/playlist/" + id, function(res){
-               if (!(res instanceof Error)){
-                       callback(res);
-               } else {
-                       callback(null, res)
-               }
+       getJSON("https://api.deezer.com/playlist/" + id, function(res, err){
+               callback(res, err);
        });
 }
 
 Deezer.prototype.getAlbum = function(id, callback) {
-       getJSON("https://api.deezer.com/album/" + id, function(res){
-               if (!(res instanceof Error)){
-                       callback(res);
-               } else {
-                       callback(null, res)
-               }
+       getJSON("https://api.deezer.com/album/" + id, function(res, err){
+               callback(res, err);
        });
 }
 
+Deezer.prototype.getAAlbum = function(id, callback) {
+       var self = this;
+       self.getToken().then(data=>{
+               request.post({
+                       url: self.apiUrl,
+                       headers: self.httpHeaders,
+                       qs: {
+                               api_version: "1.0",
+                               input: "3",
+                               api_token: data,
+                               method: "album.getData"
+                       },
+                       body: {alb_id:id},
+                       jar: true,
+                       json: true
+               }, (function (err, res, body) {
+                       if(!err && res.statusCode == 200 && typeof body.results != 'undefined'){
+                               let ajson = {};
+                               ajson.artist = {}
+                               ajson.artist.name = body.results.ART_NAME
+                               ajson.nb_tracks = body.results.NUMBER_TRACK
+                               ajson.label = body.results.LABEL_NAME
+                               ajson.release_date = body.results.PHYSICAL_RELEASE_DATE
+                               ajson.totalDiskNumber = body.results.NUMBER_DISK
+                               callback(ajson);
+                       } else {
+                               callback(null, new Error("Unable to get Album" + id));
+                       }
+               }).bind(self));
+       })
+}
+
 Deezer.prototype.getATrack = function(id, callback) {
-       getJSON("https://api.deezer.com/track/" + id, function(res){
-               if (!(res instanceof Error)){
-                       callback(res);
-               } else {
-                       callback(null, res)
-               }
+       getJSON("https://api.deezer.com/track/" + id, function(res, err){
+               callback(res, err);
        });
 }
 
 Deezer.prototype.getArtist = function(id, callback) {
-       getJSON("https://api.deezer.com/artist/" + id, function(res){
-               if (!(res instanceof Error)){
-                       callback(res);
-               } else {
-                       callback(null, res)
-               }
+       getJSON("https://api.deezer.com/artist/" + id, function(res, err){
+               callback(res, err);
        });
 
 }
 
 Deezer.prototype.getPlaylistTracks = function(id, callback) {
-       getJSON("https://api.deezer.com/playlist/" + id + "/tracks?limit=-1", function(res){
-               if (!(res instanceof Error)){
-                       callback(res)
-               } else {
-                       callback(null, res)
-               }
+       getJSON("https://api.deezer.com/playlist/" + id + "/tracks?limit=-1", function(res, err){
+               callback(res, err);
        });
 }
 
 Deezer.prototype.getAlbumSize = function(id, callback) {
-       getJSON("https://api.deezer.com/album/" + id + "/tracks?limit=1", function(res){
-               if (!(res instanceof Error)){
-                       callback(res.total);
-               } else {
-                       callback(null, res)
-               }
+       getJSON("https://api.deezer.com/album/" + id + "/tracks?limit=1", function(res, err){
+               callback(res, err);
        });
 
 }
 
 Deezer.prototype.getAlbumTracks = function(id, callback) {
-       getJSON("https://api.deezer.com/album/" + id + "/tracks?limit=-1", function(res){
-               if (!(res instanceof Error)){
-                       callback(res);
-               } else {
-                       callback(null, res)
-               }
-
+       getJSON("https://api.deezer.com/album/" + id + "/tracks?limit=-1", function(res, err){
+               callback(res, err);
        });
 }
 
 Deezer.prototype.getArtistAlbums = function(id, callback) {
-       getJSON("https://api.deezer.com/artist/" + id + "/albums?limit=-1", function(res){
-               if (!(res instanceof Error)){
-                       if(!res.data) {
-                               res.data = [];
-                       }
-                       callback(res);
-               } else {
-                       callback(null, res)
+       getJSON("https://api.deezer.com/artist/" + id + "/albums?limit=-1", function(res, err){
+               if(!res.data) {
+                       res.data = [];
                }
+               callback(res, err);
        });
 }
 
@@ -172,95 +174,111 @@ Deezer.prototype.getArtistAlbums = function(id, callback) {
 **     From user https://api.deezer.com/user/637006841/playlists?limit=-1
 */
 Deezer.prototype.getChartsTopCountry = function(callback) {
-       getJSON("https://api.deezer.com/user/637006841/playlists?limit=-1", function(res){
-               if (!(res instanceof Error)){
-                       if(!res.data) {
-                               res.data = [];
-                       } else {
-                               //Remove "Loved Tracks"
-                               res.data.shift();
-                       }
-                       callback(res);
+       getJSON("https://api.deezer.com/user/637006841/playlists?limit=-1", function(res, err){
+               if(!res.data) {
+                       res.data = [];
                } else {
-                       callback(null, res)
+                       //Remove "Loved Tracks"
+                       res.data.shift();
                }
+               callback(res, err);
        });
 
 }
 
 Deezer.prototype.getMePlaylists = function(callback) {
-       getJSON("https://api.deezer.com/user/"+this.userId+"/playlists?limit=-1", function(res){
-               if (!(res instanceof Error)){
-                       if(!res.data) {
-                               res.data = [];
-                       }
-                       callback(res);
-               } else {
-                       callback(null, res)
+       getJSON("https://api.deezer.com/user/"+this.userId+"/playlists?limit=-1", function(res, err){
+               if(!res.data) {
+                       res.data = [];
                }
+               callback(res, err);
        });
 }
 
-Deezer.prototype.getTrack = function(id, maxBitrate, callback) {
+Deezer.prototype.getLocalTrack = function(id, callback) {
        var scopedid = id;
        var self = this;
-       request.get({url: "https://www.deezer.com/track/"+id, headers: this.httpHeaders, jar: true}, (function(err, res, body) {
-               var regex = new RegExp(/<script>window\.__DZR_APP_STATE__ = (.*)<\/script>/g);
-               var rexec = regex.exec(body);
-               var _data;
-               try{
-                       _data = rexec[1];
-               }catch(e){
-                       callback(null, new Error("Unable to get Track"));
-                       return;
-               }
-               if(!err && res.statusCode == 200 && typeof JSON.parse(_data)["DATA"] != 'undefined') {
-                       var json = JSON.parse(_data)["DATA"];
-                       var lyrics = JSON.parse(_data)["LYRICS"];
-                       if(lyrics){
-                               json["LYRICS_TEXT"] = lyrics["LYRICS_TEXT"];
-                               json["LYRICS_SYNC_JSON"] = lyrics["LYRICS_SYNC_JSON"];
-                               json["LYRICS_COPYRIGHTS"] = lyrics["LYRICS_COPYRIGHTS"];
-                               json["LYRICS_WRITERS"] = lyrics["LYRICS_WRITERS"];
-                       }
-                       if(json["TOKEN"]) {
-                               callback(null, new Error("Uploaded Files are currently not supported"));
-                               return;
-                       }
-                       var id = json["SNG_ID"];
-                       var md5Origin = json["MD5_ORIGIN"];
-                       var format;
-                       switch(maxBitrate){
-                               case "9":
-                                       format = 9;
-                                       if (json["FILESIZE_FLAC"]>0) break;
-                               case "3":
-                                       format = 3;
-                                       if (json["FILESIZE_MP3_320"]>0) break;
-                               case "5":
-                                       format = 5;
-                                       if (json["FILESIZE_MP3_256"]>0) break;
-                               case "1":
-                                       format = 1;
-                                       if (json["FILESIZE_MP3_128"]>0) break;
-                               case "8":
-                                       format = 8;
+       self.getToken().then(data=>{
+               request.post({
+                       url: self.apiUrl,
+                       headers: self.httpHeaders,
+                       qs: {
+                               api_version: "1.0",
+                               input: "3",
+                               api_token: data,
+                               method: "song.getData"
+                       },
+                       body: {sng_id:scopedid},
+                       jar: true,
+                       json: true
+               }, (function (err, res, body) {
+                       if(!err && res.statusCode == 200 && typeof body.results != 'undefined'){
+                               var json = body.results;
+                               json.format = (json["MD5_ORIGIN"].split('.').pop() == "flac" ? "9" : "3");
+                               json.downloadUrl = self.getDownloadUrl(json["MD5_ORIGIN"], json["SNG_ID"], 0 ,parseInt(json["MEDIA_VERSION"]));
+                               callback(json);
+                       } else {
+                               callback(null, new Error("Unable to get Track " + id));
                        }
-                       json.format = format;
-                       var mediaVersion = parseInt(json["MEDIA_VERSION"]);
-                       json.downloadUrl = self.getDownloadUrl(md5Origin, id, format, mediaVersion);
-
-                       self.getATrack(id,function(trckjson, err){
-                               if (err)
-                                       json["BPM"] = 0;
-                               else
-                                       json["BPM"] = trckjson.bpm;
+               }).bind(self));
+       })
+}
+
+Deezer.prototype.getTrack = function(id, maxBitrate, callback) {
+       var scopedid = id;
+       var self = this;
+       self.getToken().then(data=>{
+               request.post({
+                       url: self.apiUrl,
+                       headers: self.httpHeaders,
+                       qs: {
+                               api_version: "1.0",
+                               input: "3",
+                               api_token: data,
+                               method: "deezer.pageTrack"
+                       },
+                       body: {sng_id:scopedid},
+                       jar: true,
+                       json: true
+               }, (function (err, res, body) {
+                       if(!err && res.statusCode == 200 && typeof body.results != 'undefined'){
+                               var json = body.results.DATA;
+                               if (body.results.LYRICS){
+                                       json.LYRICS_SYNC_JSON = body.results.LYRICS.LYRICS_SYNC_JSON;
+                                       json.LYRICS_TEXT = body.results.LYRICS.LYRICS_TEXT;
+                               }
+                               if(json["TOKEN"]) {
+                                       callback(null, new Error("Uploaded Files are currently not supported"));
+                                       return;
+                               }
+                               var id = json["SNG_ID"];
+                               var md5Origin = json["MD5_ORIGIN"];
+                               var format;
+                               switch(maxBitrate){
+                                       case "9":
+                                               format = 9;
+                                               if (json["FILESIZE_FLAC"]>0) break;
+                                       case "3":
+                                               format = 3;
+                                               if (json["FILESIZE_MP3_320"]>0) break;
+                                       case "5":
+                                               format = 5;
+                                               if (json["FILESIZE_MP3_256"]>0) break;
+                                       case "1":
+                                               format = 1;
+                                               if (json["FILESIZE_MP3_128"]>0) break;
+                                       case "8":
+                                               format = 8;
+                               }
+                               json.format = format;
+                               var mediaVersion = parseInt(json["MEDIA_VERSION"]);
+                               json.downloadUrl = self.getDownloadUrl(md5Origin, id, format, mediaVersion);
                                callback(json);
-                       });
-               } else {
-                       callback(null, new Error("Unable to get Track " + id));
-               }
-       }).bind(self));
+                       } else {
+                               callback(null, new Error("Unable to get Track " + id));
+                       }
+               }).bind(self));
+       })
 }
 
 Deezer.prototype.search = function(text, type, callback) {
@@ -270,6 +288,7 @@ Deezer.prototype.search = function(text, type, callback) {
        } else {
                type += "?";
        }
+
        request.get({url: "https://api.deezer.com/search/" + type + "q=" + text, headers: this.httpHeaders, jar: true}, function(err, res, body) {
                if(!err && res.statusCode == 200) {
                        var json = JSON.parse(body);
@@ -412,7 +431,7 @@ Deezer.prototype.decryptTrack = function(writePath, track, queueId, callback) {
        if (self.delStream.indexOf(queueId) == -1){
                if (typeof self.reqStream[queueId] != "object") self.reqStream[queueId] = [];
                self.reqStream[queueId].push(
-                       request.get({url: track.downloadUrl, headers: self.httpHeaders, encoding: null}, function(err, res, body) {
+                       request.get({url: track.downloadUrl, headers: self.httpHeaders, encoding: 'binary'}, function(err, res, body) {
                                if(!err && res.statusCode == 200) {
                                        var decryptedSource = decryptDownload(new Buffer(body, 'binary'), track);
                                        fs.outputFile(writePath,decryptedSource,function(err){
@@ -509,23 +528,37 @@ Deezer.prototype.onDownloadProgress = function(track, progress) {
        return;
 }
 
+Deezer.prototype.getToken = async function(){
+       const res = await request.get({
+               url: this.apiUrl,
+               headers: this.httpHeaders,
+               qs: {
+                       api_version: "1.0",
+                       api_token: "null",
+                       input: "3",
+                       method: 'deezer.getUserData'
+               },
+               json: true,
+               jar: true,
+       })
+       return res.body.results.checkForm;
+}
+
 function getJSON(url, callback){
-       request.get({url: url, headers: this.httpHeaders, jar: true}, function(err, res, body) {
+       request.get({url: url, headers: this.httpHeaders, jar: true, json: true}, function(err, res, body) {
                if(err || res.statusCode != 200 || !body) {
-                       logger.error("Unable to initialize Deezer API");
-                       callback(new Error("Unable to initialize Deezer API"));
+                       callback(null, new Error("Unable to initialize Deezer API"));
                } else {
-                       var json = JSON.parse(body);
-                       if (json.error) {
-                               if (json.error.message == "Quota limit exceeded"){
+                       if (body.error) {
+                               if (body.error.message == "Quota limit exceeded"){
                                        logger.warn("Quota limit exceeded, retrying in 500ms");
                                        setTimeout(function(){ getJSON(url, callback); }, 500);
                                        return;
                                }
-                               logger.error(json.error.message);
+                               callback(null, new Error(body.error.message));
                                return;
                        }
-                       callback(json);
+                       callback(body);
                }
        });
 }
index 7f162de32b5bacb38b4b2c798651bf990976bccb..0f45da0d7f7c7ba29571639b997fae2dc2327187 100644 (file)
@@ -5,24 +5,57 @@
                "playlistTrackNameTemplate": "%number% - %artist% - %title%",
                "albumTrackNameTemplate": "%number% - %title%",
                "albumNameTemplate": "%artist% - %album%",
+               "artistImageTemplate": "folder",
+               "coverImageTemplate": "folder",
                "createM3UFile": false,
                "createArtistFolder": false,
                "createAlbumFolder": false,
+               "createCDFolder": false,
                "downloadLocation": "",
                "artworkSize": 800,
                "hifi": false,
                "padtrck": false,
                "syncedlyrics": false,
                "numplaylistbyalbum": false,
-               "extendedTags": false,
-               "partOfSet": false,
                "chartsCountry": "UK",
                "spotifyUser": "",
                "saveArtwork": false,
+               "saveArtworkArtist": false,
                "logErrors": false,
+               "logSearched": false,
                "queueConcurrency": 3,
                "multitagSeparator": ";",
                "maxBitrate": "3",
-               "PNGcovers": false
+               "PNGcovers": false,
+               "tags": {
+                       "title": true,
+                       "artist": true,
+                       "album": true,
+                       "cover": true,
+                       "trackNumber": true,
+                       "trackTotal": false,
+                       "discNumber": true,
+                       "discTotal": false,
+                       "albumArtist": true,
+                       "genre": true,
+                       "year": true,
+                       "date": false,
+                       "explicit": false,
+                       "isrc": true,
+                       "length": false,
+                       "barcode": false,
+                       "bpm": true,
+                       "replayGain": true,
+                       "publisher": true,
+                       "unsynchronisedLyrics": false,
+                       "copyright": false,
+                       "musicpublisher": false,
+                       "composer": false,
+                       "mixer": false,
+                       "author": false,
+                       "writer": false,
+                       "engineer": false,
+                       "producer": false
+               }
        }
 }
index 76d61e639d558536a3d82cfa5cedf9caca7120f6..5edfca2320ef81ed46bd2c0b4a9f8f2b01cf6bb8 100644 (file)
@@ -1,7 +1,7 @@
 {
        "name": "deezloader-rmx",
        "productName": "Deezloader Remix",
-       "version": "4.1.1",
+       "version": "4.1.2",
        "description": "Download music from Deezer",
        "main": "main.js",
        "author": "RemixDevs",
index c8b70ef3b48c742dabb4e52bbfcb818b6326de85..2b5638ef72db091b201ac5d946ca20b1ef7dded8 100644 (file)
@@ -289,13 +289,6 @@ a.single-cover {
   right: 0;
 }
 
-:not(input):not(textarea),
-:not(input):not(textarea)::after,
-:not(input):not(textarea)::before {
-    -webkit-user-select: none;
-    user-select: none;
-    cursor: default;
-}
 input, button, textarea, :focus {
     outline: none; // You should add some other style for :focus to help UX/a11y
 }
@@ -310,6 +303,9 @@ a[href^="ftp://"] {
     -webkit-user-drag: auto;
     user-drag: auto; /* Technically not supported in Electron yet */
 }
+.preview_playlist_controls{
+       cursor:pointer;
+}
 .toast{
        justify-content: normal !important;
 }
index 71614d1c3d312fa4f061d4333432e412f32e620f..9283371be46a54b1c388055df52b01f1c0649645 100644 (file)
@@ -16,7 +16,7 @@
   <meta charset="utf-8"/>
 </head>
 <body>
-<span id="appVersionFallback" hidden>4.1.1</span>
+<span id="appVersionFallback" hidden>4.1.2</span>
 
 <div id="title-bar" class="deezloader-black">
        <div class="resize-padding" style="width: 100%; height: 3px;"></div>
                        <h4 class="col s12">Settings</h4>
                </div>
                <div class="row">
-                       <div class="input-field col s12">
+                       <div class="input-field col s12 m6">
                                <i class="material-icons prefix">label</i>
                                <input type="text" id="modal_settings_input_trackNameTemplate"/>
-                               <label for="modal_settings_input_trackNameTemplate">Track names <i class="material-icons valignicon tiny tooltipped" data-position="right" data-delay="50" data-tooltip="Supported variables are: %number%, %year%, %artist%, %title% and %album%">info_outline</i></label>
+                               <label for="modal_settings_input_trackNameTemplate">Track names <i class="material-icons valignicon tiny tooltipped" data-position="right" data-delay="50"
+          data-tooltip="Supported variables are: %number%, %year%, %artist%, %title%, %album% and %label%">info_outline</i></label>
                        </div>
-               </div>
-               <div class="row">
-                       <div class="input-field col s12">
+                       <div class="input-field col s12 m6">
                                <i class="material-icons prefix">label</i>
                                <input type="text" id="modal_settings_input_playlistTrackNameTemplate"/>
-                               <label for="modal_settings_input_playlistTrackNameTemplate">Playlist track names <i class="material-icons valignicon tiny tooltipped" data-position="right" data-delay="50" data-tooltip="Supported variables are: %number%, %year%, %artist%, %title% and %album%">info_outline</i></label>
+                               <label for="modal_settings_input_playlistTrackNameTemplate">Playlist track names <i class="material-icons valignicon tiny tooltipped" data-position="right" data-delay="50"
+          data-tooltip="Supported variables are: %number%, %year%, %artist%, %title%, %album% and %label%">info_outline</i></label>
                        </div>
                </div>
     <div class="row">
-                       <div class="input-field col s12">
+                       <div class="input-field col s12 m6">
                                <i class="material-icons prefix">label</i>
                                <input type="text" id="modal_settings_input_albumTrackNameTemplate"/>
-                               <label for="modal_settings_input_albumTrackNameTemplate">Album track names <i class="material-icons valignicon tiny tooltipped" data-position="right" data-delay="50" data-tooltip="Supported variables are: %number%, %year%, %artist%, %title% and %album%">info_outline</i></label>
+                               <label for="modal_settings_input_albumTrackNameTemplate">Album track names <i class="material-icons valignicon tiny tooltipped" data-position="right" data-delay="50"
+          data-tooltip="Supported variables are: %number%, %year%, %artist%, %title%, %album% and %label%">info_outline</i></label>
                        </div>
-               </div>
-               <div class="row">
-                       <div class="input-field col s12">
+                       <div class="input-field col s12 m6">
                                <i class="material-icons prefix">label</i>
                                <input type="text" id="modal_settings_input_albumNameTemplate"/>
-                               <label for="modal_settings_input_albumNameTemplate">Album names <i class="material-icons valignicon tiny tooltipped" data-position="right" data-delay="50" data-tooltip="Supported variables are: %year%, %artist%, %type% and %album%">info_outline</i></label>
+                               <label for="modal_settings_input_albumNameTemplate">Album names <i class="material-icons valignicon tiny tooltipped" data-position="right" data-delay="50"
+          data-tooltip="Supported variables are: %year%, %artist%, %type%, %album% and %label%">info_outline</i></label>
+                       </div>
+               </div>
+    <div class="row">
+                       <div class="input-field col s12 m6">
+                               <i class="material-icons prefix">label</i>
+                               <input type="text" id="modal_settings_input_coverImageTemplate"/>
+                               <label for="modal_settings_input_albumTrackNameTemplate">Cover Image name <i class="material-icons valignicon tiny tooltipped" data-position="right" data-delay="50"
+          data-tooltip="Supported variables are: %artist% and %name%">info_outline</i></label>
+                       </div>
+                       <div class="input-field col s12 m6">
+                               <i class="material-icons prefix">label</i>
+                               <input type="text" id="modal_settings_input_artistImageTemplate"/>
+                               <label for="modal_settings_input_albumNameTemplate">Artist Image name <i class="material-icons valignicon tiny tooltipped" data-position="right" data-delay="50"
+          data-tooltip="Supported variables are: %artist%">info_outline</i></label>
                        </div>
                </div>
                <div class="row">
                                <i class="material-icons prefix">label</i>
                                <select name="multitagSeparator" id="modal_settings_select_multitagSeparator">
                                        <option value="null">Null Character</option>
-                                       <option value=",">,</option>
+                                       <option value=", ">,</option>
                                        <option value="/">/</option>
                                        <option value=";">;</option>
                                </select>
                                <span>Create M3U (Playlist) file</span>
         </label>
                        </p>
+      <p class="col s12 m4">
+        <label>
+                               <input type="checkbox" id="modal_settings_cbox_syncedlyrics" class="filled-in"/>
+                               <span class="tooltipped" data-position="top" data-delay="500"
+            data-tooltip="Downloads lyrics .lyr file">Download synced lyrics file</span>
+        </label>
+      </p>
+      <p class="col s12 m4">
+        <label>
+                               <input type="checkbox" id="modal_settings_cbox_numplaylistbyalbum" class="filled-in"/>
+                               <span class="tooltipped" data-position="top" data-delay="500"
+            data-tooltip="Track numbers when downloading a Playlist will be the original ones">Number playlist by album</span>
+        </label>
+      </p>
                        <p class="col s12 m4">
         <label>
                                <input type="checkbox" id="modal_settings_cbox_createArtistFolder" class="filled-in"/>
                                <span>Create folder for albums</span>
         </label>
                        </p>
-                       <p class="col s12 m4">
+      <p class="col s12 m4">
         <label>
-                               <input type="checkbox" id="modal_settings_cbox_padtrck" class="filled-in"/>
-                               <span class="tooltipped" data-position="top" data-delay="500" data-tooltip="Adds 0s before %number% to have the same character length">Pad track numbers</span>
+                               <input type="checkbox" id="modal_settings_cbox_createCDFolder" class="filled-in"/>
+                               <span>Create folder for CDs</span>
         </label>
       </p>
                        <p class="col s12 m4">
         <label>
-                               <input type="checkbox" id="modal_settings_cbox_syncedlyrics" class="filled-in"/>
-                               <span class="tooltipped" data-position="top" data-delay="500" data-tooltip="Downloads lyrics .lyr file">Enable synced lyrics</span>
+                               <input type="checkbox" id="modal_settings_cbox_padtrck" class="filled-in"/>
+                               <span class="tooltipped" data-position="top" data-delay="500"
+            data-tooltip="Adds 0s before %number% to have the same character length">Pad track numbers</span>
         </label>
       </p>
-                       <p class="col s12 m4">
+      <p class="col s12 m4">
         <label>
-                               <input type="checkbox" id="modal_settings_cbox_numplaylistbyalbum" class="filled-in"/>
-                               <span class="tooltipped" data-position="top" data-delay="500" data-tooltip="Track numbers when downloading a Playlist will be the original ones">Number playlists by album</span>
+                               <input type="checkbox" id="modal_settings_cbox_logErrors" class="filled-in"/>
+                               <span>Create log file for Errors</span>
         </label>
       </p>
-                       <p class="col s12 m4">
-        <label>
-                               <input type="checkbox" id="modal_settings_cbox_extendedTags" class="filled-in"/>
-                               <span>Enable Extended Tags</label>
-        </label>
-                       </p>
-                       <p class="col s12 m4">
+      <p class="col s12 m4">
         <label>
-                               <input type="checkbox" id="modal_settings_cbox_partOfSet" class="filled-in"/>
-                               <span class="tooltipped" data-position="top" data-delay="500" data-tooltip="Track number and disc number will be formatted as 1/16 instead of just 1">Add "out of" tag</span>
+                               <input type="checkbox" id="modal_settings_cbox_logSearched" class="filled-in"/>
+                               <span>Create log file for alternatives</span>
         </label>
       </p>
       <p class="col s12 m4">
         <label>
                                <input type="checkbox" id="modal_settings_cbox_saveArtwork" class="filled-in"/>
-                               <span>Save Artwork</span>
+                               <span>Save Album Artwork</span>
         </label>
       </p>
       <p class="col s12 m4">
         <label>
-                               <input type="checkbox" id="modal_settings_cbox_logErrors" class="filled-in"/>
-                               <span>Create log file for Errors</span>
+                               <input type="checkbox" id="modal_settings_cbox_saveArtworkArtist" class="filled-in"/>
+                               <span>Save Artist Artwork</span>
         </label>
       </p>
       <p class="col s12 m4">
         <label>
                                <input type="checkbox" id="modal_settings_cbox_PNGcovers" class="filled-in"/>
-                               <span>Save covers as PNGs</span>
+                               <span>Download images as PNGs</span>
         </label>
                        </p>
                </div>
+    <div class="row">
+      <div class="col s12">
+        <a href="#modal_tags" class="modal-trigger waves-effect waves-light btn btn-large" style="width:100%;">Choose which tags to Save</a>
+      </div>
+    </div>
                <div class="row">
                        <div class="col s12">
         <img id="modal_settings_picture" src="" alt="Profile Picture" class="circle left" style="height:125px; margin-right: 12px;"/>
        </div>
 </div>
 
+<!--#############################################MODAL_TAGS############################################-->
+<div id="modal_tags" class="modal modal-fixed-footer">
+       <div class="modal-content">
+               <div class="row">
+                       <h4 class="col s12">Saved Tags</h4>
+               </div>
+               <div class="row">
+                       <p class="col s12 m4">
+        <label>
+                               <input type="checkbox" id="modal_tags_title" class="filled-in"/>
+                               <span>Title</span>
+        </label>
+                       </p>
+      <p class="col s12 m4">
+        <label>
+                               <input type="checkbox" id="modal_tags_artist" class="filled-in"/>
+                               <span>Artist</span>
+        </label>
+                       </p>
+      <p class="col s12 m4">
+        <label>
+                               <input type="checkbox" id="modal_tags_album" class="filled-in"/>
+                               <span>Album</span>
+        </label>
+                       </p>
+      <p class="col s12 m4">
+        <label>
+                               <input type="checkbox" id="modal_tags_cover" class="filled-in"/>
+                               <span>Cover</span>
+        </label>
+                       </p>
+      <p class="col s12 m4">
+        <label>
+                               <input type="checkbox" id="modal_tags_trackNumber" class="filled-in"/>
+                               <span>Track Number</span>
+        </label>
+                       </p>
+      <p class="col s12 m4">
+        <label>
+                               <input type="checkbox" id="modal_tags_trackTotal" class="filled-in"/>
+                               <span>Track Total</span>
+        </label>
+                       </p>
+      <p class="col s12 m4">
+        <label>
+                               <input type="checkbox" id="modal_tags_discNumber" class="filled-in"/>
+                               <span>Disc Number</span>
+        </label>
+                       </p>
+      <p class="col s12 m4">
+        <label>
+                               <input type="checkbox" id="modal_tags_discTotal" class="filled-in"/>
+                               <span>Disc Total</span>
+        </label>
+                       </p>
+      <p class="col s12 m4">
+        <label>
+                               <input type="checkbox" id="modal_tags_albumArtist" class="filled-in"/>
+                               <span>Album Artist</span>
+        </label>
+                       </p>
+      <p class="col s12 m4">
+        <label>
+                               <input type="checkbox" id="modal_tags_genre" class="filled-in"/>
+                               <span>Genre</span>
+        </label>
+                       </p>
+      <p class="col s12 m4">
+        <label>
+                               <input type="checkbox" id="modal_tags_year" class="filled-in"/>
+                               <span>Year</span>
+        </label>
+                       </p>
+      <p class="col s12 m4">
+        <label>
+                               <input type="checkbox" id="modal_tags_date" class="filled-in"/>
+                               <span>Date</span>
+        </label>
+                       </p>
+      <p class="col s12 m4">
+        <label>
+                               <input type="checkbox" id="modal_tags_explicit" class="filled-in"/>
+                               <span>Explicit</span>
+        </label>
+                       </p>
+      <p class="col s12 m4">
+        <label>
+                               <input type="checkbox" id="modal_tags_isrc" class="filled-in"/>
+                               <span>ISRC</span>
+        </label>
+                       </p>
+      <p class="col s12 m4">
+        <label>
+                               <input type="checkbox" id="modal_tags_length" class="filled-in"/>
+                               <span>Length</span>
+        </label>
+                       </p>
+      <p class="col s12 m4">
+        <label>
+                               <input type="checkbox" id="modal_tags_barcode" class="filled-in"/>
+                               <span>Barcode</span>
+        </label>
+                       </p>
+      <p class="col s12 m4">
+        <label>
+                               <input type="checkbox" id="modal_tags_bpm" class="filled-in"/>
+                               <span>BPM</span>
+        </label>
+                       </p>
+      <p class="col s12 m4">
+        <label>
+                               <input type="checkbox" id="modal_tags_replayGain" class="filled-in"/>
+                               <span>Replay Gain</span>
+        </label>
+                       </p>
+      <p class="col s12 m4">
+        <label>
+                               <input type="checkbox" id="modal_tags_publisher" class="filled-in"/>
+                               <span>Label</span>
+        </label>
+                       </p>
+      <p class="col s12 m4">
+        <label>
+                               <input type="checkbox" id="modal_tags_unsynchronisedLyrics" class="filled-in"/>
+                               <span>Unsynchronised Lyrics</span>
+        </label>
+                       </p>
+      <p class="col s12 m4">
+        <label>
+                               <input type="checkbox" id="modal_tags_copyright" class="filled-in"/>
+                               <span>Copyright</span>
+        </label>
+                       </p>
+      <p class="col s12 m4">
+        <label>
+                               <input type="checkbox" id="modal_tags_musicpublisher" class="filled-in"/>
+                               <span>Publisher</span>
+        </label>
+                       </p>
+      <p class="col s12 m4">
+        <label>
+                               <input type="checkbox" id="modal_tags_composer" class="filled-in"/>
+                               <span>Composer</span>
+        </label>
+                       </p>
+      <p class="col s12 m4">
+        <label>
+                               <input type="checkbox" id="modal_tags_mixer" class="filled-in"/>
+                               <span>Mixer</span>
+        </label>
+                       </p>
+      <p class="col s12 m4">
+        <label>
+                               <input type="checkbox" id="modal_tags_author" class="filled-in"/>
+                               <span>Author</span>
+        </label>
+                       </p>
+      <p class="col s12 m4">
+        <label>
+                               <input type="checkbox" id="modal_tags_writer" class="filled-in"/>
+                               <span>Writer</span>
+        </label>
+                       </p>
+      <p class="col s12 m4">
+        <label>
+                               <input type="checkbox" id="modal_tags_engineer" class="filled-in"/>
+                               <span>Engineer</span>
+        </label>
+                       </p>
+      <p class="col s12 m4">
+        <label>
+                               <input type="checkbox" id="modal_tags_producer" class="filled-in"/>
+                               <span>Producer</span>
+        </label>
+                       </p>
+               </div>
+       </div>
+       <div class="modal-footer">
+               <a href="#" class="modal-close waves-effect btn-flat">Close</a>
+       </div>
+</div>
+
 <!--#############################################MODAL_ABOUT############################################-->
 <div id="modal_about" class="modal modal-fixed-footer">
        <div class="modal-content">
                                        <div class="collapsible-header waves-effect"><i class="material-icons">history</i>Changelog</div>
                                        <div class="collapsible-body">
                                                <p>
+                         <b>Version 4.1.2</b><br/>
+                         - Fixed Login Problem (for real this time)<br/>
+                         - Fixed Login after refresh<br/>
+                         - Regionlock free download<br/>
+                         - Added support for download of User Uploaded tracks<br/>
+                         - Now you can select which tags your songs has<br/>
+                         - Fixed selecting problem<br/>
+                         - Tracks without preview will display a disabled play button<br/>
+                         - Previews inside modal will stop with modal close<br/>
+                         - New %label% field for tracks and albums<br/>
+                         - Added option to create folder for CDs<br/>
+                         - Added rename option for cover file<br/>
+                         - Added option to download Artist artwork<br/>
+                         - Added option do log downloaded alternative tracks<br/>
+                         - Fixed some minor bugs
+                         <br/>
               <b>Version 4.1.1</b><br/>
               - Fixed Login Problem (again)<br/>
               - Added Dark Mode<br/>
index d9bf63723720136ce18a9aebc3f3342e272f90b9..dd4477e7dcc84ba5310222a5dd05df831b3ad145 100644 (file)
@@ -54,6 +54,7 @@ socket.on("login", function (data) {
                // Load top charts list for countries
                socket.emit("getChartsCountryList", {selected: userSettings.chartsCountry});
                socket.emit("getChartsTrackListByCountry", {country: userSettings.chartsCountry});
+               // Load personal pubblic playlists
                socket.emit("getMePlaylistList", {});
        }else{
                        $('#login-res-text').text(data.error);
@@ -118,7 +119,7 @@ $(document).ready(function () {
                if (preview_track.currentTime > preview_track.duration-1){
                        $(preview_track).animate({volume: 0}, 800);
                        preview_stopped = true;
-                       $("*").removeProp("playing");
+                       $("*").removeAttr("playing");
                        $('.preview_controls').text("play_arrow");
                        $('.preview_playlist_controls').text("play_arrow");
                }
@@ -126,16 +127,16 @@ $(document).ready(function () {
 
        $('#nightTimeSwitcher').change(function(){
                if(this.checked){
-                       $('link[name=darkMode]').removeAttr("disabled")
+                       document.getElementsByTagName('link')[4].disabled = false;
                        $("#nightModeSwitch2").html(`<i class="material-icons">brightness_7</i>Disable Night Mode`)
                }else{
-                       $('link[name=darkMode]').attr("disabled","disabled")
+                       document.getElementsByTagName('link')[4].disabled = true;
                        $("#nightModeSwitch2").html(`<i class="material-icons">brightness_2</i>Enable Night Mode`)
                }
                localStorage.darkMode = this.checked;
        });
 
-       $("#nightModeSwitch2").click(()=>{
+       $('#nightModeSwitch2').click(()=>{
                $('#nightTimeSwitcher').prop('checked', !$('#nightTimeSwitcher').prop('checked'))
                $('#nightTimeSwitcher').change();
        })
@@ -147,12 +148,28 @@ $(document).ready(function () {
                $('#nightTimeSwitcher').prop('checked', false);
                $('#nightTimeSwitcher').change();
        }
-       $("#downloadChartPlaylist").click(function(){
+
+       $('#downloadChartPlaylist').click(function(){
                addToQueue(`https://www.deezer.com/playlist/${$(this).data("id")}`);
        })
 
        $('.modal').modal();
        socket.emit("getUserSettings");
+
+       $('#modal_trackList, #modal_trackListSelective').modal({
+               onCloseStart: ()=>{
+                       if ($('.preview_playlist_controls').filter(function(){return $(this).attr("playing")}).length > 0){
+                               $(preview_track).animate({volume: 0}, 800);
+                               preview_stopped = true;
+                               $(".preview_playlist_controls").removeAttr("playing");
+                               $('.preview_playlist_controls').text("play_arrow");
+                       }
+               }
+       })
+
+       $('input[name=searchMode][type=radio]').change(()=>{
+               $('#tab_search_form_search').submit();
+       })
 });
 
 // Load settings
@@ -181,42 +198,73 @@ $('#nav_btn_openSettingsModal').click(function () {
 // Save settings button
 $('#modal_settings_btn_saveSettings').click(function () {
        let settings = {};
-
        // Save
        settings.userDefined = {
                trackNameTemplate: $('#modal_settings_input_trackNameTemplate').val(),
                playlistTrackNameTemplate: $('#modal_settings_input_playlistTrackNameTemplate').val(),
                albumTrackNameTemplate: $('#modal_settings_input_albumTrackNameTemplate').val(),
                albumNameTemplate: $('#modal_settings_input_albumNameTemplate').val(),
+               coverImageTemplate: $('#modal_settings_input_coverImageTemplate').val(),
+               artistImageTemplate: $('#modal_settings_input_artistImageTemplate').val(),
                createM3UFile: $('#modal_settings_cbox_createM3UFile').is(':checked'),
                createArtistFolder: $('#modal_settings_cbox_createArtistFolder').is(':checked'),
                createAlbumFolder: $('#modal_settings_cbox_createAlbumFolder').is(':checked'),
+               createCDFolder: $('#modal_settings_cbox_createCDFolder').is(':checked'),
                downloadLocation: $('#modal_settings_input_downloadTracksLocation').val(),
                artworkSize: parseInt($('#modal_settings_select_artworkSize').val()),
                hifi: $('#modal_settings_cbox_hifi').is(':checked'),
                padtrck: $('#modal_settings_cbox_padtrck').is(':checked'),
                syncedlyrics: $('#modal_settings_cbox_syncedlyrics').is(':checked'),
                numplaylistbyalbum: $('#modal_settings_cbox_numplaylistbyalbum').is(':checked'),
-               extendedTags: $('#modal_settings_cbox_extendedTags').is(':checked'),
-               partOfSet: $('#modal_settings_cbox_partOfSet').is(':checked'),
                chartsCountry: $('#modal_settings_select_chartsCounrty').val(),
                spotifyUser: $('#modal_settings_input_spotifyUser').val(),
                saveArtwork: $('#modal_settings_cbox_saveArtwork').is(':checked'),
+               saveArtworkArtist: $('#modal_settings_cbox_saveArtworkArtist').is(':checked'),
                logErrors: $('#modal_settings_cbox_logErrors').is(':checked'),
+               logSearched: $('#modal_settings_cbox_logSearched').is(':checked'),
                queueConcurrency: parseInt($('#modal_settings_number_queueConcurrency').val()),
                multitagSeparator: $('#modal_settings_select_multitagSeparator').val(),
                maxBitrate: $('#modal_settings_select_maxBitrate').val(),
-               PNGcovers: $('#modal_settings_cbox_PNGcovers').is(':checked')
+               PNGcovers: $('#modal_settings_cbox_PNGcovers').is(':checked'),
+               tags: {
+                       title: $('#modal_tags_title').is(':checked'),
+                       artist: $('#modal_tags_artist').is(':checked'),
+                       album: $('#modal_tags_album').is(':checked'),
+                       cover: $('#modal_tags_cover').is(':checked'),
+                       trackNumber: $('#modal_tags_trackNumber').is(':checked'),
+                       trackTotal: $('#modal_tags_trackTotal').is(':checked'),
+                       discNumber: $('#modal_tags_discNumber').is(':checked'),
+                       discTotal: $('#modal_tags_discTotal').is(':checked'),
+                       albumArtist: $('#modal_tags_albumArtist').is(':checked'),
+                       genre: $('#modal_tags_genre').is(':checked'),
+                       year: $('#modal_tags_year').is(':checked'),
+                       date: $('#modal_tags_date').is(':checked'),
+                       explicit: $('#modal_tags_explicit').is(':checked'),
+                       isrc: $('#modal_tags_isrc').is(':checked'),
+                       length: $('#modal_tags_length').is(':checked'),
+                       barcode: $('#modal_tags_barcode').is(':checked'),
+                       bpm: $('#modal_tags_bpm').is(':checked'),
+                       replayGain: $('#modal_tags_replayGain').is(':checked'),
+                       publisher: $('#modal_tags_publisher').is(':checked'),
+                       unsynchronisedLyrics: $('#modal_tags_unsynchronisedLyrics').is(':checked'),
+                       copyright: $('#modal_tags_copyright').is(':checked'),
+                       musicpublisher: $('#modal_tags_musicpublisher').is(':checked'),
+                       composer: $('#modal_tags_composer').is(':checked'),
+                       mixer: $('#modal_tags_mixer').is(':checked'),
+                       author: $('#modal_tags_author').is(':checked'),
+                       writer: $('#modal_tags_writer').is(':checked'),
+                       engineer: $('#modal_tags_engineer').is(':checked'),
+                       producer: $('#modal_tags_producer').is(':checked')
+               }
        };
-
        // Send updated settings to be saved into config file
        socket.emit('saveSettings', settings);
-       socket.emit("getUserSettings");
+       socket.emit('getUserSettings');
 });
 
 // Reset defaults button
 $('#modal_settings_btn_defaultSettings').click(function () {
-       if(typeof defaultDownloadLocation !== "undefined"){
+       if(typeof defaultDownloadLocation !== 'undefined'){
                defaultUserSettings.downloadLocation = defaultDownloadLocation;
                fillSettingsModal(defaultUserSettings);
        }
@@ -231,15 +279,15 @@ $('#modal_login_btn_signup').click(function(){
 });
 
 $('#modal_settings_btn_logout').click(function () {
-               $('#initializing').css('display', '');
-               $('#initializing').addClass('animated fadeIn').on('webkitAnimationEnd', function () {
-                       $(this).removeClass('animated fadeIn');
-                       $(this).css('display', '');
-               });
-               socket.emit('logout');
-               $('#modal_login_input_username').val("");
-               $('#modal_login_input_password').val("");
-               $('#modal_login_input_autologin').prop("checked",false);
+       $('#initializing').css('display', '');
+       $('#initializing').addClass('animated fadeIn').on('webkitAnimationEnd', function () {
+               $(this).removeClass('animated fadeIn');
+               $(this).css('display', '');
+       });
+       socket.emit('logout');
+       $('#modal_login_input_username').val("");
+       $('#modal_login_input_password').val("");
+       $('#modal_login_input_autologin').prop("checked",false);
 });
 
 // Populate settings fields
@@ -248,25 +296,56 @@ function fillSettingsModal(settings) {
        $('#modal_settings_input_playlistTrackNameTemplate').val(settings.playlistTrackNameTemplate);
        $('#modal_settings_input_albumTrackNameTemplate').val(settings.albumTrackNameTemplate);
        $('#modal_settings_input_albumNameTemplate').val(settings.albumNameTemplate);
+       $('#modal_settings_input_coverImageTemplate').val(settings.coverImageTemplate);
+       $('#modal_settings_input_artistImageTemplate').val(settings.artistImageTemplate);
        $('#modal_settings_cbox_createM3UFile').prop('checked', settings.createM3UFile);
        $('#modal_settings_cbox_createArtistFolder').prop('checked', settings.createArtistFolder);
        $('#modal_settings_cbox_createAlbumFolder').prop('checked', settings.createAlbumFolder);
+       $('#modal_settings_cbox_createCDFolder').prop('checked', settings.createCDFolder);
        $('#modal_settings_cbox_hifi').prop('checked', settings.hifi);
        $('#modal_settings_cbox_padtrck').prop('checked', settings.padtrck);
        $('#modal_settings_cbox_syncedlyrics').prop('checked', settings.syncedlyrics);
        $('#modal_settings_cbox_numplaylistbyalbum').prop('checked', settings.numplaylistbyalbum);
        $('#modal_settings_input_downloadTracksLocation').val(settings.downloadLocation);
        $('#modal_settings_select_artworkSize').val(settings.artworkSize).formSelect();
-       $('#modal_settings_cbox_extendedTags').prop('checked', settings.extendedTags);
-       $('#modal_settings_cbox_partOfSet').prop('checked', settings.partOfSet);
        $('#modal_settings_select_chartsCounrty').val(settings.chartsCountry).formSelect();
        $('#modal_settings_input_spotifyUser').val(settings.spotifyUser);
        $('#modal_settings_cbox_saveArtwork').prop('checked', settings.saveArtwork);
+       $('#modal_settings_cbox_saveArtworkArtist').prop('checked', settings.saveArtworkArtist);
        $('#modal_settings_cbox_logErrors').prop('checked', settings.logErrors);
+       $('#modal_settings_cbox_logSearched').prop('checked', settings.logSearched);
        $('#modal_settings_number_queueConcurrency').val(settings.queueConcurrency);
        $('#modal_settings_select_multitagSeparator').val(settings.multitagSeparator).formSelect();
        $('#modal_settings_select_maxBitrate').val(settings.maxBitrate).formSelect();
        $('#modal_settings_cbox_PNGcovers').prop('checked', settings.PNGcovers);
+       $('#modal_tags_title').prop('checked', settings.tags.title);
+       $('#modal_tags_artist').prop('checked', settings.tags.artist);
+       $('#modal_tags_album').prop('checked', settings.tags.album);
+       $('#modal_tags_cover').prop('checked', settings.tags.cover);
+       $('#modal_tags_trackNumber').prop('checked', settings.tags.trackNumber);
+       $('#modal_tags_trackTotal').prop('checked', settings.tags.trackTotal);
+       $('#modal_tags_discNumber').prop('checked', settings.tags.discNumber);
+       $('#modal_tags_discTotal').prop('checked', settings.tags.discTotal);
+       $('#modal_tags_albumArtist').prop('checked', settings.tags.albumArtist);
+       $('#modal_tags_genre').prop('checked', settings.tags.genre);
+       $('#modal_tags_year').prop('checked', settings.tags.year);
+       $('#modal_tags_date').prop('checked', settings.tags.date);
+       $('#modal_tags_explicit').prop('checked', settings.tags.explicit);
+       $('#modal_tags_isrc').prop('checked', settings.tags.isrc);
+       $('#modal_tags_length').prop('checked', settings.tags.length);
+       $('#modal_tags_barcode').prop('checked', settings.tags.barcode);
+       $('#modal_tags_bpm').prop('checked', settings.tags.bpm);
+       $('#modal_tags_replayGain').prop('checked', settings.tags.replayGain);
+       $('#modal_tags_publisher').prop('checked', settings.tags.publisher);
+       $('#modal_tags_unsynchronisedLyrics').prop('checked', settings.tags.unsynchronisedLyrics);
+       $('#modal_tags_copyright').prop('checked', settings.tags.copyright);
+       $('#modal_tags_musicpublisher').prop('checked', settings.tags.musicpublisher);
+       $('#modal_tags_composer').prop('checked', settings.tags.composer);
+       $('#modal_tags_mixer').prop('checked', settings.tags.mixer);
+       $('#modal_tags_author').prop('checked', settings.tags.author);
+       $('#modal_tags_writer').prop('checked', settings.tags.writer);
+       $('#modal_tags_engineer').prop('checked', settings.tags.engineer);
+       $('#modal_tags_producer').prop('checked', settings.tags.producer);
 
        M.updateTextFields()
 }
@@ -304,10 +383,6 @@ $('#tab_search_form_search').submit(function (ev) {
 
 });
 
-$('input[name=searchMode][type=radio]').change(()=>{
-       $('#tab_search_form_search').submit();
-})
-
 socket.on('search', function (data) {
 
        $('#tab_search_table_results_tbody_loadingIndicator').addClass('hide');
@@ -336,52 +411,16 @@ function showResults_table_track(tracks) {
        for (var i = 0; i < tracks.length; i++) {
                var currentResultTrack = tracks[i];
                $(tableBody).append(
-                       '<tr>' +
-                       '<td><a href="#" class="circle single-cover" preview="'+currentResultTrack['preview']+'"><i class="material-icons preview_controls white-text">play_arrow</i><img style="width:56px" class="circle" src="' + (currentResultTrack['album']['cover_small'] ? currentResultTrack['album']['cover_small'] : "img/noCover.jpg" ) + '"/></a></td>' +
-                       '<td>' + currentResultTrack['title'] + (currentResultTrack.explicit_lyrics ? ' <i class="material-icons valignicon tiny materialize-red-text">error_outline</i>' : '')+ '</td>' +
-                       '<td>' + currentResultTrack['artist']['name'] + '</td>' +
-                       '<td>' + currentResultTrack['album']['title'] + '</td>' +
-                       '<td>' + convertDuration(currentResultTrack['duration']) + '</td>' +
-                       '</tr>');
-               generateDownloadLink(currentResultTrack['link']).appendTo(tableBody.children('tr:last')).wrap('<td>');
-
-               tableBody.children('tr:last').find('.preview_controls').hover( function () {
-                       $(this).css({opacity: 1});
-               }, function () {
-                       if (($(this).parent().prop("playing") && preview_stopped) || !$(this).parent().prop("playing")){
-                               $(this).css({opacity: 0}, 200);
-                       }
-               });
-
-               tableBody.children('tr:last').find('.single-cover').click(function (e) {
-                       e.preventDefault();
-                       if ($(this).prop("playing")){
-                               if (preview_track.paused){
-                                       preview_track.play();
-                                       preview_stopped = false;
-                                       $(this).children('i').text("pause");
-                                       $(preview_track).animate({volume: 1}, 500);
-                               }else{
-                                       preview_stopped = true;
-                                       $(this).children('i').text("play_arrow");
-                                       $(preview_track).animate({volume: 0}, 250, "swing", ()=>{ preview_track.pause() });
-                               }
-                       }else{
-                               $("*").removeProp("playing");
-                               $(this).prop("playing","playing");
-                               $('.preview_controls').text("play_arrow");
-                               $('.preview_playlist_controls').text("play_arrow");
-                               $('.preview_controls').css({opacity:0});
-                               $(this).children('i').text("pause");
-                               $(this).children('i').css({opacity: 1});
-                               preview_stopped = false;
-                               $(preview_track).animate({volume: 0}, 250, "swing", ()=>{
-                                       preview_track.pause();
-                                       $('#preview-track_source').prop("src", $(this).attr("preview"));
-                                       preview_track.load();
-                               });
-                       }
-               });
+                       `<tr>
+                       <td><a href="#" class="circle ${(currentResultTrack.preview ? `single-cover" preview="${currentResultTrack.preview}"><i class="material-icons preview_controls white-text">play_arrow</i>` : '">')}<img style="width:56px" class="circle" src="${(currentResultTrack.album.cover_small ? currentResultTrack.album.cover_small : "img/noCover.jpg" )}"/></a></td>
+                       <td>${(currentResultTrack.explicit_lyrics ? ' <i class="material-icons valignicon tiny materialize-red-text">error_outline</i>' : '')} ${currentResultTrack.title}</td>
+                       <td>${currentResultTrack.artist.name}</td>
+                       <td>${currentResultTrack.album.title}</td>
+                       <td>${convertDuration(currentResultTrack.duration)}</td>
+                       </tr>`);
+               generateDownloadLink(currentResultTrack.link).appendTo(tableBody.children('tr:last')).wrap('<td>');
+               addPreviewControlsHover(tableBody.children('tr:last').find('.preview_controls'))
+               addPreviewControlsClick(tableBody.children('tr:last').find('.single-cover'))
        }
 }
 
@@ -392,15 +431,15 @@ function showResults_table_album(albums) {
        for (var i = 0; i < albums.length; i++) {
                var currentResultAlbum = albums[i];
                $(tableBody).append(
-                               '<tr>' +
-                               '<td><img style="width:56px" src="' + (currentResultAlbum['cover_small'] ? currentResultAlbum['cover_small'] : "img/noCover.jpg") + '" class="circle" /></td>' +
-                               (currentResultAlbum.explicit_lyrics ? '<td><i class="material-icons valignicon tiny materialize-red-text tooltipped" data-tooltip="Explicit">error_outline</i> ' : '<td> ') + currentResultAlbum['title'] + '</td>' +
-                               '<td>' + currentResultAlbum['artist']['name'] + '</td>' +
-                               '<td>' + currentResultAlbum['nb_tracks'] + '</td>' +
-                               '<td>' + currentResultAlbum['record_type'] + '</td>' +
-                               '</tr>');
-               generateShowTracklistSelectiveButton(currentResultAlbum['link']).appendTo(tableBody.children('tr:last')).wrap('<td>');
-               generateDownloadLink(currentResultAlbum['link']).appendTo(tableBody.children('tr:last')).wrap('<td>');
+                               `<tr>
+                               <td><img style="width:56px" src="${(currentResultAlbum.cover_small ? currentResultAlbum.cover_small : "img/noCover.jpg")}" class="circle" /></td>
+                               <td>${(currentResultAlbum.explicit_lyrics ? '<i class="material-icons valignicon tiny materialize-red-text tooltipped" data-tooltip="Explicit">error_outline</i>' : '')} ${currentResultAlbum.title}</td>
+                               <td>${currentResultAlbum.artist.name}</td>
+                               <td>${currentResultAlbum.nb_tracks}</td>
+                               <td>${currentResultAlbum.record_type[0].toUpperCase() + currentResultAlbum.record_type.substring(1)}</td>
+                               </tr>`);
+               generateShowTracklistSelectiveButton(currentResultAlbum.link).appendTo(tableBody.children('tr:last')).wrap('<td>');
+               generateDownloadLink(currentResultAlbum.link).appendTo(tableBody.children('tr:last')).wrap('<td>');
        }
        $('.tooltipped').tooltip({delay: 100});
 }
@@ -412,13 +451,13 @@ function showResults_table_artist(artists) {
        for (var i = 0; i < artists.length; i++) {
                var currentResultArtist = artists[i];
                $(tableBody).append(
-                               '<tr>' +
-                               '<td><img style="width:56px" src="' + (currentResultArtist['picture_small'] ? currentResultArtist['picture_small'] : "img/noCover.jpg")  + '" class="circle" /></td>' +
-                               '<td>' + currentResultArtist['name'] + '</td>' +
-                               '<td>' + currentResultArtist['nb_album'] + '</td>' +
-                               '</tr>');
-               generateShowTracklistButton(currentResultArtist['link']).appendTo(tableBody.children('tr:last')).wrap('<td>');
-               generateDownloadLink(currentResultArtist['link']).appendTo(tableBody.children('tr:last')).wrap('<td>');
+                               `<tr>
+                               <td><img style="width:56px" src="${(currentResultArtist.picture_small ? currentResultArtist.picture_small : "img/noCover.jpg")}" class="circle" /></td>
+                               <td>${currentResultArtist.name}</td>
+                               <td>${currentResultArtist.nb_album}</td>
+                               </tr>`);
+               generateShowTracklistButton(currentResultArtist.link).appendTo(tableBody.children('tr:last')).wrap('<td>');
+               generateDownloadLink(currentResultArtist.link).appendTo(tableBody.children('tr:last')).wrap('<td>');
        }
 }
 
@@ -429,13 +468,13 @@ function showResults_table_playlist(playlists) {
        for (var i = 0; i < playlists.length; i++) {
                var currentResultPlaylist = playlists[i];
                $(tableBody).append(
-                               '<tr>' +
-                               '<td><img style="width:56px" src="' + (currentResultPlaylist['picture_small'] ? currentResultPlaylist['picture_small'] : "img/noCover.jpg") + '" class="circle" /></td>' +
-                               '<td>' + currentResultPlaylist['title'] + '</td>' +
-                               '<td>' + currentResultPlaylist['nb_tracks'] + '</td>' +
-                               '</tr>');
-               generateShowTracklistSelectiveButton(currentResultPlaylist['link']).appendTo(tableBody.children('tr:last')).wrap('<td>');
-               generateDownloadLink(currentResultPlaylist['link']).appendTo(tableBody.children('tr:last')).wrap('<td>');
+                               `<tr>
+                               <td><img style="width:56px" src="${(currentResultPlaylist.picture_small ? currentResultPlaylist.picture_small : "img/noCover.jpg")}" class="circle" /></td>
+                               <td>${currentResultPlaylist.title}</td>
+                               <td>${currentResultPlaylist.nb_tracks}</td>
+                               </tr>`);
+               generateShowTracklistSelectiveButton(currentResultPlaylist.link).appendTo(tableBody.children('tr:last')).wrap('<td>');
+               generateDownloadLink(currentResultPlaylist.link).appendTo(tableBody.children('tr:last')).wrap('<td>');
        }
        $('.tooltipped').tooltip({delay: 100});
 }
@@ -527,7 +566,6 @@ socket.on("getTrackList", function (data) {
                        var tableBody = $('#modal_trackList_table_trackList_tbody_trackList');
                }
                $(tableBody).html('');
-               console.log(trackList)
                //############################################
                if (data.reqType == 'artist') {
                        trackListModalApp.title = 'Album List';
@@ -540,10 +578,15 @@ socket.on("getTrackList", function (data) {
                                {title: 'Download Album'}
                        ];
                        for (var i = 0; i < trackList.length; i++) {
-                               $(tableBody).append('<tr><td>' + (i + 1) + '</td>' +
-                                               (trackList[i].explicit_lyrics ? '<td><i class="material-icons valignicon tiny materialize-red-text tooltipped" data-tooltip="Explicit">error_outline</i></td>' : '<td></td>') +
-                                               '<td><a href="#" class="album_chip" data-link="' + trackList[i].link + '"><div class="chip"><img src="' + trackList[i].cover_small + '" />' + trackList[i].title + '</div></a></td>' +
-                                               '<td>' + trackList[i].release_date + '</td><td>' + trackList[i].record_type + '</td></tr>');
+                               $(tableBody).append(
+                                       `<tr>
+                                       <td>${(i + 1)}</td>
+                                       <td>${(trackList[i].explicit_lyrics ? '<i class="material-icons valignicon tiny materialize-red-text tooltipped" data-tooltip="Explicit">error_outline</i>' : '')}</td>
+                                       <td><a href="#" class="album_chip" data-link="${trackList[i].link}"><div class="chip"><img src="${trackList[i].cover_small}"/>${trackList[i].title}</div></a></td>
+                                       <td>${trackList[i].release_date}</td>
+                                       <td>${trackList[i].record_type[0].toUpperCase() + trackList[i].record_type.substring(1)}</td>
+                                       </tr>`
+                               );
                                generateDownloadLink(trackList[i].link).appendTo(tableBody.children('tr:last')).wrap('<td>');
                        }
                        $('.album_chip').click(function(e){
@@ -562,42 +605,22 @@ socket.on("getTrackList", function (data) {
                        $('.selectAll').prop('checked', false);
                        for (var i = 0; i < trackList.length; i++) {
                                $(tableBody).append(
-                                       '<tr><td><i class="material-icons preview_playlist_controls" preview="'+trackList[i].preview+'">play_arrow</i></td>'+
-                                       '<td>' + (i + 1) + '</td>' +
-                                       (trackList[i].explicit_lyrics ? '<td><i class="material-icons valignicon tiny materialize-red-text tooltipped" data-tooltip="Explicit">error_outline</i> ' : '<td> ') + trackList[i].title + '</td>' +
-                                       '<td>' + trackList[i].artist.name + '</td>' +
-                                       '<td>' + convertDuration(trackList[i].duration) + '</td>' +
-                                       '<td><div class="valign-wrapper"><label><input class="trackCheckbox valign" type="checkbox" id="trackChk'+ i +'" value="' + trackList[i].link + '"><span></span></label></div></tr>'
+                                       `<tr>
+                                       <td><i class="material-icons ${(trackList[i].preview ? `preview_playlist_controls" preview="${trackList[i].preview}"` : 'grey-text"')}>play_arrow</i></td>
+                                       <td>${(i + 1)}</td>
+                                       <td>${(trackList[i].explicit_lyrics ? '<i class="material-icons valignicon tiny materialize-red-text tooltipped" data-tooltip="Explicit">error_outline</i> ' : '')}${trackList[i].title}</td>
+                                       <td>${trackList[i].artist.name}</td>
+                                       <td>${convertDuration(trackList[i].duration)}</td>
+                                       <td>
+                                               <div class="valign-wrapper">
+                                               <label>
+                                               <input class="trackCheckbox valign" type="checkbox" id="trackChk${i}" value="${trackList[i].link}"><span></span>
+                                               </label>
+                                               </div>
+                                       </td>
+                                       </tr>`
                                );
-                               tableBody.children('tr:last').find('.preview_playlist_controls').click(function (e) {
-                                       e.preventDefault();
-                                       if ($(this).prop("playing")){
-                                               if (preview_track.paused){
-                                                       preview_track.play();
-                                                       preview_stopped = false;
-                                                       $(this).text("pause");
-                                                       $(preview_track).animate({volume: 1}, 500);
-                                               }else{
-                                                       preview_stopped = true;
-                                                       $(this).text("play_arrow");
-                                                       $(preview_track).animate({volume: 0}, 250, "swing", ()=>{ preview_track.pause() });
-                                               }
-                                       }else{
-                                               $("*").removeProp("playing");
-                                               $(this).prop("playing","playing");
-                                               $('.preview_controls').text("play_arrow");
-                                               $('.preview_playlist_controls').text("play_arrow");
-                                               $('.preview_controls').css({opacity:0});
-                                               $(this).text("pause");
-                                               $(this).css({opacity: 1});
-                                               preview_stopped = false;
-                                               $(preview_track).animate({volume: 0}, 250, "swing", ()=>{
-                                                       preview_track.pause();
-                                                       $('#preview-track_source').prop("src", $(this).attr("preview"));
-                                                       preview_track.load();
-                                               });
-                                       }
-                               });
+                               addPreviewControlsClick(tableBody.children('tr:last').find('.preview_playlist_controls'));
                        }
                } else if(data.reqType == 'album') {
                        trackListSelectiveModalApp.title = 'Tracklist';
@@ -618,46 +641,26 @@ socket.on("getTrackList", function (data) {
                        for (var i = 0; i < trackList.length; i++) {
                                discNum = trackList[i].disk_number
                                if (discNum != baseDisc){
-                                       $(tableBody).append('<tr><td colspan="4" style="opacity: 0.54;"><i class="material-icons valignicon tiny">album</i> '+discNum+'</td></tr>');
+                                       $(tableBody).append(`<tr><td colspan="4" style="opacity: 0.54;"><i class="material-icons valignicon tiny">album</i>${discNum}</td></tr>`);
                                        baseDisc = discNum;
                                }
                                $(tableBody).append(
-                                       '<tr><td><i class="material-icons preview_playlist_controls" preview="'+trackList[i].preview+'">play_arrow</i></td>'+
-                                       '<td>' + trackList[i].track_position + '</td>' +
-                                       (trackList[i].explicit_lyrics ? '<td><i class="material-icons valignicon tiny materialize-red-text tooltipped" data-tooltip="Explicit">error_outline</i> ' : '<td> ') + trackList[i].title + '</td>' +
-                                       '<td>' + trackList[i].artist.name + '</td>' +
-                                       '<td>' + convertDuration(trackList[i].duration) + '</td>' +
-                                       '<td><div class="valign-wrapper"><label><input class="trackCheckbox valign" type="checkbox" id="trackChk'+ i +'" value="' + trackList[i].link + '"><span></span></label></div></tr>'
+                                       `<tr>
+                                       <td><i class="material-icons ${(trackList[i].preview ? `preview_playlist_controls" preview="${trackList[i].preview}"` : 'grey-text"')}>play_arrow</i></td>
+                                       <td>${trackList[i].track_position}</td>
+                                       <td>${(trackList[i].explicit_lyrics ? '<i class="material-icons valignicon tiny materialize-red-text tooltipped" data-tooltip="Explicit">error_outline</i> ' : '')}${trackList[i].title}</td>
+                                       <td>${trackList[i].artist.name}</td>
+                                       <td>${convertDuration(trackList[i].duration)}</td>
+                                       <td>
+                                               <div class="valign-wrapper">
+                                               <label>
+                                               <input class="trackCheckbox valign" type="checkbox" id="trackChk${i}" value="${trackList[i].link}"><span></span>
+                                               </label>
+                                               </div>
+                                       </td>
+                                       </tr>`
                                );
-                               tableBody.children('tr:last').find('.preview_playlist_controls').click(function (e) {
-                                       e.preventDefault();
-                                       if ($(this).prop("playing")){
-                                               if (preview_track.paused){
-                                                       preview_track.play();
-                                                       preview_stopped = false;
-                                                       $(this).text("pause");
-                                                       $(preview_track).animate({volume: 1}, 500);
-                                               }else{
-                                                       preview_stopped = true;
-                                                       $(this).text("play_arrow");
-                                                       $(preview_track).animate({volume: 0}, 250, "swing", ()=>{ preview_track.pause() });
-                                               }
-                                       }else{
-                                               $("*").removeProp("playing");
-                                               $(this).prop("playing","playing");
-                                               $('.preview_controls').text("play_arrow");
-                                               $('.preview_playlist_controls').text("play_arrow");
-                                               $('.preview_controls').css({opacity:0});
-                                               $(this).text("pause");
-                                               $(this).css({opacity: 1});
-                                               preview_stopped = false;
-                                               $(preview_track).animate({volume: 0}, 250, "swing", ()=>{
-                                                       preview_track.pause();
-                                                       $('#preview-track_source').prop("src", $(this).attr("preview"));
-                                                       preview_track.load();
-                                               });
-                                       }
-                               });
+                               addPreviewControlsClick(tableBody.children('tr:last').find('.preview_playlist_controls'));
                        }
                } else {
                        trackListModalApp.title = 'Tracklist';
@@ -670,43 +673,15 @@ socket.on("getTrackList", function (data) {
                        ];
                        for (var i = 0; i < trackList.length; i++) {
                                $(tableBody).append(
-                                       '<tr>'+
-                                       '<td><i class="material-icons preview_playlist_controls" preview="'+trackList[i].preview+'">play_arrow</i></td>'+
-                                       '<td>' + (i + 1) + '</td>' +
-                                       (trackList[i].explicit_lyrics ? '<td><i class="material-icons valignicon tiny materialize-red-text tooltipped" data-tooltip="Explicit">error_outline</i> ' : '<td> ') +
-                                       trackList[i].title + '</td>' +
-                                       '<td>' + trackList[i].artist.name + '</td>' +
-                                       '<td>' + convertDuration(trackList[i].duration) + '</td></tr>'
+                                       `<tr>
+                                       <td><i class="material-icons ${(trackList[i].preview ? `preview_playlist_controls" preview="${trackList[i].preview}"` : 'grey-text"')}>play_arrow</i></td>
+                                       <td>${(i + 1)}</td>
+                                       <td>${(trackList[i].explicit_lyrics ? '<i class="material-icons valignicon tiny materialize-red-text tooltipped" data-tooltip="Explicit">error_outline</i> ' : '')}${trackList[i].title}</td>
+                                       <td>${trackList[i].artist.name}</td>
+                                       <td>${convertDuration(trackList[i].duration)}</td>
+                                       </tr>`
                                );
-                               tableBody.children('tr:last').find('.preview_playlist_controls').click(function (e) {
-                                       e.preventDefault();
-                                       if ($(this).prop("playing")){
-                                               if (preview_track.paused){
-                                                       preview_track.play();
-                                                       preview_stopped = false;
-                                                       $(this).text("pause");
-                                                       $(preview_track).animate({volume: 1}, 500);
-                                               }else{
-                                                       preview_stopped = true;
-                                                       $(this).text("play_arrow");
-                                                       $(preview_track).animate({volume: 0}, 250, "swing", ()=>{ preview_track.pause() });
-                                               }
-                                       }else{
-                                               $("*").removeProp("playing");
-                                               $(this).prop("playing","playing");
-                                               $('.preview_controls').text("play_arrow");
-                                               $('.preview_playlist_controls').text("play_arrow");
-                                               $('.preview_controls').css({opacity:0});
-                                               $(this).text("pause");
-                                               $(this).css({opacity: 1});
-                                               preview_stopped = false;
-                                               $(preview_track).animate({volume: 0}, 250, "swing", ()=>{
-                                                       preview_track.pause();
-                                                       $('#preview-track_source').prop("src", $(this).attr("preview"));
-                                                       preview_track.load();
-                                               });
-                                       }
-                               });
+                               addPreviewControlsClick(tableBody.children('tr:last').find('.preview_playlist_controls'));
                        }
                }
                if(data.reqType == 'album' || data.reqType == 'playlist'){
@@ -757,52 +732,17 @@ socket.on("getChartsTrackListByCountry", function (data) {
        for (var i = 0; i < data.tracks.length; i++) {
                currentChartTrack = data.tracks[i];
                $(chartsTableBody).append(
-                               '<tr>' +
-                               '<td>' + (i + 1) + '</td>' +
-                               '<td><a href="#" class="circle single-cover" preview="'+currentChartTrack['preview']+'"><i class="material-icons preview_controls white-text">play_arrow</i><img style="width:56px" src="' + (currentChartTrack['album']['cover_small'] ? currentChartTrack['album']['cover_small'] : "img/noCover.jpg") + '" class="circle" /></a></td>' +
-                               '<td>' + currentChartTrack['title'] + '</td>' +
-                               '<td>' + currentChartTrack['artist']['name'] + '</td>' +
-                               '<td>' + currentChartTrack['album']['title'] + '</td>' +
-                               '<td>' + convertDuration(currentChartTrack['duration']) + '</td>' +
-                               '</tr>');
-               generateDownloadLink(currentChartTrack['link']).appendTo(chartsTableBody.children('tr:last')).wrap('<td>');
-               chartsTableBody.children('tr:last').find('.preview_controls').hover( function () {
-                       $(this).css({opacity: 1});
-               }, function () {
-                       if (($(this).parent().prop("playing") && preview_stopped) || !$(this).parent().prop("playing")){
-                               $(this).css({opacity: 0}, 200);
-                       }
-               });
-               chartsTableBody.children('tr:last').find('.single-cover').click(function (e) {
-                       e.preventDefault();
-                       if ($(this).prop("playing")){
-                               if (preview_track.paused){
-                                       preview_track.play();
-                                       preview_stopped = false;
-                                       $(this).children('i').text("pause");
-                                       $(preview_track).animate({volume: 1}, 500);
-                               }else{
-                                       preview_stopped = true;
-                                       $(this).children('i').text("play_arrow");
-                                       $(preview_track).animate({volume: 0}, 250, "swing", ()=>{ preview_track.pause() });
-                               }
-                       }else{
-                               $("*").removeProp("playing");
-                               $(this).prop("playing","playing");
-                               $('.preview_controls').text("play_arrow");
-                               $('.preview_playlist_controls').text("play_arrow");
-                               $('.preview_controls').css({opacity:0});
-                               $(this).children('i').text("pause");
-                               $(this).children('i').css({opacity: 1});
-                               preview_stopped = false;
-                               $(preview_track).animate({volume: 0}, 250, "swing", ()=>{
-                                       preview_track.pause();
-                                       $('#preview-track_source').prop("src", $(this).attr("preview"));
-                                       preview_track.load();
-                               });
-                       }
-               });
-
+                               `<tr>
+                               <td>${(i + 1)}</td>
+                               <td><a href="#" class="circle ${(currentChartTrack.preview ? `single-cover" preview="${currentChartTrack.preview}"><i class="material-icons preview_controls white-text">play_arrow</i>` : '">')}<img style="width:56px" src="${(currentChartTrack.album.cover_small ? currentChartTrack.album.cover_small : "img/noCover.jpg")}" class="circle" /></a></td>
+                               <td>${currentChartTrack.title}</td>
+                               <td>${currentChartTrack.artist.name}</td>
+                               <td>${currentChartTrack.album.title}</td>
+                               <td>${convertDuration(currentChartTrack.duration)}</td>
+                               </tr>`);
+               generateDownloadLink(currentChartTrack.link).appendTo(chartsTableBody.children('tr:last')).wrap('<td>');
+               addPreviewControlsHover(chartsTableBody.children('tr:last').find('.preview_controls'))
+               addPreviewControlsClick(chartsTableBody.children('tr:last').find('.single-cover'))
        }
        $('#tab_charts_table_charts_tbody_loadingIndicator').addClass('hide');
        chartsTableBody.removeClass('hide');
@@ -815,17 +755,17 @@ socket.on("getMePlaylistList", function (data) {
        for (var i = 0; i < data.playlists.length; i++) {
                var currentResultPlaylist = data.playlists[i];
                $(tableBody).append(
-                               '<tr>' +
-                               '<td><img src="' + currentResultPlaylist['image'] + '" class="circle" width="56px" /></td>' +
-                               '<td>' + currentResultPlaylist['title'] + '</td>' +
-                               '<td>' + currentResultPlaylist['songs'] + '</td>' +
-                               '</tr>');
+                               `<tr>
+                               <td><img src="${currentResultPlaylist.image}" class="circle" width="56px" /></td>
+                               <td>${currentResultPlaylist.title}</td>
+                               <td>${currentResultPlaylist.songs}</td>
+                               </tr>`);
                if (currentResultPlaylist.spotify)
-                       generateShowTracklistButton(currentResultPlaylist['link']).appendTo(tableBody.children('tr:last')).wrap('<td>')
+                       generateShowTracklistButton(currentResultPlaylist.link).appendTo(tableBody.children('tr:last')).wrap('<td>')
                else
-                       generateShowTracklistSelectiveButton(currentResultPlaylist['link']).appendTo(tableBody.children('tr:last')).wrap('<td>')
+                       generateShowTracklistSelectiveButton(currentResultPlaylist.link).appendTo(tableBody.children('tr:last')).wrap('<td>')
 
-               generateDownloadLink(currentResultPlaylist['link']).appendTo(tableBody.children('tr:last')).wrap('<td>');
+               generateDownloadLink(currentResultPlaylist.link).appendTo(tableBody.children('tr:last')).wrap('<td>');
        }
        $('.tooltipped').tooltip({delay: 100});
 });
@@ -853,7 +793,7 @@ $('#tab_url_form_url').submit(function (ev) {
                }
                if (url.indexOf('open.spotify.com/') >= 0 ||  url.indexOf('spotify:') >= 0){
                        if (url.indexOf('user') < 0 || url.indexOf('playlist') < 0){
-                               message('Playlist not found', 'Spotify for now can only download playlists.');
+                               message('Playlist not found', 'Deezloader for now can only download Spotify playlists.');
                                return false;
                        }
                }
@@ -864,6 +804,7 @@ $('#tab_url_form_url').submit(function (ev) {
 //############################################TAB_DOWNLOADS###########################################\\
 function addToQueue(url) {
        var type = getTypeFromLink(url), id = getIDFromLink(url);
+       console.log(type, id)
        if (type == 'spotifyplaylist'){
                [user, id] = getPlayUserFromURI(url)
                userSettings.currentSpotifyUser = user;
@@ -878,15 +819,15 @@ function addToQueue(url) {
                userSettings.filename = userSettings.albumTrackNameTemplate;
                userSettings.foldername = userSettings.albumNameTemplate;
        } else {
-               $('#modal_wrongURL').modal('open');
+               M.toast({html: '<i class="material-icons left">error</i> Wrong Type!', displayLength: 5000, classes: 'rounded'});
                return false;
        }
        if (alreadyInQueue(id)) {
                M.toast({html: '<i class="material-icons left">playlist_add_check</i> Already in download-queue!', displayLength: 5000, classes: 'rounded'});
                return false;
        }
-       if (id.match(/^[0-9]+$/) == null && type != 'spotifyplaylist') {
-               $('#modal_wrongURL').modal('open');
+       if (id.match(/^[0-9]+$/) == null && type != 'spotifyplaylist' && parseInt(id)>0) {
+               M.toast({html: '<i class="material-icons left">error</i> Wrong ID!', displayLength: 5000, classes: 'rounded'});
                return false;
        }
        socket.emit("download" + type, {id: id, settings: userSettings});
@@ -909,13 +850,13 @@ socket.on('addToQueue', function (data) {
        var tableBody = $('#tab_downloads_table_downloads').find('tbody');
 
        $(tableBody).append(
-                       '<tr id="' + data.queueId + '" data-deezerid="' + data.id + '">' +
-                       '<td class="queueTitle">' + data.name + '</td>' +
-                       '<td class="queueSize">' + data.size + '</td>' +
-                       '<td class="queueDownloaded">' + data.downloaded + '</td>' +
-                       '<td class="queueFailed">' + data.failed + '</td>' +
-                       '<td><div class="progress"><div class="indeterminate"></div></div></td>' +
-                       '</tr>');
+                       `<tr id="${data.queueId}" data-deezerid="${data.id}">
+                       <td class="queueTitle">${data.name}</td>
+                       <td class="queueSize">${data.size}</td>
+                       <td class="queueDownloaded">${data.downloaded}</td>
+                       <td class="queueFailed">${data.failed}</td>
+                       <td><div class="progress"><div class="indeterminate"></div></div></td>
+                       </tr>`);
 
        var btn_remove = $('<a href="#" class="btn-flat waves-effect"><i class="material-icons">remove</i></a>');
 
@@ -1081,6 +1022,49 @@ function generateDownloadLink(url) {
        return btn_download;
 }
 
+function addPreviewControlsHover(el){
+       el.hover( function () {
+               $(this).css({opacity: 1});
+       }, function () {
+               if (($(this).parent().attr("playing") && preview_stopped) || !$(this).parent().attr("playing")){
+                       $(this).css({opacity: 0}, 200);
+               }
+       });
+}
+
+function addPreviewControlsClick(el){
+       el.click(function (e) {
+               e.preventDefault();
+               var icon = (this.tagName == "I" ? $(this) : $(this).children('i'))
+               if ($(this).attr("playing")){
+                       if (preview_track.paused){
+                               preview_track.play();
+                               preview_stopped = false;
+                               icon.text("pause");
+                               $(preview_track).animate({volume: 1}, 500);
+                       }else{
+                               preview_stopped = true;
+                               icon.text("play_arrow");
+                               $(preview_track).animate({volume: 0}, 250, "swing", ()=>{ preview_track.pause() });
+                       }
+               }else{
+                       $("*").removeAttr("playing");
+                       $(this).attr("playing",true);
+                       $('.preview_controls').text("play_arrow");
+                       $('.preview_playlist_controls').text("play_arrow");
+                       $('.preview_controls').css({opacity:0});
+                       icon.text("pause");
+                       icon.css({opacity: 1});
+                       preview_stopped = false;
+                       $(preview_track).animate({volume: 0}, 250, "swing", ()=>{
+                               preview_track.pause();
+                               $('#preview-track_source').prop("src", $(this).attr("preview"));
+                               preview_track.load();
+                       });
+               }
+       });
+}
+
 function convertDuration(duration) {
        //convert from seconds only to mm:ss format
        var mm, ss;
index 2d1edd6c1914a713fa143804e66eb8d33baaa0e1..34c2f94d2cc3567f312a772228b76915770bc096 100644 (file)
                "appId": "deezloader-rmx",
                "productName": "Deezloader Remix",
                "linux": {
-                       "target": "AppImage",
-                       "category": "Audio",
-                       "arch": [
-                               "x64",
-                               "ia32"
-                       ]
+                       "target": [
+                               {
+                                       "target": "AppImage",
+                                       "arch": [
+                                               "x64",
+                                               "ia32"
+                                       ]
+                               }
+                       ],
+                       "category": "Audio"
                },
                "mac": {
                        "category": "public.app-category.music"