]> git.sesse.net Git - vlc/blob - share/lua/intf/modules/httprequests.lua
clean up json output
[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         local result={}
350         --paths are returned as an array of elements
351         result.element={}
352         result.element._array={}
353
354         if dir then
355                 if dir == "~" then dir = vlc.misc.homedir() end
356                         dir = common.realpath(dir.."/")
357                         local d = vlc.net.opendir(dir)
358                         table.sort(d)
359
360                         for _,f in pairs(d) do
361                                 if f == ".." or not string.match(f,"^%.") then
362                                 local df = common.realpath(dir..f)
363                                 local s = vlc.net.stat(df)
364                                 local path, name =  df, f
365                                 local element={}
366
367                                 for k,v in pairs(s) do
368                                         element[k]=v
369                                 end
370                                 element["path"]=path
371                                 element["name"]=name
372
373                                 local uri=vlc.strings.make_uri(df)
374                                 --windows paths are returned with / separators, but make_uri expects \ for windows and returns nil
375                                 if not uri then
376                                         --convert failed path to windows format and try again
377                                         path=string.gsub(path,"/","\\")
378                                         uri=vlc.strings.make_uri(df)
379                                 end
380                                 element["uri"]=uri
381
382                                 table.insert(result.element._array,element)
383                         end
384
385                 end
386         end
387
388         return result;
389 end
390
391
392 getstatus = function (includecategories)
393
394
395 local input = vlc.object.input()
396 local item = vlc.input.item()
397 local playlist = vlc.object.playlist()
398 local vout = vlc.object.vout()
399 local aout = vlc.object.aout()
400
401         local s ={}
402
403         --update api version when new data/commands added
404         s.apiversion=1
405         s.version=vlc.misc.version()
406         s.volume=vlc.volume.get()
407
408         if input then
409                 s.length=math.floor(vlc.var.get(input,"length"))
410                 s.time=math.floor(vlc.var.get(input,"time"))
411                 s.position=vlc.var.get(input,"position")
412                 s.audiodelay=vlc.var.get(input,"audio-delay")
413                 s.rate=vlc.var.get(input,"rate")
414                 s.subtitledelay=vlc.var.get(input,"spu-delay")
415         else
416                 s.length=0
417                 s.time=0
418                 s.position=0
419                 s.audiodelay=0
420                 s.rate=1
421                 s.subtitledelay=0
422         end
423
424         if vout then
425                 s.fullscreen=vlc.var.get(vout,"fullscreen")
426                 s.aspectratio=vlc.var.get(vout,"aspect-ratio");
427                 if s.aspectratio=="" then s.aspectratio = "default" end
428         else
429                 s.fullscreen=0
430         end
431
432         if aout then
433                 local filters=vlc.var.get(aout,"audio-filter")
434                 local temp=strsplit(filters,":")
435                 s.audiofilters={}
436                 local id=0
437                 for i,j in pairs(temp) do
438                         s.audiofilters['filter_'..id]=j
439                         id=id+1
440                 end
441         end
442
443         s.videoeffects={}
444         s.videoeffects.hue=round(vlc.config.get("hue"),2)
445         s.videoeffects.brightness=round(vlc.config.get("brightness"),2)
446         s.videoeffects.contrast=round(vlc.config.get("contrast"),2)
447         s.videoeffects.saturation=round(vlc.config.get("saturation"),2)
448         s.videoeffects.gamma=round(vlc.config.get("gamma"),2)
449
450         s.state=vlc.playlist.status()
451         s.random=vlc.var.get(playlist,"random")
452         s.loop=vlc.var.get(playlist,"loop")
453         s["repeat"]=vlc.var.get(playlist,"repeat")
454
455         s.equalizer={}
456                 s.equalizer.preamp=round(vlc.equalizer.preampget(),2)
457                 s.equalizer.bands=vlc.equalizer.equalizerget()
458                 if s.equalizer.bands ~= null then
459                         for k,i in pairs(s.equalizer.bands) do s.equalizer.bands[k]=round(i,2) end
460                         s.equalizer.presets=vlc.equalizer.presets()
461                 end
462
463         if (includecategories and item) then
464                 s.information={}
465                 s.information.category={}
466                 s.information.category.meta=item:metas()
467
468                 local info = item:info()
469                 for k, v in pairs(info) do
470                         local streamTable={}
471                         for k2, v2 in pairs(v) do
472                                 local tag = string.gsub(k2," ","_")
473                                 streamTable[tag]=v2
474                         end
475
476                         s.information.category[k]=streamTable
477                 end
478
479                 s.stats={}
480
481                 local statsdata = item:stats()
482         for k,v in pairs(statsdata) do
483                 local tag = string.gsub(k,"_","")
484         s.stats[tag]=v
485       end
486         end
487         return s
488 end
489