From 54a14277c8afe34d61153171b28cdc9fc08609f6 Mon Sep 17 00:00:00 2001
From: jcorporation <mail@jcgames.de>
Date: Thu, 20 Sep 2018 19:56:24 +0100
Subject: [PATCH 01/11] Fix: show lastPlayed in song details

---
 htdocs/js/mympd.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/htdocs/js/mympd.js b/htdocs/js/mympd.js
index 9fab572..54df2b0 100644
--- a/htdocs/js/mympd.js
+++ b/htdocs/js/mympd.js
@@ -1482,7 +1482,7 @@ function parseSongDetails(obj) {
         songDetails += '<tr><th colspan="2">Statistics</th></tr>' +
             '<tr><th>Play count</th><td>' + obj.data.playCount + '</td></tr>' +
             '<tr><th>Skip count</th><td>' + obj.data.skipCount + '</td></tr>' +
-            '<tr><th>Last played</th><td>' + (obj.data.lastPlayed == 0 ? 'never' : new Date(value * 1000).toUTCString()) + '</td></tr>' +
+            '<tr><th>Last played</th><td>' + (obj.data.lastPlayed == 0 ? 'never' : new Date(obj.data.lastPlayed * 1000).toUTCString()) + '</td></tr>' +
             '<tr><th>Like</th><td>' + like + '</td></tr>';
     }
     

From 77be445fc1eb7b13a9ad03747a7f2ea8f892b765 Mon Sep 17 00:00:00 2001
From: jcorporation <mail@jcgames.de>
Date: Thu, 20 Sep 2018 19:59:08 +0100
Subject: [PATCH 02/11] Fix: bump version to 4.2.1

---
 CMakeLists.txt     | 2 +-
 PKGBUILD           | 2 +-
 contrib/myMPD.spec | 9 +++++----
 debian/changelog   | 4 ++--
 htdocs/sw.js       | 2 +-
 mkdebian.sh        | 2 +-
 6 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index a6a7d76..664d075 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -4,7 +4,7 @@ project (mympd C)
 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/")
 set(CPACK_PACKAGE_VERSION_MAJOR "4")
 set(CPACK_PACKAGE_VERSION_MINOR "2")
-set(CPACK_PACKAGE_VERSION_PATCH "0")
+set(CPACK_PACKAGE_VERSION_PATCH "1")
 
 if(CMAKE_BUILD_TYPE MATCHES RELEASE)
     set(ASSETS_PATH "/usr/share/${PROJECT_NAME}/htdocs")
diff --git a/PKGBUILD b/PKGBUILD
index a689af7..2156840 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -5,7 +5,7 @@
 
 pkgname=mympd
 _pkgname=myMPD
-pkgver=4.2.0
+pkgver=4.2.1
 pkgrel=1
 pkgdesc="A standalone MPD Web GUI based on YMPD - Default port set to 80"
 arch=('x86_64' 'armv7h' 'aarch64')
diff --git a/contrib/myMPD.spec b/contrib/myMPD.spec
index 9b7da3f..bd899a0 100644
--- a/contrib/myMPD.spec
+++ b/contrib/myMPD.spec
@@ -4,13 +4,13 @@
 # (c) 2018 Juergen Mang <mail@jcgames.de
 
 Name:           myMPD
-Version:        4.2.0
+Version:        4.2.1
 Release:        0 
 License:        GPL-2.0 
 Group:          Productivity/Multimedia/Sound/Players
 Summary:        Standalone webclient for mpd
 Url:            https://github.com/jcorporation/myMPD
-Source:         https://github.com/jcorporation/myMPD/archive/v4.2.0.zip
+Source:         https://github.com/jcorporation/myMPD/archive/v4.2.1.zip
 BuildRequires:  gcc
 BuildRequires:  cmake
 BuildRequires:  unzip
@@ -50,9 +50,10 @@ then
   chown -R mympd.mympd /var/lib/mympd
 fi
 
-if [ -d /usr/lib/systemd/ ]
+SYSTEMCTL=$(which systemctl > /dev/null 2>&1)
+if [ "$?" == "0" ]
 then
-  [ -d /usr/lib/systemd/system ] || sudo mkdir /usr/lib/systemd/system 
+  [ -d /usr/lib/systemd/system ] || sudo mkdir -p /usr/lib/systemd/system 
   cp /usr/share/mympd/mympd.service /usr/lib/systemd/system/
   systemctl daemon-reload
   systemctl enable mympd
diff --git a/debian/changelog b/debian/changelog
index 0a70634..2d2c8bf 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,5 +1,5 @@
-mympd (4.2.0-1) stable; urgency=medium
+mympd (4.2.1-1) stable; urgency=medium
 
   * Release from master
 
