Багфиксы. Обработка особенностей поведения mopidy и mpd. Обработка пустых и малознача...
authorRoman Bazalevskiy <rvb@rvb.name>
Thu, 28 Dec 2017 17:41:17 +0000 (20:41 +0300)
committerRoman Bazalevskiy <rvb@rvb.name>
Thu, 28 Dec 2017 17:41:17 +0000 (20:41 +0300)
LICENSE [deleted file]
mpd.js
mpd.js~ [deleted file]
mpd.lua
mpd.lua~ [deleted file]

diff --git a/LICENSE b/LICENSE
deleted file mode 100644 (file)
index 456c488..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,13 +0,0 @@
-        DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 
-                    Version 2, December 2004 
-
- Copyright (C) 2004 Sam Hocevar <sam@hocevar.net> 
-
- Everyone is permitted to copy and distribute verbatim or modified 
- copies of this license document, and changing it is allowed as long 
- as the name is changed. 
-
-            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 
-
-  0. You just DO WHAT THE FUCK YOU WANT TO.
diff --git a/mpd.js b/mpd.js
index 78d9c8bb4697dd8955182c74e5476c24546930cb..b5ff51305aa12cd321aa5b7f38e3a2951246fca3 100644 (file)
--- a/mpd.js
+++ b/mpd.js
@@ -1,4 +1,4 @@
-urlbase="mpd.lua?"
+urlbase="/cgi-bin/mpd.cgi?"
 minScrollHeight=200
 
 currentState=""
