]> git.sesse.net Git - vlc/blob - share/lua/intf/modules/httprequests.lua
bed51a0e9d936f039febdb4634c7611fea015cb7
[vlc] / share / lua / intf / modules / httprequests.lua
1 --[==========================================================================[
2  httprequests.lua: code for processing httprequests commands and output
3 --[==========================================================================[
4  Copyright (C) 2007 the VideoLAN team
5  $Id$
6
7  Authors: Antoine Cellerier <dionoea at videolan dot org>
8  Rob Jonson <rob at hobbyistsoftware.com>
9
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.
14
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.
19
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 --]==========================================================================]
24
25 module("httprequests",package.seeall)
26
27 local dkjson = require ("dkjson")
28
29
30
31 --Round the number to the specified precision
32 function round(what, precision)
33   if what then return math.floor(what*math.pow(10,precision)+0.5) / math.pow(10,precision) else return "" end
34 end
35
36 --split text where it matches the delimiter
37 function strsplit(text, delimiter)
38     local strfind = string.find
39     local strsub = string.sub
40     local tinsert = table.insert
41     local list = {}
42     local pos = 1
43     if strfind("", delimiter, 1) then -- this would result in endless loops
44         error("delimiter matches empty string!")
45     end
46     local i=1
47     while 1 do
48         i=i+1
49         local first, last = strfind(text, delimiter, pos)
50         if first then -- found?
51             tinsert(list,i, strsub(text, pos, first-1))
52             pos = last+1
53         else
54             tinsert(list,i, strsub(text, pos))
55         break
56         end
57     end
58     return list
59 end
60
61 function round(what, precision)
62 if what then return math.floor(what*math.pow(10,precision)+0.5) / math.pow(10,precision) else return "" end
63 end
64
65 --main function to process commands sent with the request
66
67 processcommands = function ()
68
69     local input = _GET['input']
70     local command = _GET['command']
71     local id = tonumber(_GET['id'] or -1)
72     local val = _GET['val']
73     local options = _GET['option']
74     local band = _GET['band']
75     if type(options) ~= "table" then -- Deal with the 0 or 1 option case
76       options = { options }
77     end
78
79     if command == "in_play" then
80       --[[
81       vlc.msg.err( "<options>" )
82       for a,b in ipairs(options) do
83         vlc.msg.err(b)
84       end
85       vlc.msg.err( "</options>" )
86       --]]
87       vlc.playlist.add({{path=vlc.strings.make_uri(input),options=options}})
88     elseif command == "addsubtitle" then
89       vlc.input.add_subtitle (vlc.strings.make_uri(val))
90     elseif command == "in_enqueue" then
91       vlc.playlist.enqueue({{path=vlc.strings.make_uri(input),options=options}})
92     elseif command == "pl_play" then
93       if id == -1 then
94         vlc.playlist.play()
95       else
96         vlc.playlist.goto(id)
97       end
98     elseif command == "pl_pause" then
99       if vlc.playlist.status() == "stopped" then
100         if id == -1 then
101           vlc.playlist.play()
102         else
103           vlc.playlist.goto(id)
104         end
105       else
106         vlc.playlist.pause()
107       end
108     elseif command == "pl_forcepause" then
109       if vlc.playlist.status() == "playing" then
110         vlc.playlist.pause()
111       end
112     elseif command == "pl_forceresume" then
113       if vlc.playlist.status() == "paused" then
114         vlc.playlist.pause()
115       end
116     elseif command == "pl_stop" then
117       vlc.playlist.stop()
118     elseif command == "pl_next" then
119       vlc.playlist.next()
120     elseif command == "pl_previous" then
121       vlc.playlist.prev()
122     elseif command == "pl_delete" then
123       vlc.playlist.delete(id)
124     elseif command == "pl_empty" then
125       vlc.playlist.clear()
126     elseif command == "pl_sort" then
127       vlc.playlist.sort( val, id > 0 )
128     elseif command == "pl_random" then
129       vlc.playlist.random()
130     elseif command == "pl_loop" then
131     --if loop is set true, then repeat needs to be set false
132       if vlc.playlist.loop() then
133         vlc.playlist.repeat_("off")
134       end
135     elseif command == "pl_repeat" then
136     --if repeat is set true, then loop needs to be set false
137       if vlc.playlist.repeat_() then
138         vlc.playlist.loop("off")
139       end
140     elseif command == "pl_sd" then
141       if vlc.sd.is_loaded(val) then
142         vlc.sd.remove(val)
143       else
144         vlc.sd.add(val)
145       end
146     elseif command == "fullscreen" then
147       vlc.video.fullscreen()
148     elseif command == "snapshot" then
149       common.snapshot()
150     elseif command == "volume" then
151       common.volume(val)
152     elseif command == "seek" then
153       common.seek(val)
154     elseif command == "key" then
155       common.hotkey("key-"..val)
156     elseif command == "audiodelay" then
157       if vlc.object.input() and val then
158        vlc.var.set(vlc.object.input(),"audio-delay",val)
159       end
160     elseif command == "rate" then
161       if vlc.object.input() and tonumber(val) >= 0 then
162        vlc.var.set(vlc.object.input(),"rate",val)
163       end
164     elseif command == "subdelay" then
165       if vlc.object.input() then
166        vlc.var.set(vlc.object.input(),"spu-delay",val)
167       end
168     elseif command == "aspectratio" then
169       if vlc.object.vout() then
170        vlc.var.set(vlc.object.vout(),"aspect-ratio",val)
171       end
172     elseif command == "preamp" then
173       vlc.equalizer.preampset(val)
174     elseif command == "equalizer" then
175       vlc.equalizer.equalizerset(band,val)
176     elseif command == "enableeq" then
177       if val == '0' then vlc.equalizer.enable(false) else vlc.equalizer.enable(true) end
178     elseif command == "setpreset" then
179       vlc.equalizer.setpreset(val)
180     end
181
182     local input = nil
183     local command = nil
184     local id = nil
185     local val = nil
186
187 end
188
189 --utilities for formatting output
190
191 function xmlString(s)
192   if (type(s)=="string") then
193       return vlc.strings.convert_xml_special_chars(s)
194   else
195       return tostring(s)
196   end
197 end
198
199 --dkjson outputs numbered tables as arrays
200 --so we don't need the array indicators
201 function removeArrayIndicators(dict)
202     local newDict=dict
203
204     for k,v in pairs(dict) do
205         if (type(v)=="table") then
206             local arrayEntry=v._array
207             if arrayEntry then
208                 v=arrayEntry
209             end
210
211             dict[k]=removeArrayIndicators(v)
212         end
213     end
214
215     return newDict
216 end
217
218 printTableAsJson = function (dict)
219     dict=removeArrayIndicators(dict)
220
221     local output=dkjson.encode (dict, { indent = true })
222     print(output)
223 end
224
225 local printXmlKeyValue = function (k,v,indent)
226     print("\n")
227     for i=1,indent do print(" ") end
228     if (k) then
229         print("<"..k..">")
230     end
231
232     if (type(v)=="table") then
233         printTableAsXml(v,indent+2)
234     else
235         print(xmlString(v))
236     end
237
238     if (k) then
239         print("</"..xmlString(k)..">")
240     end
241 end
242
243 printTableAsXml = function (dict,indent)
244     for k,v in pairs(dict) do
245         printXmlKeyValue(k,v,indent)
246     end
247 end
248
249 --[[
250 function logTable(t,pre)
251   local pre = pre or ""
252   for k,v in pairs(t) do
253     vlc.msg.err(pre..tostring(k).." : "..tostring(v))
254     if type(v) == "table" then
255       a(v,pre.."  ")
256     end
257   end
258 end
259 --]]
260
261 --main accessors
262
263 getplaylist = function ()
264     local p
265
266     if _GET["search"] then
267       if _GET["search"] ~= "" then
268         _G.search_key = _GET["search"]
269       else
270         _G.search_key = nil
271       end
272       local key = vlc.strings.decode_uri(_GET["search"])
273       p = vlc.playlist.search(key)
274     else
275       p = vlc.playlist.get()
276     end
277
278     --logTable(p) --Uncomment to debug
279
280     return p
281 end
282
283 parseplaylist = function (item)
284     if item.flags.disabled then return end
285
286     if (item.children) then
287         local result={}
288         local name = (item.name or "")
289
290         result["type"]="node"
291         result.id=tostring(item.id)
292         result.name=tostring(name)
293         result.ro=item.flags.ro and "ro" or "rw"
294
295         --store children in an array
296         --we use _array as a proxy for arrays
297         result.children={}
298         result.children._array={}
299
300         for _, child in ipairs(item.children) do
301             local nextChild=parseplaylist(child)
302             table.insert(result.children._array,nextChild)
303         end
304
305         return result
306     else
307         local result={}
308         local name, path = item.name or ""
309         local path = item.path or ""
310         local current_item = vlc.input.item()
311
312         -- Is the item the one currently played
313         if(current_item ~= nil) then
314             if(vlc.input.item().uri(current_item) == path) then
315                 result.current = "current"
316             end
317         end
318
319         result["type"]="leaf"
320         result.id=tostring(item.id)
321         result.uri=tostring(path)
322         result.name=name
323         result.ro=item.flags.ro and "ro" or "rw"
324         result.duration=math.floor(item.duration)
325
326         return result
327     end
328
329 end
330
331 playlisttable = function ()
332
333     local basePlaylist=getplaylist()
334
335     return parseplaylist(basePlaylist)
336 end
337
338 getbrowsetable = function ()
339
340     local dir = nil
341     local uri = _GET["uri"]
342     --uri takes precedence, but fall back to dir
343     if uri then
344         dir = vlc.strings.make_path(uri)
345     else
346         dir = _GET["dir"]
347     end
348
349     --backwards compatibility with old format driveLetter:\\..
350     --this is forgiving with the slash type and number
351     local position=string.find(dir, '%a:[\\/]*%.%.',0)
352     if position==1 then dir="" end
353
354     local result={}
355     --paths are returned as an array of elements
356     result.element={}
357     result.element._array={}
358
359     if dir then
360         if dir == "~" then dir = vlc.misc.homedir() end
361         -- FIXME: hack for Win32 drive list
362         if dir~="" then
363             dir = common.realpath(dir.."/")
364         end
365
366         local d = vlc.net.opendir(dir)
367         table.sort(d)
368
369         for _,f in pairs(d) do
370             if f == ".." or not string.match(f,"^%.") then
371                 local df = common.realpath(dir..f)
372                 local s = vlc.net.stat(df)
373                 local path, name =  df, f
374                 local element={}
375
376                 for k,v in pairs(s) do
377                     element[k]=v
378                 end
379                 element["path"]=path
380                 element["name"]=name
381
382                 local uri=vlc.strings.make_uri(df)
383                 --windows paths are returned with / separators, but make_uri expects \ for windows and returns nil
384                 if not uri then
385                     --convert failed path to windows format and try again
386                     path=string.gsub(path,"/","\\")
387                     uri=vlc.strings.make_uri(df)
388                 end
389                 element["uri"]=uri
390
391                 table.insert(result.element._array,element)
392             end
393
394         end
395     end
396
397     return result;
398 end
399
400
401 getstatus = function (includecategories)
402
403
404 local input = vlc.object.input()
405 local item = vlc.input.item()
406 local playlist = vlc.object.playlist()
407 local vout = vlc.object.vout()
408 local aout = vlc.object.aout()
409
410     local s ={}
411
412     --update api version when new data/commands added
413     s.apiversion=1
414     s.version=vlc.misc.version()
415     s.volume=vlc.volume.get()
416
417     if input then
418         s.length=math.floor(vlc.var.get(input,"length"))
419         s.time=math.floor(vlc.var.get(input,"time"))
420         s.position=vlc.var.get(input,"position")
421         s.audiodelay=vlc.var.get(input,"audio-delay")
422         s.rate=vlc.var.get(input,"rate")
423         s.subtitledelay=vlc.var.get(input,"spu-delay")
424     else
425         s.length=0
426         s.time=0
427         s.position=0
428         s.audiodelay=0
429         s.rate=1
430         s.subtitledelay=0
431     end
432
433     if vout then
434         s.fullscreen=vlc.var.get(vout,"fullscreen")
435         s.aspectratio=vlc.var.get(vout,"aspect-ratio");
436         if s.aspectratio=="" then s.aspectratio = "default" end
437     else
438         s.fullscreen=0
439     end
440
441     if aout then
442         local filters=vlc.var.get(aout,"audio-filter")
443         local temp=strsplit(filters,":")
444         s.audiofilters={}
445         local id=0
446         for i,j in pairs(temp) do
447             s.audiofilters['filter_'..id]=j
448             id=id+1
449         end
450     end
451
452     s.videoeffects={}
453     s.videoeffects.hue=round(vlc.config.get("hue"),2)
454     s.videoeffects.brightness=round(vlc.config.get("brightness"),2)
455     s.videoeffects.contrast=round(vlc.config.get("contrast"),2)
456     s.videoeffects.saturation=round(vlc.config.get("saturation"),2)
457     s.videoeffects.gamma=round(vlc.config.get("gamma"),2)
458
459     s.state=vlc.playlist.status()
460     s.random=vlc.var.get(playlist,"random")
461     s.loop=vlc.var.get(playlist,"loop")
462     s["repeat"]=vlc.var.get(playlist,"repeat")
463
464         s.equalizer={}
465         s.equalizer.preamp=round(vlc.equalizer.preampget(),2)
466         s.equalizer.bands=vlc.equalizer.equalizerget()
467             if s.equalizer.bands ~= null then
468                 for k,i in pairs(s.equalizer.bands) do s.equalizer.bands[k]=round(i,2) end
469                 s.equalizer.presets=vlc.equalizer.presets()
470         end
471
472     if (includecategories and item) then
473         s.information={}
474         s.information.category={}
475         s.information.category.meta=item:metas()
476
477         local info = item:info()
478         for k, v in pairs(info) do
479             local streamTable={}
480             for k2, v2 in pairs(v) do
481                 local tag = string.gsub(k2," ","_")
482                 streamTable[tag]=v2
483             end
484
485             s.information.category[k]=streamTable
486         end
487
488         s.stats={}
489
490         local statsdata = item:stats()
491           for k,v in pairs(statsdata) do
492             local tag = string.gsub(k,"_","")
493         s.stats[tag]=v
494       end
495     end
496     return s
497 end
498