]> git.sesse.net Git - vlc/blobdiff - share/lua/intf/rc.lua
Add new common.volume(). Understands use of strings like "+10", "-10" or "10" for...
[vlc] / share / lua / intf / rc.lua
index 17a62789ece416a9e56d373eb1cde9a14a521b19..1926497ba2e29d68775fb3050f5573de5862d993 100644 (file)
@@ -1,7 +1,7 @@
 --[==========================================================================[
  rc.lua: remote control module for VLC
 --[==========================================================================[
- Copyright (C) 2007 the VideoLAN team
+ Copyright (C) 2007-2009 the VideoLAN team
  $Id$
 
  Authors: Antoine Cellerier <dionoea at videolan dot org>
@@ -26,14 +26,14 @@ description=
  Remote control interface for VLC
 
  This is a modules/control/rc.c look alike (with a bunch of new features)
+
  Use on local term:
     vlc -I luarc
  Use on tcp connection:
     vlc -I luarc --lua-config "rc={host='localhost:4212'}"
  Use on multiple hosts (term + 2 tcp ports):
     vlc -I luarc --lua-config "rc={hosts={'*console','localhost:4212','localhost:5678'}}"
+
  Note:
     -I luarc is an alias for -I lua --lua-intf rc
 
@@ -73,7 +73,7 @@ for k,v in pairs(env) do
     if config[k] then
         if type(env[k]) == type(config[k]) then
             env[k] = config[k]
-            vlc.msg.dbg("set environement variable `"..k.."' to "..tonumber(env[k]))
+            vlc.msg.dbg("set environement variable `"..k.."' to "..tostring(env[k]))
         else
             vlc.msg.err("environement variable `"..k.."' should be of type "..type(env[k])..". config value will be discarded.")
         end
@@ -143,7 +143,7 @@ function shutdown(name,client)
     client:append("Bye-bye!")
     h:broadcast("Shutting down.")
     vlc.msg.info("Requested shutdown.")
-    vlc.quit()
+    vlc.misc.quit()
 end
 
 function quit(name,client)
@@ -155,14 +155,19 @@ function quit(name,client)
 end
 
 function add(name,client,arg)
-    -- TODO: parse (and use) options
+    -- TODO: par single and double quotes properly
     local f
     if name == "enqueue" then
         f = vlc.playlist.enqueue
     else
         f = vlc.playlist.add
     end
-    f({{path=arg}})
+    local options = {}
+    for o in string.gmatch(arg," +:([^ ]*)") do
+        table.insert(options,o)
+    end
+    arg = string.gsub(arg," +:.*$","")
+    f({{path=arg,options=options}})
 end
 
 function playlist_is_tree( client )
@@ -303,7 +308,7 @@ function help(name,client,arg)
 end
 
 function input_info(name,client)
-    local categories = vlc.input_info()
+    local categories = vlc.input.info()
     for cat, infos in pairs(categories) do
         client:append("+----[ "..cat.." ]")
         client:append("|")
@@ -315,15 +320,43 @@ function input_info(name,client)
     client:append("+----[ end of stream info ]")
 end
 
+function stats(name,client)
+    local stats_tab = vlc.input.stats()
+
+    client:append("+----[ begin of statistical info")
+    client:append("+-[Incoming]")
+    client:append("| input bytes read : "..string.format("%8.0f kB",stats_tab["read_bytes"]/1000))
+    client:append("| input bitrate    :   "..string.format("%6.0f bB/s",stats_tab["input_bitrate"]*8000))
+    client:append("| demux bytes read : "..string.format("%8.0f kB",stats_tab["demux_read_bytes"]/1000))
+    client:append("| demux bitrate    :   "..string.format("%6.0f kB/s",stats_tab["demux_bitrate"]*8000))
+    client:append("| demux corrupted  :    "..string.format("%5i",stats_tab["demux_corrupted"]))
+    client:append("| discontinuities  :    "..string.format("%5i",stats_tab["demux_discontinuity"]))
+    client:append("|")
+    client:append("+-[Video Decoding]")
+    client:append("| video decoded    :    "..string.format("%5i",stats_tab["decoded_video"]))
+    client:append("| frames displayed :    "..string.format("%5i",stats_tab["displayed_pictures"]))
+    client:append("| frames lost      :    "..string.format("%5i",stats_tab["lost_pictures"]))
+    client:append("|")
+    client:append("+-[Audio Decoding]")
+    client:append("| audio decoded    :    "..string.format("%5i",stats_tab["decoded_audio"]))
+    client:append("| buffers played   :    "..string.format("%5i",stats_tab["played_abuffers"]))
+    client:append("| buffers lost     :    "..string.format("%5i",stats_tab["lost_abuffers"]))
+    client:append("|")
+    client:append("+-[Streaming]")
+    client:append("| packets sent     :    "..string.format("%5i",stats_tab["sent_packets"]))
+    client:append("| bytes sent       : "..string.format("%8.0f kB",stats_tab["sent_bytes"]/1000))
+    client:append("| sending bitrate  :   "..string.format("%6.0f kb/s",stats_tab["send_bitrate"]*8000))
+    client:append("+----[ end of statistical info ]")
+end
+
 function playlist_status(name,client)
-    local a,b,c = vlc.playlist.status()
-    client:append( "( new input: " .. tostring(a) .. " )" )
-    client:append( "( audio volume: " .. tostring(b) .. " )")
-    client:append( "( state " .. tostring(c) .. " )")
+    client:append( "( new input: " .. "FIXME" .. " )" )
+    client:append( "( audio volume: " .. tostring(vlc.volume.get()) .. " )")
+    client:append( "( state " .. vlc.playlist.status() .. " )")
 end
 
 function is_playing(name,client)
-    if vlc.is_playing() then client:append "1" else client:append "0" end
+    if vlc.input.is_playing() then client:append "1" else client:append "0" end
 end
 
 function ret_print(foo,start,stop)
@@ -332,8 +365,8 @@ function ret_print(foo,start,stop)
     return function(discard,client,...) client:append(start..tostring(foo(...))..stop) end
 end
 
-function get_time(var,client)
-    return function()
+function get_time(var)
+    return function(name,client)
         local input = vlc.object.input()
         client:append(math.floor(vlc.var.get( input, var )))
     end
@@ -347,7 +380,7 @@ function titlechap(name,client,value)
     else
         local item = vlc.var.get( input, var )
         -- Todo: add item name conversion
-        client:apped(item)
+        client:append(item)
     end
 end
 function titlechap_offset(client,offset)
@@ -364,7 +397,7 @@ end
 
 function volume(name,client,value)
     if value then
-        vlc.volume.set(value)
+        common.volume(value)
     else
         client:append(tostring(vlc.volume.get()))
     end
@@ -373,12 +406,16 @@ end
 function rate(name,client)
     local input = vlc.object.input()
     if name == "normal" then
-        vlc.var.set(input,"rate",1000) -- FIXME: INPUT_RATE_DEFAULT
+        vlc.var.set(input,"rate",1)
     else
         vlc.var.set(input,"rate-"..name,nil)
     end
 end
 
+function frame(name,client)
+    vlc.var.trigger_callback(vlc.object.input(),"frame-next");
+end
+
 function listvalue(obj,var)
     return function(client,value)
         local o = vlc.object.find(nil,obj,"anywhere")
@@ -438,11 +475,13 @@ commands_ordered = {
     { "faster"; { func = rate; help = "faster playing of stream" } };
     { "slower"; { func = rate; help = "slower playing of stream" } };
     { "normal"; { func = rate; help = "normal playing of stream" } };
-    { "fullscreen"; { func = skip2(vlc.fullscreen); args = "[on|off]"; help = "toggle fullscreen"; aliases = { "f", "F" } } };
+    { "frame"; { func = frame; help = "play frame by frame" } };
+    { "fullscreen"; { func = skip2(vlc.video.fullscreen); args = "[on|off]"; help = "toggle fullscreen"; aliases = { "f", "F" } } };
     { "info"; { func = input_info; help = "information about the current stream" } };
+    { "stats"; { func = stats; help = "show statistical information" } };
     { "get_time"; { func = get_time("time"); help = "seconds elapsed since stream's beginning" } };
     { "is_playing"; { func = is_playing; help = "1 if a stream plays, 0 otherwise" } };
-    { "get_title"; { func = ret_print(vlc.get_title); help = "the title of the current stream" } };
+    { "get_title"; { func = ret_print(vlc.input.get_title); help = "the title of the current stream" } };
     { "get_length"; { func = get_time("length"); help = "the length of the current stream" } };
     { "" };
     { "volume"; { func = volume; args = "[X]"; help = "set/get audio volume" } };
@@ -465,7 +504,7 @@ commands_ordered = {
     { "alias"; { func = skip(alias); args = "[cmd]"; help = "set/get command aliases"; adv = true } };
     { "eval"; { func = skip(eval); help = "eval some lua (*debug*)"; adv =true } }; -- FIXME: comment out if you're not debugging
     { "description"; { func = print_text("Description",description); help = "describe this module" } };
-    { "license"; { func = print_text("License message",vlc.license()); help = "print VLC's license message"; adv = true } };
+    { "license"; { func = print_text("License message",vlc.misc.license()); help = "print VLC's license message"; adv = true } };
     { "help"; { func = help; args = "[pattern]"; help = "a help message"; aliases = { "?" } } };
     { "longhelp"; { func = help; args = "[pattern]"; help = "a longer help message" } };
     { "logout"; { func = logout; help = "exit (if in a socket connection)" } };
@@ -508,7 +547,7 @@ do
         end
     end
     list = list..")"
-    if count ~= 0 then
+    if count ~= 0 and env.welcome then
         env.welcome = env.welcome .. "\r\nWarning: "..count.." functions are still unimplemented "..list.."."
     end
 end
@@ -542,7 +581,7 @@ function call_command(cmd,client,arg)
 end
 
 function call_libvlc_command(cmd,client,arg)
-    local ok, vlcerr, vlcmsg = pcall( vlc.libvlc_command, cmd, arg )
+    local ok, vlcerr, vlcmsg = pcall( vlc.var.libvlc_command, cmd, arg )
     if not ok then
         local a = arg or ""
         if a ~= "" then a = " " .. a end
@@ -551,6 +590,18 @@ function call_libvlc_command(cmd,client,arg)
     return vlcerr
 end
 
+function call_object_command(cmd,client,arg)
+    local var, val = split_input(arg)
+    local ok, vlcmsg, vlcerr, vlcerrmsg = pcall( vlc.var.command, cmd, var, val )
+    if not ok then
+        client:append("Error in `"..cmd.." "..var.." "..val.."' ".. vlcmsg) -- when pcall fails the 2nd arg is the error message
+    end
+    if vlcmsg ~= "" then
+        client:append(vlcmsg)
+    end
+    return vlcerr
+end
+
 --[[ Setup host ]]
 require("host")
 h = host.host()
@@ -568,7 +619,7 @@ end
 h:listen( config.hosts or config.host or "*console" )
 
 --[[ The main loop ]]
-while not vlc.should_die() do
+while not vlc.misc.should_die() do
     h:accept()
     local write, read = h:select(0.1)
 
@@ -599,36 +650,38 @@ while not vlc.should_die() do
             client:switch_status(host.status.write)
             if commands[cmd] then
                 call_command(cmd,client,arg)
+            elseif string.sub(cmd,0,1)=='@'
+            and call_object_command(string.sub(cmd,2,#cmd),client,arg) == 0 then
+                --
+            elseif client.type == host.client_type.stdio
+            and call_libvlc_command(cmd,client,arg) == 0 then
+                --
             else
-                if client.type == host.client_type.stdio 
-                and call_libvlc_command(cmd,client,arg) == 0 then
-                else
-                    local choices = {}
-                    if client.env.autocompletion ~= 0 then
-                        for v,_ in common.pairs_sorted(commands) do
-                            if string.sub(v,0,#cmd)==cmd then
-                                table.insert(choices, v)
-                            end
+                local choices = {}
+                if client.env.autocompletion ~= 0 then
+                    for v,_ in common.pairs_sorted(commands) do
+                        if string.sub(v,0,#cmd)==cmd then
+                            table.insert(choices, v)
                         end
                     end
-                    if #choices == 1 and client.env.autoalias ~= 0 then
-                        -- client:append("Aliasing to \""..choices[1].."\".")
-                        cmd = choices[1]
-                        call_command(cmd,client,arg)
-                    else
-                        client:append("Unknown command `"..cmd.."'. Type `help' for help.")
-                        if #choices ~= 0 then
-                            client:append("Possible choices are:")
-                            local cols = math.floor(client.env.width/(client.env.colwidth+1))
-                            local fmt = "%-"..client.env.colwidth.."s"
-                            for i = 1, #choices do
-                                choices[i] = string.format(fmt,choices[i])
-                            end
-                            for i = 1, #choices, cols do
-                                local j = i + cols - 1
-                                if j > #choices then j = #choices end
-                                client:append("  "..table.concat(choices," ",i,j))
-                            end
+                end
+                if #choices == 1 and client.env.autoalias ~= 0 then
+                    -- client:append("Aliasing to \""..choices[1].."\".")
+                    cmd = choices[1]
+                    call_command(cmd,client,arg)
+                else
+                    client:append("Unknown command `"..cmd.."'. Type `help' for help.")
+                    if #choices ~= 0 then
+                        client:append("Possible choices are:")
+                        local cols = math.floor(client.env.width/(client.env.colwidth+1))
+                        local fmt = "%-"..client.env.colwidth.."s"
+                        for i = 1, #choices do
+                            choices[i] = string.format(fmt,choices[i])
+                        end
+                        for i = 1, #choices, cols do
+                            local j = i + cols - 1
+                            if j > #choices then j = #choices end
+                            client:append("  "..table.concat(choices," ",i,j))
                         end
                     end
                 end