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 function round(what, precision)
35 if what then return math.floor(what*math.pow(10,precision)+0.5) / math.pow(10,precision) else return "" end
38 function strsplit(text, delimiter)
39 local strfind = string.find
40 local strsub = string.sub
41 local tinsert = table.insert
44 if strfind("", delimiter, 1) then -- this would result in endless loops
45 error("delimiter matches empty string!")
50 local first, last = strfind(text, delimiter, pos)
51 if first then -- found?
52 tinsert(list,i, strsub(text, pos, first-1))
55 tinsert(list,i, strsub(text, pos))
63 --main function to process commands sent with the request
65 processcommands = function ()
67 local input = _GET['input']
68 local command = _GET['command']
69 local id = tonumber(_GET['id'] or -1)
70 local val = _GET['val']
71 local options = _GET['option']
72 if type(options) ~= "table" then -- Deal with the 0 or 1 option case
76 if command == "in_play" then
78 vlc.msg.err( "<options>" )
79 for a,b in ipairs(options) do
82 vlc.msg.err( "</options>" )
84 vlc.playlist.add({{path=stripslashes(input),options=options}})
85 elseif command == "in_enqueue" then
86 vlc.playlist.enqueue({{path=stripslashes(input),options=options}})
87 elseif command == "pl_play" then
93 elseif command == "pl_pause" then
94 if vlc.playlist.status() == "stopped" then
103 elseif command == "pl_forcepause" then
104 if vlc.playlist.status() == "playing" then
107 elseif command == "pl_forceresume" then
108 if vlc.playlist.status() == "paused" then
111 elseif command == "pl_stop" then
113 elseif command == "pl_next" then
115 elseif command == "pl_previous" then
117 elseif command == "pl_delete" then
118 vlc.playlist.delete(id)
119 elseif command == "pl_empty" then
121 elseif command == "pl_sort" then
122 vlc.playlist.sort( val, id > 0 )
123 elseif command == "pl_random" then
124 vlc.playlist.random()
125 elseif command == "pl_loop" then
127 elseif command == "pl_repeat" then
128 vlc.playlist.repeat_()
129 elseif command == "pl_sd" then
130 if vlc.sd.is_loaded(val) then
135 elseif command == "fullscreen" then
136 vlc.video.fullscreen()
137 elseif command == "snapshot" then
139 elseif command == "volume" then
141 elseif command == "seek" then
143 elseif command == "key" then
144 common.hotkey("key-"..val)
145 elseif command == "audiodelay" then
146 if vlc.object.input() and val then
147 vlc.var.set(vlc.object.input(),"audio-delay",val)
149 elseif command == "rate" then
150 if vlc.object.input() and tonumber(val) >= 0 then
151 vlc.var.set(vlc.object.input(),"rate",val)
153 elseif command == "subdelay" then
154 if vlc.object.input() then
155 vlc.var.set(vlc.object.input(),"spu-delay",val)
157 elseif command == "aspectratio" then
158 if vlc.object.vout() then
159 vlc.var.set(vlc.object.vout(),"aspect-ratio",val)
170 --utilities for formatting output
172 local function xmlString(s)
173 if (type(s)=="string") then
174 return vlc.strings.convert_xml_special_chars(s)
180 local printJsonKeyValue = function (k,v,indent)
182 for i=1,indent do print(" ") end
184 print("\""..k.."\":")
187 if (type(v)=="number") then
189 elseif (type(v)=="table") then
190 if (v._array==NULL) then
192 printTableAsJson(v,indent+2)
196 printArrayAsJson(v._array,indent+2)
200 print("\""..xmlString(v).."\"")
205 printArrayAsJson = function(array,indent)
207 for i,v in ipairs(array) do
208 if not first then print(",") end
209 printJsonKeyValue(NULL,v,indent)
214 printTableAsJson = function (dict,indent)
216 for k,v in pairs(dict) do
217 if not first then print(",") end
218 printJsonKeyValue(k,v,indent)
223 local printXmlKeyValue = function (k,v,indent)
225 for i=1,indent do print(" ") end
230 if (type(v)=="table") then
231 printTableAsXml(v,indent+2)
241 printTableAsXml = function (dict,indent)
242 for k,v in pairs(dict) do
243 printXmlKeyValue(k,v,indent)
248 function logTable(t,pre)
249 local pre = pre or ""
250 for k,v in pairs(t) do
251 vlc.msg.err(pre..tostring(k).." : "..tostring(v))
252 if type(v) == "table" then
261 getplaylist = function ()
264 if _GET["search"] then
265 if _GET["search"] ~= "" then
266 _G.search_key = _GET["search"]
270 local key = vlc.strings.decode_uri(_GET["search"])
271 p = vlc.playlist.search(key)
273 p = vlc.playlist.get()
276 --logTable(p) --Uncomment to debug
281 parseplaylist = function (item)
282 if item.flags.disabled then return end
284 if (item.children) then
286 local name = vlc.strings.convert_xml_special_chars(item.name or "")
288 result["type"]="node"
289 result.id=tostring(item.id)
290 result.name=tostring(name)
291 result.ro=item.flags.ro and "ro" or "rw"
293 --store children in an array
294 --we use _array as a proxy for arrays
296 result.children._array={}
298 for _, child in ipairs(item.children) do
299 local nextChild=parseplaylist(child)
300 table.insert(result.children._array,nextChild)
306 local name, path = vlc.strings.convert_xml_special_chars(item.name or "", item.path or "")
307 local current_item = vlc.input.item()
309 -- Is the item the one currently played
310 if(current_item ~= nil) then
311 if(vlc.input.item().uri(current_item) == path) then
312 result.current = "current"
316 result["type"]="leaf"
317 result.id=tostring(item.id)
318 result.uri=tostring(path)
320 result.ro=item.flags.ro and "ro" or "rw"
321 result.duration=math.floor(item.duration)
328 playlisttable = function ()
330 local basePlaylist=getplaylist()
332 return parseplaylist(basePlaylist)
336 getstatus = function (includecategories)
339 local input = vlc.object.input()
340 local item = vlc.input.item()
341 local playlist = vlc.object.playlist()
342 local vout = vlc.object.vout()
343 local aout = vlc.object.aout()
347 --update api version when new data/commands added
349 s.version=vlc.misc.version()
350 s.volume=vlc.volume.get()
353 s.length=math.floor(vlc.var.get(input,"length"))
354 s.time=math.floor(vlc.var.get(input,"time"))
355 s.position=vlc.var.get(input,"position")
356 s.audiodelay=vlc.var.get(input,"audio-delay")
357 s.rate=vlc.var.get(input,"rate")
358 s.subtitledelay=vlc.var.get(input,"spu-delay")
368 s.fullscreen=vlc.var.get(vout,"fullscreen")
369 s.aspectratio=vlc.var.get(vout,"aspect-ratio");
370 if s.aspectratio=="" then s.aspectratio = "default" end
375 local filters=vlc.var.get(aout,"audio-filter")
376 local temp=strsplit(filters,":")
379 for i,j in pairs(temp) do
380 s.audiofilters['filter_'..id]=j
385 s.videoeffects.hue=round(vlc.config.get("hue"),2)
386 s.videoeffects.brightness=round(vlc.config.get("brightness"),2)
387 s.videoeffects.contrast=round(vlc.config.get("contrast"),2)
388 s.videoeffects.saturation=round(vlc.config.get("saturation"),2)
389 s.videoeffects.gamma=round(vlc.config.get("gamma"),2)
390 s.state=vlc.playlist.status()
391 s.random=vlc.var.get(playlist,"random")
392 s.loop=vlc.var.get(playlist,"loop")
393 s["repeat"]=vlc.var.get(playlist,"repeat")
395 if (includecategories and item) then
397 s.information.category={}
398 s.information.category.meta=item:metas()
400 local info = item:info()
401 for k, v in pairs(info) do
403 for k2, v2 in pairs(v) do
404 local tag = string.gsub(k2," ","_")
405 streamTable[xmlString(tag)]=xmlString(v2)
408 s.information.category[xmlString(k)]=streamTable
413 local statsdata = item:stats()
414 for k,v in pairs(statsdata) do
415 local tag = string.gsub(k,"_","")
416 s.stats[tag]=xmlString(v)