@@ -48,8 +48,12 @@ function toHHMMSS(seconds) {
 function RefreshTime() {
   if (currentSeconds) {
     currentTime = toHHMMSS(currentSeconds)
-    trackTime = toHHMMSS(trackSeconds)
-    nowPlayingTime = currentTime+"/"+trackTime
+    if (trackSeconds) {
+      trackTime = toHHMMSS(trackSeconds)
+      nowPlayingTime = currentTime+"/"+trackTime
+    } else {
+      nowPlayingTime = currentTime
+    }
   } else {
     nowPlayingTime = "-:--/-:--"
   }
@@ -61,7 +65,7 @@ function PeriodicRefreshTime() {
     nowTime = Date.now()
     delta = (nowTime - updateTime)/1000
     currentSeconds = updateSeconds + Math.round(delta)
-    if (currentSeconds > trackSeconds) {
+    if (trackSeconds && (currentSeconds > trackSeconds)) {
       currentSeconds = trackSeconds
     }
     RefreshTime()
@@ -76,7 +80,14 @@ function RefreshPageStatus() {
     if (this.readyState != 4 || this.status != 200) return;
     var returnedData = JSON.parse(this.responseText);
     trackName = GetFilename(returnedData['current_playing']);
+    try {
+      var trackName=decodeURI(trackName).replace(/%2C/g,",")
+    }  
+    catch(e) {
+      console.log(trackName)
+    }
     trackNo = returnedData['song'];
+    trackId = returnedData['songid']
     currentState = returnedData['state'];
     document.title='MPD Player: '+trackName;
     if (trackNo) {
@@ -121,7 +132,7 @@ function RefreshPageStatus() {
 
     var items = document.getElementById('items');
     var table = items.getElementsByClassName('track');
-    var current_track="track_"+trackNo;
+    var current_track="track_"+trackId;
     for (var i = 0; i < table.length; i++) {
       if (table[i].id==current_track) {
         table[i].classList.add("itemActive");
@@ -162,7 +173,13 @@ req.onreadystatechange = function () {
   var even = 0;
   for (var key in returnedData) {
        var rec=returnedData[key];
-       var name=GetFilename(rec["name"]);
+       var name=GetFilename(rec["title"]);
+       try {
+         var name=decodeURI(name).replace(/%2C/g,",")
+       }  
+       catch(e) {
+         console.log(name)
+       }
        var id=rec["id"];
 
        if (even) { 
@@ -175,7 +192,7 @@ req.onreadystatechange = function () {
 
        itemsText = itemsText + "<tr id=\"track_"+id+"\" class=\"track "+evText+"\">\
   <td class=\"track_number\">\
-  <a name=\""+id+"\">"+(Number(id)+1)+"</a></td>\
+  <a name=\""+id+"\">"+(Number(key)+1)+"</a></td>\
   </td>\
   <td class=\"file\">\
   <span class=\"link\" onclick=\"PlaylistCommand('playitem',"+id+")\">"+name+"</span>\
@@ -214,7 +231,7 @@ req.onreadystatechange = function () {
 
   var playlistMenuText = "<table>\
   <tr>\
-  <td><span onclick=\"RefreshPlaylist()\"><img class=\"medium-button\" title=\"Home\" src=\"images/list.svg\"></span><td>\
+  <td><span onclick=\"RefreshPageContent()\"><img class=\"medium-button\" title=\"Home\" src=\"images/list.svg\"></span><td>\
   <td><span onclick=\"return confirm('Add all to the list, are you sure?') ? PlaylistEditCommand('add','"+EscapeStr(dir)+"') : false;\" ><img class=\"medium-button\" title=\"Add all\" src=\"images/plus.svg\"></span><td>\
   </tr>\
   </table>";
@@ -250,6 +267,12 @@ req.onreadystatechange = function () {
        } else {
          var tailName=name
        };
+       try {
+         var tailName=decodeURI(tailName).replace(/%2C/g,",")
+       }  
+       catch(e) {
+         console.log(tailName)
+       }
 
        if (type == "directory" || type == "file") {
          if (even) { 
@@ -306,7 +329,7 @@ req.onreadystatechange = function () {
   var returnedData = JSON.parse(this.responseText);
   playlistMenuText="<table>\
     <tr>\
-      <td><span onclick=\"RefreshPlaylist()\"><img class=\"medium-button\" title=\"Home\" src=\"images/list.svg\"></span><td>\
+      <td><span onclick=\"RefreshPageContent()\"><img class=\"medium-button\" title=\"Home\" src=\"images/list.svg\"></span><td>\
       <td><span onclick=\"confirm('Clear current playlist, are you sure?') ? PlaylistCommandRefStatus('clear') : false;\" ><img class=\"medium-button\" title=\"Clear all\" src=\"images/cancel.svg\"></span><td>\
     </tr>\
     </table>";
diff --git a/mpd.js~ b/mpd.js~
deleted file mode 100644 (file)
index 3412633..0000000
--- a/mpd.js~
+++ /dev/null
@@ -1,473 +0,0 @@
-urlbase="mpd.lua?"
-minScrollHeight=200
-
-currentState=""
-
-function GetFilename(url)
-{
-   if (url)
-   return url.split('/').pop().split('#')[0].split('?')[0];
-}
-
-function EscapeStr(str) {
-  res = str.replace(/'/g,"\\'");
-  return res;
-}
-
-function SetSize() {
-  var w = window,
-      d = document,
-      e = d.documentElement,
-      g = d.getElementsByTagName('body')[0],
-      body_h = g.clientHeight,
-      window_h = w.innerHeight|| e.clientHeight|| g.clientHeight,
-      items = d.getElementById('items'),
-      current_h = items.clientHeight,
-      new_h=(window_h-body_h)+current_h;
-      if (new_h>minScrollHeight) {
-        items.style.height=new_h+"px";
-      }
-}
-
-function toHHMMSS(seconds) {
-    var hours = Math.floor(seconds / 3600);
-    seconds -= hours*3600;
-    var minutes = Math.floor(seconds / 60);
-    seconds -= minutes*60;
-
-    if (hours   < 10) {hours   = "0"+hours;}
-    if (minutes < 10) {minutes = "0"+minutes;}
-    if (seconds < 10) {seconds = "0"+seconds;}
-    if (hours == 0) {
-     return minutes+':'+seconds;
-    } else {
-     return hours+':'+minutes+':'+seconds;
-    }
-}
-
-function RefreshTime() {
-  if (currentSeconds) {
-    currentTime = toHHMMSS(currentSeconds)
-    trackTime = toHHMMSS(trackSeconds)
-    nowPlayingTime = currentTime+"/"+trackTime
-  } else {
-    nowPlayingTime = "-:--/-:--"
-  }
-  document.getElementById('nowplaying_tracklen').innerHTML=nowPlayingTime;
-}
-
-function PeriodicRefreshTime() {
-  if (currentState == "play") {
-    nowTime = Date.now()
-    delta = (nowTime - updateTime)/1000
-    currentSeconds = updateSeconds + Math.round(delta)
-    if (currentSeconds > trackSeconds) {
-      currentSeconds = trackSeconds
-    }
-    RefreshTime()
-  }
-}
-
-function RefreshPageStatus() {
-
-  var req = new XMLHttpRequest();
-
-  req.onreadystatechange = function () {
-    if (this.readyState != 4 || this.status != 200) return;
-    var returnedData = JSON.parse(this.responseText);
-    trackName = GetFilename(returnedData['current_playing']);
-    trackNo = returnedData['song'];
-    currentState = returnedData['state'];
-    document.title='MPD Player: '+trackName;
-    if (trackNo) {
-      var nowPlayingTrackNo=String(1+Number(trackNo))
-    } else {
-      var nowPlayingTrackNo="-"
-    }
-    nowPlayingTrack = nowPlayingTrackNo + '/' + returnedData['playlistlength'];
-    nowPlayingName = trackName;
-    playingTime = returnedData['time']
-    if (playingTime) {
-      var splits = playingTime.split(":")
-      updateTime = Date.now()
-      currentSeconds = Number(splits[0])
-      updateSeconds = currentSeconds
-      trackSeconds = Number(splits[1])
-    } else {
-      currentSeconds = null
-    }
-    if (currentState=='stop') {
-      nowPlayingName = '<font color="gray">' + nowPlayingName+ '</font>'
-    }
-    document.getElementById('nowplaying_trackno').innerHTML=nowPlayingTrack;
-    document.getElementById('nowplaying_trackname').innerHTML=nowPlayingName;
-    RefreshTime()
-    if (currentState=="play") {
-      document.getElementById('playpausebutton').innerHTML="<span onclick=\"Command('pause')\"><img class=\"button\" title=\"Pause\" src=\"images/pause.svg\"></span>";
-    } else {
-      document.getElementById('playpausebutton').innerHTML="<span onclick=\"Command('play')\"><img class=\"button\" title=\"Play\" src=\"images/play-button.svg\"></span>";
-    }
-    if (currentState=="stop") {
-      document.getElementById('stopbutton').innerHTML="<span><img class=\"button\" src=\"images/stopoff.svg\"></span>";
-    } else {
-      document.getElementById('stopbutton').innerHTML="<span onclick=\"Command('stop')\"><img class=\"button\" title=\"Stop\" src=\"images/stop.svg\"></span>";
-    }
-    if (returnedData["repeat"]=="1") {
-      document.getElementById('repeatstate').innerHTML="<img class=\"button\" title=\"Replay is on\" src=\"images/replay.svg\"></a>";
-    } else {
-      document.getElementById('repeatstate').innerHTML="<img class=\"button\" title=\"Replay is off\" src=\"images/replayoff.svg\"></a>";
-    }
-    document.getElementById('volume_total').innerHTML="<div id=\"volume_actual\" style=\"width:"+returnedData["volume"]+"%\">";
-
-    var items = document.getElementById('items');
-    var table = items.getElementsByClassName('track');
-    var current_track="track_"+trackNo;
-    for (var i = 0; i < table.length; i++) {
-      if (table[i].id==current_track) {
-        table[i].classList.add("itemActive");
-      } else {
-        table[i].classList.remove("itemActive")
-      }
-    }
-        
-  };
-
-  req.open("GET", urlbase+"status", true);
-  req.send();
-
-}
-
-function RefreshPlaylist() {
-
-var req = new XMLHttpRequest();
-
-req.onreadystatechange = function () {
-  if (this.readyState != 4 || this.status != 200) return;
-  var returnedData = JSON.parse(this.responseText);
-
-  var playlistMenuText = "<table>\
-  <tr>\
-  <td><span onclick=\"EditPlayList()\"><img class=\"medium-button\" title=\"Files\" src=\"images/folder.svg\"></span><td>\
-  <td><span onclick=\"LoadPlayList()\"><img class=\"medium-button\" title=\"Lists\" src=\"images/list.svg\"></span><td>\
-  <td><span onclick=\"SavePlayList()\"><img class=\"medium-button\" title=\"Save current list\" src=\"images/download.svg\"></span><td>\
-  <td><span onclick=\"return confirm('Clear current playlist, are you sure?') ? PlaylistCommand('clear') : false;\" ><img class=\"medium-button\" title=\"Clear current list\"  src=\"images/cancel.svg\"></span><td>\
-  </tr>\
-  </table>";
-
-  var itemsText="<table>\
-  <tr id=\"items_heading\">\
-  <td></td class=\"track_number\"><td class=\"file\">Title</td><td class=\"medium-button\" colspan=\"3\">Controls</td>\
-  </tr>";
-
-  var even = 0;
-  for (var key in returnedData) {
-       var rec=returnedData[key];
-       var name=GetFilename(rec["name"]);
-       var id=rec["id"];
-
-       if (even) { 
-         evText="itemEven"; 
-       } else { 
-         evText="itemOdd";
-       };
-
-       even = ! even;
-
-       itemsText = itemsText + "<tr id=\"track_"+id+"\" class=\"track "+evText+"\">\
-  <td class=\"track_number\">\
-  <a name=\""+id+"\">"+(Number(id)+1)+"</a></td>\
-  </td>\
-  <td class=\"file\">\
-  <span class=\"link\" onclick=\"PlaylistCommand('playitem',"+id+")\">"+name+"</span>\
-  </td>\
-  <td class=\"move\">\
-  <span onclick=\"PlaylistCommand('moveup',"+id+")\"><img class=\"small-button\" title=\"Move up\" src=\"images/up-arrow.svg\"></span>\
-  </td>\
-  <td class=\"move\">\
-  <span onclick=\"PlaylistCommand('movedown',"+id+")\"><img class=\"small-button\" title=\"Move down\" src=\"images/down-arrow.svg\"></span>\
-  </td>\
-  <td class=\"remove\">\
-  <span onclick=\"PlaylistCommand('remove',"+id+")\"><img class=\"small-button\" title=\"Remove\" src=\"images/cancel.svg\"></span>\
-  </td>\
-  </tr>"; 
-  }
-
-  itemsText = itemsText + "</table>";
-
-  document.getElementById('items').innerHTML=itemsText;
-  document.getElementById('playlist_menu_top').innerHTML=playlistMenuText;
-  document.getElementById('playlist_menu_bottom').innerHTML=playlistMenuText;
-};
-
-req.open("GET", urlbase+"playlist", true);
-req.send();
-
-}
-
-function EditPlayList(dir) {
-
-var req = new XMLHttpRequest();
-
-req.onreadystatechange = function () {
-  if (this.readyState != 4 || this.status != 200) return;
-  var returnedData = JSON.parse(this.responseText);
-
-  var playlistMenuText = "<table>\
-  <tr>\
-  <td><span onclick=\"RefreshPlaylist()\"><img class=\"medium-button\" title=\"Home\" src=\"images/list.svg\"></span><td>\
-  <td><span onclick=\"return confirm('Add all to the list, are you sure?') ? PlaylistEditCommand('add','"+EscapeStr(dir)+"') : false;\" ><img class=\"medium-button\" title=\"Add all\" src=\"images/plus.svg\"></span><td>\
-  </tr>\
-  </table>";
-
-  var itemsText= "<table>\
-  <tr id=\"items_heading\">\
-  <td></td class=\"track_number\"><td class=\"file\">Title</td><td colspan=\"2\">Controls</td>\
-  </tr>";
-
-  var even = 0;
-  if (dir) {
-    var lastSlash=dir.lastIndexOf("/");
-    if (lastSlash>0) {
-      var upperLevel=dir.slice(0,lastSlash);
-    } else {
-      var upperLevel="";
-    }
-    even = ! even;
-    var itemsText = itemsText + "<tr class=\"itemOdd\">\
-  <td class=\"track_number\"></td>\
-  <td class=\"file\"><span class=\"link\" onclick=\"EditPlayList('"+upperLevel+"')\">..</span></td>\
-  <td></td><td></td>";
-  } 
-
-  var i = 0;
-  for (var key in returnedData) {
-       var rec=returnedData[key];
-       var type=rec["type"];
-       var name=rec["name"];
-       var lastSlash=name.lastIndexOf("/");
-       if (lastSlash>0) {
-         var tailName=name.slice(lastSlash+1);
-       } else {
-         var tailName=name
-       };
-
-       if (type == "directory" || type == "file") {
-         if (even) { 
-           evText="itemEven"; 
-         } else { 
-           evText="itemOdd";
-         };
-
-         i = i + 1;
-         even = ! even;
-
-         itemsText = itemsText + "<tr class=\""+evText+"\">\
-           <td class=\"track_number\">\
-           <a name=\""+i+"\"></a></td>\
-           </td>";
-      
-         if (type == "directory") {
-           itemsText = itemsText + "<td class=\"file\">\
-             <span class=\"link\" onclick=\"EditPlayList('"+EscapeStr(name)+"')\">"+tailName+"</span></td><td>\
-             <span onclick=\"PlaylistEditCommand('add','"+EscapeStr(name)+"')\"><img class=\"small-button\" title=\"Add\" src=\"images/plus.svg\"></span></td>";
-         }; 
-
-         if (type == "file") {
-           itemsText = itemsText + "<td class=\"file\">\
-             <span class=\"link\" onclick=\"PlaylistEditCommand('add','"+EscapeStr(name)+"')\">"+tailName+"</span></td><td>\
-             <span onclick=\"PlaylistEditCommand('add','"+EscapeStr(name)+"')\"><img class=\"small-button\" title=\"Add\" src=\"images/plus.svg\"></span></td>";
-         };
-
-         itemsText = itemsText + "</tr>";
-
-       }       
-       
-  }
-
-  var itemsText = itemsText+"</table>";
-  document.getElementById('items').innerHTML=itemsText;
-  document.getElementById('playlist_menu_top').innerHTML=playlistMenuText;
-  document.getElementById('playlist_menu_bottom').innerHTML=playlistMenuText;
-};
-
-if (!dir) { dir = ''; };
-
-req.open("GET", urlbase+"lists|edit|"+dir, true);
-req.send();
-
-}
-
-function LoadPlayList() {
-
-var req = new XMLHttpRequest();
-
-req.onreadystatechange = function () {
-  if (this.readyState != 4 || this.status != 200) return;
-  var returnedData = JSON.parse(this.responseText);
-  playlistMenuText="<table>\
-    <tr>\
-      <td><span onclick=\"RefreshPlaylist()\"><img class=\"medium-button\" title=\"Home\" src=\"images/list.svg\"></span><td>\
-      <td><span onclick=\"confirm('Clear current playlist, are you sure?') ? PlaylistCommandRefStatus('clear') : false;\" ><img class=\"medium-button\" title=\"Clear all\" src=\"images/cancel.svg\"></span><td>\
-    </tr>\
-    </table>";
-  itemsText="<table>\
-    <tr id=\"items_heading\">\
-      <td class=\"track_number\"></td><td class=\"file\">Name</td><td>Controls</td>\
-    </tr>";
-
-  var even = 0;
-  for (var key in returnedData) {
-       var name=returnedData[key];
-
-       if (even) { 
-         evText="itemEven"; 
-       } else { 
-         evText="itemOdd";
-       };
-
-       even = ! even;
-
-       itemsText = itemsText + "<tr class=\""+evText+"\">\
-      <td class=\"track_number\"><a name=\"0\"></a></td>\
-      <td class=\"file\"><span class=\"link\" onclick=\"PlaylistEditCommandRefFull('load','"+EscapeStr(name)+"')\">"+name+"</td>\
-      <td class=\"controls\"><span onclick=\"confirm('Delete playlist "+name+", are you sure?') ? DelPlayList('"+EscapeStr(name)+"') : false;\"><img class=\"small-button\" title=\"Delete\" src=\"images/minus.svg\"></span></td>\
-    </tr>";
-  }
-
-  itemsText=itemsText+"</table>";
-  document.getElementById('items').innerHTML=itemsText;
-  document.getElementById('playlist_menu_top').innerHTML=playlistMenuText;
-  document.getElementById('playlist_menu_bottom').innerHTML=playlistMenuText;
-};
-
-req.open("GET", urlbase+"lists|load", true);
-req.send();
-
-}
-
-function SavePlayList() {
-
-var name=window.prompt('List name','');
-
-var req = new XMLHttpRequest();
-
-req.onreadystatechange = function () {
-  if (this.readyState != 4 || this.status != 200) return;
-  if (this.responseText != 'OK') {
-    window.alert(this.responseText);
-  }
-};
-
-req.open("GET", urlbase+"lists|save|"+name, true);
-req.send();
-
-}
-
-function DelPlayList(item) {
-
-var req = new XMLHttpRequest();
-
-req.onreadystatechange = function () {
-  if (this.readyState != 4 || this.status != 200) return;
-  LoadPlayList();
-  RefreshPageStatus();
-};
-
-req.open("GET", urlbase+"lists|delete|"+item, true);
-req.send();
-
-}
-
-function RefreshPageContent() {
-  RefreshPlaylist();
-  RefreshPageStatus();
-}
-
-function Command(cmd) {
-
-var req = new XMLHttpRequest();
-
-req.onreadystatechange = function () {
-  if (this.readyState != 4 || this.status != 200) return;
-  RefreshPageStatus();
-};
-
-req.open("GET", urlbase+cmd, true);
-req.send();
-
-}
-
-function PlaylistCommand(cmd,item) {
-
-var req = new XMLHttpRequest();
-
-req.onreadystatechange = function () {
-  if (this.readyState != 4 || this.status != 200) return;
-  RefreshPageContent();
-};
-
-req.open("GET", urlbase+"cpl|"+cmd+"|"+item, true);
-req.send();
-
-}
-
-function PlaylistCommandRefStatus(cmd,item) {
-
-var req = new XMLHttpRequest();
-
-req.onreadystatechange = function () {
-  if (this.readyState != 4 || this.status != 200) return;
-  RefreshPageStatus();
-};
-
-req.open("GET", urlbase+"cpl|"+cmd+"|"+item, true);
-req.send();
-
-}
-
-function PlaylistEditCommand(cmd,item) {
-
-var req = new XMLHttpRequest();
-
-req.onreadystatechange = function () {
-  if (this.readyState != 4 || this.status != 200) return;
-  RefreshPageStatus();
-};
-
-req.open("GET", urlbase+"lists|"+cmd+"|"+item, true);
-req.send();
-
-}
-
-function PlaylistEditCommandRefFull(cmd,item) {
-
-var req = new XMLHttpRequest();
-
-req.onreadystatechange = function () {
-  if (this.readyState != 4 || this.status != 200) return;
-  RefreshPageContent();
-};
-
-req.open("GET", urlbase+"lists|"+cmd+"|"+item, true);
-req.send();
-
-}
-
-function subscribe_status() {
-  var xhr = new XMLHttpRequest();
-
-  xhr.onreadystatechange = function() {
-    if (this.readyState != 4) return;
-    if (this.status == 200) {
-      RefreshPageStatus()
-      setTimeout(subscribe_status,1000)
-    } else {
-      setTimeout(subscribe_status,15000)
-    }
-  }
-  xhr.open("GET", urlbase+"idle", true);
-  xhr.send();
-}
-
-setTimeout(subscribe_status,5000)
-setInterval(PeriodicRefreshTime, 1000);
diff --git a/mpd.lua b/mpd.lua
index 8935c9a605af940fa108e19c62424f8bee5ce26e..f421b755ba9d0aa817d2dc5ce4f4e721d0f71bbc 100755 (executable)
--- a/mpd.lua
+++ b/mpd.lua
@@ -14,6 +14,23 @@ function url_decode(str)
   return str
 end
 
+function url_encode(str)
+
+  --Ensure all newlines are in CRLF form
+  str = string.gsub (str, "\r?\n", "\r\n")
+
+  --Percent-encode all non-unreserved characters
+  --as per RFC 3986, Section 2.3
+  --(except for space, which gets plus-encoded)
+  str = string.gsub (str, "([^%w%-%.%_%~:/])",
+    function (c) return string.format ("%%%02X", string.byte(c)) end)
+
+  --Convert spaces to plus signs
+  str = string.gsub (str, " ", "+")
+
+  return str
+end
+
 function split(s, delimiter)
     local result = {};
     for match in (s..delimiter):gmatch("(.-)"..delimiter) do
@@ -26,25 +43,53 @@ function string.starts(String,Start)
    return string.sub(String,1,string.len(Start))==Start
 end
 
+function filename(path)
+  local path_elems=split(path,'/')
+  return path_elems[#path_elems]
+end
+
 function process_playlist(playlist)
   local res={}
+  local rec={}
   for _,record in pairs(playlist) do
+    if record=="OK" then 
+      break
+    end  
     local splitted = split(record,": ")
-    local name = splitted[2]
-    local splitted = split(splitted[1],":")
-    local id = splitted[1]
-    local rectype = splitted[2]
-    local rec = {}
-    if not (id == "OK") then
-      rec["id"] = id
-      rec["type"] = rectype
-      rec["name"] = name
-      res[id] = rec
+    local fieldname = string.lower(splitted[1])
+    local fieldvalue = splitted[2]
+    rec[fieldname] = fieldvalue
+    if fieldname=="id" then
+      local title = rec['title']
+      if title then
+        local filtered_title=string.gsub(string.lower(title),'track','')
+        local filtered_title=string.gsub(filtered_title,'[ _.-]','')
+      else
+        filtered_title=""
+      end  
+      if not filtered_title or string.len(filtered_title)<4 then
+        if title then
+          rec['title']=title..' - '..filename(rec['file'])
+        else
+          rec['title']=filename(rec['file'])
+        end  
+      end
+      res[#res+1] = rec
+      rec={}
     end
   end
   return res
 end
 
+function find_by_id(playlist,id)
+  for key,record in pairs(playlist) do
+    if record['id']==id then
+      return key
+    end
+  end
+  return nil
+end
+
 function process_playlists(playlists)
   local res={}
   for _,record in pairs(playlists) do
@@ -72,6 +117,7 @@ end
 
 function mpd_new(settings)
     local client = {}
+
     if settings == nil then settings = {} end
 
     client.hostname = settings.hostname or "localhost"
@@ -161,6 +207,8 @@ function mpd_send(mpd,action,raw)
     return values
 end
 
+hasuci = false
+
 if hasuci then
 
   x = uci.cursor()
@@ -176,16 +224,13 @@ if hasuci then
 
 else
 
-  config = arg[1]
-  if not config then
-    config="/etc/mpd-lua.json"
-  end
+  config="/etc/mpd-lua.json"
 
   settings={}
   local open = io.open
-  local file = open(config, "r")
+  file = open(config, "r")
   if file then
-    local content = file:read "*a"
+    content = file:read "*a"
     file:close()
     settings=json.decode(content)
   end
@@ -198,7 +243,6 @@ else
 
 end
   
-  
 if password then
   settings["password"] = password
 end
@@ -247,7 +291,7 @@ elseif string.starts(command,"fastfwd") then
 
   status=mpd_send(m,"status")
   rec_time=status["time"]
-  song=status["song"]
+  song=status["songid"]
   
   if song then
 
@@ -256,12 +300,13 @@ elseif string.starts(command,"fastfwd") then
       cur_time=tonumber(rec_time[1])
 
       track_time=tonumber(rec_time[2])
-      cur_time=cur_time+skip
-      if cur_time>track_time then
-        cur_time=track_time
-      end
-
-      mpd_send(m,"seek "..song.." "..cur_time)
+      if track_time then
+        cur_time=cur_time+skip
+        if cur_time>track_time then
+          cur_time=track_time
+        end
+      end  
+      mpd_send(m,"seekid "..song.." "..cur_time)
 
     else
 
@@ -283,22 +328,22 @@ elseif string.starts(command,"rewind") then
 
   status=mpd_send(m,"status")
   rec_time=status["time"]
-  song=status["song"]
+  song=status["songid"]
   
   if song then
 
     if rec_time then
       rec_time=split(rec_time,":")
       cur_time=tonumber(rec_time[1])
-
-      track_time=tonumber(rec_time[2])
       cur_time=cur_time-skip
       if cur_time<0 then
         cur_time=0
       end
 
-      mpd_send(m,"seek "..song.." "..cur_time)
-
+      print(song)
+      print(cur_time)
+      mpd_send(m,"seekid "..song.." "..cur_time)
+        
     else
 
       mpd_send(m,"play")
@@ -313,19 +358,18 @@ elseif string.starts(command,"rewind") then
 elseif command=="status" then
 
   res=mpd_send(m,"status")
-  song=res["song"]
-  playlist=mpd_send(m,"playlist",1)
-  pl=process_playlist(playlist)
-
+  song=tonumber(res["songid"])
   if song then 
-    res['current_playing']=pl[song]['name']
+    playlist=mpd_send(m,"playlistid "..song,1)
+    pl=process_playlist(playlist)
+    res['current_playing']=pl[1]['title']
   else  
     res['current_playing']="---"
   end
 
 elseif command=="playlist" then
 
-  playlist=mpd_send(m,"playlist",1)
+  playlist=mpd_send(m,"playlistinfo",1)
   res=process_playlist(playlist)
 
 elseif command=="repeat" then
@@ -341,7 +385,7 @@ elseif string.starts(command,"cpl") then
   command=cmd[2]
 
   if command=="playitem" then
-    command="play "..id
+    command="playid "..id
     res=mpd_send(m,command)
   end
 
@@ -350,17 +394,27 @@ elseif string.starts(command,"cpl") then
   end
 
   if command=="remove" then
-    command="delete "..id
+    command="deleteid "..id
     res=mpd_send(m,command)
   end
 
   if command=="moveup" then
-    command="swap "..id.." "..(id-1)
+    playlist=mpd_send(m,"playlistinfo ",1)
+    pl=process_playlist(playlist)
+    idx=find_by_id(pl,id)
+    if idx>1 then
+      command="swap "..(idx-1).." "..(idx-2)
+    end  
     res=mpd_send(m,command)
   end
 
   if command=="movedown" then
-    command="swap "..id.." "..(id+1)
+    playlist=mpd_send(m,"playlistinfo ",1)
+    pl=process_playlist(playlist)
+    idx=find_by_id(pl,id)
+    if idx<#pl then
+      command="swap "..(idx-1).." "..(idx)
+    end  
     res=mpd_send(m,command)
   end
 
@@ -374,16 +428,16 @@ elseif string.starts(command,"lists") then
       lists=mpd_send(m,"listplaylists",1)
       res=process_playlists(lists)
     else
-      res=mpd_send(m,"load "..cmd[3],1)
+      res=mpd_send(m,"load \""..cmd[3].."\"",1)
     end
   end
 
   if command=="save" and cmd[3] then
-    res=mpd_send(m,"save "..cmd[3],1)
+    res=mpd_send(m,"save \""..cmd[3].."\"",1)
   end
 
   if command=="delete" and cmd[3] then
-    res=mpd_send(m,"rm "..cmd[3],1)
+    res=mpd_send(m,"rm \""..cmd[3].."\"",1)
   end
 
   if command=="edit" then
@@ -399,6 +453,10 @@ elseif string.starts(command,"lists") then
     res={}
     if cmd[3] then
       res=mpd_send(m,"add \""..cmd[3].."\"")
+      if (res['errormsg']) then
+        path=url_encode(cmd[3])
+        res=mpd_send(m,"add \""..path.."\"")
+      end
     end
   end
 
@@ -407,9 +465,9 @@ end
 if not res then
   print("Content-Type: text/plain\r\n")
   print("MPD server - unknown command "..command)
-elseif (res['error_msg']) then
+elseif (res['errormsg']) then
   print("Content-Type: text/plain\r\n")
-  print("MPD server connection error: "..res['error_msg'])
+  print("MPD server connection error: "..res['errormsg'])
 else
   print "Content-Type: text/plain\r\n"
   print(json.encode(res))
diff --git a/mpd.lua~ b/mpd.lua~
deleted file mode 100755 (executable)
index 97ac4f4..0000000
--- a/mpd.lua~
+++ /dev/null
@@ -1,417 +0,0 @@
-#!/usr/bin/lua
-
-local hasuci,uci = pcall(require,"uci")
-
-require("socket")
-json=require("json")
-
-function url_decode(str)
-  if not str then return nil end
-  str = string.gsub (str, "+", " ")
-  str = string.gsub (str, "%%(%x%x)", function(h) return
-    string.char(tonumber(h,16)) end)
-  str = string.gsub (str, "\r\n", "\n")
-  return str
-end
-
-function split(s, delimiter)
-    local result = {};
-    for match in (s..delimiter):gmatch("(.-)"..delimiter) do
-        result[#result+1] = match;
-    end
-    return result;
-end
-
-function string.starts(String,Start)
-   return string.sub(String,1,string.len(Start))==Start
-end
-
-function process_playlist(playlist)
-  local res={}
-  for _,record in pairs(playlist) do
-    local splitted = split(record,": ")
-    local name = splitted[2]
-    local splitted = split(splitted[1],":")
-    local id = splitted[1]
-    local rectype = splitted[2]
-    local rec = {}
-    if not (id == "OK") then
-      rec["id"] = id
-      rec["type"] = rectype
-      rec["name"] = name
-      res[id] = rec
-    end
-  end
-  return res
-end
-
-function process_playlists(playlists)
-  local res={}
-  for _,record in pairs(playlists) do
-    local splitted = split(record,": ")
-    if splitted[1]=="playlist" then
-      res[#res+1] = splitted[2]
-    end
-  end
-  return res
-end
-
-function process_directory(directory)
-  local res={}
-  for _,record in pairs(directory) do
-    local splitted = split(record,": ")
-    if splitted[1]=="directory" or splitted[1]=="file" then
-      local rec={}
-      rec["type"] = splitted[1]
-      rec["name"] = splitted[2]
-      res[#res+1] = rec
-    end
-  end
-  return res
-end
-
-function mpd_new(settings)
-    local client = {}
-    if settings == nil then settings = {} end
-
-    client.hostname = settings.hostname or "localhost"
-    client.port     = settings.port or 6600
-    client.desc     = settings.desc or client.hostname
-    client.password = settings.password
-    client.timeout  = settings.timeout or 1
-    client.retry    = settings.retry or 60
-
-    return client
-end
-
-function mpd_send(mpd,action,raw)
-
-    local command = string.format("%s\n", action)
-    local values = {}
-
-    -- connect to MPD server if not already done.
-    if not mpd.connected then
-        local now = os.time();
-        if not mpd.last_try or (now - mpd.last_try) > mpd.retry then
-            mpd.socket = socket.tcp()
-            mpd.socket:settimeout(mpd.timeout, 't')
-            mpd.last_try = os.time()
-            mpd.connected = mpd.socket:connect(mpd.hostname, mpd.port)
-            if not mpd.connected then
-                return { errormsg = "could not connect" }
-            end
-            mpd.last_error = nil
-
-            -- Read the server's hello message
-            local line = mpd.socket:receive("*l")
-            if not line:match("^OK MPD") then -- Invalid hello message?
-                mpd.connected = false
-                return { errormsg = string.format("invalid hello message: %s", line) }
-            else
-                _, _, mpd.version = string.find(line, "^OK MPD ([0-9.]+)")
-            end
-
-            -- send the password if needed
-            if mpd.password then
-                local rsp = mpd_send(mpd,string.format("password %s", mpd.password))
-                if rsp.errormsg then
-                    return rsp
-                end
-            end
-        else
-            local retry_sec = mpd.retry - (now - mpd.last_try)
-            return { errormsg = string.format("%s (retrying in %d sec)", mpd.last_error, retry_sec) }
-        end
-    end
-
-    mpd.socket:send(command)
-
-    local line = ""; err=0
-    while not line:match("^OK$") do
-        line, err = mpd.socket:receive("*l")
-        if not line then -- closed,timeout (mpd killed?)
-            mpd.last_error = err
-            mpd.connected = false
-            mpd.socket:close()
-            return mpd_send(mpd,action)
-        end
-
-        if line:match("^ACK") then
-            return { errormsg = line }
-        end
-
-        if not raw then
-
-         local pattern = string.format("(%s)", ": ")
-         local i = string.find (line, pattern, 0)
-
-          if i ~= nil then
-              local key=string.sub(line,1,i-1)
-              local value=string.sub(line,i+2,-1)
-              values[string.lower(key)] = value
-          end
-
-       else
-
-         values[#values+1]=line
-
-       end
-    end
-
-    return values
-end
-
-if hasuci then
-
-  x = uci.cursor()
-
-  settings = {}
-  settings['host'] = x.get("mpd","server","host") or "localhost"
-  settings['port'] = x.get("mpd","server","port") or 6600
-  settings['timeout'] = x.get("mpd","server","timeout") or 1
-
-  volstep = x.get("mpd","control","volume_step") or 3
-
-  password = x.get("mpd","server","password")
-
-else
-
-  config = arg[1]
-  if not config then
-    config="/etc/mpd-lua.json"
-  end
-
-  settings={}
-  local open = io.open
-  local file = open(config, "r")
-  if file then
-    local content = file:read "*a"
-    file:close()
-    settings=json.decode(content)
-  end
-    
-  settings['host'] = settings['host'] or "localhost"
-  settings['port'] = settings["port"] or 6600
-  settings['timeout'] = settings["timeout"] or 1
-
-  volstep = settings["volstep"] or 3
-
-end
-  
-  
-if password then
-  settings["password"] = password
-end
-
-m = mpd_new(settings)
-
-command = url_decode(os.getenv('QUERY_STRING'))
-
-if not command or command=="" then
-  command="idle"
-end
-
-if command=="play" or command=="pause" or command=="stop" then
-
-  res=mpd_send(m,command)
-
-elseif command=="previous" or command=="next" then
-
-  res=mpd_send(m,"play")
-  res=mpd_send(m,command)
-
-elseif command=="idle" then
-
-  m.timeout=30
-  res=mpd_send(m,command)
-
-elseif command=="vold" then
-
-  status=mpd_send(m,"status")
-  volume=tonumber(status["volume"])
-  res=mpd_send(m,"setvol "..(volume-volstep))
-
-elseif command=="volu" then
-
-  status=mpd_send(m,"status")
-  volume=tonumber(status["volume"])
-  res=mpd_send(m,"setvol "..(volume+volstep))
-
-elseif string.starts(command,"fastfwd") then
-
-  cmd=split(command,"|")
-  skip=tonumber(cmd[2])
-  if not skip then
-    skip=15
-  end
-
-  status=mpd_send(m,"status")
-  rec_time=status["time"]
-  song=status["song"]
-  
-  if song then
-
-    if rec_time then
-      rec_time=split(rec_time,":")
-      cur_time=tonumber(rec_time[1])
-
-      track_time=tonumber(rec_time[2])
-      cur_time=cur_time+skip
-      if cur_time>track_time then
-        cur_time=track_time
-      end
-
-      mpd_send(m,"seek "..song.." "..cur_time)
-
-    else
-
-      mpd_send(m,"play")
-
-    end  
-  
-  end
-
-  res={}
-
-elseif string.starts(command,"rewind") then
-
-  cmd=split(command,"|")
-  skip=tonumber(cmd[2])
-  if not skip then
-    skip=15
-  end
-
-  status=mpd_send(m,"status")
-  rec_time=status["time"]
-  song=status["song"]
-  
-  if song then
-
-    if rec_time then
-      rec_time=split(rec_time,":")
-      cur_time=tonumber(rec_time[1])
-
-      track_time=tonumber(rec_time[2])
-      cur_time=cur_time-skip
-      if cur_time<0 then
-        cur_time=0
-      end
-
-      mpd_send(m,"seek "..song.." "..cur_time)
-
-    else
-
-      mpd_send(m,"play")
-      mpd_send(m,"previous")
-
-    end  
-  
-  end
-
-  res={}
-
-elseif command=="status" then
-
-  res=mpd_send(m,"status")
-  song=res["song"]
-  playlist=mpd_send(m,"playlist",1)
-  pl=process_playlist(playlist)
-
-  if song then 
-    res['current_playing']=pl[song]['name']
-  else
-    res['song']="--"
-    res['current_playing']="---"
-  end
-
-elseif command=="playlist" then
-
-  playlist=mpd_send(m,"playlist",1)
-  res=process_playlist(playlist)
-
-elseif command=="repeat" then
-
-  status=mpd_send(m,"status")
-  rep=1-status["repeat"]
-  res=mpd_send(m,"repeat "..rep)
-
-elseif string.starts(command,"cpl") then
-
-  cmd=split(command,"|")
-  id=cmd[3]
-  command=cmd[2]
-
-  if command=="playitem" then
-    command="play "..id
-    res=mpd_send(m,command)
-  end
-
-  if command=="clear" then
-    res=mpd_send(m,"clear")
-  end
-
-  if command=="remove" then
-    command="delete "..id
-    res=mpd_send(m,command)
-  end
-
-  if command=="moveup" then
-    command="swap "..id.." "..(id-1)
-    res=mpd_send(m,command)
-  end
-
-  if command=="movedown" then
-    command="swap "..id.." "..(id+1)
-    res=mpd_send(m,command)
-  end
-
-elseif string.starts(command,"lists") then
-
-  cmd=split(command,"|")
-  command=cmd[2]
-
-  if command=="load" then
-    if not cmd[3] then
-      lists=mpd_send(m,"listplaylists",1)
-      res=process_playlists(lists)
-    else
-      res=mpd_send(m,"load "..cmd[3],1)
-    end
-  end
-
-  if command=="save" and cmd[3] then
-    res=mpd_send(m,"save "..cmd[3],1)
-  end
-
-  if command=="delete" and cmd[3] then
-    res=mpd_send(m,"rm "..cmd[3],1)
-  end
-
-  if command=="edit" then
-    if cmd[3] then
-      dir=mpd_send(m,"lsinfo \""..cmd[3].."\"",1)
-    else
-      dir=mpd_send(m,"lsinfo",1)
-    end
-    res=process_directory(dir)
-  end
-
-  if command=="add" then
-    res={}
-    if cmd[3] then
-      res=mpd_send(m,"add \""..cmd[3].."\"")
-    end
-  end
-
-end
-
-if not res then
-  print("Content-Type: text/plain\r\n")
-  print("MPD server - unknown command "..command)
-elseif (res['error_msg']) then
-  print("Content-Type: text/plain\r\n")
-  print("MPD server connection error: "..res['error_msg'])
-else
-  print "Content-Type: text/plain\r\n"
-  print(json.encode(res))
-end