+++ /dev/null
-#!/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