1 --[==========================================================================[
2 httprequests.lua: code for processing httprequests commands and output
3 --[==========================================================================[
4 Copyright (C) 2007 the VideoLAN team
7 Authors: Antoine Cellerier <dionoea at videolan dot org>
8 Rob Jonson <rob at hobbyistsoftware.com>
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 --]==========================================================================]
25 module("httprequests",package.seeall)
30 local function stripslashes(s)
31 return string.gsub(s,"\\(.)","%1")
34 --Round the number to the specified precision
35 function round(what, precision)
36 if what then return math.floor(what*math.pow(10,precision)+0.5) / math.pow(10,precision) else return "" end
39 --split text where it matches the delimiter
40 function strsplit(text, delimiter)
41 local strfind = string.find
42 local strsub = string.sub
43 local tinsert = table.insert
46 if strfind("", delimiter, 1) then -- this would result in endless loops
47 error("delimiter matches empty string!")
52 local first, last = strfind(text, delimiter, pos)
53 if first then -- found?
54 tinsert(list,i, strsub(text, pos, first-1))
57 tinsert(list,i, strsub(text, pos))
64 function round(what, precision)
65 if what then return math.floor(what*math.pow(10,precision)+0.5) / math.pow(10,precision) else return "" end
68 --main function to process commands sent with the request
70 processcommands = function ()
72 local input = _GET['input']
73 local command = _GET['command']
74 local id = tonumber(_GET['id'] or -1)
75 local val = _GET['val']
76 local options = _GET['option']
77 local band = _GET['band']
78 if type(options) ~= "table" then -- Deal with the 0 or 1 option case
82 if command == "in_play" then
84 vlc.msg.err( "<options>" )
85 for a,b in ipairs(options) do
88 vlc.msg.err( "</options>" )
90 vlc.playlist.add({{path=stripslashes(input),options=options}})
91 elseif command == "addsubtitle" then
92 vlc.input.add_subtitle (stripslashes(val))
93 elseif command == "in_enqueue" then
94 vlc.playlist.enqueue({{path=stripslashes(input),options=options}})
95 elseif command == "pl_play" then
101 elseif command == "pl_pause" then
102 if vlc.playlist.status() == "stopped" then
106 vlc.playlist.goto(id)
111 elseif command == "pl_forcepause" then
112 if vlc.playlist.status() == "playing" then
115 elseif command == "pl_forceresume" then
116 if vlc.playlist.status() == "paused" then
119 elseif command == "pl_stop" then
121 elseif command == "pl_next" then
123 elseif command == "pl_previous" then
125 elseif command == "pl_delete" then
126 vlc.playlist.delete(id)
127 elseif command == "pl_empty" then
129 elseif command == "pl_sort" then
130 vlc.playlist.sort( val, id > 0 )
131 elseif command == "pl_random" then
132 vlc.playlist.random()
133 elseif command == "pl_loop" then
134 --if loop is set true, then repeat needs to be set false
135 if vlc.playlist.loop() then
136 vlc.playlist.repeat_("off")
138 elseif command == "pl_repeat" then
139 --if repeat is set true, then loop needs to be set false
140 if vlc.playlist.repeat_() then
141 vlc.playlist.loop("off")
143 elseif command == "pl_sd" then
144 if vlc.sd.is_loaded(val) then
149 elseif command == "fullscreen" then
150 vlc.video.fullscreen()
151 elseif command == "snapshot" then
153 elseif command == "volume" then
155 elseif command == "seek" then
157 elseif command == "key" then
158 common.hotkey("key-"..val)
159 elseif command == "audiodelay" then
160 if vlc.object.input() and val then
161 vlc.var.set(vlc.object.input(),"audio-delay",val)
163 elseif command == "rate" then
164 if vlc.object.input() and tonumber(val) >= 0 then
165 vlc.var.set(vlc.object.input(),"rate",val)
167 elseif command == "subdelay" then
168 if vlc.object.input() then
169 vlc.var.set(vlc.object.input(),"spu-delay",val)
171 elseif command == "aspectratio" then
172 if vlc.object.vout() then
173 vlc.var.set(vlc.object.vout(),"aspect-ratio",val)
175 elseif command == "preamp" then
176 vlc.equalizer.preampset(val)
177 elseif command == "equalizer" then
178 vlc.equalizer.equalizerset(band,val)
179 elseif command == "enableeq" then
180 if val == '0' then vlc.equalizer.enable(false) else vlc.equalizer.enable(true) end
181 elseif command == "setpreset" then
182 vlc.equalizer.setpreset(val)
192 --utilities for formatting output
194 local function xmlString(s)
195 if (type(s)=="string") then
196 return vlc.strings.convert_xml_special_chars(s)
202 local printJsonKeyValue = function (k,v,indent)
204 for i=1,indent do print(" ") end
206 print("\""..k.."\":")
209 if (type(v)=="number") then
211 elseif (type(v)=="table") then
212 if (v._array==NULL) then
214 printTableAsJson(v,indent+2)
218 printArrayAsJson(v._array,indent+2)
222 print("\""..xmlString(v).."\"")
227 printArrayAsJson = function(array,indent)
229 for i,v in ipairs(array) do
230 if not first then print(",") end
231 printJsonKeyValue(NULL,v,indent)
236 printTableAsJson = function (dict,indent)
238 for k,v in pairs(dict) do
239 if not first then print(",") end
240 printJsonKeyValue(k,v,indent)
245 local printXmlKeyValue = function (k,v,indent)
247 for i=1,indent do print(" ") end
252 if (type(v)=="table") then
253 printTableAsXml(v,indent+2)
263 printTableAsXml = function (dict,indent)
264 for k,v in pairs(dict) do
265 printXmlKeyValue(k,v,indent)
270 function logTable(t,pre)
271 local pre = pre or ""
272 for k,v in pairs(t) do
273 vlc.msg.err(pre..tostring(k).." : "..tostring(v))
274 if type(v) == "table" then
283 getplaylist = function ()
286 if _GET["search"] then
287 if _GET["search"] ~= "" then
288 _G.search_key = _GET["search"]
292 local key = vlc.strings.decode_uri(_GET["search"])
293 p = vlc.playlist.search(key)
295 p = vlc.playlist.get()
298 --logTable(p) --Uncomment to debug
303 parseplaylist = function (item)
304 if item.flags.disabled then return end
306 if (item.children) then
308 local name = vlc.strings.convert_xml_special_chars(item.name or "")
310 result["type"]="node"
311 result.id=tostring(item.id)
312 result.name=tostring(name)
313 result.ro=item.flags.ro and "ro" or "rw"
315 --store children in an array
316 --we use _array as a proxy for arrays
318 result.children._array={}
320 for _, child in ipairs(item.children) do
321 local nextChild=parseplaylist(child)
322 table.insert(result.children._array,nextChild)
328 local name, path = vlc.strings.convert_xml_special_chars(item.name or "", item.path or "")
329 local current_item = vlc.input.item()
331 -- Is the item the one currently played
332 if(current_item ~= nil) then
333 if(vlc.input.item().uri(current_item) == path) then
334 result.current = "current"
338 result["type"]="leaf"
339 result.id=tostring(item.id)
340 result.uri=tostring(path)
342 result.ro=item.flags.ro and "ro" or "rw"
343 result.duration=math.floor(item.duration)
350 playlisttable = function ()
352 local basePlaylist=getplaylist()
354 return parseplaylist(basePlaylist)
357 getbrowsetable = function ()
360 local uri = _GET["uri"]
361 --uri takes precedence, but fall back to dir
363 dir = vlc.strings.make_path(uri)
369 --paths are returned as an array of elements
371 result.element._array={}
374 if dir == "~" then dir = vlc.misc.homedir() end
375 dir = common.realpath(dir.."/")
376 local d = vlc.net.opendir(dir)
379 for _,f in pairs(d) do
380 if f == ".." or not string.match(f,"^%.") then
381 local df = common.realpath(dir..f)
382 local s = vlc.net.stat(df)
383 local path, name = vlc.strings.convert_xml_special_chars( df, f )
386 for k,v in pairs(s) do
392 local uri=vlc.strings.make_uri(df)
393 --windows paths are returned with / separators, but make_uri expects \ for windows and returns nil
395 --convert failed path to windows format and try again
396 path=string.gsub(path,"/","\\")
397 uri=vlc.strings.make_uri(df)
401 table.insert(result.element._array,element)
411 getstatus = function (includecategories)
414 local input = vlc.object.input()
415 local item = vlc.input.item()
416 local playlist = vlc.object.playlist()
417 local vout = vlc.object.vout()
418 local aout = vlc.object.aout()
422 --update api version when new data/commands added
424 s.version=vlc.misc.version()
425 s.volume=vlc.volume.get()
428 s.length=math.floor(vlc.var.get(input,"length"))
429 s.time=math.floor(vlc.var.get(input,"time"))
430 s.position=vlc.var.get(input,"position")
431 s.audiodelay=vlc.var.get(input,"audio-delay")
432 s.rate=vlc.var.get(input,"rate")
433 s.subtitledelay=vlc.var.get(input,"spu-delay")
444 s.fullscreen=vlc.var.get(vout,"fullscreen")
445 s.aspectratio=vlc.var.get(vout,"aspect-ratio");
446 if s.aspectratio=="" then s.aspectratio = "default" end
452 local filters=vlc.var.get(aout,"audio-filter")
453 local temp=strsplit(filters,":")
456 for i,j in pairs(temp) do
457 s.audiofilters['filter_'..id]=j
463 s.videoeffects.hue=round(vlc.config.get("hue"),2)
464 s.videoeffects.brightness=round(vlc.config.get("brightness"),2)
465 s.videoeffects.contrast=round(vlc.config.get("contrast"),2)
466 s.videoeffects.saturation=round(vlc.config.get("saturation"),2)
467 s.videoeffects.gamma=round(vlc.config.get("gamma"),2)
469 s.state=vlc.playlist.status()
470 s.random=vlc.var.get(playlist,"random")
471 s.loop=vlc.var.get(playlist,"loop")
472 s["repeat"]=vlc.var.get(playlist,"repeat")
475 s.equalizer.preamp=round(vlc.equalizer.preampget(),2)
476 s.equalizer.bands=vlc.equalizer.equalizerget()
477 if s.equalizer.bands ~= null then
478 for k,i in pairs(s.equalizer.bands) do s.equalizer.bands[k]=round(i,2) end
479 s.equalizer.presets=vlc.equalizer.presets()
482 if (includecategories and item) then
484 s.information.category={}
485 s.information.category.meta=item:metas()
487 local info = item:info()
488 for k, v in pairs(info) do
490 for k2, v2 in pairs(v) do
491 local tag = string.gsub(k2," ","_")
492 streamTable[xmlString(tag)]=xmlString(v2)
495 s.information.category[xmlString(k)]=streamTable
500 local statsdata = item:stats()
501 for k,v in pairs(statsdata) do
502 local tag = string.gsub(k,"_","")
503 s.stats[tag]=xmlString(v)