- -- Juergen Mang <mail@jcgames.de>  Mon, 17 Sep 2018 17:59:00 +0200
+ -- Juergen Mang <mail@jcgames.de>  Thu, 20 Sep 2018 19:32:00 +0200
diff --git a/htdocs/sw.js b/htdocs/sw.js
index 3e63157..cce5f88 100644
--- a/htdocs/sw.js
+++ b/htdocs/sw.js
@@ -1,4 +1,4 @@
-var CACHE = 'myMPD-cache-v4.2.0';
+var CACHE = 'myMPD-cache-v4.2.1';
 var urlsToCache = [
     '/',
     '/player.html',
diff --git a/mkdebian.sh b/mkdebian.sh
index 45e05dc..5214536 100755
--- a/mkdebian.sh
+++ b/mkdebian.sh
@@ -1,4 +1,4 @@
 #!/bin/bash
 ./mkclean.sh
-tar -czvf ../mympd_4.2.0.orig.tar.gz *
+tar -czvf ../mympd_4.2.1.orig.tar.gz *
 dpkg-buildpackage -rfakeroot

From 82029ce39dbc5692116659598b3428f59e1d0fa0 Mon Sep 17 00:00:00 2001
From: jcorporation <mail@jcgames.de>
Date: Thu, 20 Sep 2018 21:13:04 +0100
Subject: [PATCH 03/11] Fix: dont't remove user/group on uninstall Fix: moved
 pics directory to /var/lib/mympd

---
 CMakeLists.txt            |  3 +--
 contrib/archlinux.install | 20 +++++++-------------
 contrib/myMPD.spec        | 33 ++++++++++++++-------------------
 debian/postinst           |  9 ++++++---
 debian/postrm             | 12 ++----------
 debian/rules              |  1 +
 6 files changed, 31 insertions(+), 47 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 664d075..0a5bff0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -54,5 +54,4 @@ install(FILES dist/htdocs/js/mympd.min.js DESTINATION share/${PROJECT_NAME}/htdo
 install(FILES dist/htdocs/css/bootstrap.min.css DESTINATION share/${PROJECT_NAME}/htdocs/css/)
 install(FILES dist/htdocs/css/mympd.min.css DESTINATION share/${PROJECT_NAME}/htdocs/css/)
 install(DIRECTORY htdocs/assets DESTINATION share/${PROJECT_NAME}/htdocs)
-install(DIRECTORY DESTINATION share/${PROJECT_NAME}/htdocs/pics)
-install(DIRECTORY DESTINATION ../var/lib/${PROJECT_NAME}/)
+install(DIRECTORY DESTINATION ../var/lib/${PROJECT_NAME}/pics)
diff --git a/contrib/archlinux.install b/contrib/archlinux.install
index 6e10041..35963b7 100644
--- a/contrib/archlinux.install
+++ b/contrib/archlinux.install
@@ -27,6 +27,9 @@ post_upgrade() {
     echo "/etc/mpd.conf not found, you must link your musicdir manually to /usr/share/mympd/htdocs/library"
   fi
 
+  echo "Linking pics directory"
+  [ -e /usr/share/mympd/htdocs/pics ] || ln -s /var/lib/mympd/pics /usr/share/mympd/htdocs/
+
   # install systemd service
   echo "INFO: Installing systemd service"
   if [ -d /etc/systemd/system ]
@@ -77,18 +80,9 @@ post_remove() {
     echo -e "\e[93mINFO\e[0m: /etc/mympd/mympd.conf backed up to /etc/mympd/mympd.conf.pacsave"
   fi
 
-  # unlink music dir
-  echo "unlinking musicdir to library"
-  [ -e /usr/share/mympd/htdocs/library ] && rm -v /usr/share/mympd/htdocs/library
-
-  # remove mympd user and group
-  getent passwd mympd > /dev/null
-  echo -e "\e[93mWARNING\e[0m: Removing \e[1mmympd \e[0muser and group!"
-  [ "$?" != "2" ] && userdel -r mympd
-  getent group mympd > /dev/null
-  [ "$?" != "2" ] && groupdel mympd 
-
   # remove leftover directories
-  rmdir -v /usr/share/{mympd/htdocs/,mympd/}
+  rm -v -f /usr/share/mympd/htdocs/pics
+  rm -v -f /usr/share/mympd/htdocs/library
+  rmdir -v /usr/share/mympd/htdocs/
+  rmdir -v /usr/share/mympd/
 }
-
diff --git a/contrib/myMPD.spec b/contrib/myMPD.spec
index bd899a0..0e67dbd 100644
--- a/contrib/myMPD.spec
+++ b/contrib/myMPD.spec
@@ -50,8 +50,7 @@ then
   chown -R mympd.mympd /var/lib/mympd
 fi
 
-SYSTEMCTL=$(which systemctl > /dev/null 2>&1)
-if [ "$?" == "0" ]
+if [ -d /etc/systemd ]
 then
   [ -d /usr/lib/systemd/system ] || sudo mkdir -p /usr/lib/systemd/system 
   cp /usr/share/mympd/mympd.service /usr/lib/systemd/system/
@@ -65,6 +64,8 @@ then
   [ "$LIBRARY" != "" ] && [ ! -e /usr/share/mympd/htdocs/library ] && ln -s "$LIBRARY" /usr/share/mympd/htdocs/library
 fi
 
+[ -e /usr/share/mympd/htdocs/pics ] || ln -s /var/lib/mympd/pics /usr/share/mympd/htdocs/
+
 if [ ! -f /etc/mympd/mympd.conf ]
 then 
   mv /etc/mympd/mympd.conf.dist /etc/mympd/mympd.conf
@@ -75,28 +76,22 @@ fi
 /usr/share/mympd/crcert.sh
 
 %postun
-if [ -f /usr/lib/systemd/system/mympd.service ]
+if [ "$1" = "0" ]
 then
-  if `systemctl is-active --quiet mympd`
+  if [ -f /usr/lib/systemd/system/mympd.service ]
   then
-    echo "stopping mympd.service" && systemctl stop mympd 
+    if `systemctl is-active --quiet mympd`
+    then
+      echo "stopping mympd.service" && systemctl stop mympd 
+    fi
+    echo "disabling mympd.service" && systemctl disable mympd
+    rm -v -f /usr/lib/systemd/system/mympd.service
+    systemctl daemon-reload
   fi
-  echo "disabling mympd.service" && systemctl disable mympd
-  rm -v -f /usr/lib/systemd/system/mympd.service
-  systemctl daemon-reload
+  rm -v -f /usr/share/mympd/htdocs/pics
+  rm -v -f /usr/share/mympd/htdocs/library
 fi
 
-rm -v -fr /var/lib/mympd
-[ -e /usr/share/mympd/htdocs/library ] && rm -v /usr/share/mympd/htdocs/library
-rmdir -v /usr/share/{mympd/htdocs/,mympd/}
-
-getent passwd mympd > /dev/null
-echo "Removing mympd user and group"
-[ "$?" != "2" ] && userdel -r mympd
-getent group mympd > /dev/null
-[ "$?" != "2" ] && groupdel mympd
-
-
 %files 
 %defattr(-,root,root,-)
 %doc README.md LICENSE
diff --git a/debian/postinst b/debian/postinst
index 199efbc..ca6f8d6 100755
--- a/debian/postinst
+++ b/debian/postinst
@@ -6,7 +6,7 @@ getent group mympd > /dev/null
 getent passwd mympd > /dev/null
 [ "$?" = "2" ] && useradd -r mympd -g mympd -d /var/lib/mympd -s /usr/sbin/nologin
 
-if ! [ $(stat -c '%U:%G' /var/lib/mympd/) == 'mympd:mympd' ]
+if ! [ $(stat -c '%U:%G' /var/lib/mympd/) = 'mympd:mympd' ]
 then
   echo "Fixing ownership of /var/lib/mympd"
   chown -R mympd.mympd /var/lib/mympd
@@ -21,10 +21,13 @@ else
   echo "/etc/mpd.conf not found, you must link your music_directory manually to /usr/share/mympd/htdocs/library"
 fi
 
-if [ -d /usr/lib/systemd/ ]
+echo "Linking pics directory"
+[ -e /usr/share/mympd/htdocs/pics ] || ln -s /var/lib/mympd/pics /usr/share/mympd/htdocs/
+
+if [ -d /etc/systemd ]
 then
   echo "Installing systemd service"
-  [ -d /usr/lib/systemd/system ] || mkdir /usr/lib/systemd/system 
+  [ -d /usr/lib/systemd/system ] || mkdir -p /usr/lib/systemd/system 
   if [ contrib/mympd.service -nt /usr/lib/systemd/system/mympd.service ]
   then
     cp contrib/mympd.service /usr/lib/systemd/system/
diff --git a/debian/postrm b/debian/postrm
index d93626e..9ddda89 100755
--- a/debian/postrm
+++ b/debian/postrm
@@ -9,13 +9,5 @@ then
   systemctl daemon-reload
 fi
 
-rm -v -fr /var/lib/mympd
-
-[ -e /usr/share/mympd/htdocs/library ] && rm -v /usr/share/mympd/htdocs/library
-rmdir -v /usr/share/{mympd/htdocs/,mympd/}
-
-getent passwd mympd > /dev/null
-echo "Removing mympd user and group"
-[ "$?" != "2" ] && userdel -r mympd
-getent group mympd > /dev/null
-[ "$?" != "2" ] && groupdel mympd 
+rm -v -f /usr/share/mympd/htdocs/pics
+rm -v -f /usr/share/mympd/htdocs/library
diff --git a/debian/rules b/debian/rules
index 132d6ee..20e2c14 100755
--- a/debian/rules
+++ b/debian/rules
@@ -16,6 +16,7 @@ binary-arch:
 	cd $(BUILDDIR); cmake -P cmake_install.cmake
 	mkdir debian/tmp/DEBIAN
 	cp debian/postinst debian/tmp/DEBIAN
+	cp debian/postrm debian/tmp/DEBIAN
 	dpkg-gencontrol -pmympd
 	dpkg --build debian/tmp ..
 

From c605bbb29fbaf085738a3742afa14c44ff3a802f Mon Sep 17 00:00:00 2001
From: jcorporation <mail@jcgames.de>
Date: Thu, 20 Sep 2018 21:23:33 +0100
Subject: [PATCH 04/11] Fix: test of /var/lib/mympd ownership

---
 contrib/archlinux.install | 2 +-
 contrib/myMPD.spec        | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/contrib/archlinux.install b/contrib/archlinux.install
index 35963b7..133983d 100644
--- a/contrib/archlinux.install
+++ b/contrib/archlinux.install
@@ -11,7 +11,7 @@ post_upgrade() {
   [ "$?" = "2" ] && useradd --system -d /var/lib/mympd -s /usr/sbin/nologin -g mympd mympd
 
   # fix ownership of /var/lib/mympd
-  if ! [ $(stat -c '%U:%G' /var/lib/mympd/) == 'mympd:mympd' ]
+  if ! [ $(stat -c '%U:%G' /var/lib/mympd/) = 'mympd:mympd' ]
   then
     echo "INFO: Fixing ownership of /var/lib/mympd"
     chown -R mympd.mympd /var/lib/mympd
diff --git a/contrib/myMPD.spec b/contrib/myMPD.spec
index 0e67dbd..f40de92 100644
--- a/contrib/myMPD.spec
+++ b/contrib/myMPD.spec
@@ -44,7 +44,7 @@ getent group mympd > /dev/null
 getent passwd mympd > /dev/null
 [ "$?" = "2" ] && useradd -r mympd -g mympd -d /var/lib/mympd -s /usr/sbin/nologin
 
-if ! [ $(stat -c '%U:%G' /var/lib/mympd/) == 'mympd:mympd' ]
+if ! [ $(stat -c '%U:%G' /var/lib/mympd/) = 'mympd:mympd' ]
 then
   echo "Fixing ownership of /var/lib/mympd"
   chown -R mympd.mympd /var/lib/mympd

From 1df960d4461743c74af3143f3d65a3bb981f624e Mon Sep 17 00:00:00 2001
From: jcorporation <mail@jcgames.de>
Date: Thu, 20 Sep 2018 21:24:17 +0100
Subject: [PATCH 05/11] Fix: update minified files

---
 dist/htdocs/js/mympd.min.js | 2 +-
 dist/htdocs/sw.min.js       | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/dist/htdocs/js/mympd.min.js b/dist/htdocs/js/mympd.min.js
index e0d8e8e..13b13f6 100644
--- a/dist/htdocs/js/mympd.min.js
+++ b/dist/htdocs/js/mympd.min.js
@@ -93,7 +93,7 @@ function appendQueue(a,b,c){switch(a){case "song":case "dir":sendAPI({cmd:"MPD_A
 function replaceQueue(a,b,c){switch(a){case "song":case "dir":sendAPI({cmd:"MPD_API_QUEUE_REPLACE_TRACK",data:{uri:b}});showNotification('"'+c+'" replaced',"","","success");break;case "plist":sendAPI({cmd:"MPD_API_QUEUE_REPLACE_PLAYLIST",data:{plist:b}}),showNotification('"'+c+'" replaced',"","","success")}}function songClick(){var a=domCache.currentTrack.getAttribute("data-uri");""!=a&&songDetails(a)}
 function artistClick(){var a=domCache.currentArtist.getAttribute("data-albumartist");""!=a&&appGoto("Browse","Database","AlbumArtist","0/-/"+a)}function albumClick(){var a=domCache.currentAlbum.getAttribute("data-album");""!=a&&appGoto("Browse","Database","Album","0/-/"+a)}function songDetails(a){sendAPI({cmd:"MPD_API_DATABASE_SONGDETAILS",data:{uri:a}},parseSongDetails);modalSongDetails.show()}
 function parseSongDetails(a){var b=document.getElementById("modalSongDetails");b.getElementsByClassName("album-cover")[0].style.backgroundImage='url("'+a.data.cover+'")';b.getElementsByTagName("h1")[0].innerText=a.data.title;var c="";for(f in settings.tags)if(1==settings.tags[f]){var d=a.data[f.toLowerCase()];if("duration"==f){var e=Math.floor(d/60);d-=60*e;d=e+":"+(10>d?"0":"")+d}c+="<tr><th>"+f+"</th><td>"+d+"</td></tr>"}c+='<tr><th>Uri</th><td><a class="text-success" href="/library/'+a.data.uri+
-'">'+a.data.uri+"</a></td></tr>";if(1==settings.stickers){var f="not voted";0==a.data.like?f='<span class="material-icons">thumb_down_alt</span>':2==a.data.like&&(f='<span class="material-icons">thumb_up_alt</span>');c+='<tr><th colspan="2">Statistics</th></tr><tr><th>Play count</th><td>'+a.data.playCount+"</td></tr><tr><th>Skip count</th><td>"+a.data.skipCount+"</td></tr><tr><th>Last played</th><td>"+(0==a.data.lastPlayed?"never":(new Date(1E3*d)).toUTCString())+"</td></tr><tr><th>Like</th><td>"+
+'">'+a.data.uri+"</a></td></tr>";if(1==settings.stickers){var f="not voted";0==a.data.like?f='<span class="material-icons">thumb_down_alt</span>':2==a.data.like&&(f='<span class="material-icons">thumb_up_alt</span>');c+='<tr><th colspan="2">Statistics</th></tr><tr><th>Play count</th><td>'+a.data.playCount+"</td></tr><tr><th>Skip count</th><td>"+a.data.skipCount+"</td></tr><tr><th>Last played</th><td>"+(0==a.data.lastPlayed?"never":(new Date(1E3*a.data.lastPlayed)).toUTCString())+"</td></tr><tr><th>Like</th><td>"+
 f+"</td></tr>"}b.getElementsByTagName("tbody")[0].innerHTML=c}function playlistDetails(a){appGoto("Browse","Playlists","Detail","0/-/"+a)}function removeFromPlaylist(a,b){b--;sendAPI({cmd:"MPD_API_PLAYLIST_RM_TRACK",data:{uri:a,track:b}});document.getElementById("BrowsePlaylistsDetailList").classList.add("opacity05");sendAPI({cmd:"MPD_API_PLAYLIST_CONTENT_LIST",data:{offset:app.current.page,filter:app.current.filter,uri:app.current.search}},parsePlaylists)}
 function playlistClear(){var a=document.getElementById("BrowsePlaylistsDetailList").getAttribute("data-uri");sendAPI({cmd:"MPD_API_PLAYLIST_CLEAR",data:{uri:a}});document.getElementById("BrowsePlaylistsDetailList").classList.add("opacity05");sendAPI({cmd:"MPD_API_PLAYLIST_CONTENT_LIST",data:{offset:app.current.page,filter:app.current.filter,uri:app.current.search}},parsePlaylists)}
 function getAllPlaylists(a){var b=a.data.length,c="";0==a.offset&&("addToPlaylistPlaylist"==playlistEl?c="<option></option><option>New Playlist</option>":"jukeboxPlaylist"==playlistEl&&(c="<option>Database</option>"));for(var d=0;d<b;d++)c+="<option","jukeboxPlaylist"==playlistEl&&a.data[d].uri==settings.jukeboxPlaylist&&(c+=" selected"),c+=">"+a.data[d].uri+"</option>";0==a.offset?document.getElementById(playlistEl).innerHTML=c:document.getElementById(playlistEl).innerHTML+=c;a.totalEntities>a.returnedEntities&&
diff --git a/dist/htdocs/sw.min.js b/dist/htdocs/sw.min.js
index 01bc1cc..5fe336d 100644
--- a/dist/htdocs/sw.min.js
+++ b/dist/htdocs/sw.min.js
@@ -10,5 +10,5 @@ function(){function a(a){return function(d){c||(c=!0,a.call(b,d))}}var b=this,c=
 void 0;try{d=a.then}catch(h){this.reject_(h);return}"function"==typeof d?this.settleSameAsThenable_(d,a):this.fulfill_(a)};c.prototype.reject_=function(a){this.settle_(2,a)};c.prototype.fulfill_=function(a){this.settle_(1,a)};c.prototype.settle_=function(a,b){if(0!=this.state_)throw Error("Cannot settle("+a+", "+b+"): Promise already settled in state"+this.state_);this.state_=a;this.result_=b;this.executeOnSettledCallbacks_()};c.prototype.executeOnSettledCallbacks_=function(){if(null!=this.onSettledCallbacks_){for(var a=
 0;a<this.onSettledCallbacks_.length;++a)l.asyncExecute(this.onSettledCallbacks_[a]);this.onSettledCallbacks_=null}};var l=new b;c.prototype.settleSameAsPromise_=function(a){var b=this.createResolveAndReject_();a.callWhenSettled_(b.resolve,b.reject)};c.prototype.settleSameAsThenable_=function(a,b){var c=this.createResolveAndReject_();try{a.call(b,c.resolve,c.reject)}catch(k){c.reject(k)}};c.prototype.then=function(a,b){function d(a,b){return"function"==typeof a?function(b){try{f(a(b))}catch(m){e(m)}}:
 b}var f,e,g=new c(function(a,b){f=a;e=b});this.callWhenSettled_(d(a,f),d(b,e));return g};c.prototype.catch=function(a){return this.then(void 0,a)};c.prototype.callWhenSettled_=function(a,b){function c(){switch(d.state_){case 1:a(d.result_);break;case 2:b(d.result_);break;default:throw Error("Unexpected state: "+d.state_);}}var d=this;null==this.onSettledCallbacks_?l.asyncExecute(c):this.onSettledCallbacks_.push(c)};c.resolve=f;c.reject=function(a){return new c(function(b,c){c(a)})};c.race=function(a){return new c(function(b,
-c){for(var d=$jscomp.makeIterator(a),e=d.next();!e.done;e=d.next())f(e.value).callWhenSettled_(b,c)})};c.all=function(a){var b=$jscomp.makeIterator(a),d=b.next();return d.done?f([]):new c(function(a,c){function e(b){return function(c){g[b]=c;h--;0==h&&a(g)}}var g=[],h=0;do g.push(void 0),h++,f(d.value).callWhenSettled_(e(g.length-1),c),d=b.next();while(!d.done)})};return c},"es6","es3");var CACHE="myMPD-cache-v4.2.0",urlsToCache="/ /player.html /css/bootstrap.min.css /css/mympd.min.css /js/bootstrap-native-v4.min.js /js/mympd.min.js /js/player.min.js /assets/appicon-167.png /assets/appicon-192.png /assets/appicon-512.png /assets/coverimage-httpstream.png /assets/coverimage-notavailable.png /assets/favicon.ico /assets/MaterialIcons-Regular.eot /assets/MaterialIcons-Regular.ttf /assets/MaterialIcons-Regular.woff /assets/MaterialIcons-Regular.woff2".split(" ");
+c){for(var d=$jscomp.makeIterator(a),e=d.next();!e.done;e=d.next())f(e.value).callWhenSettled_(b,c)})};c.all=function(a){var b=$jscomp.makeIterator(a),d=b.next();return d.done?f([]):new c(function(a,c){function e(b){return function(c){g[b]=c;h--;0==h&&a(g)}}var g=[],h=0;do g.push(void 0),h++,f(d.value).callWhenSettled_(e(g.length-1),c),d=b.next();while(!d.done)})};return c},"es6","es3");var CACHE="myMPD-cache-v4.2.1",urlsToCache="/ /player.html /css/bootstrap.min.css /css/mympd.min.css /js/bootstrap-native-v4.min.js /js/mympd.min.js /js/player.min.js /assets/appicon-167.png /assets/appicon-192.png /assets/appicon-512.png /assets/coverimage-httpstream.png /assets/coverimage-notavailable.png /assets/favicon.ico /assets/MaterialIcons-Regular.eot /assets/MaterialIcons-Regular.ttf /assets/MaterialIcons-Regular.woff /assets/MaterialIcons-Regular.woff2".split(" ");
 self.addEventListener("install",function(a){a.waitUntil(caches.open(CACHE).then(function(a){return a.addAll(urlsToCache)}))});self.addEventListener("fetch",function(a){a.respondWith(caches.match(a.request).then(function(b){return b?b:fetch(a.request)}))});self.addEventListener("activate",function(a){a.waitUntil(caches.keys().then(function(a){return Promise.all(a.map(function(a){if(a!=CACHE)return caches.delete(a)}))}))});

From 9272b69c9f531a6b72e8ebe795d1bf531ded3771 Mon Sep 17 00:00:00 2001
From: jcorporation <mail@jcgames.de>
Date: Thu, 20 Sep 2018 21:36:38 +0100
Subject: [PATCH 06/11] Fix: link/remove library and pics

---
 mkclean.sh |  2 ++
 mkdebug.sh | 14 +++++++++++++-
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/mkclean.sh b/mkclean.sh
index 0ccc345..50d573c 100755
--- a/mkclean.sh
+++ b/mkclean.sh
@@ -5,4 +5,6 @@ rm -rf debian/tmp
 rm -f debian/files
 rm -f htdocs/js/bootstrap-native-v4.min.js
 rm -f htdocs/css/bootstrap.min.css
+rm -f htdocs/library
+rm -f htdocs/pics
 find ./ -name \*~ -delete
diff --git a/mkdebug.sh b/mkdebug.sh
index f46b39a..9b8fa67 100755
--- a/mkdebug.sh
+++ b/mkdebug.sh
@@ -1,8 +1,20 @@
 #/bin/sh
 
-cp dist/htdocs/js/bootstrap-native-v4.min.js htdocs/js/
+cp dist/htdocs/js/bootstrap-native-v4.js htdocs/js/bootstrap-native-v4.min.js
 cp dist/htdocs/css/bootstrap.min.css htdocs/css/
 
+echo "Trying to link musicdir to library"
+if [ -f /etc/mpd.conf ]
+then
+  LIBRARY=$(grep ^music_directory /etc/mpd.conf | awk {'print $2'} | sed -e 's/"//g')
+  [ "$LIBRARY" != "" ] && [ ! -e htdocs/library ] && ln -s "$LIBRARY" htdocs/library
+else
+  echo "/etc/mpd.conf not found, you must link your music_directory manually to htdocs/library"
+fi
+
+echo "Linking pics directory"
+[ -e htdocs/pics ] || ln -s /var/lib/mympd/pics htdocs/
+
 [ -d debug ] || mkdir debug
 cd debug
 cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr -DCMAKE_BUILD_TYPE=DEBUG ..

From 4961daa6a3366d922093562883b8f2f7927bdcb2 Mon Sep 17 00:00:00 2001
From: jcorporation <mail@jcgames.de>
Date: Thu, 20 Sep 2018 23:04:35 +0100
Subject: [PATCH 07/11] Fix: simplified packaging

---
 PKGBUILD                    | 51 +++----------------------------------
 contrib/myMPD.spec          |  4 +--
 dist/htdocs/js/mympd.min.js |  4 +--
 htdocs/index.html           |  4 +--
 htdocs/js/mympd.js          |  2 +-
 htdocs/player.html          |  4 +--
 mkclean.sh                  | 12 +++++++--
 mkdebug.sh                  | 10 +++++---
 mkrelease.sh                | 11 +++-----
 9 files changed, 33 insertions(+), 69 deletions(-)

diff --git a/PKGBUILD b/PKGBUILD
index 2156840..ff6356d 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -1,7 +1,6 @@
-# Maintainer: K. Loz <cultofrobots [at] protonmail [dot] com>
-# Based on jcorporation's myMPD mkrelease.sh 
+# Maintainer: Juergen Mang <mail [at] jcgames [dot] de>
 # Website: https://github.com/jcorporation/myMPD
-# PKGBUILD Based on mympd-archphile by Mike Andonov <info [at] archphile [dot] org>
+# PKGBUILD Based on https://github.com/CultofRobots/archphile-custom/tree/master/mympd
 
 pkgname=mympd
 _pkgname=myMPD
@@ -12,7 +11,7 @@ arch=('x86_64' 'armv7h' 'aarch64')
 url="http://github.org/jcorporation/myMPD"
 license=('GPL')
 depends=('libmpdclient' 'openssl')
-makedepends=('cmake' 'git')
+makedepends=('cmake')
 optdepends=()
 provides=()
 conflicts=()
@@ -21,49 +20,6 @@ install=contrib/archlinux.install
 source=("https://github.com/jcorporation/${_pkgname}/archive/v${pkgver}.tar.gz")
 sha256sums=('SKIP')
 
-prepare() {
-  export java=$(which java 2> /dev/null)
-
-  if [ -f ${srcdir}/${_pkgname}-${pkgver}/dist/buildtools/closure-compiler.jar ] && [ "$java" != "$NULL" ]
-  then
-    echo "Minifying javascript"
-    [ ${srcdir}/${_pkgname}-${pkgver}/htdocs/js/player.js -nt ${srcdir}/${_pkgname}-${pkgver}/dist/htdocs/js/player.min.js ] && \
-      java -jar ${srcdir}/${_pkgname}-${pkgver}/dist/buildtools/closure-compiler.jar ${srcdir}/${_pkgname}-${pkgver}/htdocs/js/player.js > ${srcdir}/${_pkgname}-${pkgver}/dist/htdocs/js/player.min.js
-    [ ${srcdir}/${_pkgname}-${pkgver}/htdocs/js/mympd.js -nt  ${srcdir}/${_pkgname}-${pkgver}/dist/htdocs/js/mympd.min.js ] && \
-      java -jar ${srcdir}/${_pkgname}-${pkgver}/dist/buildtools/closure-compiler.jar ${srcdir}/${_pkgname}-${pkgver}/htdocs/js/mympd.js > ${srcdir}/${_pkgname}-${pkgver}/dist/htdocs/js/mympd.min.js
-    [ ${srcdir}/${_pkgname}-${pkgver}/htdocs/sw.js -nt ${srcdir}/${_pkgname}-${pkgver}/dist/htdocs/sw.min.js ] && \
-      java -jar ${srcdir}/${_pkgname}-${pkgver}/dist/buildtools/closure-compiler.jar ${srcdir}/${_pkgname}-${pkgver}/htdocs/sw.js > ${srcdir}/${_pkgname}-${pkgver}/dist/htdocs/sw.min.js
-  else
-    echo "${srcdir}/${_pkgname}-${pkgver}/dist/buildtools/closure-compiler.jar not found, using non-minified files"
-    [ ${srcdir}/${_pkgname}-${pkgver}/htdocs/js/player.js -nt ${srcdir}/${_pkgname}-${pkgver}/dist/htdocs/js/player.min.js ] && \
-      cp ${srcdir}/${_pkgname}-${pkgver}/htdocs/js/player.js ${srcdir}/${_pkgname}-${pkgver}/dist/htdocs/js/player.min.js
-    [ ${srcdir}/${_pkgname}-${pkgver}/htdocs/js/mympd.js -nt  ${srcdir}/${_pkgname}-${pkgver}/dist/htdocs/js/mympd.min.js ] && \
-      cp ${srcdir}/${_pkgname}-${pkgver}/htdocs/js/mympd.js  ${srcdir}/${_pkgname}-${pkgver}/dist/htdocs/js/mympd.min.js
-    [ ${srcdir}/${_pkgname}-${pkgver}/htdocs/sw.js -nt ${srcdir}/${_pkgname}-${pkgver}/dist/htdocs/sw.min.js ] && \
-      cp ${srcdir}/${_pkgname}-${pkgver}/htdocs/sw.js ${srcdir}/${_pkgname}-${pkgver}/dist/htdocs/sw.min.js    
-  fi
-
-  if [ -f ${srcdir}/${_pkgname}-${pkgver}/dist/buildtools/closure-stylesheets.jar ] && [ "$java" != "$NULL" ]
-  then
-    echo "Minifying stylesheets"
-    [ ${srcdir}/${_pkgname}-${pkgver}/htdocs/css/mympd.css -nt ${srcdir}/${_pkgname}-${pkgver}/dist/htdocs/css/mympd.min.css ] && \
-      java -jar ${srcdir}/${_pkgname}-${pkgver}/dist/buildtools/closure-stylesheets.jar --allow-unrecognized-properties ${srcdir}/${_pkgname}-${pkgver}/htdocs/css/mympd.css > ${srcdir}/${_pkgname}-${pkgver}/dist/htdocs/css/mympd.min.css
-  else
-    echo "${srcdir}/${_pkgname}-${pkgver}/dist/buildtools/closure-stylesheets.jar not found, using non-minified files"
-    [ ${srcdir}/${_pkgname}-${pkgver}/htdocs/css/mympd.css -nt ${srcdir}/${_pkgname}-${pkgver}/dist/htdocs/css/mympd.min.css ] && \
-      cp ${srcdir}/${_pkgname}-${pkgver}/htdocs/css/mympd.css ${srcdir}/${_pkgname}-${pkgver}/dist/htdocs/css/mympd.min.css    
-  fi
-
-  echo "Replacing javascript and stylesheets with minified files"
-  sed -e 's/mympd\.css/mympd\.min\.css/' -e 's/mympd\.js/mympd\.min\.js/' ${srcdir}/${_pkgname}-${pkgver}/htdocs/index.html > ${srcdir}/${_pkgname}-${pkgver}/dist/htdocs/index.html
-  sed -e 's/mympd\.css/mympd\.min\.css/' -e 's/player\.js/player\.min\.js/' ${srcdir}/${_pkgname}-${pkgver}/htdocs/player.html > ${srcdir}/${_pkgname}-${pkgver}/dist/htdocs/player.html
-  sed -i -e 's/mympd\.css/mympd\.min\.css/' -e 's/mympd\.js/mympd\.min\.js/' -e 's/player\.js/player\.min\.js/' ${srcdir}/${_pkgname}-${pkgver}/dist/htdocs/sw.min.js
-  sed -i -e 's/\/sw\.js/\/sw\.min\.js/' ${srcdir}/${_pkgname}-${pkgver}/dist/htdocs/js/mympd.min.js
-  echo "Minifying html"
-  perl -i -pe 's/^\s*//gm; s/\s*$//gm' ${srcdir}/${_pkgname}-${pkgver}/dist/htdocs/index.html
-  perl -i -pe 's/^\s*//gm; s/\s*$//gm' ${srcdir}/${_pkgname}-${pkgver}/dist/htdocs/player.html
-}
-
 build() {
   cd "${srcdir}/${_pkgname}-${pkgver}"
   
@@ -80,4 +36,3 @@ package() {
   install -Dm644  "${srcdir}/${_pkgname}-${pkgver}/contrib/mympd.service" "$pkgdir/usr/lib/systemd/system/mympd.service"
   /usr/share/mympd/crcert.sh
 }
-
diff --git a/contrib/myMPD.spec b/contrib/myMPD.spec
index f40de92..58b864b 100644
--- a/contrib/myMPD.spec
+++ b/contrib/myMPD.spec
@@ -1,7 +1,7 @@
 #
 # spec file for package myMPD
 #
-# (c) 2018 Juergen Mang <mail@jcgames.de
+# (c) 2018 Juergen Mang <mail@jcgames.de>
 
 Name:           myMPD
 Version:        4.2.1
@@ -102,5 +102,5 @@ fi
 /var/lib/mympd
 
 %changelog
-* Wed Sep 17 2018 Juergen Mang <mail@jcgames.de> - master
+* Fri Sep 21 2018 Juergen Mang <mail@jcgames.de> - master
 - Version from master
diff --git a/dist/htdocs/js/mympd.min.js b/dist/htdocs/js/mympd.min.js
index 13b13f6..451bc1f 100644
--- a/dist/htdocs/js/mympd.min.js
+++ b/dist/htdocs/js/mympd.min.js
@@ -40,8 +40,8 @@ function(a){"BUTTON"==a.target.nodeName&&("Add all to queue"==a.target.innerText
 app.current.tab,app.current.view,"0/"+app.current.filter+"/"+this.value)},!1);document.getElementById("searchqueuetag").addEventListener("click",function(a){"BUTTON"==a.target.nodeName&&appGoto(app.current.app,app.current.tab,app.current.view,app.current.page+"/"+a.target.getAttribute("data-tag")+"/"+app.current.search)},!1);document.getElementById("search").addEventListener("submit",function(){return!1},!1);document.getElementById("searchqueue").addEventListener("submit",function(){return!1},!1);
 document.getElementById("searchstr").addEventListener("keyup",function(a){appGoto("Search",void 0,void 0,"0/"+app.current.filter+"/"+this.value)},!1);document.getElementById("BrowseDatabaseByTagDropdown").addEventListener("click",function(a){"BUTTON"==a.target.nodeName&&appGoto(app.current.app,app.current.tab,a.target.getAttribute("data-tag"),"0/"+app.current.filter+"/"+app.current.search)},!1);document.getElementsByTagName("body")[0].addEventListener("click",function(a){a=document.getElementsByClassName("popover");
 for(var b=0;b<a.length;b++)a[b].remove()},!1);dragAndDropTable("QueueList");dragAndDropTable("BrowsePlaylistsDetailList");window.addEventListener("hashchange",appRoute,!1);window.addEventListener("focus",function(){sendAPI({cmd:"MPD_API_PLAYER_STATE"},parseState)},!1);document.addEventListener("keydown",function(a){if("INPUT"!=a.target.tagName){switch(a.which){case 37:clickPrev();break;case 39:clickNext();break;case 32:clickPlay();break;default:return}a.preventDefault()}},!1);"serviceWorker"in navigator&&
-"https"==document.URL.substring(0,5)&&window.addEventListener("load",function(){navigator.serviceWorker.register("/sw.min.js",{scope:"/"}).then(function(a){console.log("ServiceWorker registration successful with scope: ",a.scope);a.update()},function(a){console.log("ServiceWorker registration failed: ",a)})});window.addEventListener("beforeinstallprompt",function(a){a.preventDefault();deferredPrompt=a});window.addEventListener("beforeinstallprompt",function(a){a.preventDefault();deferredPrompt=a;domCache.btnAdd.classList.remove("hide")});
-domCache.btnAdd.addEventListener("click",function(a){domCache.btnAdd.classList.add("hide");deferredPrompt.prompt();deferredPrompt.userChoice.then(function(a){"accepted"===a.outcome?console.log("User accepted the A2HS prompt"):console.log("User dismissed the A2HS prompt");deferredPrompt=null})});window.addEventListener("appinstalled",function(a){console.log("myMPD installed as app")})}
+"https"==document.URL.substring(0,5)&&window.addEventListener("load",function(){navigator.serviceWorker.register("/sw.min.js",{scope:"/"}).then(function(a){console.log("ServiceWorker registration successful with scope: ",a.scope);a.update()},function(a){console.log("ServiceWorker registration failed: ",a)})});window.addEventListener("beforeinstallprompt",function(a){a.preventDefault();deferredPrompt=a});window.addEventListener("beforeinstallprompt",function(a){a.preventDefault();deferredPrompt=a;
+domCache.btnAdd.classList.remove("hide")});domCache.btnAdd.addEventListener("click",function(a){domCache.btnAdd.classList.add("hide");deferredPrompt.prompt();deferredPrompt.userChoice.then(function(a){"accepted"===a.outcome?console.log("User accepted the A2HS prompt"):console.log("User dismissed the A2HS prompt");deferredPrompt=null})});window.addEventListener("appinstalled",function(a){console.log("myMPD installed as app")})}
 function dragAndDropTable(a){var b=document.getElementById(a).getElementsByTagName("tbody")[0];b.addEventListener("dragstart",function(a){"TR"==a.target.nodeName&&(a.target.classList.add("opacity05"),a.dataTransfer.setDragImage(a.target,0,0),a.dataTransfer.effectAllowed="move",a.dataTransfer.setData("Text",a.target.getAttribute("id")),dragEl=a.target.cloneNode(!0))},!1);b.addEventListener("dragleave",function(a){a.preventDefault();var b=a.target;"TD"==a.target.nodeName&&(b=a.target.parentNode);"TR"==
 b.nodeName&&b.classList.remove("dragover")},!1);b.addEventListener("dragover",function(a){a.preventDefault();for(var c=b.getElementsByClassName("dragover"),e=c.length,f=0;f<e;f++)c[f].classList.remove("dragover");c=a.target;"TD"==a.target.nodeName&&(c=a.target.parentNode);"TR"==c.nodeName&&c.classList.add("dragover");a.dataTransfer.dropEffect="move"},!1);b.addEventListener("dragend",function(a){for(var c=b.getElementsByClassName("dragover"),e=c.length,f=0;f<e;f++)c[f].classList.remove("dragover");
 document.getElementById(a.dataTransfer.getData("Text"))&&document.getElementById(a.dataTransfer.getData("Text")).classList.remove("opacity05")},!1);b.addEventListener("drop",function(c){c.stopPropagation();c.preventDefault();var d=c.target;"TD"==c.target.nodeName&&(d=c.target.parentNode);var e=document.getElementById(c.dataTransfer.getData("Text")).getAttribute("data-songpos"),f=d.getAttribute("data-songpos");document.getElementById(c.dataTransfer.getData("Text")).remove();dragEl.classList.remove("opacity05");
diff --git a/htdocs/index.html b/htdocs/index.html
index 4a4dac3..9bdc732 100644
--- a/htdocs/index.html
+++ b/htdocs/index.html
@@ -10,7 +10,7 @@
   <meta name="apple-mobile-web-app-status-bar-style" content="black">
   <meta name="theme-color" content="#343a40">
   <link href="/css/bootstrap.min.css" rel="stylesheet">
-  <link href="/css/mympd.css" rel="stylesheet">
+  <link href="/css/mympd.min.css" rel="stylesheet">
   <link href="/assets/favicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon">  
   <link rel="manifest" href="/mympd.webmanifest">
   <link rel="apple-touch-icon" href="/assets/appicon-167.png">
@@ -833,6 +833,6 @@
   </div>
 
   <script src="/js/bootstrap-native-v4.min.js"></script>
-  <script src="/js/mympd.js"></script>
+  <script src="/js/mympd.min.js"></script>
  </body>
 </html>
diff --git a/htdocs/js/mympd.js b/htdocs/js/mympd.js
index 54df2b0..12379e4 100644
--- a/htdocs/js/mympd.js
+++ b/htdocs/js/mympd.js
@@ -550,7 +550,7 @@ function appInit() {
     
     if ('serviceWorker' in navigator && document.URL.substring(0, 5) == 'https') {
         window.addEventListener('load', function() {
-            navigator.serviceWorker.register('/sw.js', {scope: '/'}).then(function(registration) {
+            navigator.serviceWorker.register('/sw.min.js', {scope: '/'}).then(function(registration) {
                 // Registration was successful
                 console.log('ServiceWorker registration successful with scope: ', registration.scope);
                 registration.update();
diff --git a/htdocs/player.html b/htdocs/player.html
index 3752433..c3ac9b9 100644
--- a/htdocs/player.html
+++ b/htdocs/player.html
@@ -7,7 +7,7 @@
   <meta name="author" content="mail@jcgames.de">
   <title>myMPD: Local Player</title>
   <link href="css/bootstrap.min.css" rel="stylesheet">
-  <link href="css/mympd.css" rel="stylesheet">
+  <link href="css/mympd.min.css" rel="stylesheet">
   <link href="assets/favicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon">
   <meta name="apple-mobile-web-app-capable" content="yes" />
   <meta name="apple-mobile-web-app-status-bar-style" content="black"/>
@@ -29,6 +29,6 @@
       </div>
     </div>
   </main>
-  <script type="text/javascript" src="js/player.js"></script>  
+  <script type="text/javascript" src="js/player.min.js"></script>  
 </body>
 </html>
diff --git a/mkclean.sh b/mkclean.sh
index 50d573c..688a570 100755
--- a/mkclean.sh
+++ b/mkclean.sh
@@ -3,8 +3,16 @@ rm -rf release
 rm -rf debug
 rm -rf debian/tmp
 rm -f debian/files
-rm -f htdocs/js/bootstrap-native-v4.min.js
-rm -f htdocs/css/bootstrap.min.css
+
 rm -f htdocs/library
 rm -f htdocs/pics
+
+rm -f htdocs/sw.min.js
+rm -f htdocs/js/mympd.min.js
+rm -f htdocs/js/player.min.js
+rm -f htdocs/js/bootstrap-native-v4.min.js
+
+rm -f htdocs/css/mympd.min.css
+rm -f htdocs/css/bootstrap.min.css
+
 find ./ -name \*~ -delete
diff --git a/mkdebug.sh b/mkdebug.sh
index 9b8fa67..dfcd094 100755
--- a/mkdebug.sh
+++ b/mkdebug.sh
@@ -1,7 +1,11 @@
 #/bin/sh
+[ -e $PWD/htdocs/sw.min.js ] || ln -s $PWD/htdocs/sw.js $PWD/htdocs/sw.min.js
+[ -e $PWD/htdocs/js/mympd.min.js ] || ln -s $PWD/htdocs/js/mympd.js $PWD/htdocs/js/mympd.min.js
+[ -e $PWD/htdocs/js/player.min.js ] || ln -s $PWD/htdocs/js/player.js $PWD/htdocs/js/player.min.js
+[ -e $PWD/htdocs/js/bootstrap-native-v4.min.js ] || ln -s $PWD/dist/htdocs/js/bootstrap-native-v4.js $PWD/htdocs/js/bootstrap-native-v4.min.js
 
-cp dist/htdocs/js/bootstrap-native-v4.js htdocs/js/bootstrap-native-v4.min.js
-cp dist/htdocs/css/bootstrap.min.css htdocs/css/
+[ -e $PWD/htdocs/css/mympd.min.css ] || ln -s $PWD/htdocs/css/mympd.css $PWD/htdocs/css/mympd.min.css
+[ -e $PWD/htdocs/css/bootstrap.min.css ] || ln -s $PWD/dist/htdocs/css/bootstrap.min.css $PWD/htdocs/css/bootstrap.min.css
 
 echo "Trying to link musicdir to library"
 if [ -f /etc/mpd.conf ]
@@ -13,7 +17,7 @@ else
 fi
 
 echo "Linking pics directory"
-[ -e htdocs/pics ] || ln -s /var/lib/mympd/pics htdocs/
+[ -e $PWD/htdocs/pics ] || ln -s /var/lib/mympd/pics htdocs/
 
 [ -d debug ] || mkdir debug
 cd debug
diff --git a/mkrelease.sh b/mkrelease.sh
index f2f346c..a243aca 100755
--- a/mkrelease.sh
+++ b/mkrelease.sh
@@ -32,14 +32,11 @@ else
     cp htdocs/css/mympd.css dist/htdocs/css/mympd.min.css    
 fi
 
-echo "Replacing javascript and stylesheets with minified files"
-sed -e 's/mympd\.css/mympd\.min\.css/' -e 's/mympd\.js/mympd\.min\.js/' htdocs/index.html > dist/htdocs/index.html
-sed -e 's/mympd\.css/mympd\.min\.css/' -e 's/player\.js/player\.min\.js/' htdocs/player.html > dist/htdocs/player.html
-sed -i -e 's/mympd\.css/mympd\.min\.css/' -e 's/mympd\.js/mympd\.min\.js/' -e 's/player\.js/player\.min\.js/' dist/htdocs/sw.min.js
-sed -i -e 's/\/sw\.js/\/sw\.min\.js/' dist/htdocs/js/mympd.min.js
 echo "Minifying html"
-perl -i -pe 's/^\s*//gm; s/\s*$//gm' dist/htdocs/index.html
-perl -i -pe 's/^\s*//gm; s/\s*$//gm' dist/htdocs/player.html
+[ htdocs/index.html -nt dist/htdocs/index.html ] && \
+  perl -pe 's/^\s*//gm; s/\s*$//gm' htdocs/index.html > dist/htdocs/index.html
+[ htdocs/player.html -nt dist/htdocs/player.html ] && \
+  perl -pe 's/^\s*//gm; s/\s*$//gm' htdocs/player.html > dist/htdocs/player.html
 
 echo "Compiling and installing mympd"
 [ -d release ] || mkdir release

From 05b93894e8371f4ad4efad7bdad9f4ad9954159d Mon Sep 17 00:00:00 2001
From: jcorporation <mail@jcgames.de>
Date: Thu, 20 Sep 2018 23:22:44 +0100
Subject: [PATCH 08/11] Feat: add cppcheck

---
 mkrelease.sh | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/mkrelease.sh b/mkrelease.sh
index a243aca..89f8fb8 100755
--- a/mkrelease.sh
+++ b/mkrelease.sh
@@ -47,3 +47,6 @@ sudo make install
 cd ..
 
 debian/postinst
+
+echo "Running cppcheck"
+[ -x /usr/bin/cppcheck ] && cppcheck --enable=warning --inconclusive --force --inline-suppr src/*.c src/*.h

From 006eb6d28ce3a124abcbf531f0b3cd3e680837df Mon Sep 17 00:00:00 2001
From: jcorporation <mail@jcgames.de>
Date: Thu, 20 Sep 2018 23:43:58 +0100
Subject: [PATCH 09/11] Fix: don't use serviceworker for http:// uris -> fixes
 http stream in local player

---
 htdocs/sw.js | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/htdocs/sw.js b/htdocs/sw.js
index cce5f88..b1d4ed4 100644
--- a/htdocs/sw.js
+++ b/htdocs/sw.js
@@ -28,15 +28,16 @@ self.addEventListener('install', function(event) {
 });
 
 self.addEventListener('fetch', function(event) {
-  event.respondWith(
-    caches.match(event.request).then(function(response) {
-        if (response)
-            return response
-        else
-            return fetch(event.request);
-      }
-    )
-  );    
+    if (event.request.url.match('^http://'))
+        return false;
+    event.respondWith(
+        caches.match(event.request).then(function(response) {
+            if (response)
+                return response
+            else
+                return fetch(event.request);
+        })
+    );    
 });
 
 self.addEventListener('activate', function(event) {

From f71bef42fee5f29945dc7797ed635e305b3c7042 Mon Sep 17 00:00:00 2001
From: jcorporation <mail@jcgames.de>
Date: Sun, 23 Sep 2018 22:48:12 +0100
Subject: [PATCH 10/11] Feat: add rescan database command

---
 htdocs/css/mympd.css | 10 ++++++++++
 htdocs/index.html    |  6 +++++-
 htdocs/js/mympd.js   | 15 +++++++++++++++
 src/mpd_client.c     |  5 +++++
 src/mpd_client.h     |  1 +
 5 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/htdocs/css/mympd.css b/htdocs/css/mympd.css
index 65e5cbf..3ad943d 100644
--- a/htdocs/css/mympd.css
+++ b/htdocs/css/mympd.css
@@ -128,6 +128,12 @@ small {
   font-feature-settings: 'liga';
 }
 
+.material-icons-left {
+  font-size: 1rem;
+  margin-left: -1em;
+  vertical-align:middle;
+}
+
 .material-icons-small {
   font-size: 16px;
 }
@@ -281,3 +287,7 @@ caption {
   width:100%;
   margin-left: 15px;
 }
+
+#menu-dbupdate {
+  padding-left:1rem;
+}
\ No newline at end of file
diff --git a/htdocs/index.html b/htdocs/index.html
index 9bdc732..7df746f 100644
--- a/htdocs/index.html
+++ b/htdocs/index.html
@@ -24,7 +24,11 @@
           </a>
           <div class="dropdown-menu bg-dark">
             <a class="dropdown-item text-light bg-dark" href="#" data-href='{"cmd": "showAddToPlaylist", "options": ["stream"]}'>Add Stream</a>
-            <a class="dropdown-item text-light bg-dark" href="#" data-href='{"cmd": "updateDB", "options": []}'>Update Database</a>
+            <a id="navDBupdate" class="dropdown-item text-light bg-dark" data-toggle="collapse" href="#menu-dbupdate"><span class="material-icons material-icons-left">keyboard_arrow_right</span>Database</a>
+              <div class="collapse" id="menu-dbupdate">
+                <a class="dropdown-item text-light bg-dark" href="#" data-href='{"cmd": "updateDB", "options": []}'>Update</a>
+                <a class="dropdown-item text-light bg-dark" href="#" data-href='{"cmd": "rescanDB", "options": []}'>Rescan</a>
+              </div>
             <a class="dropdown-item text-light bg-dark" href="#" data-href='{"cmd": "openLocalPlayer", "options": []}'>Local Player</a>
             <a class="dropdown-item text-light bg-dark" href="#" data-toggle="modal" data-target="#modalSettings">Settings</a>
             <a class="dropdown-item text-light bg-dark" href="#" data-toggle="modal" data-target="#modalAbout">About</a>
diff --git a/htdocs/js/mympd.js b/htdocs/js/mympd.js
index 12379e4..0f750ab 100644
--- a/htdocs/js/mympd.js
+++ b/htdocs/js/mympd.js
@@ -309,6 +309,16 @@ function appInit() {
             sendAPI({"cmd": "MPD_API_PLAYER_SEEK", "data": {"songid": currentSong.currentSongId, "seek": seekVal}});
         }
     }, false);
+
+    document.getElementById('navDBupdate').addEventListener('click', function(event) {
+        event.stopPropagation();
+        event.preventDefault();
+        var icon = this.getElementsByTagName('span')[0];
+        if (icon.innerText == 'keyboard_arrow_right')
+            icon.innerText = 'keyboard_arrow_down';
+        else
+            icon.innerText = 'keyboard_arrow_right';        
+    }, false);
   
     document.getElementById('volumeIcon').parentNode.addEventListener('show.bs.dropdown', function () {
         sendAPI({"cmd": "MPD_API_PLAYER_OUTPUT_LIST"}, parseOutputs);
@@ -1840,6 +1850,11 @@ function updateDB() {
     updateDBstarted(true);
 }
 
+function rescanDB() {
+    sendAPI({"cmd": "MPD_API_DATABASE_RESCAN"});
+    updateDBstarted(true);
+}
+
 function updateDBstarted(showModal) {
     if (showModal == true) {
         document.getElementById('updateDBfinished').innerText = '';
diff --git a/src/mpd_client.c b/src/mpd_client.c
index 1814ec8..cdbcfd7 100644
--- a/src/mpd_client.c
+++ b/src/mpd_client.c
@@ -179,6 +179,11 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) {
             if (uint_rc > 0)
                 n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"result\", \"data\": \"ok\"}");
             break;
+        case MPD_API_DATABASE_RESCAN:
+            uint_rc = mpd_run_rescan(mpd.conn, NULL);
+            if (uint_rc > 0)
+                n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"result\", \"data\": \"ok\"}");
+            break;            
         case MPD_API_PLAYER_PAUSE:
             mpd_run_toggle_pause(mpd.conn);
             n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"result\", \"data\": \"ok\"}");
diff --git a/src/mpd_client.h b/src/mpd_client.h
index f0d3e02..96763a1 100644
--- a/src/mpd_client.h
+++ b/src/mpd_client.h
@@ -74,6 +74,7 @@
     X(MPD_API_PLAYLIST_CONTENT_LIST) \
     X(MPD_API_DATABASE_SEARCH) \
     X(MPD_API_DATABASE_UPDATE) \
+    X(MPD_API_DATABASE_RESCAN) \
     X(MPD_API_DATABASE_FILESYSTEM_LIST) \
     X(MPD_API_DATABASE_TAG_LIST) \
     X(MPD_API_DATABASE_TAG_ALBUM_LIST) \

From a8a8503a26aa99a52dc7036ad7fff79af76d3a30 Mon Sep 17 00:00:00 2001
From: jcorporation <mail@jcgames.de>
Date: Sun, 23 Sep 2018 22:56:00 +0100
Subject: [PATCH 11/11] Fix: update minified files

---
 dist/htdocs/css/mympd.min.css |  2 +-
 dist/htdocs/index.html        |  2 +-
 dist/htdocs/js/mympd.min.js   | 35 ++++++++++++++++++-----------------
 dist/htdocs/sw.min.js         |  2 +-
 htdocs/sw.js                  |  6 +++---
 5 files changed, 24 insertions(+), 23 deletions(-)

diff --git a/dist/htdocs/css/mympd.min.css b/dist/htdocs/css/mympd.min.css
index 88b784e..722d16d 100644
--- a/dist/htdocs/css/mympd.min.css
+++ b/dist/htdocs/css/mympd.min.css
@@ -1 +1 @@
-html{position:relative;min-height:100%}body{margin-bottom:60px;padding-top:50px;padding-bottom:50px;background-color:#888}main{padding-top:20px}footer{position:absolute;bottom:0}button{overflow:hidden}#BrowseBreadrumb{overflow:auto;white-space:nowrap}#BrowseBreadcrumb>li>a{cursor:pointer}.card{min-height:350px}@media only screen and (max-width:576px){.header-logo{display:none!important}}.clickable{cursor:pointer}.tblnum,.tblaction{width:30px}small{color:#aaa}.card-footer-playback{padding:0}.album-cover{background-size:cover;border:1px solid black;border-radius:5px;overflow:hidden;width:240px;height:240px;background-color:#eee;float:left;margin-right:20px;margin-bottom:20px}.album-desc{min-width:240px;float:left}.hide{display:none!important}.pull-right{float:right!important}.card-toolbar{margin-bottom:10px}.card-toolbar>div,.card-toolbar>form{margin-bottom:5px}@font-face{font-family:'Material Icons';font-style:normal;font-weight:400;src:url(/assets/MaterialIcons-Regular.eot);src:local('Material Icons'),local('MaterialIcons-Regular');src:url(/assets/MaterialIcons-Regular.woff2) format('woff2'),url(/assets/MaterialIcons-Regular.woff) format('woff'),url(/assets/MaterialIcons-Regular.ttf) format('truetype')}.material-icons{font-family:'Material Icons';font-weight:normal;font-style:normal;font-size:18px;display:inline-block;line-height:1;text-transform:none;letter-spacing:normal;word-wrap:normal;white-space:nowrap;direction:ltr;vertical-align:top;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;-moz-osx-font-smoothing:grayscale;font-feature-settings:'liga'}.material-icons-small{font-size:16px}.material-icons-small-left{font-size:1rem;margin-left:-1em}.color-darkgrey,.color-darkgrey:hover{color:#6c757d!important}#btn-outputs-block>button{margin-bottom:10px}#btn-outputs-block>button:last-child{margin-bottom:0}.card-body{overflow-x:hidden}.progressBarPlay{font-size:22px}#counter{cursor:text}#volumeBar{margin-top:2px;width:160px}.title-icon{float:left;margin-right:5px;font-size:1.8rem}.header-logo{font-size:2rem;float:left;margin-right:5px}.letters>button{width:28px;height:28px}.col-md{max-width:250px;min-width:250px}a.card-img-top{overflow:hidden;display:block}button.active{color:#fff;background-color:#28a745!important;border-color:#28a745!important}button.active-fg-green{color:#28a745!important}button.active-fg-red{color:#bd2130!important}div#alertBox{position:fixed;top:50px;right:10px;width:80%;max-width:400px;z-index:1000;opacity:0;visibility:visible;transition:opacity .5s ease-in}div.alertBoxActive{opacity:1!important;visibility:visible!important;transition:opacity .5s ease-in}.popover-content{padding-top:4px;padding-bottom:4px}.opacity05{opacity:.5}caption{caption-side:top;font-size:120%;font-weight:bold;color:black}.dragover>td{border-top:25px solid transparent}[draggable]{-moz-user-select:none;-khtml-user-select:none;-webkit-user-select:none;user-select:none;-khtml-user-drag:element;-webkit-user-drag:element}@keyframes changewidth{0%{margin-left:-20px}to{margin-left:100%}}#updateDBprogress{width:20px}.updateDBprogressAnimate{animation-duration:2s;animation-name:changewidth;animation-iteration-count:infinite}.modal-body{overflow-x:hidden}.modal-body .album-cover{float:none}#BrowseDatabaseAlbumListCaption{width:100%;margin-left:15px}
\ No newline at end of file
+html{position:relative;min-height:100%}body{margin-bottom:60px;padding-top:50px;padding-bottom:50px;background-color:#888}main{padding-top:20px}footer{position:absolute;bottom:0}button{overflow:hidden}#BrowseBreadrumb{overflow:auto;white-space:nowrap}#BrowseBreadcrumb>li>a{cursor:pointer}.card{min-height:350px}@media only screen and (max-width:576px){.header-logo{display:none!important}}.clickable{cursor:pointer}.tblnum,.tblaction{width:30px}small{color:#aaa}.card-footer-playback{padding:0}.album-cover{background-size:cover;border:1px solid black;border-radius:5px;overflow:hidden;width:240px;height:240px;background-color:#eee;float:left;margin-right:20px;margin-bottom:20px}.album-desc{min-width:240px;float:left}.hide{display:none!important}.pull-right{float:right!important}.card-toolbar{margin-bottom:10px}.card-toolbar>div,.card-toolbar>form{margin-bottom:5px}@font-face{font-family:'Material Icons';font-style:normal;font-weight:400;src:url(/assets/MaterialIcons-Regular.eot);src:local('Material Icons'),local('MaterialIcons-Regular');src:url(/assets/MaterialIcons-Regular.woff2) format('woff2'),url(/assets/MaterialIcons-Regular.woff) format('woff'),url(/assets/MaterialIcons-Regular.ttf) format('truetype')}.material-icons{font-family:'Material Icons';font-weight:normal;font-style:normal;font-size:18px;display:inline-block;line-height:1;text-transform:none;letter-spacing:normal;word-wrap:normal;white-space:nowrap;direction:ltr;vertical-align:top;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;-moz-osx-font-smoothing:grayscale;font-feature-settings:'liga'}.material-icons-left{font-size:1rem;margin-left:-1em;vertical-align:middle}.material-icons-small{font-size:16px}.material-icons-small-left{font-size:1rem;margin-left:-1em}.color-darkgrey,.color-darkgrey:hover{color:#6c757d!important}#btn-outputs-block>button{margin-bottom:10px}#btn-outputs-block>button:last-child{margin-bottom:0}.card-body{overflow-x:hidden}.progressBarPlay{font-size:22px}#counter{cursor:text}#volumeBar{margin-top:2px;width:160px}.title-icon{float:left;margin-right:5px;font-size:1.8rem}.header-logo{font-size:2rem;float:left;margin-right:5px}.letters>button{width:28px;height:28px}.col-md{max-width:250px;min-width:250px}a.card-img-top{overflow:hidden;display:block}button.active{color:#fff;background-color:#28a745!important;border-color:#28a745!important}button.active-fg-green{color:#28a745!important}button.active-fg-red{color:#bd2130!important}div#alertBox{position:fixed;top:50px;right:10px;width:80%;max-width:400px;z-index:1000;opacity:0;visibility:visible;transition:opacity .5s ease-in}div.alertBoxActive{opacity:1!important;visibility:visible!important;transition:opacity .5s ease-in}.popover-content{padding-top:4px;padding-bottom:4px}.opacity05{opacity:.5}caption{caption-side:top;font-size:120%;font-weight:bold;color:black}.dragover>td{border-top:25px solid transparent}[draggable]{-moz-user-select:none;-khtml-user-select:none;-webkit-user-select:none;user-select:none;-khtml-user-drag:element;-webkit-user-drag:element}@keyframes changewidth{0%{margin-left:-20px}to{margin-left:100%}}#updateDBprogress{width:20px}.updateDBprogressAnimate{animation-duration:2s;animation-name:changewidth;animation-iteration-count:infinite}.modal-body{overflow-x:hidden}.modal-body .album-cover{float:none}#BrowseDatabaseAlbumListCaption{width:100%;margin-left:15px}#menu-dbupdate{padding-left:1rem}
\ No newline at end of file
diff --git a/dist/htdocs/index.html b/dist/htdocs/index.html
index c20df44..821a2b7 100644
--- a/dist/htdocs/index.html
+++ b/dist/htdocs/index.html
@@ -1 +1 @@
-<!DOCTYPE html><html lang="en"><head><title>myMPD</title><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="description" content="myMPD - fast and lightweight MPD webclient"><meta name="author" content="mail@jcgames.de"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black"><meta name="theme-color" content="#343a40"><link href="/css/bootstrap.min.css" rel="stylesheet"><link href="/css/mympd.min.css" rel="stylesheet"><link href="/assets/favicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon"><link rel="manifest" href="/mympd.webmanifest"><link rel="apple-touch-icon" href="/assets/appicon-167.png"></head><body><header><nav class="navbar navbar-expand navbar-dark fixed-top bg-dark"><div class="dropdown col-auto mr-auto pl-0" id="mainMenu"><a class="dropdown-toggle navbar-brand" data-toggle="dropdown" href="#"><span class="material-icons header-logo">play_circle_outline</span>myMPD</a><div class="dropdown-menu bg-dark"><a class="dropdown-item text-light bg-dark" href="#" data-href='{"cmd": "showAddToPlaylist", "options": ["stream"]}'>Add Stream</a><a class="dropdown-item text-light bg-dark" href="#" data-href='{"cmd": "updateDB", "options": []}'>Update Database</a><a class="dropdown-item text-light bg-dark" href="#" data-href='{"cmd": "openLocalPlayer", "options": []}'>Local Player</a><a class="dropdown-item text-light bg-dark" href="#" data-toggle="modal" data-target="#modalSettings">Settings</a><a class="dropdown-item text-light bg-dark" href="#" data-toggle="modal" data-target="#modalAbout">About</a><a id="nav-add2homescreen" class="dropdown-item text-light bg-dark hide" href="#">Add2HomeScreen</a></div></div><div class="btn-toolbar col-auto pl-0 pr-0"><div class="btn-group mr-2" id="playControlBtns"><button data-href='{"cmd": "clickPrev", "options": []}' id="btnPrev" type="button" class="btn btn-secondary pl-2 pr-2 material-icons">skip_previous</button><button data-href='{"cmd": "clickStop", "options": []}' id="btnStop" type="button" class="btn btn-secondary pl-2 pr-2 material-icons">stop</button><button data-href='{"cmd": "clickPlay", "options": []}' id="btnPlay" type="button" class="btnPlay btn btn-secondary pl-2 pr-2 material-icons">pause</button><button data-href='{"cmd": "clickNext", "options": []}' id="btnNext" type="button" class="btn btn-secondary pl-2 pr-2 material-icons">skip_next</button></div><div class="btn-group"><button id="volumeIcon" class="btn btn-secondary dropdown-toggle pl-2 pr-2 material-icons" type="button" data-toggle="dropdown">volume_up</button><div class="dropdown-menu dropdown-menu-right bg-dark"><h2 class="dropdown-header text-light">Volume: <span id="volumePrct"></span></h2><form class="px-4 py-0 pb-3" id="volumeControl"><div class="btn-group"><button data-href='{"cmd": "chVolume", "options": [-5]}' class="btn btn-secondary">&minus;</button><div class="btn btn-secondary"><input type="range" min="0" max="100" step="1" class="form-control-range" id="volumeBar"></div><button data-href='{"cmd": "chVolume", "options": [5]}' class="btn btn-secondary">+</button></div></form><div class="dropdown-divider"></div><form id="outputs" class="px-4 py-3"></form></div></div></div></nav></header><main class="container"><noscript><div class="alert alert-danger">JavaScript is disabled!</div></noscript><div class="card" id="cardPlayback"><div class="card-header">Playback<div class="btn-group btn-group-sm stickers pull-right"><button title="Dislike song" id="btnVoteDown" data-href='{"cmd": "voteSong", "options": [0]}' class="btn btn-sm btn-light material-icons">thumb_down</button><button title="Like song" id="btnVoteUp" data-href='{"cmd": "voteSong", "options": [2]}' class="btn btn-sm btn-light material-icons">thumb_up</button></div></div><div class="card-body"><div class="album-cover" id="currentCover"></div><div class="album-desc"><h2 id="currentTrack" data-href='{"cmd": "songClick", "options": []}'></h2><small>Artist</small><h4 id="currentArtist" data-href='{"cmd": "artistClick", "options": []}'></h4><small>Album</small><h4 id="currentAlbum" data-href='{"cmd": "albumClick", "options": []}'></h4></div></div><div class="card-footer card-footer-playback"><div class="d-flex align-items-center"><button data-href='{"cmd": "clickPlay", "options": []}' class="mr-1 ml-1 btn btn-light material-icons btnPlay progressBarPlay">pause</button><input type="range" min="0" max="100" step="1" class="mr-1 ml-1 form-control-range flex-grow-1" id="progressBar"><div class="btn ml-1 mr-1" id="counter">&nbsp;&nbsp;</div></div></div></div><div class="card hide" id="cardQueue"><div class="card-header">Queue<span id="panel-heading-queue" class="text pull-right"></span></div><div class="card-body"><div class="btn-toolbar card-toolbar" id="queue-buttons"><div class="btn-group mr-2"><button type="button" class="btn btn-secondary material-icons" data-toggle="modal" data-target="#modalSaveQueue" title="Save queue">save</button></div><div class="btn-group mr-2"><button type="button" class="btn btn-secondary material-icons"data-href='{"cmd": "sendAPI", "options": [{"cmd": "MPD_API_QUEUE_SHUFFLE"}]}' title="Shuffle queue">shuffle</button></div><div class="input-group mr-2"><div class="input-group-prepend"><button type="button" class="btn btn-secondary material-icons" data-href='{"cmd": "sendAPI", "options": [{"cmd": "MPD_API_QUEUE_CLEAR"}]}' title="Clear queue">clear_all</button><button id="clearQueueBtn" class="btn btn-secondary dropdown-toggle dropdown-toggle-split rounded-right" type="button" data-toggle="dropdown"></button><div class="dropdown-menu bg-dark dropdown-menu-right px-2" id="clearQueueDropdown"><button type="button" class="btn btn-secondary btn-sm btn-block" data-href='{"cmd": "sendAPI", "options": [{"cmd": "MPD_API_QUEUE_CLEAR"}]}' >Clear queue</button><button type="button" class="btn btn-secondary btn-sm btn-block" data-href='{"cmd": "sendAPI", "options": [{"cmd": "MPD_API_QUEUE_CROP"}]}' >Crop queue</button></div></div></div><form id="searchqueue"><div class="input-group mr-2"><input type="text" class="form-control" placeholder="Search Queue" id="searchqueuestr"/><div class="input-group-append"><button title="Select tags to search" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown"><span class="material-icons">search</span><span id="searchqueuetagdesc">Any Tag</span></button><div class="dropdown-menu bg-dark dropdown-menu-right px-2" id="searchqueuetag"></div></div></div></form><div id="QueuePaginationTop" class="btn-group mr-2 hide"><button data-href='{"cmd": "gotoPage", "options": ["prev"]}' id="QueuePaginationTopPrev" title="Previous Page" type="button" class="btn btn-secondary">&laquo;</button><div class="input-group-append"><button id="QueuePaginationTopPage" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">1 / 1</button><div class="dropdown-menu bg-dark px-2 pages" id="QueuePaginationTopPages"></div></div><button data-href='{"cmd": "gotoPage", "options": ["next"]}' id="QueuePaginationTopNext" title="Next Page" type="button" class="btn btn-secondary input-group-append">&raquo;</button></div></div><div class="table-responsive-md"><table id="QueueList" class="table table-hover table-sm" data-version=""><col class="tblnum"/><col class="tbltitle"/><col class="tblartist"/><col class="tblalbum"/><col class="tbllength"/><col class="tblaction"/><thead><tr><th>#</th><th>Title</th><th>Artist</th><th>Album</th><th>Duration</th><th></th></tr></thead><tbody class="clickable"></tbody></table></div><div class="btn-toolbar hide" id="QueueButtonsBottom"><div class="btn-group mr-2"><button type="button" class="btn btn-secondary material-icons" data-href='{"cmd": "scrollTo", "options: [0]}' title="To top">keyboard_arrow_up</button></div><div id="QueuePaginationBottom" class="btn-group mr-2 dropup"><button data-href='{"cmd": "gotoPage", "options": ["prev"]}' id="QueuePaginationBottomPrev" title="Previous Page" type="button" class="btn btn-secondary">&laquo;</button><div class="input-group-append"><button id="QueuePaginationBottomPage" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">1 / 1</button><div class="dropdown-menu bg-dark px-2 pages" id="QueuePaginationBottomPages"></div></div><button data-href='{"cmd": "gotoPage", "options": ["next"]}' id="QueuePaginationBottomNext" title="Next Page" type="button" class="btn btn-secondary input-group-append">&raquo;</button></div></div></div></div><div class="card hide" id="cardBrowse"><div class="card-header" id="panel-heading-browse"><ul class="nav nav-tabs card-header-tabs"><li class="nav-item"><a data-href='{"cmd": "appGoto", "options": ["Browse", "Database"]}' class="nav-link text-dark" href="#" id="cardBrowseNavDatabase">Database</a></li><li class="nav-item"><a data-href='{"cmd": "appGoto", "options": ["Browse", "Playlists"]}' class="nav-link text-dark" href="#" id="cardBrowseNavPlaylists">Playlists</a></li><li class="nav-item"><a data-href='{"cmd": "appGoto", "options": ["Browse", "Filesystem"]}' class="nav-link text-dark" href="#" id="cardBrowseNavFilesystem">Filesystem</a></li></ul></div><div class="card-body hide" id="cardBrowsePlaylists"><div class="btn-toolbar card-toolbar" id="BrowsePlaylistsButtons"><div class="btn-group mr-2 hide"><button data-href='{"cmd": "appGoto", "options": ["Browse", "Playlists", "All"]}' id="btnBrowsePlaylistsAll" type="button" class="btn btn-secondary">&laquo; Playlists</button></div><div class="btn-group mr-2 hide"><button id="btnPlaylistClear" type="button" class="btn btn-secondary material-icons" data-href='{"cmd": "playlistClear", "options": []}' title="Clear playlist">clear_all</button></div><div class="btn-group mr-2"><button id="BrowsePlaylistsFilter" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">Filter</button><div class="dropdown-menu bg-dark px-2 letters" id="BrowsePlaylistsFilterLetters"></div></div><div id="BrowsePlaylistsPaginationTop" class="btn-group mr-2 hide"><button data-href='{"cmd": "gotoPage", "options": ["prev"]}' id="BrowsePlaylistsPaginationTopPrev" title="Previous Page" type="button" class="btn btn-secondary">&laquo;</button><div class="input-group-append"><button id="BrowsePlaylistsPaginationTopPage" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">1 / 1</button><div class="dropdown-menu bg-dark px-2 pages" id="BrowsePlaylistsPaginationTopPages"></div></div><button data-href='{"cmd": "gotoPage", "options": ["next"]}' id="BrowsePlaylistsPaginationTopNext" title="Next Page" type="button" class="btn btn-secondary input-group-append">&raquo;</button></div></div><div class="table-responsive-md"><table id="BrowsePlaylistsAllList" class="table table-hover table-sm"><col class="tblnum"/><col class="tbltitle"/><col class="tbllastmodified"/><col class="tblaction"/><thead><tr><th></th><th>Playlist</th><th>Last modified</th><th></th></tr></thead><tbody class="clickable"></tbody></table><table id="BrowsePlaylistsDetailList" class="table table-hover table-sm hide"><caption>Playlist List</caption><col class="tblnum"/><col class="tbltitle"/><col class="tblartist"/><col class="tblalbum"/><col class="tbllength"/><col class="tblaction"/><thead><tr><th>#</th><th>Title</th><th>Artist</th><th>Album</th><th>Duration</th><th></th></tr></thead><tbody class="clickable"></tbody></table></div><div class="btn-toolbar hide" id="BrowsePlaylistsButtonsBottom"><div class="btn-group mr-2"><button type="button" class="btn btn-secondary material-icons" data-href='{"cmd": "scrollTo", "options": [0]}' title="To top">keyboard_arrow_up</button></div><div id="BrowsePlaylistsPaginationBottom" class="btn-group mr-2 dropup"><button data-href='{"cmd": "gotoPage", "options": ["prev"]}' id="BrowsePlaylistsPaginationBottomPrev" title="Previous Page" type="button" class="btn btn-secondary">&laquo;</button><div class="input-group-append"><button id="BrowsePlaylistsPaginationBottomPage" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">1 / 1</button><div class="dropdown-menu bg-dark px-2 pages" id="BrowsePlaylistsPaginationBottomPages"></div></div><button data-href='{"cmd": "gotoPage", "options": ["next"]}' id="BrowsePlaylistsPaginationBottomNext" title="Next Page" type="button" class="btn btn-secondary input-group-append">&raquo;</button></div></div></div><div class="card-body hide" id="cardBrowseDatabase"><div class="btn-toolbar card-toolbar" id="BrowseDatabaseButtons"><div class="btn-group mr-2"><button id="btnBrowseDatabaseByTag" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">AlbumArtist</button><div class="dropdown-menu bg-dark px-2" id="BrowseDatabaseByTagDropdown"></div></div><div class="btn-group mr-2 hide"><button data-href='{"cmd": "gotoTagList", "options": []}' id="btnBrowseDatabaseTag" type="button" class="btn btn-secondary">&laquo; Artists</button></div><div class="btn-group mr-2"><button id="BrowseDatabaseFilter" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">Filter</button><div class="dropdown-menu bg-dark px-2 letters" id="BrowseDatabaseFilterLetters"></div></div><div class="input-group mr-2 hide"><div class="input-group-prepend"><button data-href='{"cmd": "addAllFromBrowseDatabase", "options": []}' id="BrowseDatabaseAddAllSongs" class="btn btn-secondary">Add all</button><button id="BrowseDatabaseAddAllSongsBtn" class="btn btn-secondary dropdown-toggle dropdown-toggle-split rounded-right" type="button" data-toggle="dropdown"></button><div class="dropdown-menu bg-dark dropdown-menu-right px-2" id="BrowseDatabaseAddAllSongsDropdown"><button type="button" class="btn btn-secondary btn-sm btn-block">Add all to queue</button><button type="button" class="btn btn-secondary btn-sm btn-block">Add all to playlist</button></div></div></div><div id="BrowseDatabasePaginationTop" class="btn-group mr-2 hide"><button data-href='{"cmd": "gotoPage", "options": ["prev"]}' id="BrowseDatabasePaginationTopPrev" title="Previous Page" type="button" class="btn btn-secondary">&laquo;</button><div class="input-group-append"><button id="BrowseDatabasePaginationTopPage" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">1 / 1</button><div class="dropdown-menu bg-dark px-2 pages" id="BrowseDatabasePaginationTopPages"></div></div><button data-href='{"cmd": "gotoPage", "options": ["next"]}' id="BrowseDatabasePaginationTopNext" title="Next Page" type="button" class="btn btn-secondary input-group-append">&raquo;</button></div></div><div class="table-responsive-md"><table id="BrowseDatabaseTagList" class="table table-hover table-sm"><col class="tblnum"/><col class="tbltitle"/><thead><tr><th></th><th>Artist</th></tr></thead><tbody class="clickable"></tbody></table></div><div id="BrowseDatabaseAlbumList" class="row hide"><h2 id="BrowseDatabaseAlbumListCaption"></h2></div><div class="btn-toolbar hide" id="BrowseDatabaseButtonsBottom"><div class="btn-group mr-2"><button type="button" class="btn btn-secondary material-icons" data-href='{"cmd": "scrollTo", "options": [0]}' title="To top">keyboard_arrow_up</button></div><div id="BrowseDatabasePaginationBottom" class="btn-group mr-2 dropup"><button data-href='{"cmd": "gotoPage", "options": ["prev"]}' id="BrowseDatabasePaginationBottomPrev" title="Previous Page" type="button" class="btn btn-secondary">&laquo;</button><div class="input-group-append"><button id="BrowseDatabasePaginationBottomPage" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">1 / 1</button><div class="dropdown-menu bg-dark px-2 pages" id="BrowseDatabasePaginationBottomPages"></div></div><button data-href='{"cmd": "gotoPage", "options": ["next"]}' id="BrowseDatabasePaginationBottomNext" title="Next Page" type="button" class="btn btn-secondary input-group-append">&raquo;</button></div></div></div><div class="card-body hide" id="cardBrowseFilesystem"><div class="btn-toolbar card-toolbar" id="BrowseFilesystemButtons"><div class="btn-group mr-2"><button id="BrowseFilesystemFilter" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">Filter</button><div class="dropdown-menu bg-dark px-2 letters" id="BrowseFilesystemFilterLetters"></div></div><div class="input-group mr-2"><div class="input-group-prepend"><button data-href='{"cmd": "addAllFromBrowseFilesystem", "options": []}' id="BrowseFilesystemAddAllSongs" class="btn btn-secondary">Add all</button><button id="BrowseFilesystemAddAllSongsBtn" class="btn btn-secondary dropdown-toggle dropdown-toggle-split rounded-right" type="button" data-toggle="dropdown"></button><div class="dropdown-menu bg-dark dropdown-menu-right px-2" id="BrowseFilesystemAddAllSongsDropdown"><button type="button" class="btn btn-secondary btn-sm btn-block">Add all to queue</button><button type="button" class="btn btn-secondary btn-sm btn-block">Add all to playlist</button></div></div></div><div id="BrowseFilesystemPaginationTop" class="btn-group mr-2 hide"><button data-href='{"cmd": "gotoPage", "options": ["prev"]}' id="BrowseFilesystemPaginationTopPrev" title="Previous Page" type="button" class="btn btn-secondary">&laquo;</button><div class="input-group-append"><button id="BrowseFilesystemPaginationTopPage" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">1 / 1</button><div class="dropdown-menu bg-dark px-2 pages" id="BrowseFilesystemPaginationTopPages"></div></div><button data-href='{"cmd": "gotoPage", "options": ["next"]}' id="BrowseFilesystemPaginationTopNext" title="Next Page" type="button" class="btn btn-secondary input-group-append">&raquo;</button></div></div><ol id="BrowseBreadcrumb" class="breadcrumb"></ol><div class="table-responsive-md"><table id="BrowseFilesystemList" class="table table-hover table-sm"><col class="tblnum"/><col class="tbltitle"/><col class="tblartist"/><col class="tblalbum"/><col class="tbllength"/><col class="tblaction"/><thead><tr><th></th><th>Title</th><th>Artist</th><th>Album</th><th>Duration</th><th></th></tr></thead><tbody class="clickable"></tbody></table></div><div class="btn-toolbar hide" id="BrowseFilesystemButtonsBottom"><div class="btn-group mr-2"><button type="button" class="btn btn-secondary material-icons" data-href='{"cmd": "scrollTo", "options": [0]}' title="To top">keyboard_arrow_up</button></div><div id="BrowseFilesystemPaginationBottom" class="btn-group mr-2 dropup"><button data-href='{"cmd": "gotoPage", "options": ["prev"]}' id="BrowseFilesystemPaginationBottomPrev" title="Previous Page" type="button" class="btn btn-secondary">&laquo;</button><div class="input-group-append"><button id="BrowseFilesystemPaginationBottomPage" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">1 / 1</button><div class="dropdown-menu bg-dark px-2 pages" id="BrowseFilesystemPaginationBottomPages"></div></div><button data-href='{"cmd": "gotoPage", "options": ["next"]}' id="BrowseFilesystemPaginationBottomNext" title="Next Page" type="button" class="btn btn-secondary input-group-append">&raquo;</button></div></div></div></div><div class="card hide" id="cardSearch"><div class="card-header">Search<span id="panel-heading-search" class="text pull-right"></span></div><div class="card-body"><div class="btn-toolbar card-toolbar" id="SearchButtons"><form id="search"><div class="input-group mr-2"><input type="text" class="form-control" placeholder="Search" id="searchstr"/><div class="input-group-append"><button title="Select tags to search" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown"><span class="material-icons">search</span><span id="searchtagsdesc">Any Tag</span></button><div class="dropdown-menu bg-dark dropdown-menu-right px-2" id="searchtags"></div></div></div></form><div class="input-group mr-2"><div class="input-group-prepend"><button id="searchAddAllSongs" class="btn btn-secondary" data-href='{"cmd": "addAllFromSearch", "options": []}'>Add all</button><button id="searchAddAllSongsBtn" class="btn btn-secondary dropdown-toggle dropdown-toggle-split rounded-right" type="button" data-toggle="dropdown"></button><div class="dropdown-menu bg-dark dropdown-menu-right px-2" id="searchAddAllSongsDropdown"><button type="button" class="btn btn-secondary btn-sm btn-block">Add all to queue</button><button type="button" class="btn btn-secondary btn-sm btn-block">Add all to playlist</button></div></div></div><div id="SearchPaginationTop" class="btn-group mr-2 hide"><button data-href='{"cmd": "gotoPage", "options": ["prev"]}' id="SearchPaginationTopPrev" title="Previous Page" type="button" class="btn btn-secondary">&laquo;</button><div class="input-group-append"><button id="SearchPaginationTopPage" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">1 / 1</button><div class="dropdown-menu bg-dark px-2 pages" id="SearchPaginationTopPages"></div></div><button data-href='{"cmd": "gotoPage", "options": ["next"]}' id="SearchPaginationTopNext" title="Next Page" type="button" class="btn btn-secondary input-group-append">&raquo;</button></div></div><div class="table-responsive-md"><table id="SearchList" class="table table-hover table-sm"><col class="tblnum"/><col class="tbltitle"/><col class="tblartist"/><col class="tblalbum"/><col class="tbllength"/><col class="tblaction"/><thead><tr><th></th><th>Title</th><th>Artist</th><th>Album</th><th>Duration</th><th></th></tr></thead><tbody class="clickable"></tbody></table></div><div class="btn-toolbar hide" id="SearchButtonsBottom"><div class="btn-group mr-2"><button type="button" class="btn btn-secondary material-icons" data-href='{"cmd": "scrollTo", "options": [0]}' title="To top">keyboard_arrow_up</button></div><div id="SearchPaginationBottom" class="btn-group mr-2 dropup"><button data-href='{"cmd": "gotoPage", "options": ["prev"]}' id="SearchPaginationBottomPrev" title="Previous Page" type="button" class="btn btn-secondary">&laquo;</button><div class="input-group-append"><button id="SearchPaginationBottomPage" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">1 / 1</button><div class="dropdown-menu bg-dark px-2 pages" id="SearchPaginationBottomPages"></div></div><button data-href='{"cmd": "gotoPage", "options": ["next"]}' id="SearchPaginationBottomNext" title="Next Page" type="button" class="btn btn-secondary input-group-append">&raquo;</button></div></div></div></div></main><footer class="footer"><nav class="navbar navbar-expand navbar-dark fixed-bottom bg-dark"><div class="d-flex flex-fill navbar-nav" id="navbar-bottom"><div id="navPlayback" class="nav-item flex-fill text-center"><a data-href='{"cmd": "appGoto", "options": ["Playback"]}' class="nav-link" href="#">Playback</a></div><div id="navQueue" class="nav-item flex-fill text-center"><a data-href='{"cmd": "appGoto", "options": ["Queue"]}' class="nav-link" href="#">Queue</a></div><div class="nav-item flex-fill text-center" id="navBrowse"><a data-href='{"cmd": "appGoto", "options": ["Browse"]}' class="nav-link" href="#">Browse</a></div><div class="nav-item flex-fill text-center" id="navSearch"><a data-href='{"cmd": "appGoto", "options": ["Search"]}' class="nav-link" href="#">Search</a></div></div></nav></footer><!-- Modals --><div class="modal fade" id="modalConnectionError" tabindex="-1"><div class="modal-dialog"><div class="modal-content"><div class="modal-header bg-danger text-light"><h5 class="modal-title"><span class="material-icons title-icon">error</span> Connection Error</h5></div><div class="modal-body"><p>Connection to myMPD failed. Trying to reconnect.</p></div></div></div></div><div class="modal fade" id="modalUpdateDB" tabindex="-1"><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><h5 class="modal-title"><span class="material-icons title-icon">update</span> Updating MPD database</h5><button type="button" class="close" data-dismiss="modal">&times;</button></div><div class="modal-body"><p>Dependent on the size of your music collection this can take a while.</p><div class="progress"><div id="updateDBprogress" class="progress-bar bg-success" role="progressbar"></div></div><br/><p id="updateDBfinished"></p></div><div class="modal-footer hide" id="updateDBfooter"><button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button></div></div></div></div><div class="modal fade" id="modalAddToPlaylist" tabindex="-1"><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><h5 class="modal-title"><span class="material-icons title-icon">playlist_add</span> <span id="addToPlaylistLabel">Add to playlist</span></h5><button type="button" class="close" data-dismiss="modal">&times;</button></div><div class="modal-body"><form id="addStreamFrm" class="needs-validation hide" novalidate><div class="row"><div class="form-group col-md-12"><label class="control-label" for="streamUrl">Stream URL</label><input type="text" class="form-control" id="streamUrl" placeholder="http://uri.to/stream.mp3"/><div class="invalid-feedback">Invalid uri</div></div></div><div class="row"><div class="form-group col-md-12"><button id="toggleAddToPlaylistBtn" class="btn btn-secondary" data-href='{"cmd": "toggleAddToPlaylistFrm", "options":[]}'>Add to playlist</button></div></div></form><form class="needs-validation hide" id="addToPlaylistFrm" novalidate><input type="hidden" id="addToPlaylistUri"/><div class="form-group"><label for="addToPlaylistPlaylist">Playlist</label><select id="addToPlaylistPlaylist" class="form-control custom-select"></select><div class="invalid-feedback">Please choose playlist.</div></div><div class="form-group hide" id="addToPlaylistNewPlaylistDiv"><label for="addToPlaylistNewPlaylist">Create Playlist</label><input id="addToPlaylistNewPlaylist" class="form-control"/><div class="invalid-feedback">Invalid filename.</div></div></form></div><div class="modal-footer" id="addToPlaylistFooter"><button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button><button type="button" class="btn btn-success" data-href='{"cmd": "addToPlaylist", "options": []}'>Add</button></div><div class="modal-footer hide" id="addStreamFooter"><button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button><button type="button" class="btn btn-success" data-href='{"cmd": "addStream", "options": []}'>Add</button></div></div></div></div><div class="modal fade" id="modalRenamePlaylist" tabindex="-1"><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><h5 class="modal-title"><span class="material-icons title-icon">playlist_add</span>Rename playlist</h5><button type="button" class="close" data-dismiss="modal">&times;</button></div><div class="modal-body"><form class="needs-validation" id="renamePlaylistFrm" novalidate><div class="form-group"><label for="renamePlaylistFrom">From</label><input type="text" class="form-control" id="renamePlaylistFrom" readonly></div><div class="form-group"><label for="renamePlaylistTo">To</label><input type="text" class="form-control" id="renamePlaylistTo"/><div class="invalid-feedback">Invalid filename.</div></div></form></div><div class="modal-footer"><button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button><button type="button" class="btn btn-success" data-href='{"cmd": "renamePlaylist", "options": []}'>Save</button></div></div></div></div><div class="modal fade" id="modalSettings" tabindex="-1"><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><h5 class="modal-title" id="settingsLabel"><span class="material-icons title-icon">settings</span> Settings</h5><button type="button" class="close" data-dismiss="modal">&times;</button></div><div class="modal-body"><form class="needs-validation" id="settingsFrm" novalidate><h4>MPD</h4><div class="row"><div class="form-group col-md-6"><button data-href='{"cmd":"toggleBtn", "options":["btnRandom"]}' id="btnRandom" type="button" class="btn btn-secondary btn-block" title="Random">Random</button></div><div class="form-group col-md-6" data-toggle="buttons"><button data-href='{"cmd": "toggleBtn", "options": ["btnConsume"]}' id="btnConsume" type="button" class="btn btn-secondary btn-block" title="Consume">Consume</button></div></div><div class="row"><div class="form-group col-md-6" data-toggle="buttons"><button data-href='{"cmd": "toggleBtn", "options": ["btnSingle"]}' id="btnSingle" type="button" class="btn btn-secondary btn-block" title="Single">Single</button></div><div class="form-group col-md-6" data-toggle="buttons"><button data-href='{"cmd": "toggleBtn", "options": ["btnRepeat"]}' id="btnRepeat" type="button" class="btn btn-secondary btn-block" title="Repeat">Repeat</button></div></div><div class="row"><div class="form-group input-group col-md-6 border-secondary"><div class="input-group-prepend"><div class="input-group-text bg-secondary text-light border-secondary">Crossfade</div></div><input id="inputCrossfade" type="text" class="form-control border-secondary" value=""><div class="invalid-feedback">Must be a number.</div></div><div class="form-group input-group col-md-6 border-secondary"><div class="input-group-prepend"><div class="input-group-text bg-secondary text-light border-secondary">Replaygain</div></div><select id="selectReplaygain" class="form-control custom-select border-secondary"><option value="off">Off</option><option value="track">Track</option><option value="album">Album</option></select></div></div><div class="row mixramp"><div class="form-group input-group col-md-6 border-secondary"><div class="input-group-prepend"><div class="input-group-text bg-secondary text-light border-secondary">Mixramp DB</div></div><input id="inputMixrampdb" type="text" class="form-control border-secondary" value=""><div class="invalid-feedback">Must be a number.</div></div><div class="form-group input-group col-md-6 border-secondary"><div class="input-group-prepend"><div class="input-group-text bg-secondary text-light border-secondary">Mixramp Delay</div></div><input id="inputMixrampdelay" type="text" class="form-control border-secondary" value=""><div class="invalid-feedback">Must be a number.</div></div></div><hr/><h4>Jukebox</h4><div class="row"><div class="form-group col-md-6" data-toggle="buttons"><button data-href='{"cmd": "toggleBtn", "options": ["btnJukebox"]}' id="btnJukebox" type="button" class="btn btn-secondary btn-block" title="Jukebox">Jukebox</button></div><div class="form-group input-group col-md-6 border-secondary"><select id="jukeboxPlaylist" class="form-control custom-select border-secondary"></select></div></div><hr/><h4>Notifications</h4><div class="row"><div class="form-group col-md-6" data-toggle="buttons"><button data-href='{"cmd": "toggleBtn", "options": ["btnnotifyPage"]}' type="button" class="btn btn-secondary btn-block" id="btnnotifyPage">Page Notifications</button></div><div class="form-group col-md-6" data-toggle="buttons"><button data-href='{"cmd": "toggleBtn", "options": ["btnnotifyWeb"]}' type="button" class="btn btn-secondary btn-block" id="btnnotifyWeb">Web Notifications</button></div></div></form></div><div class="modal-footer"><button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button><button type="button" class="btn btn-success" data-href='{"cmd": "confirmSettings", "options": []}'>Save</button></div></div></div></div><div class="modal fade" id="modalAbout" tabindex="-1"><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><h5 class="modal-title" id="aboutLabel"><span class="material-icons title-icon">play_circle_outline</span> About</h5><button type="button" class="close" data-dismiss="modal">&times;</button></div><div class="modal-body"><h4><a class="text-success" rel="noreferrer" href="https://github.com/jcorporation/ympd">myMPD</a>&nbsp;&ndash;&nbsp;<small>MPD Web GUI - written in C, utilizing Websockets and Bootstrap/JS</small></h4><p>myMPD is a lightweight MPD web client that runs without a dedicated webserver or interpreter. It's tuned for minimal resource usage and requires only very litte dependencies. myMPD is a fork of <a class="text-success" href="http://www.ympd.org">ympd</a>.</p><ul><li>Version: <span id="mympdVersion"></span></li><li>Homepage: <a class="text-success" target="_blank" rel="noreferrer" href="https://github.com/jcorporation/mympd">https://github.com/jcorporation/mympd</a></li><li>Autor: Jürgen Mang &lt;<a class="text-success" href="mailto:mail@jcgames.de">mail@jcgames.de</a>&gt;</li></ul><table class="table table-sm"><tbody><tr><td colspan="2" class="pt-3"><h5>Database Statistics</h5></td></tr><tr><th>Artists</th><td id="mpdstats_artists"></td></tr><tr><th>Albums</th><td id="mpdstats_albums"></td></tr><tr><th>Songs</th><td id="mpdstats_songs"></td></tr><tr><th>DB Play Time</th><td id="mpdstats_dbPlaytime"></td></tr><tr><th>DB Updated</th><td id="mpdstats_dbUpdated"></td></tr><tr><td colspan="2" class="pt-3"><h5>Play Statistics</h5></td></tr><tr><th>Uptime</th><td id="mpdstats_uptime"></td></tr><tr><th>Play Time</th><td id="mpdstats_playtime"></td></tr><tr><td colspan="2" class="pt-3"><h5>MPD</h5></td></tr><tr><th>Protocol Version</th><td id="mpdVersion"></td></tr></tbody></table></div></div></div></div><div class="modal fade" id="modalSaveQueue" tabindex="-1"><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><h5 class="modal-title"><span class="material-icons title-icon">save</span> Save Queue</h5><button type="button" class="close" data-dismiss="modal">&times;</button></div><div class="modal-body"><form class="needs-validation" id="saveQueueFrm" novalidate><div class="row"><div class="form-group col-md-9"><label class="control-label" for="saveQueueName">Playlist Name</label><input type="text" class="form-control" id="saveQueueName"/><div class="invalid-feedback">Invalid filename</div></div></div></form></div><div class="modal-footer"><button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button><button type="button" class="btn btn-success" data-href='{"cmd": "saveQueue", "options": []}'>Save Queue</button></div></div></div></div><div class="modal fade" id="modalSongDetails" tabindex="-1"><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><h5 class="modal-title"><span class="material-icons title-icon">music_note</span> Song Details</h5><button type="button" class="close" data-dismiss="modal">&times;</button></div><div class="modal-body"><div class="album-cover"></div><h1></h1><div class="table-responsive-md"><table class="table table-sm"><tbody></tbody></table></div></div><div class="modal-footer"><button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button></div></div></div></div><script src="/js/bootstrap-native-v4.min.js"></script><script src="/js/mympd.min.js"></script></body></html>
\ No newline at end of file
+<!DOCTYPE html><html lang="en"><head><title>myMPD</title><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="description" content="myMPD - fast and lightweight MPD webclient"><meta name="author" content="mail@jcgames.de"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black"><meta name="theme-color" content="#343a40"><link href="/css/bootstrap.min.css" rel="stylesheet"><link href="/css/mympd.min.css" rel="stylesheet"><link href="/assets/favicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon"><link rel="manifest" href="/mympd.webmanifest"><link rel="apple-touch-icon" href="/assets/appicon-167.png"></head><body><header><nav class="navbar navbar-expand navbar-dark fixed-top bg-dark"><div class="dropdown col-auto mr-auto pl-0" id="mainMenu"><a class="dropdown-toggle navbar-brand" data-toggle="dropdown" href="#"><span class="material-icons header-logo">play_circle_outline</span>myMPD</a><div class="dropdown-menu bg-dark"><a class="dropdown-item text-light bg-dark" href="#" data-href='{"cmd": "showAddToPlaylist", "options": ["stream"]}'>Add Stream</a><a id="navDBupdate" class="dropdown-item text-light bg-dark" data-toggle="collapse" href="#menu-dbupdate"><span class="material-icons material-icons-left">keyboard_arrow_right</span>Database</a><div class="collapse" id="menu-dbupdate"><a class="dropdown-item text-light bg-dark" href="#" data-href='{"cmd": "updateDB", "options": []}'>Update</a><a class="dropdown-item text-light bg-dark" href="#" data-href='{"cmd": "rescanDB", "options": []}'>Rescan</a></div><a class="dropdown-item text-light bg-dark" href="#" data-href='{"cmd": "openLocalPlayer", "options": []}'>Local Player</a><a class="dropdown-item text-light bg-dark" href="#" data-toggle="modal" data-target="#modalSettings">Settings</a><a class="dropdown-item text-light bg-dark" href="#" data-toggle="modal" data-target="#modalAbout">About</a><a id="nav-add2homescreen" class="dropdown-item text-light bg-dark hide" href="#">Add2HomeScreen</a></div></div><div class="btn-toolbar col-auto pl-0 pr-0"><div class="btn-group mr-2" id="playControlBtns"><button data-href='{"cmd": "clickPrev", "options": []}' id="btnPrev" type="button" class="btn btn-secondary pl-2 pr-2 material-icons">skip_previous</button><button data-href='{"cmd": "clickStop", "options": []}' id="btnStop" type="button" class="btn btn-secondary pl-2 pr-2 material-icons">stop</button><button data-href='{"cmd": "clickPlay", "options": []}' id="btnPlay" type="button" class="btnPlay btn btn-secondary pl-2 pr-2 material-icons">pause</button><button data-href='{"cmd": "clickNext", "options": []}' id="btnNext" type="button" class="btn btn-secondary pl-2 pr-2 material-icons">skip_next</button></div><div class="btn-group"><button id="volumeIcon" class="btn btn-secondary dropdown-toggle pl-2 pr-2 material-icons" type="button" data-toggle="dropdown">volume_up</button><div class="dropdown-menu dropdown-menu-right bg-dark"><h2 class="dropdown-header text-light">Volume: <span id="volumePrct"></span></h2><form class="px-4 py-0 pb-3" id="volumeControl"><div class="btn-group"><button data-href='{"cmd": "chVolume", "options": [-5]}' class="btn btn-secondary">&minus;</button><div class="btn btn-secondary"><input type="range" min="0" max="100" step="1" class="form-control-range" id="volumeBar"></div><button data-href='{"cmd": "chVolume", "options": [5]}' class="btn btn-secondary">+</button></div></form><div class="dropdown-divider"></div><form id="outputs" class="px-4 py-3"></form></div></div></div></nav></header><main class="container"><noscript><div class="alert alert-danger">JavaScript is disabled!</div></noscript><div class="card" id="cardPlayback"><div class="card-header">Playback<div class="btn-group btn-group-sm stickers pull-right"><button title="Dislike song" id="btnVoteDown" data-href='{"cmd": "voteSong", "options": [0]}' class="btn btn-sm btn-light material-icons">thumb_down</button><button title="Like song" id="btnVoteUp" data-href='{"cmd": "voteSong", "options": [2]}' class="btn btn-sm btn-light material-icons">thumb_up</button></div></div><div class="card-body"><div class="album-cover" id="currentCover"></div><div class="album-desc"><h2 id="currentTrack" data-href='{"cmd": "songClick", "options": []}'></h2><small>Artist</small><h4 id="currentArtist" data-href='{"cmd": "artistClick", "options": []}'></h4><small>Album</small><h4 id="currentAlbum" data-href='{"cmd": "albumClick", "options": []}'></h4></div></div><div class="card-footer card-footer-playback"><div class="d-flex align-items-center"><button data-href='{"cmd": "clickPlay", "options": []}' class="mr-1 ml-1 btn btn-light material-icons btnPlay progressBarPlay">pause</button><input type="range" min="0" max="100" step="1" class="mr-1 ml-1 form-control-range flex-grow-1" id="progressBar"><div class="btn ml-1 mr-1" id="counter">&nbsp;&nbsp;</div></div></div></div><div class="card hide" id="cardQueue"><div class="card-header">Queue<span id="panel-heading-queue" class="text pull-right"></span></div><div class="card-body"><div class="btn-toolbar card-toolbar" id="queue-buttons"><div class="btn-group mr-2"><button type="button" class="btn btn-secondary material-icons" data-toggle="modal" data-target="#modalSaveQueue" title="Save queue">save</button></div><div class="btn-group mr-2"><button type="button" class="btn btn-secondary material-icons"data-href='{"cmd": "sendAPI", "options": [{"cmd": "MPD_API_QUEUE_SHUFFLE"}]}' title="Shuffle queue">shuffle</button></div><div class="input-group mr-2"><div class="input-group-prepend"><button type="button" class="btn btn-secondary material-icons" data-href='{"cmd": "sendAPI", "options": [{"cmd": "MPD_API_QUEUE_CLEAR"}]}' title="Clear queue">clear_all</button><button id="clearQueueBtn" class="btn btn-secondary dropdown-toggle dropdown-toggle-split rounded-right" type="button" data-toggle="dropdown"></button><div class="dropdown-menu bg-dark dropdown-menu-right px-2" id="clearQueueDropdown"><button type="button" class="btn btn-secondary btn-sm btn-block" data-href='{"cmd": "sendAPI", "options": [{"cmd": "MPD_API_QUEUE_CLEAR"}]}' >Clear queue</button><button type="button" class="btn btn-secondary btn-sm btn-block" data-href='{"cmd": "sendAPI", "options": [{"cmd": "MPD_API_QUEUE_CROP"}]}' >Crop queue</button></div></div></div><form id="searchqueue"><div class="input-group mr-2"><input type="text" class="form-control" placeholder="Search Queue" id="searchqueuestr"/><div class="input-group-append"><button title="Select tags to search" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown"><span class="material-icons">search</span><span id="searchqueuetagdesc">Any Tag</span></button><div class="dropdown-menu bg-dark dropdown-menu-right px-2" id="searchqueuetag"></div></div></div></form><div id="QueuePaginationTop" class="btn-group mr-2 hide"><button data-href='{"cmd": "gotoPage", "options": ["prev"]}' id="QueuePaginationTopPrev" title="Previous Page" type="button" class="btn btn-secondary">&laquo;</button><div class="input-group-append"><button id="QueuePaginationTopPage" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">1 / 1</button><div class="dropdown-menu bg-dark px-2 pages" id="QueuePaginationTopPages"></div></div><button data-href='{"cmd": "gotoPage", "options": ["next"]}' id="QueuePaginationTopNext" title="Next Page" type="button" class="btn btn-secondary input-group-append">&raquo;</button></div></div><div class="table-responsive-md"><table id="QueueList" class="table table-hover table-sm" data-version=""><col class="tblnum"/><col class="tbltitle"/><col class="tblartist"/><col class="tblalbum"/><col class="tbllength"/><col class="tblaction"/><thead><tr><th>#</th><th>Title</th><th>Artist</th><th>Album</th><th>Duration</th><th></th></tr></thead><tbody class="clickable"></tbody></table></div><div class="btn-toolbar hide" id="QueueButtonsBottom"><div class="btn-group mr-2"><button type="button" class="btn btn-secondary material-icons" data-href='{"cmd": "scrollTo", "options: [0]}' title="To top">keyboard_arrow_up</button></div><div id="QueuePaginationBottom" class="btn-group mr-2 dropup"><button data-href='{"cmd": "gotoPage", "options": ["prev"]}' id="QueuePaginationBottomPrev" title="Previous Page" type="button" class="btn btn-secondary">&laquo;</button><div class="input-group-append"><button id="QueuePaginationBottomPage" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">1 / 1</button><div class="dropdown-menu bg-dark px-2 pages" id="QueuePaginationBottomPages"></div></div><button data-href='{"cmd": "gotoPage", "options": ["next"]}' id="QueuePaginationBottomNext" title="Next Page" type="button" class="btn btn-secondary input-group-append">&raquo;</button></div></div></div></div><div class="card hide" id="cardBrowse"><div class="card-header" id="panel-heading-browse"><ul class="nav nav-tabs card-header-tabs"><li class="nav-item"><a data-href='{"cmd": "appGoto", "options": ["Browse", "Database"]}' class="nav-link text-dark" href="#" id="cardBrowseNavDatabase">Database</a></li><li class="nav-item"><a data-href='{"cmd": "appGoto", "options": ["Browse", "Playlists"]}' class="nav-link text-dark" href="#" id="cardBrowseNavPlaylists">Playlists</a></li><li class="nav-item"><a data-href='{"cmd": "appGoto", "options": ["Browse", "Filesystem"]}' class="nav-link text-dark" href="#" id="cardBrowseNavFilesystem">Filesystem</a></li></ul></div><div class="card-body hide" id="cardBrowsePlaylists"><div class="btn-toolbar card-toolbar" id="BrowsePlaylistsButtons"><div class="btn-group mr-2 hide"><button data-href='{"cmd": "appGoto", "options": ["Browse", "Playlists", "All"]}' id="btnBrowsePlaylistsAll" type="button" class="btn btn-secondary">&laquo; Playlists</button></div><div class="btn-group mr-2 hide"><button id="btnPlaylistClear" type="button" class="btn btn-secondary material-icons" data-href='{"cmd": "playlistClear", "options": []}' title="Clear playlist">clear_all</button></div><div class="btn-group mr-2"><button id="BrowsePlaylistsFilter" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">Filter</button><div class="dropdown-menu bg-dark px-2 letters" id="BrowsePlaylistsFilterLetters"></div></div><div id="BrowsePlaylistsPaginationTop" class="btn-group mr-2 hide"><button data-href='{"cmd": "gotoPage", "options": ["prev"]}' id="BrowsePlaylistsPaginationTopPrev" title="Previous Page" type="button" class="btn btn-secondary">&laquo;</button><div class="input-group-append"><button id="BrowsePlaylistsPaginationTopPage" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">1 / 1</button><div class="dropdown-menu bg-dark px-2 pages" id="BrowsePlaylistsPaginationTopPages"></div></div><button data-href='{"cmd": "gotoPage", "options": ["next"]}' id="BrowsePlaylistsPaginationTopNext" title="Next Page" type="button" class="btn btn-secondary input-group-append">&raquo;</button></div></div><div class="table-responsive-md"><table id="BrowsePlaylistsAllList" class="table table-hover table-sm"><col class="tblnum"/><col class="tbltitle"/><col class="tbllastmodified"/><col class="tblaction"/><thead><tr><th></th><th>Playlist</th><th>Last modified</th><th></th></tr></thead><tbody class="clickable"></tbody></table><table id="BrowsePlaylistsDetailList" class="table table-hover table-sm hide"><caption>Playlist List</caption><col class="tblnum"/><col class="tbltitle"/><col class="tblartist"/><col class="tblalbum"/><col class="tbllength"/><col class="tblaction"/><thead><tr><th>#</th><th>Title</th><th>Artist</th><th>Album</th><th>Duration</th><th></th></tr></thead><tbody class="clickable"></tbody></table></div><div class="btn-toolbar hide" id="BrowsePlaylistsButtonsBottom"><div class="btn-group mr-2"><button type="button" class="btn btn-secondary material-icons" data-href='{"cmd": "scrollTo", "options": [0]}' title="To top">keyboard_arrow_up</button></div><div id="BrowsePlaylistsPaginationBottom" class="btn-group mr-2 dropup"><button data-href='{"cmd": "gotoPage", "options": ["prev"]}' id="BrowsePlaylistsPaginationBottomPrev" title="Previous Page" type="button" class="btn btn-secondary">&laquo;</button><div class="input-group-append"><button id="BrowsePlaylistsPaginationBottomPage" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">1 / 1</button><div class="dropdown-menu bg-dark px-2 pages" id="BrowsePlaylistsPaginationBottomPages"></div></div><button data-href='{"cmd": "gotoPage", "options": ["next"]}' id="BrowsePlaylistsPaginationBottomNext" title="Next Page" type="button" class="btn btn-secondary input-group-append">&raquo;</button></div></div></div><div class="card-body hide" id="cardBrowseDatabase"><div class="btn-toolbar card-toolbar" id="BrowseDatabaseButtons"><div class="btn-group mr-2"><button id="btnBrowseDatabaseByTag" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">AlbumArtist</button><div class="dropdown-menu bg-dark px-2" id="BrowseDatabaseByTagDropdown"></div></div><div class="btn-group mr-2 hide"><button data-href='{"cmd": "gotoTagList", "options": []}' id="btnBrowseDatabaseTag" type="button" class="btn btn-secondary">&laquo; Artists</button></div><div class="btn-group mr-2"><button id="BrowseDatabaseFilter" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">Filter</button><div class="dropdown-menu bg-dark px-2 letters" id="BrowseDatabaseFilterLetters"></div></div><div class="input-group mr-2 hide"><div class="input-group-prepend"><button data-href='{"cmd": "addAllFromBrowseDatabase", "options": []}' id="BrowseDatabaseAddAllSongs" class="btn btn-secondary">Add all</button><button id="BrowseDatabaseAddAllSongsBtn" class="btn btn-secondary dropdown-toggle dropdown-toggle-split rounded-right" type="button" data-toggle="dropdown"></button><div class="dropdown-menu bg-dark dropdown-menu-right px-2" id="BrowseDatabaseAddAllSongsDropdown"><button type="button" class="btn btn-secondary btn-sm btn-block">Add all to queue</button><button type="button" class="btn btn-secondary btn-sm btn-block">Add all to playlist</button></div></div></div><div id="BrowseDatabasePaginationTop" class="btn-group mr-2 hide"><button data-href='{"cmd": "gotoPage", "options": ["prev"]}' id="BrowseDatabasePaginationTopPrev" title="Previous Page" type="button" class="btn btn-secondary">&laquo;</button><div class="input-group-append"><button id="BrowseDatabasePaginationTopPage" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">1 / 1</button><div class="dropdown-menu bg-dark px-2 pages" id="BrowseDatabasePaginationTopPages"></div></div><button data-href='{"cmd": "gotoPage", "options": ["next"]}' id="BrowseDatabasePaginationTopNext" title="Next Page" type="button" class="btn btn-secondary input-group-append">&raquo;</button></div></div><div class="table-responsive-md"><table id="BrowseDatabaseTagList" class="table table-hover table-sm"><col class="tblnum"/><col class="tbltitle"/><thead><tr><th></th><th>Artist</th></tr></thead><tbody class="clickable"></tbody></table></div><div id="BrowseDatabaseAlbumList" class="row hide"><h2 id="BrowseDatabaseAlbumListCaption"></h2></div><div class="btn-toolbar hide" id="BrowseDatabaseButtonsBottom"><div class="btn-group mr-2"><button type="button" class="btn btn-secondary material-icons" data-href='{"cmd": "scrollTo", "options": [0]}' title="To top">keyboard_arrow_up</button></div><div id="BrowseDatabasePaginationBottom" class="btn-group mr-2 dropup"><button data-href='{"cmd": "gotoPage", "options": ["prev"]}' id="BrowseDatabasePaginationBottomPrev" title="Previous Page" type="button" class="btn btn-secondary">&laquo;</button><div class="input-group-append"><button id="BrowseDatabasePaginationBottomPage" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">1 / 1</button><div class="dropdown-menu bg-dark px-2 pages" id="BrowseDatabasePaginationBottomPages"></div></div><button data-href='{"cmd": "gotoPage", "options": ["next"]}' id="BrowseDatabasePaginationBottomNext" title="Next Page" type="button" class="btn btn-secondary input-group-append">&raquo;</button></div></div></div><div class="card-body hide" id="cardBrowseFilesystem"><div class="btn-toolbar card-toolbar" id="BrowseFilesystemButtons"><div class="btn-group mr-2"><button id="BrowseFilesystemFilter" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">Filter</button><div class="dropdown-menu bg-dark px-2 letters" id="BrowseFilesystemFilterLetters"></div></div><div class="input-group mr-2"><div class="input-group-prepend"><button data-href='{"cmd": "addAllFromBrowseFilesystem", "options": []}' id="BrowseFilesystemAddAllSongs" class="btn btn-secondary">Add all</button><button id="BrowseFilesystemAddAllSongsBtn" class="btn btn-secondary dropdown-toggle dropdown-toggle-split rounded-right" type="button" data-toggle="dropdown"></button><div class="dropdown-menu bg-dark dropdown-menu-right px-2" id="BrowseFilesystemAddAllSongsDropdown"><button type="button" class="btn btn-secondary btn-sm btn-block">Add all to queue</button><button type="button" class="btn btn-secondary btn-sm btn-block">Add all to playlist</button></div></div></div><div id="BrowseFilesystemPaginationTop" class="btn-group mr-2 hide"><button data-href='{"cmd": "gotoPage", "options": ["prev"]}' id="BrowseFilesystemPaginationTopPrev" title="Previous Page" type="button" class="btn btn-secondary">&laquo;</button><div class="input-group-append"><button id="BrowseFilesystemPaginationTopPage" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">1 / 1</button><div class="dropdown-menu bg-dark px-2 pages" id="BrowseFilesystemPaginationTopPages"></div></div><button data-href='{"cmd": "gotoPage", "options": ["next"]}' id="BrowseFilesystemPaginationTopNext" title="Next Page" type="button" class="btn btn-secondary input-group-append">&raquo;</button></div></div><ol id="BrowseBreadcrumb" class="breadcrumb"></ol><div class="table-responsive-md"><table id="BrowseFilesystemList" class="table table-hover table-sm"><col class="tblnum"/><col class="tbltitle"/><col class="tblartist"/><col class="tblalbum"/><col class="tbllength"/><col class="tblaction"/><thead><tr><th></th><th>Title</th><th>Artist</th><th>Album</th><th>Duration</th><th></th></tr></thead><tbody class="clickable"></tbody></table></div><div class="btn-toolbar hide" id="BrowseFilesystemButtonsBottom"><div class="btn-group mr-2"><button type="button" class="btn btn-secondary material-icons" data-href='{"cmd": "scrollTo", "options": [0]}' title="To top">keyboard_arrow_up</button></div><div id="BrowseFilesystemPaginationBottom" class="btn-group mr-2 dropup"><button data-href='{"cmd": "gotoPage", "options": ["prev"]}' id="BrowseFilesystemPaginationBottomPrev" title="Previous Page" type="button" class="btn btn-secondary">&laquo;</button><div class="input-group-append"><button id="BrowseFilesystemPaginationBottomPage" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">1 / 1</button><div class="dropdown-menu bg-dark px-2 pages" id="BrowseFilesystemPaginationBottomPages"></div></div><button data-href='{"cmd": "gotoPage", "options": ["next"]}' id="BrowseFilesystemPaginationBottomNext" title="Next Page" type="button" class="btn btn-secondary input-group-append">&raquo;</button></div></div></div></div><div class="card hide" id="cardSearch"><div class="card-header">Search<span id="panel-heading-search" class="text pull-right"></span></div><div class="card-body"><div class="btn-toolbar card-toolbar" id="SearchButtons"><form id="search"><div class="input-group mr-2"><input type="text" class="form-control" placeholder="Search" id="searchstr"/><div class="input-group-append"><button title="Select tags to search" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown"><span class="material-icons">search</span><span id="searchtagsdesc">Any Tag</span></button><div class="dropdown-menu bg-dark dropdown-menu-right px-2" id="searchtags"></div></div></div></form><div class="input-group mr-2"><div class="input-group-prepend"><button id="searchAddAllSongs" class="btn btn-secondary" data-href='{"cmd": "addAllFromSearch", "options": []}'>Add all</button><button id="searchAddAllSongsBtn" class="btn btn-secondary dropdown-toggle dropdown-toggle-split rounded-right" type="button" data-toggle="dropdown"></button><div class="dropdown-menu bg-dark dropdown-menu-right px-2" id="searchAddAllSongsDropdown"><button type="button" class="btn btn-secondary btn-sm btn-block">Add all to queue</button><button type="button" class="btn btn-secondary btn-sm btn-block">Add all to playlist</button></div></div></div><div id="SearchPaginationTop" class="btn-group mr-2 hide"><button data-href='{"cmd": "gotoPage", "options": ["prev"]}' id="SearchPaginationTopPrev" title="Previous Page" type="button" class="btn btn-secondary">&laquo;</button><div class="input-group-append"><button id="SearchPaginationTopPage" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">1 / 1</button><div class="dropdown-menu bg-dark px-2 pages" id="SearchPaginationTopPages"></div></div><button data-href='{"cmd": "gotoPage", "options": ["next"]}' id="SearchPaginationTopNext" title="Next Page" type="button" class="btn btn-secondary input-group-append">&raquo;</button></div></div><div class="table-responsive-md"><table id="SearchList" class="table table-hover table-sm"><col class="tblnum"/><col class="tbltitle"/><col class="tblartist"/><col class="tblalbum"/><col class="tbllength"/><col class="tblaction"/><thead><tr><th></th><th>Title</th><th>Artist</th><th>Album</th><th>Duration</th><th></th></tr></thead><tbody class="clickable"></tbody></table></div><div class="btn-toolbar hide" id="SearchButtonsBottom"><div class="btn-group mr-2"><button type="button" class="btn btn-secondary material-icons" data-href='{"cmd": "scrollTo", "options": [0]}' title="To top">keyboard_arrow_up</button></div><div id="SearchPaginationBottom" class="btn-group mr-2 dropup"><button data-href='{"cmd": "gotoPage", "options": ["prev"]}' id="SearchPaginationBottomPrev" title="Previous Page" type="button" class="btn btn-secondary">&laquo;</button><div class="input-group-append"><button id="SearchPaginationBottomPage" class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">1 / 1</button><div class="dropdown-menu bg-dark px-2 pages" id="SearchPaginationBottomPages"></div></div><button data-href='{"cmd": "gotoPage", "options": ["next"]}' id="SearchPaginationBottomNext" title="Next Page" type="button" class="btn btn-secondary input-group-append">&raquo;</button></div></div></div></div></main><footer class="footer"><nav class="navbar navbar-expand navbar-dark fixed-bottom bg-dark"><div class="d-flex flex-fill navbar-nav" id="navbar-bottom"><div id="navPlayback" class="nav-item flex-fill text-center"><a data-href='{"cmd": "appGoto", "options": ["Playback"]}' class="nav-link" href="#">Playback</a></div><div id="navQueue" class="nav-item flex-fill text-center"><a data-href='{"cmd": "appGoto", "options": ["Queue"]}' class="nav-link" href="#">Queue</a></div><div class="nav-item flex-fill text-center" id="navBrowse"><a data-href='{"cmd": "appGoto", "options": ["Browse"]}' class="nav-link" href="#">Browse</a></div><div class="nav-item flex-fill text-center" id="navSearch"><a data-href='{"cmd": "appGoto", "options": ["Search"]}' class="nav-link" href="#">Search</a></div></div></nav></footer><!-- Modals --><div class="modal fade" id="modalConnectionError" tabindex="-1"><div class="modal-dialog"><div class="modal-content"><div class="modal-header bg-danger text-light"><h5 class="modal-title"><span class="material-icons title-icon">error</span> Connection Error</h5></div><div class="modal-body"><p>Connection to myMPD failed. Trying to reconnect.</p></div></div></div></div><div class="modal fade" id="modalUpdateDB" tabindex="-1"><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><h5 class="modal-title"><span class="material-icons title-icon">update</span> Updating MPD database</h5><button type="button" class="close" data-dismiss="modal">&times;</button></div><div class="modal-body"><p>Dependent on the size of your music collection this can take a while.</p><div class="progress"><div id="updateDBprogress" class="progress-bar bg-success" role="progressbar"></div></div><br/><p id="updateDBfinished"></p></div><div class="modal-footer hide" id="updateDBfooter"><button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button></div></div></div></div><div class="modal fade" id="modalAddToPlaylist" tabindex="-1"><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><h5 class="modal-title"><span class="material-icons title-icon">playlist_add</span> <span id="addToPlaylistLabel">Add to playlist</span></h5><button type="button" class="close" data-dismiss="modal">&times;</button></div><div class="modal-body"><form id="addStreamFrm" class="needs-validation hide" novalidate><div class="row"><div class="form-group col-md-12"><label class="control-label" for="streamUrl">Stream URL</label><input type="text" class="form-control" id="streamUrl" placeholder="http://uri.to/stream.mp3"/><div class="invalid-feedback">Invalid uri</div></div></div><div class="row"><div class="form-group col-md-12"><button id="toggleAddToPlaylistBtn" class="btn btn-secondary" data-href='{"cmd": "toggleAddToPlaylistFrm", "options":[]}'>Add to playlist</button></div></div></form><form class="needs-validation hide" id="addToPlaylistFrm" novalidate><input type="hidden" id="addToPlaylistUri"/><div class="form-group"><label for="addToPlaylistPlaylist">Playlist</label><select id="addToPlaylistPlaylist" class="form-control custom-select"></select><div class="invalid-feedback">Please choose playlist.</div></div><div class="form-group hide" id="addToPlaylistNewPlaylistDiv"><label for="addToPlaylistNewPlaylist">Create Playlist</label><input id="addToPlaylistNewPlaylist" class="form-control"/><div class="invalid-feedback">Invalid filename.</div></div></form></div><div class="modal-footer" id="addToPlaylistFooter"><button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button><button type="button" class="btn btn-success" data-href='{"cmd": "addToPlaylist", "options": []}'>Add</button></div><div class="modal-footer hide" id="addStreamFooter"><button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button><button type="button" class="btn btn-success" data-href='{"cmd": "addStream", "options": []}'>Add</button></div></div></div></div><div class="modal fade" id="modalRenamePlaylist" tabindex="-1"><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><h5 class="modal-title"><span class="material-icons title-icon">playlist_add</span>Rename playlist</h5><button type="button" class="close" data-dismiss="modal">&times;</button></div><div class="modal-body"><form class="needs-validation" id="renamePlaylistFrm" novalidate><div class="form-group"><label for="renamePlaylistFrom">From</label><input type="text" class="form-control" id="renamePlaylistFrom" readonly></div><div class="form-group"><label for="renamePlaylistTo">To</label><input type="text" class="form-control" id="renamePlaylistTo"/><div class="invalid-feedback">Invalid filename.</div></div></form></div><div class="modal-footer"><button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button><button type="button" class="btn btn-success" data-href='{"cmd": "renamePlaylist", "options": []}'>Save</button></div></div></div></div><div class="modal fade" id="modalSettings" tabindex="-1"><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><h5 class="modal-title" id="settingsLabel"><span class="material-icons title-icon">settings</span> Settings</h5><button type="button" class="close" data-dismiss="modal">&times;</button></div><div class="modal-body"><form class="needs-validation" id="settingsFrm" novalidate><h4>MPD</h4><div class="row"><div class="form-group col-md-6"><button data-href='{"cmd":"toggleBtn", "options":["btnRandom"]}' id="btnRandom" type="button" class="btn btn-secondary btn-block" title="Random">Random</button></div><div class="form-group col-md-6" data-toggle="buttons"><button data-href='{"cmd": "toggleBtn", "options": ["btnConsume"]}' id="btnConsume" type="button" class="btn btn-secondary btn-block" title="Consume">Consume</button></div></div><div class="row"><div class="form-group col-md-6" data-toggle="buttons"><button data-href='{"cmd": "toggleBtn", "options": ["btnSingle"]}' id="btnSingle" type="button" class="btn btn-secondary btn-block" title="Single">Single</button></div><div class="form-group col-md-6" data-toggle="buttons"><button data-href='{"cmd": "toggleBtn", "options": ["btnRepeat"]}' id="btnRepeat" type="button" class="btn btn-secondary btn-block" title="Repeat">Repeat</button></div></div><div class="row"><div class="form-group input-group col-md-6 border-secondary"><div class="input-group-prepend"><div class="input-group-text bg-secondary text-light border-secondary">Crossfade</div></div><input id="inputCrossfade" type="text" class="form-control border-secondary" value=""><div class="invalid-feedback">Must be a number.</div></div><div class="form-group input-group col-md-6 border-secondary"><div class="input-group-prepend"><div class="input-group-text bg-secondary text-light border-secondary">Replaygain</div></div><select id="selectReplaygain" class="form-control custom-select border-secondary"><option value="off">Off</option><option value="track">Track</option><option value="album">Album</option></select></div></div><div class="row mixramp"><div class="form-group input-group col-md-6 border-secondary"><div class="input-group-prepend"><div class="input-group-text bg-secondary text-light border-secondary">Mixramp DB</div></div><input id="inputMixrampdb" type="text" class="form-control border-secondary" value=""><div class="invalid-feedback">Must be a number.</div></div><div class="form-group input-group col-md-6 border-secondary"><div class="input-group-prepend"><div class="input-group-text bg-secondary text-light border-secondary">Mixramp Delay</div></div><input id="inputMixrampdelay" type="text" class="form-control border-secondary" value=""><div class="invalid-feedback">Must be a number.</div></div></div><hr/><h4>Jukebox</h4><div class="row"><div class="form-group col-md-6" data-toggle="buttons"><button data-href='{"cmd": "toggleBtn", "options": ["btnJukebox"]}' id="btnJukebox" type="button" class="btn btn-secondary btn-block" title="Jukebox">Jukebox</button></div><div class="form-group input-group col-md-6 border-secondary"><select id="jukeboxPlaylist" class="form-control custom-select border-secondary"></select></div></div><hr/><h4>Notifications</h4><div class="row"><div class="form-group col-md-6" data-toggle="buttons"><button data-href='{"cmd": "toggleBtn", "options": ["btnnotifyPage"]}' type="button" class="btn btn-secondary btn-block" id="btnnotifyPage">Page Notifications</button></div><div class="form-group col-md-6" data-toggle="buttons"><button data-href='{"cmd": "toggleBtn", "options": ["btnnotifyWeb"]}' type="button" class="btn btn-secondary btn-block" id="btnnotifyWeb">Web Notifications</button></div></div></form></div><div class="modal-footer"><button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button><button type="button" class="btn btn-success" data-href='{"cmd": "confirmSettings", "options": []}'>Save</button></div></div></div></div><div class="modal fade" id="modalAbout" tabindex="-1"><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><h5 class="modal-title" id="aboutLabel"><span class="material-icons title-icon">play_circle_outline</span> About</h5><button type="button" class="close" data-dismiss="modal">&times;</button></div><div class="modal-body"><h4><a class="text-success" rel="noreferrer" href="https://github.com/jcorporation/ympd">myMPD</a>&nbsp;&ndash;&nbsp;<small>MPD Web GUI - written in C, utilizing Websockets and Bootstrap/JS</small></h4><p>myMPD is a lightweight MPD web client that runs without a dedicated webserver or interpreter. It's tuned for minimal resource usage and requires only very litte dependencies. myMPD is a fork of <a class="text-success" href="http://www.ympd.org">ympd</a>.</p><ul><li>Version: <span id="mympdVersion"></span></li><li>Homepage: <a class="text-success" target="_blank" rel="noreferrer" href="https://github.com/jcorporation/mympd">https://github.com/jcorporation/mympd</a></li><li>Autor: Jürgen Mang &lt;<a class="text-success" href="mailto:mail@jcgames.de">mail@jcgames.de</a>&gt;</li></ul><table class="table table-sm"><tbody><tr><td colspan="2" class="pt-3"><h5>Database Statistics</h5></td></tr><tr><th>Artists</th><td id="mpdstats_artists"></td></tr><tr><th>Albums</th><td id="mpdstats_albums"></td></tr><tr><th>Songs</th><td id="mpdstats_songs"></td></tr><tr><th>DB Play Time</th><td id="mpdstats_dbPlaytime"></td></tr><tr><th>DB Updated</th><td id="mpdstats_dbUpdated"></td></tr><tr><td colspan="2" class="pt-3"><h5>Play Statistics</h5></td></tr><tr><th>Uptime</th><td id="mpdstats_uptime"></td></tr><tr><th>Play Time</th><td id="mpdstats_playtime"></td></tr><tr><td colspan="2" class="pt-3"><h5>MPD</h5></td></tr><tr><th>Protocol Version</th><td id="mpdVersion"></td></tr></tbody></table></div></div></div></div><div class="modal fade" id="modalSaveQueue" tabindex="-1"><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><h5 class="modal-title"><span class="material-icons title-icon">save</span> Save Queue</h5><button type="button" class="close" data-dismiss="modal">&times;</button></div><div class="modal-body"><form class="needs-validation" id="saveQueueFrm" novalidate><div class="row"><div class="form-group col-md-9"><label class="control-label" for="saveQueueName">Playlist Name</label><input type="text" class="form-control" id="saveQueueName"/><div class="invalid-feedback">Invalid filename</div></div></div></form></div><div class="modal-footer"><button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button><button type="button" class="btn btn-success" data-href='{"cmd": "saveQueue", "options": []}'>Save Queue</button></div></div></div></div><div class="modal fade" id="modalSongDetails" tabindex="-1"><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><h5 class="modal-title"><span class="material-icons title-icon">music_note</span> Song Details</h5><button type="button" class="close" data-dismiss="modal">&times;</button></div><div class="modal-body"><div class="album-cover"></div><h1></h1><div class="table-responsive-md"><table class="table table-sm"><tbody></tbody></table></div></div><div class="modal-footer"><button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button></div></div></div></div><script src="/js/bootstrap-native-v4.min.js"></script><script src="/js/mympd.min.js"></script></body></html>
\ No newline at end of file
diff --git a/dist/htdocs/js/mympd.min.js b/dist/htdocs/js/mympd.min.js
index 451bc1f..d1b7331 100644
--- a/dist/htdocs/js/mympd.min.js
+++ b/dist/htdocs/js/mympd.min.js
@@ -26,22 +26,23 @@ if("Playback"==app.current.app)sendAPI({cmd:"MPD_API_PLAYER_CURRENT_SONG"},songC
 app.last.app!=app.current.app&&""!=app.current.search&&(document.getElementById("SearchList").getElementsByTagName("tbody")[0].innerHTML='<tr><td><span class="material-icons">search</span></td><td colspan="5">Searching...</td></tr>'),2<=app.current.search.length?sendAPI({cmd:"MPD_API_DATABASE_SEARCH",data:{plist:"",offset:app.current.page,filter:app.current.filter,searchstr:app.current.search}},parseSearch):(document.getElementById("SearchList").getElementsByTagName("tbody")[0].innerHTML="",document.getElementById("searchAddAllSongs").setAttribute("disabled",
 "disabled"),document.getElementById("searchAddAllSongsBtn").setAttribute("disabled","disabled"),document.getElementById("panel-heading-search").innerText="",document.getElementById("SearchList").classList.remove("opacity05"),setPagination(0)),selectTag("searchtags","searchtagsdesc",app.current.filter)):appGoto("Playback");app.last.app=app.current.app;app.last.tab=app.current.tab;app.last.view=app.current.view}else appGoto("Playback")}
 function appInit(){getSettings();sendAPI({cmd:"MPD_API_PLAYER_STATE"},parseState);webSocketConnect();domCache.volumeBar.value=0;domCache.volumeBar.addEventListener("click",function(a){a.stopPropagation()},!1);domCache.volumeBar.addEventListener("change",function(a){sendAPI({cmd:"MPD_API_PLAYER_VOLUME",data:{volume:domCache.volumeBar.value}})},!1);domCache.progressBar.value=0;domCache.progressBar.addEventListener("change",function(a){currentSong&&0<=currentSong.currentSongId&&sendAPI({cmd:"MPD_API_PLAYER_SEEK",
-data:{songid:currentSong.currentSongId,seek:Math.ceil(domCache.progressBar.value/100*currentSong.totalTime)}})},!1);document.getElementById("volumeIcon").parentNode.addEventListener("show.bs.dropdown",function(){sendAPI({cmd:"MPD_API_PLAYER_OUTPUT_LIST"},parseOutputs)});document.getElementById("modalAbout").addEventListener("shown.bs.modal",function(){sendAPI({cmd:"MPD_API_DATABASE_STATS"},parseStats)});document.getElementById("modalUpdateDB").addEventListener("hidden.bs.modal",function(){document.getElementById("updateDBprogress").classList.remove("updateDBprogressAnimate")});
-document.getElementById("modalSaveQueue").addEventListener("shown.bs.modal",function(){var a=document.getElementById("saveQueueName");a.focus();a.value="";a.classList.remove("is-invalid");document.getElementById("saveQueueFrm").classList.remove("was-validated")});document.getElementById("modalSettings").addEventListener("shown.bs.modal",function(){getSettings();document.getElementById("settingsFrm").classList.remove("was-validated");document.getElementById("inputCrossfade").classList.remove("is-invalid");
-document.getElementById("inputMixrampdb").classList.remove("is-invalid");document.getElementById("inputMixrampdelay").classList.remove("is-invalid")});document.getElementById("addToPlaylistPlaylist").addEventListener("change",function(a){"New Playlist"==this.options[this.selectedIndex].text?(document.getElementById("addToPlaylistNewPlaylistDiv").classList.remove("hide"),document.getElementById("addToPlaylistNewPlaylist").focus()):document.getElementById("addToPlaylistNewPlaylistDiv").classList.add("hide")},
-!1);addFilterLetter("BrowseFilesystemFilterLetters");addFilterLetter("BrowseDatabaseFilterLetters");addFilterLetter("BrowsePlaylistsFilterLetters");for(var a=document.querySelectorAll("[data-href]"),b=a.length,c=0;c<b;c++)a[c].classList.add("clickable"),a[c].addEventListener("click",function(a){a.preventDefault();a=JSON.parse(this.getAttribute("data-href"));if("function"===typeof window[a.cmd])switch(a.cmd){case "sendAPI":sendAPI.apply(null,$jscomp.arrayFromIterable(a.options));break;default:window[a.cmd].apply(null,
-$jscomp.arrayFromIterable(a.options))}},!1);a=document.getElementsByClassName("pages");b=a.length;for(c=0;c<b;c++)a[c].addEventListener("click",function(a){"BUTTON"==a.target.nodeName&&gotoPage(a.target.getAttribute("data-page"))},!1);document.getElementById("outputs").addEventListener("click",function(a){"BUTTON"==a.target.nodeName&&a.stopPropagation();sendAPI({cmd:"MPD_API_PLAYER_TOGGLE_OUTPUT",data:{output:a.target.getAttribute("data-output-id"),state:a.target.classList.contains("active")?0:1}});
-toggleBtn(a.target.id)},!1);document.getElementById("QueueList").addEventListener("click",function(a){"TD"==a.target.nodeName?sendAPI({cmd:"MPD_API_PLAYER_PLAY_TRACK",data:{track:a.target.parentNode.getAttribute("data-trackid")}}):"A"==a.target.nodeName&&showMenu(a.target,a)},!1);document.getElementById("BrowseFilesystemList").addEventListener("click",function(a){if("TD"==a.target.nodeName)switch(a.target.parentNode.getAttribute("data-type")){case "dir":appGoto("Browse","Filesystem",void 0,"0/"+app.current.filter+
-"/"+decodeURI(a.target.parentNode.getAttribute("data-uri")));break;case "song":appendQueue("song",decodeURI(a.target.parentNode.getAttribute("data-uri")),a.target.parentNode.getAttribute("data-name"));break;case "plist":appendQueue("plist",decodeURI(a.target.parentNode.getAttribute("data-uri")),a.target.parentNode.getAttribute("data-name"))}else"A"==a.target.nodeName&&showMenu(a.target,a)},!1);document.getElementById("BrowsePlaylistsAllList").addEventListener("click",function(a){"TD"==a.target.nodeName?
-appendQueue("plist",decodeURI(a.target.parentNode.getAttribute("data-uri")),a.target.parentNode.getAttribute("data-name")):"A"==a.target.nodeName&&showMenu(a.target,a)},!1);document.getElementById("BrowsePlaylistsDetailList").addEventListener("click",function(a){"TD"==a.target.nodeName?appendQueue("plist",decodeURI(a.target.parentNode.getAttribute("data-uri")),a.target.parentNode.getAttribute("data-name")):"A"==a.target.nodeName&&showMenu(a.target,a)},!1);document.getElementById("BrowseDatabaseTagList").addEventListener("click",
-function(a){"TD"==a.target.nodeName&&appGoto("Browse","Database",app.current.view,"0/-/"+a.target.parentNode.getAttribute("data-uri"))},!1);document.getElementById("SearchList").addEventListener("click",function(a){"TD"==a.target.nodeName?appendQueue("song",decodeURI(a.target.parentNode.getAttribute("data-uri")),a.target.parentNode.getAttribute("data-name")):"A"==a.target.nodeName&&showMenu(a.target,a)},!1);document.getElementById("BrowseFilesystemAddAllSongsDropdown").addEventListener("click",function(a){"BUTTON"==
-a.target.nodeName&&("Add all to queue"==a.target.innerText?addAllFromBrowse():"Add all to playlist"==a.target.innerText&&showAddToPlaylist(app.current.search))},!1);document.getElementById("searchAddAllSongsDropdown").addEventListener("click",function(a){"BUTTON"==a.target.nodeName&&("Add all to queue"==a.target.innerText?addAllFromSearchPlist("queue"):"Add all to playlist"==a.target.innerText&&showAddToPlaylist("SEARCH"))},!1);document.getElementById("BrowseDatabaseAddAllSongsDropdown").addEventListener("click",
-function(a){"BUTTON"==a.target.nodeName&&("Add all to queue"==a.target.innerText?addAllFromBrowseDatabasePlist("queue"):"Add all to playlist"==a.target.innerText&&showAddToPlaylist("DATABASE"))},!1);document.getElementById("searchtags").addEventListener("click",function(a){"BUTTON"==a.target.nodeName&&appGoto(app.current.app,app.current.tab,app.current.view,"0/"+a.target.getAttribute("data-tag")+"/"+app.current.search)},!1);document.getElementById("searchqueuestr").addEventListener("keyup",function(a){appGoto(app.current.app,
-app.current.tab,app.current.view,"0/"+app.current.filter+"/"+this.value)},!1);document.getElementById("searchqueuetag").addEventListener("click",function(a){"BUTTON"==a.target.nodeName&&appGoto(app.current.app,app.current.tab,app.current.view,app.current.page+"/"+a.target.getAttribute("data-tag")+"/"+app.current.search)},!1);document.getElementById("search").addEventListener("submit",function(){return!1},!1);document.getElementById("searchqueue").addEventListener("submit",function(){return!1},!1);
-document.getElementById("searchstr").addEventListener("keyup",function(a){appGoto("Search",void 0,void 0,"0/"+app.current.filter+"/"+this.value)},!1);document.getElementById("BrowseDatabaseByTagDropdown").addEventListener("click",function(a){"BUTTON"==a.target.nodeName&&appGoto(app.current.app,app.current.tab,a.target.getAttribute("data-tag"),"0/"+app.current.filter+"/"+app.current.search)},!1);document.getElementsByTagName("body")[0].addEventListener("click",function(a){a=document.getElementsByClassName("popover");
-for(var b=0;b<a.length;b++)a[b].remove()},!1);dragAndDropTable("QueueList");dragAndDropTable("BrowsePlaylistsDetailList");window.addEventListener("hashchange",appRoute,!1);window.addEventListener("focus",function(){sendAPI({cmd:"MPD_API_PLAYER_STATE"},parseState)},!1);document.addEventListener("keydown",function(a){if("INPUT"!=a.target.tagName){switch(a.which){case 37:clickPrev();break;case 39:clickNext();break;case 32:clickPlay();break;default:return}a.preventDefault()}},!1);"serviceWorker"in navigator&&
-"https"==document.URL.substring(0,5)&&window.addEventListener("load",function(){navigator.serviceWorker.register("/sw.min.js",{scope:"/"}).then(function(a){console.log("ServiceWorker registration successful with scope: ",a.scope);a.update()},function(a){console.log("ServiceWorker registration failed: ",a)})});window.addEventListener("beforeinstallprompt",function(a){a.preventDefault();deferredPrompt=a});window.addEventListener("beforeinstallprompt",function(a){a.preventDefault();deferredPrompt=a;
-domCache.btnAdd.classList.remove("hide")});domCache.btnAdd.addEventListener("click",function(a){domCache.btnAdd.classList.add("hide");deferredPrompt.prompt();deferredPrompt.userChoice.then(function(a){"accepted"===a.outcome?console.log("User accepted the A2HS prompt"):console.log("User dismissed the A2HS prompt");deferredPrompt=null})});window.addEventListener("appinstalled",function(a){console.log("myMPD installed as app")})}
+data:{songid:currentSong.currentSongId,seek:Math.ceil(domCache.progressBar.value/100*currentSong.totalTime)}})},!1);document.getElementById("navDBupdate").addEventListener("click",function(a){a.stopPropagation();a.preventDefault();a=this.getElementsByTagName("span")[0];a.innerText="keyboard_arrow_right"==a.innerText?"keyboard_arrow_down":"keyboard_arrow_right"},!1);document.getElementById("volumeIcon").parentNode.addEventListener("show.bs.dropdown",function(){sendAPI({cmd:"MPD_API_PLAYER_OUTPUT_LIST"},
+parseOutputs)});document.getElementById("modalAbout").addEventListener("shown.bs.modal",function(){sendAPI({cmd:"MPD_API_DATABASE_STATS"},parseStats)});document.getElementById("modalUpdateDB").addEventListener("hidden.bs.modal",function(){document.getElementById("updateDBprogress").classList.remove("updateDBprogressAnimate")});document.getElementById("modalSaveQueue").addEventListener("shown.bs.modal",function(){var a=document.getElementById("saveQueueName");a.focus();a.value="";a.classList.remove("is-invalid");
+document.getElementById("saveQueueFrm").classList.remove("was-validated")});document.getElementById("modalSettings").addEventListener("shown.bs.modal",function(){getSettings();document.getElementById("settingsFrm").classList.remove("was-validated");document.getElementById("inputCrossfade").classList.remove("is-invalid");document.getElementById("inputMixrampdb").classList.remove("is-invalid");document.getElementById("inputMixrampdelay").classList.remove("is-invalid")});document.getElementById("addToPlaylistPlaylist").addEventListener("change",
+function(a){"New Playlist"==this.options[this.selectedIndex].text?(document.getElementById("addToPlaylistNewPlaylistDiv").classList.remove("hide"),document.getElementById("addToPlaylistNewPlaylist").focus()):document.getElementById("addToPlaylistNewPlaylistDiv").classList.add("hide")},!1);addFilterLetter("BrowseFilesystemFilterLetters");addFilterLetter("BrowseDatabaseFilterLetters");addFilterLetter("BrowsePlaylistsFilterLetters");for(var a=document.querySelectorAll("[data-href]"),b=a.length,c=0;c<
+b;c++)a[c].classList.add("clickable"),a[c].addEventListener("click",function(a){a.preventDefault();a=JSON.parse(this.getAttribute("data-href"));if("function"===typeof window[a.cmd])switch(a.cmd){case "sendAPI":sendAPI.apply(null,$jscomp.arrayFromIterable(a.options));break;default:window[a.cmd].apply(null,$jscomp.arrayFromIterable(a.options))}},!1);a=document.getElementsByClassName("pages");b=a.length;for(c=0;c<b;c++)a[c].addEventListener("click",function(a){"BUTTON"==a.target.nodeName&&gotoPage(a.target.getAttribute("data-page"))},
+!1);document.getElementById("outputs").addEventListener("click",function(a){"BUTTON"==a.target.nodeName&&a.stopPropagation();sendAPI({cmd:"MPD_API_PLAYER_TOGGLE_OUTPUT",data:{output:a.target.getAttribute("data-output-id"),state:a.target.classList.contains("active")?0:1}});toggleBtn(a.target.id)},!1);document.getElementById("QueueList").addEventListener("click",function(a){"TD"==a.target.nodeName?sendAPI({cmd:"MPD_API_PLAYER_PLAY_TRACK",data:{track:a.target.parentNode.getAttribute("data-trackid")}}):
+"A"==a.target.nodeName&&showMenu(a.target,a)},!1);document.getElementById("BrowseFilesystemList").addEventListener("click",function(a){if("TD"==a.target.nodeName)switch(a.target.parentNode.getAttribute("data-type")){case "dir":appGoto("Browse","Filesystem",void 0,"0/"+app.current.filter+"/"+decodeURI(a.target.parentNode.getAttribute("data-uri")));break;case "song":appendQueue("song",decodeURI(a.target.parentNode.getAttribute("data-uri")),a.target.parentNode.getAttribute("data-name"));break;case "plist":appendQueue("plist",
+decodeURI(a.target.parentNode.getAttribute("data-uri")),a.target.parentNode.getAttribute("data-name"))}else"A"==a.target.nodeName&&showMenu(a.target,a)},!1);document.getElementById("BrowsePlaylistsAllList").addEventListener("click",function(a){"TD"==a.target.nodeName?appendQueue("plist",decodeURI(a.target.parentNode.getAttribute("data-uri")),a.target.parentNode.getAttribute("data-name")):"A"==a.target.nodeName&&showMenu(a.target,a)},!1);document.getElementById("BrowsePlaylistsDetailList").addEventListener("click",
+function(a){"TD"==a.target.nodeName?appendQueue("plist",decodeURI(a.target.parentNode.getAttribute("data-uri")),a.target.parentNode.getAttribute("data-name")):"A"==a.target.nodeName&&showMenu(a.target,a)},!1);document.getElementById("BrowseDatabaseTagList").addEventListener("click",function(a){"TD"==a.target.nodeName&&appGoto("Browse","Database",app.current.view,"0/-/"+a.target.parentNode.getAttribute("data-uri"))},!1);document.getElementById("SearchList").addEventListener("click",function(a){"TD"==
+a.target.nodeName?appendQueue("song",decodeURI(a.target.parentNode.getAttribute("data-uri")),a.target.parentNode.getAttribute("data-name")):"A"==a.target.nodeName&&showMenu(a.target,a)},!1);document.getElementById("BrowseFilesystemAddAllSongsDropdown").addEventListener("click",function(a){"BUTTON"==a.target.nodeName&&("Add all to queue"==a.target.innerText?addAllFromBrowse():"Add all to playlist"==a.target.innerText&&showAddToPlaylist(app.current.search))},!1);document.getElementById("searchAddAllSongsDropdown").addEventListener("click",
+function(a){"BUTTON"==a.target.nodeName&&("Add all to queue"==a.target.innerText?addAllFromSearchPlist("queue"):"Add all to playlist"==a.target.innerText&&showAddToPlaylist("SEARCH"))},!1);document.getElementById("BrowseDatabaseAddAllSongsDropdown").addEventListener("click",function(a){"BUTTON"==a.target.nodeName&&("Add all to queue"==a.target.innerText?addAllFromBrowseDatabasePlist("queue"):"Add all to playlist"==a.target.innerText&&showAddToPlaylist("DATABASE"))},!1);document.getElementById("searchtags").addEventListener("click",
+function(a){"BUTTON"==a.target.nodeName&&appGoto(app.current.app,app.current.tab,app.current.view,"0/"+a.target.getAttribute("data-tag")+"/"+app.current.search)},!1);document.getElementById("searchqueuestr").addEventListener("keyup",function(a){appGoto(app.current.app,app.current.tab,app.current.view,"0/"+app.current.filter+"/"+this.value)},!1);document.getElementById("searchqueuetag").addEventListener("click",function(a){"BUTTON"==a.target.nodeName&&appGoto(app.current.app,app.current.tab,app.current.view,
+app.current.page+"/"+a.target.getAttribute("data-tag")+"/"+app.current.search)},!1);document.getElementById("search").addEventListener("submit",function(){return!1},!1);document.getElementById("searchqueue").addEventListener("submit",function(){return!1},!1);document.getElementById("searchstr").addEventListener("keyup",function(a){appGoto("Search",void 0,void 0,"0/"+app.current.filter+"/"+this.value)},!1);document.getElementById("BrowseDatabaseByTagDropdown").addEventListener("click",function(a){"BUTTON"==
+a.target.nodeName&&appGoto(app.current.app,app.current.tab,a.target.getAttribute("data-tag"),"0/"+app.current.filter+"/"+app.current.search)},!1);document.getElementsByTagName("body")[0].addEventListener("click",function(a){a=document.getElementsByClassName("popover");for(var b=0;b<a.length;b++)a[b].remove()},!1);dragAndDropTable("QueueList");dragAndDropTable("BrowsePlaylistsDetailList");window.addEventListener("hashchange",appRoute,!1);window.addEventListener("focus",function(){sendAPI({cmd:"MPD_API_PLAYER_STATE"},
+parseState)},!1);document.addEventListener("keydown",function(a){if("INPUT"!=a.target.tagName){switch(a.which){case 37:clickPrev();break;case 39:clickNext();break;case 32:clickPlay();break;default:return}a.preventDefault()}},!1);"serviceWorker"in navigator&&"https"==document.URL.substring(0,5)&&window.addEventListener("load",function(){navigator.serviceWorker.register("/sw.min.js",{scope:"/"}).then(function(a){console.log("ServiceWorker registration successful with scope: ",a.scope);a.update()},function(a){console.log("ServiceWorker registration failed: ",
+a)})});window.addEventListener("beforeinstallprompt",function(a){a.preventDefault();deferredPrompt=a});window.addEventListener("beforeinstallprompt",function(a){a.preventDefault();deferredPrompt=a;domCache.btnAdd.classList.remove("hide")});domCache.btnAdd.addEventListener("click",function(a){domCache.btnAdd.classList.add("hide");deferredPrompt.prompt();deferredPrompt.userChoice.then(function(a){"accepted"===a.outcome?console.log("User accepted the A2HS prompt"):console.log("User dismissed the A2HS prompt");
+deferredPrompt=null})});window.addEventListener("appinstalled",function(a){console.log("myMPD installed as app")})}
 function dragAndDropTable(a){var b=document.getElementById(a).getElementsByTagName("tbody")[0];b.addEventListener("dragstart",function(a){"TR"==a.target.nodeName&&(a.target.classList.add("opacity05"),a.dataTransfer.setDragImage(a.target,0,0),a.dataTransfer.effectAllowed="move",a.dataTransfer.setData("Text",a.target.getAttribute("id")),dragEl=a.target.cloneNode(!0))},!1);b.addEventListener("dragleave",function(a){a.preventDefault();var b=a.target;"TD"==a.target.nodeName&&(b=a.target.parentNode);"TR"==
 b.nodeName&&b.classList.remove("dragover")},!1);b.addEventListener("dragover",function(a){a.preventDefault();for(var c=b.getElementsByClassName("dragover"),e=c.length,f=0;f<e;f++)c[f].classList.remove("dragover");c=a.target;"TD"==a.target.nodeName&&(c=a.target.parentNode);"TR"==c.nodeName&&c.classList.add("dragover");a.dataTransfer.dropEffect="move"},!1);b.addEventListener("dragend",function(a){for(var c=b.getElementsByClassName("dragover"),e=c.length,f=0;f<e;f++)c[f].classList.remove("dragover");
 document.getElementById(a.dataTransfer.getData("Text"))&&document.getElementById(a.dataTransfer.getData("Text")).classList.remove("opacity05")},!1);b.addEventListener("drop",function(c){c.stopPropagation();c.preventDefault();var d=c.target;"TD"==c.target.nodeName&&(d=c.target.parentNode);var e=document.getElementById(c.dataTransfer.getData("Text")).getAttribute("data-songpos"),f=d.getAttribute("data-songpos");document.getElementById(c.dataTransfer.getData("Text")).remove();dragEl.classList.remove("opacity05");
@@ -120,7 +121,7 @@ options:[d]},"Rename playlist")+addMenuItem({cmd:"delPlaylist",options:[d]},"Del
 a.stopPropagation();if("A"==a.target.nodeName&&(a=a.target.getAttribute("data-href"))){a=JSON.parse(atob(a));if("function"===typeof window[a.cmd])switch(a.cmd){case "sendAPI":sendAPI.apply(null,$jscomp.arrayFromIterable(a.options));break;default:window[a.cmd].apply(null,$jscomp.arrayFromIterable(a.options))}g.hide()}},!1);if(a=document.getElementById("advancedMenuLink"))a.addEventListener("click",function(a){a=this.getElementsByTagName("span")[0];a.innerText="keyboard_arrow_right"==a.innerText?"keyboard_arrow_down":
 "keyboard_arrow_right"},!1),new Collapse(a)},!1));g.show()}
 function sendAPI(a,b){var c=new XMLHttpRequest;c.open("POST","/api",!0);c.setRequestHeader("Content-type","application/json");c.onreadystatechange=function(){if(4==c.readyState)if(""!=c.responseText){var d=JSON.parse(c.responseText);"error"==d.type?(showNotification("Error",d.data,d.data,"danger"),console.log("Error: "+d.data)):"result"==d.type&&"ok"!=d.data?showNotification(d.data,"","","success"):void 0!=b&&"function"==typeof b&&b(d)}else console.log("Empty response for request: "+JSON.stringify(a))};
-c.send(JSON.stringify(a))}function openLocalPlayer(){window.open("/player.html#"+settings.mpdstream,"LocalPlayer")}function updateDB(){sendAPI({cmd:"MPD_API_DATABASE_UPDATE"});updateDBstarted(!0)}
+c.send(JSON.stringify(a))}function openLocalPlayer(){window.open("/player.html#"+settings.mpdstream,"LocalPlayer")}function updateDB(){sendAPI({cmd:"MPD_API_DATABASE_UPDATE"});updateDBstarted(!0)}function rescanDB(){sendAPI({cmd:"MPD_API_DATABASE_RESCAN"});updateDBstarted(!0)}
 function updateDBstarted(a){1==a?(document.getElementById("updateDBfinished").innerText="",document.getElementById("updateDBfooter").classList.add("hide"),updateDBprogress.style.width="20px",updateDBprogress.style.marginLeft="-20px",modalUpdateDB.show(),document.getElementById("updateDBprogress").classList.add("updateDBprogressAnimate")):showNotification("Database update started","","","success")}
 function updateDBfinished(a){document.getElementById("modalUpdateDB").classList.contains("show")?("update_database"==a?document.getElementById("updateDBfinished").innerText="Database successfully updated.":"update_finished"==a&&(document.getElementById("updateDBfinished").innerText="Database update finished."),a=document.getElementById("updateDBprogress"),a.classList.remove("updateDBprogressAnimate"),a.style.width="100%",a.style.marginLeft="0px",document.getElementById("updateDBfooter").classList.remove("hide")):
 "update_database"==a?showNotification("Database successfully updated.","","","success"):"update_finished"==a&&showNotification("Database update finished.","","","success")}function clickPlay(){"play"!=playstate?sendAPI({cmd:"MPD_API_PLAYER_PLAY"}):sendAPI({cmd:"MPD_API_PLAYER_PAUSE"})}function clickStop(){sendAPI({cmd:"MPD_API_PLAYER_STOP"})}function clickPrev(){sendAPI({cmd:"MPD_API_PLAYER_PREV"})}function clickNext(){sendAPI({cmd:"MPD_API_PLAYER_NEXT"})}
diff --git a/dist/htdocs/sw.min.js b/dist/htdocs/sw.min.js
index 5fe336d..5b46321 100644
--- a/dist/htdocs/sw.min.js
+++ b/dist/htdocs/sw.min.js
@@ -11,4 +11,4 @@ void 0;try{d=a.then}catch(h){this.reject_(h);return}"function"==typeof d?this.se
 0;a<this.onSettledCallbacks_.length;++a)l.asyncExecute(this.onSettledCallbacks_[a]);this.onSettledCallbacks_=null}};var l=new b;c.prototype.settleSameAsPromise_=function(a){var b=this.createResolveAndReject_();a.callWhenSettled_(b.resolve,b.reject)};c.prototype.settleSameAsThenable_=function(a,b){var c=this.createResolveAndReject_();try{a.call(b,c.resolve,c.reject)}catch(k){c.reject(k)}};c.prototype.then=function(a,b){function d(a,b){return"function"==typeof a?function(b){try{f(a(b))}catch(m){e(m)}}:
 b}var f,e,g=new c(function(a,b){f=a;e=b});this.callWhenSettled_(d(a,f),d(b,e));return g};c.prototype.catch=function(a){return this.then(void 0,a)};c.prototype.callWhenSettled_=function(a,b){function c(){switch(d.state_){case 1:a(d.result_);break;case 2:b(d.result_);break;default:throw Error("Unexpected state: "+d.state_);}}var d=this;null==this.onSettledCallbacks_?l.asyncExecute(c):this.onSettledCallbacks_.push(c)};c.resolve=f;c.reject=function(a){return new c(function(b,c){c(a)})};c.race=function(a){return new c(function(b,
 c){for(var d=$jscomp.makeIterator(a),e=d.next();!e.done;e=d.next())f(e.value).callWhenSettled_(b,c)})};c.all=function(a){var b=$jscomp.makeIterator(a),d=b.next();return d.done?f([]):new c(function(a,c){function e(b){return function(c){g[b]=c;h--;0==h&&a(g)}}var g=[],h=0;do g.push(void 0),h++,f(d.value).callWhenSettled_(e(g.length-1),c),d=b.next();while(!d.done)})};return c},"es6","es3");var CACHE="myMPD-cache-v4.2.1",urlsToCache="/ /player.html /css/bootstrap.min.css /css/mympd.min.css /js/bootstrap-native-v4.min.js /js/mympd.min.js /js/player.min.js /assets/appicon-167.png /assets/appicon-192.png /assets/appicon-512.png /assets/coverimage-httpstream.png /assets/coverimage-notavailable.png /assets/favicon.ico /assets/MaterialIcons-Regular.eot /assets/MaterialIcons-Regular.ttf /assets/MaterialIcons-Regular.woff /assets/MaterialIcons-Regular.woff2".split(" ");
-self.addEventListener("install",function(a){a.waitUntil(caches.open(CACHE).then(function(a){return a.addAll(urlsToCache)}))});self.addEventListener("fetch",function(a){a.respondWith(caches.match(a.request).then(function(b){return b?b:fetch(a.request)}))});self.addEventListener("activate",function(a){a.waitUntil(caches.keys().then(function(a){return Promise.all(a.map(function(a){if(a!=CACHE)return caches.delete(a)}))}))});
+self.addEventListener("install",function(a){a.waitUntil(caches.open(CACHE).then(function(a){return a.addAll(urlsToCache)}))});self.addEventListener("fetch",function(a){if(a.request.url.match("^http://"))return!1;a.respondWith(caches.match(a.request).then(function(b){return b?b:fetch(a.request)}))});self.addEventListener("activate",function(a){a.waitUntil(caches.keys().then(function(a){return Promise.all(a.map(function(a){if(a!=CACHE)return caches.delete(a)}))}))});
diff --git a/htdocs/sw.js b/htdocs/sw.js
index b1d4ed4..a163b4e 100644
--- a/htdocs/sw.js
+++ b/htdocs/sw.js
@@ -3,10 +3,10 @@ var urlsToCache = [
     '/',
     '/player.html',
     '/css/bootstrap.min.css',
-    '/css/mympd.css',
+    '/css/mympd.min.css',
     '/js/bootstrap-native-v4.min.js',
-    '/js/mympd.js',
-    '/js/player.js',
+    '/js/mympd.min.js',
+    '/js/player.min.js',
     '/assets/appicon-167.png',
     '/assets/appicon-192.png',
     '/assets/appicon-512.png',