]> git.sesse.net Git - vlc/blob - share/lua/intf/modules/httprequests.lua
Move vlc.misc.*dir to vlc.config.*dir
[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.gotoitem(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.gotoitem(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     elseif command == "title" then
181           vlc.var.set(vlc.object.input(), "title", val)
182         elseif command == "chapter" then
183           vlc.var.set(vlc.object.input(), "chapter", val)
184         elseif command == "audio_track" then
185           vlc.var.set(vlc.object.input(), "audio-es", val)
186         elseif command == "video_track" then
187           vlc.var.set(vlc.object.input(), "video-es", val)
188         elseif command == "subtitle_track" then
189           vlc.var.set(vlc.object.input(), "spu-es", val)
190     end
191
192     local input = nil
193     local command = nil
194     local id = nil
195     local val = nil
196
197 end
198
199 --utilities for formatting output
200
201 function xmlString(s)
202   if (type(s)=="string") then
203       return vlc.strings.convert_xml_special_chars(s)
204   else
205       return tostring(s)
206   end
207 end
208
209 --dkjson outputs numbered tables as arrays
210 --so we don't need the array indicators
211 function removeArrayIndicators(dict)
212     local newDict=dict
213
214     for k,v in pairs(dict) do
215         if (type(v)=="table") then
216             local arrayEntry=v._array
217             if arrayEntry then
218                 v=arrayEntry
219             end
220
221             dict[k]=removeArrayIndicators(v)
222         end
223     end
224
225     return newDict
226 end
227
228 printTableAsJson = function (dict)
229     dict=removeArrayIndicators(dict)
230
231     local output=dkjson.encode (dict, { indent = true })
232     print(output)
233 end
234
235 local printXmlKeyValue = function (k,v,indent)
236     print("\n")
237     for i=1,indent do print(" ") end
238     if (k) then
239         print("<"..k..">")
240     end
241
242     if (type(v)=="table") then
243         printTableAsXml(v,indent+2)
244     else
245         print(xmlString(v))
246     end
247
248     if (k) then
249         xs=xmlString(k)
250         space_loc=string.find(xs," ")
251         if space_loc == nil then
252             print("</"..xs..">")
253         else
254             xs=string.sub(xs,1,space_loc)
255             print("</"..xs..">")
256         end
257     end
258 end
259
260 printTableAsXml = function (dict,indent)
261     for k,v in pairs(dict) do
262         printXmlKeyValue(k,v,indent)
263     end
264 end
265
266 --[[
267 function logTable(t,pre)
268   local pre = pre or ""
269   for k,v in pairs(t) do
270     vlc.msg.err(pre..tostring(k).." : "..tostring(v))
271     if type(v) == "table" then
272       a(v,pre.."  ")
273     end
274   end
275 end
276 --]]
277
278 --main accessors
279
280 getplaylist = function ()
281     local p
282
283     if _GET["search"] then
284       if _GET["search"] ~= "" then
285         _G.search_key = _GET["search"]
286       else
287         _G.search_key = nil
288       end
289       local key = vlc.strings.decode_uri(_GET["search"])
290       p = vlc.playlist.search(key)
291     else
292       p = vlc.playlist.get()
293     end
294
295     --logTable(p) --Uncomment to debug
296
297     return p
298 end
299
300 parseplaylist = function (item)
301     if item.flags.disabled then return end
302
303     if (item.children) then
304         local result={}
305         local name = (item.name or "")
306
307         result["type"]="node"
308         result.id=tostring(item.id)
309         result.name=tostring(name)
310         result.ro=item.flags.ro and "ro" or "rw"
311
312         --store children in an array
313         --we use _array as a proxy for arrays
314         result.children={}
315         result.children._array={}
316
317         for _, child in ipairs(item.children) do
318             local nextChild=parseplaylist(child)
319             table.insert(result.children._array,nextChild)
320         end
321
322         return result
323     else
324         local result={}
325         local name, path = item.name or ""
326         local path = item.path or ""
327         local current_item = vlc.input.item()
328
329         -- Is the item the one currently played
330         if(current_item ~= nil) then
331             if(vlc.input.item().uri(current_item) == path) then
332                 result.current = "current"
333             end
334         end
335
336         result["type"]="leaf"
337         result.id=tostring(item.id)
338         result.uri=tostring(path)
339         result.name=name
340         result.ro=item.flags.ro and "ro" or "rw"
341         result.duration=math.floor(item.duration)
342
343         return result
344     end
345
346 end
347
348 playlisttable = function ()
349
350     local basePlaylist=getplaylist()
351
352     return parseplaylist(basePlaylist)
353 end
354
355 getbrowsetable = function ()
356
357     local dir = nil
358     local uri = _GET["uri"]
359     --uri takes precedence, but fall back to dir
360     if uri then
361         if uri == "file://~" then
362             dir = uri
363         else
364             dir = vlc.strings.make_path(uri)
365         end
366     else
367         dir = _GET["dir"]
368     end
369
370     --backwards compatibility with old format driveLetter:\\..
371     --this is forgiving with the slash type and number
372     if dir then
373         local position=string.find(dir, '%a:[\\/]*%.%.',0)
374         if position==1 then dir="" end
375     end
376
377     local result={}
378     --paths are returned as an array of elements
379     result.element={}
380     result.element._array={}
381
382     if dir then
383         if dir == "~" or dir == "file://~" then dir = vlc.config.homedir() end
384         -- FIXME: hack for Win32 drive list
385         if dir~="" then
386             dir = common.realpath(dir.."/")
387         end
388
389         local d = vlc.net.opendir(dir)
390         table.sort(d)
391
392         for _,f in pairs(d) do
393             if f == ".." or not string.match(f,"^%.") then
394                 local df = common.realpath(dir..f)
395                 local s = vlc.net.stat(df)
396                 local path, name =  df, f
397                 local element={}
398
399                 if (s) then
400                     for k,v in pairs(s) do
401                         element[k]=v
402                     end
403                 else
404                     element["type"]="unknown"
405                 end
406                 element["path"]=path
407                 element["name"]=name
408
409                 local uri=vlc.strings.make_uri(df)
410                 --windows paths are returned with / separators, but make_uri expects \ for windows and returns nil
411                 if not uri then
412                     --convert failed path to windows format and try again
413                     path=string.gsub(path,"/","\\")
414                     uri=vlc.strings.make_uri(df)
415                 end
416                 element["uri"]=uri
417
418                 table.insert(result.element._array,element)
419             end
420
421         end
422     end
423
424     return result;
425 end
426
427
428 getstatus = function (includecategories)
429
430
431 local input = vlc.object.input()
432 local item = vlc.input.item()
433 local playlist = vlc.object.playlist()
434 local vout = vlc.object.vout()
435 local aout = vlc.object.aout()
436
437     local s ={}
438
439     --update api version when new data/commands added
440     s.apiversion=2
441     s.version=vlc.misc.version()
442     s.volume=vlc.volume.get()
443
444     if input then
445         s.length=math.floor(vlc.var.get(input,"length"))
446         s.time=math.floor(vlc.var.get(input,"time"))
447         s.position=vlc.var.get(input,"position")
448         s.audiodelay=vlc.var.get(input,"audio-delay")
449         s.rate=vlc.var.get(input,"rate")
450         s.subtitledelay=vlc.var.get(input,"spu-delay")
451     else
452         s.length=0
453         s.time=0
454         s.position=0
455         s.audiodelay=0
456         s.rate=1
457         s.subtitledelay=0
458     end
459
460     if vout then
461         s.fullscreen=vlc.var.get(vout,"fullscreen")
462         s.aspectratio=vlc.var.get(vout,"aspect-ratio");
463         if s.aspectratio=="" then s.aspectratio = "default" end
464     else
465         s.fullscreen=0
466     end
467
468     if aout then
469         local filters=vlc.var.get(aout,"audio-filter")
470         local temp=strsplit(filters,":")
471         s.audiofilters={}
472         local id=0
473         for i,j in pairs(temp) do
474             s.audiofilters['filter_'..id]=j
475             id=id+1
476         end
477     end
478
479     s.videoeffects={}
480     s.videoeffects.hue=round(vlc.config.get("hue"),2)
481     s.videoeffects.brightness=round(vlc.config.get("brightness"),2)
482     s.videoeffects.contrast=round(vlc.config.get("contrast"),2)
483     s.videoeffects.saturation=round(vlc.config.get("saturation"),2)
484     s.videoeffects.gamma=round(vlc.config.get("gamma"),2)
485
486     s.state=vlc.playlist.status()
487     s.random=vlc.var.get(playlist,"random")
488     s.loop=vlc.var.get(playlist,"loop")
489     s["repeat"]=vlc.var.get(playlist,"repeat")
490
491         s.equalizer={}
492         s.equalizer.preamp=round(vlc.equalizer.preampget(),2)
493         s.equalizer.bands=vlc.equalizer.equalizerget()
494             if s.equalizer.bands ~= null then
495                 for k,i in pairs(s.equalizer.bands) do s.equalizer.bands[k]=round(i,2) end
496                 s.equalizer.presets=vlc.equalizer.presets()
497         end
498
499     if (includecategories and item) then
500         s.information={}
501         s.information.category={}
502         s.information.category.meta=item:metas()
503
504         local info = item:info()
505         for k, v in pairs(info) do
506             local streamTable={}
507             for k2, v2 in pairs(v) do
508                 local tag = string.gsub(k2," ","_")
509                 streamTable[tag]=v2
510             end
511
512             s.information.category[k]=streamTable
513         end
514
515         s.stats={}
516
517         local statsdata = item:stats()
518           for k,v in pairs(statsdata) do
519             local tag = string.gsub(k,"_","")
520         s.stats[tag]=v
521       end
522
523         s.information.chapters=vlc.var.get_list(input, "chapter")
524         s.information.titles=vlc.var.get_list(input, "title")
525
526     end
527     return s
528 end
529