Close properly from VLC

This commit is contained in:
Et0h 2014-06-02 20:27:53 +01:00
parent 97a499a34a
commit e23609edf5
2 changed files with 82 additions and 68 deletions

View File

@ -5,14 +5,14 @@
Principal author: Etoh Principal author: Etoh
Other contributors: DerGenaue, jb Other contributors: DerGenaue, jb
Project: http://syncplay.pl/ Project: http://syncplay.pl/
Version: 0.2.0 Version: 0.2.1
Note: Note:
* This interface module is intended to be used in conjunction with Syncplay. * This interface module is intended to be used in conjunction with Syncplay.
* Syncplay provides synchronized video playback across multiple media player instances over the net. * Syncplay provides synchronized video playback across multiple media player instances over the net.
* Syncplay allows group of people who all have the same videos to watch them together wherever they are. * Syncplay allows group of people who all have the same videos to watch them together wherever they are.
* Syncplay is available to download for free from http://syncplay.pl/ * Syncplay is available to download for free from http://syncplay.pl/
--[==========================================================================[ --[==========================================================================[
=== Installation instructions === === Installation instructions ===
@ -30,28 +30,28 @@ You may also need to re-copy the syncplay.lua file when you update VLC.
. .
? >> inputstate-change: [<input/no-input>] ? >> inputstate-change: [<input/no-input>]
? >> filepath-change-notification ? >> filepath-change-notification
* >> playstate: [<playing/paused/no-input>] * >> playstate: [<playing/paused/no-input>]
* >> position: [<decimal seconds/no-input>] * >> position: [<decimal seconds/no-input>]
get-interface-version get-interface-version
* >> interface-version: [syncplay connector version] * >> interface-version: [syncplay connector version]
get-duration get-duration
* >> duration: [<duration/no-input>] * >> duration: [<duration/no-input>]
get-filepath get-filepath
* >> filepath: [<filepath/no-input>] * >> filepath: [<filepath/no-input>]
get-filename get-filename
* >> filepath: [<filename/no-input>] * >> filepath: [<filename/no-input>]
get-title get-title
* >> title: [<title/no-input>] * >> title: [<title/no-input>]
set-position: [decimal seconds] set-position: [decimal seconds]
? >> play-error: no-input ? >> play-error: no-input
seek-within-title: [decimal seconds] seek-within-title: [decimal seconds]
? >> seek-within-title-error: no-input ? >> seek-within-title-error: no-input
@ -60,7 +60,7 @@ You may also need to re-copy the syncplay.lua file when you update VLC.
set-rate: [decimal rate] set-rate: [decimal rate]
? >> set-rate-error: no-input ? >> set-rate-error: no-input
set-title set-title
? >> set-title-error: no-input ? >> set-title-error: no-input
@ -86,10 +86,11 @@ else
require "common" require "common"
end end
local connectorversion = "0.2.0" local connectorversion = "0.2.1"
local durationdelay = 500000 -- Pause for get_duration command etc for increased reliability (uses microseconds) local durationdelay = 500000 -- Pause for get_duration command etc for increased reliability (uses microseconds)
local loopsleepduration = 5000 -- Pause for every event loop (uses microseconds) local loopsleepduration = 5000 -- Pause for every event loop (uses microseconds)
local quitcheckfrequency = 20 -- Check whether VLC has closed every X loops
local host = "localhost" local host = "localhost"
local port local port
@ -107,7 +108,7 @@ local noinput = "no-input"
local notimplemented = "not-implemented" local notimplemented = "not-implemented"
local unknowncommand = "unknown-command" local unknowncommand = "unknown-command"
local unknownstream = "(Unknown Stream)" local unknownstream = "(Unknown Stream)"
local oldfilepath local oldfilepath
local oldinputstate local oldinputstate
local newfilepath local newfilepath
@ -136,7 +137,7 @@ function detectchanges()
if vlc.object.input() then if vlc.object.input() then
newinputstate = "input" newinputstate = "input"
newfilepath = get_filepath() newfilepath = get_filepath()
if newfilepath ~= oldfilepath and get_filepath() ~= unknownstream then if newfilepath ~= oldfilepath and get_filepath() ~= unknownstream then
oldfilepath = newfilepath oldfilepath = newfilepath
notificationbuffer = notificationbuffer .. "filepath-change"..notificationmarker..msgterminator notificationbuffer = notificationbuffer .. "filepath-change"..notificationmarker..msgterminator
@ -149,30 +150,30 @@ function detectchanges()
end end
oldtitle = newtitle oldtitle = newtitle
notificationbuffer = notificationbuffer .. "playstate"..msgseperator..tostring(get_play_state())..msgterminator notificationbuffer = notificationbuffer .. "playstate"..msgseperator..tostring(get_play_state())..msgterminator
notificationbuffer = notificationbuffer .. "position"..msgseperator..tostring(get_time())..msgterminator notificationbuffer = notificationbuffer .. "position"..msgseperator..tostring(get_time())..msgterminator
else else
notificationbuffer = notificationbuffer .. "playstate"..msgseperator..noinput..msgterminator notificationbuffer = notificationbuffer .. "playstate"..msgseperator..noinput..msgterminator
notificationbuffer = notificationbuffer .. "position"..msgseperator..noinput..msgterminator notificationbuffer = notificationbuffer .. "position"..msgseperator..noinput..msgterminator
newinputstate = noinput newinputstate = noinput
end end
if newinputstate ~= oldinputstate then if newinputstate ~= oldinputstate then
oldinputstate = newinputstate oldinputstate = newinputstate
notificationbuffer = notificationbuffer.."inputstate-change"..msgseperator..tostring(newinputstate)..msgterminator notificationbuffer = notificationbuffer.."inputstate-change"..msgseperator..tostring(newinputstate)..msgterminator
end end
return notificationbuffer return notificationbuffer
end end
function get_args (argument, argcount) function get_args (argument, argcount)
-- Converts comma-space-seperated values into array of a given size, with last item absorbing all remaining data if needed. -- Converts comma-space-seperated values into array of a given size, with last item absorbing all remaining data if needed.
-- [Used by the display-osd command] -- [Used by the display-osd command]
local argarray = {} local argarray = {}
local index local index
local i local i
local argbuffer local argbuffer
argbuffer = argument argbuffer = argument
for i = 1, argcount,1 do for i = 1, argcount,1 do
@ -191,38 +192,38 @@ function get_args (argument, argcount)
argarray[i] = "" argarray[i] = ""
end end
end end
end end
return argarray return argarray
end end
function get_var( vartoget, fallbackvar ) function get_var( vartoget, fallbackvar )
-- [Used by the poll / '.' command to get time] -- [Used by the poll / '.' command to get time]
local response local response
local errormsg local errormsg
local input = vlc.object.input() local input = vlc.object.input()
if input then if input then
response = vlc.var.get(input,tostring(vartoget)) response = vlc.var.get(input,tostring(vartoget))
else else
response = fallbackvar response = fallbackvar
errormsg = noinput errormsg = noinput
end end
return response, errormsg return response, errormsg
end end
function set_var(vartoset, varvalue) function set_var(vartoset, varvalue)
-- [Used by the set-time and set-rate commands] -- [Used by the set-time and set-rate commands]
local errormsg local errormsg
local input = vlc.object.input() local input = vlc.object.input()
if input then if input then
vlc.var.set(input,tostring(vartoset),varvalue) vlc.var.set(input,tostring(vartoset),varvalue)
else else
@ -268,29 +269,29 @@ end
function get_play_state() function get_play_state()
-- [Used by the get-playstate command] -- [Used by the get-playstate command]
local response local response
local errormsg local errormsg
local input = vlc.object.input() local input = vlc.object.input()
if input then if input then
response = vlc.playlist.status() response = vlc.playlist.status()
else else
errormsg = noinput errormsg = noinput
end end
return response, errormsg return response, errormsg
end end
function get_filepath () function get_filepath ()
-- [Used by get-filepath command] -- [Used by get-filepath command]
local response local response
local errormsg local errormsg
local item local item
local input = vlc.object.input() local input = vlc.object.input()
if input then if input then
local item = vlc.input.item() local item = vlc.input.item()
if item then if item then
@ -312,13 +313,13 @@ function get_filepath ()
else else
errormsg = noinput errormsg = noinput
end end
return response, errormsg return response, errormsg
end end
function get_filename () function get_filename ()
-- [Used by get-filename command] -- [Used by get-filename command]
local response local response
local index local index
local filename local filename
@ -338,7 +339,7 @@ function get_filename ()
end end
end end
end end
if(filename ~= nil) and (filename ~= "") and (filename ~= noinput) then if(filename ~= nil) and (filename ~= "") and (filename ~= noinput) then
index = string.len(tostring(string.match(filename, ".*/"))) index = string.len(tostring(string.match(filename, ".*/")))
if string.sub(filename,1,3) == ":::" then if string.sub(filename,1,3) == ":::" then
@ -349,7 +350,7 @@ function get_filename ()
else else
response = noinput response = noinput
end end
return response return response
end end
@ -360,12 +361,12 @@ function get_duration ()
local errormsg local errormsg
local item local item
local input = vlc.object.input() local input = vlc.object.input()
if input then if input then
local item = vlc.input.item() local item = vlc.input.item()
if (item and item:duration()) then if (item and item:duration()) then
-- Try to get duration, which might not be available straight away -- Try to get duration, which might not be available straight away
local i = 0 local i = 0
repeat repeat
vlc.misc.mwait(vlc.misc.mdate() + durationdelay) vlc.misc.mwait(vlc.misc.mdate() + durationdelay)
response = item:duration() response = item:duration()
@ -377,14 +378,14 @@ function get_duration ()
else else
errormsg = noinput errormsg = noinput
end end
return response, errormsg return response, errormsg
end end
function display_osd ( argument ) function display_osd ( argument )
-- [Used by display-osd command] -- [Used by display-osd command]
local errormsg local errormsg
local osdarray local osdarray
local input = vlc.object.input() local input = vlc.object.input()
@ -401,7 +402,7 @@ end
function load_file (filepath) function load_file (filepath)
-- [Used by load-file command] -- [Used by load-file command]
local uri = vlc.strings.make_uri(filepath) local uri = vlc.strings.make_uri(filepath)
vlc.playlist.add({{path=uri}}) vlc.playlist.add({{path=uri}})
return "load-file-attempted\n" return "load-file-attempted\n"
@ -409,14 +410,14 @@ end
function do_command ( command, argument) function do_command ( command, argument)
-- Processes all commands sent by Syncplay (see protocol, above). -- Processes all commands sent by Syncplay (see protocol, above).
if command == "." then if command == "." then
do return detectchanges() end do return detectchanges() end
end end
local command = tostring(command) local command = tostring(command)
local argument = tostring(argument) local argument = tostring(argument)
local errormsg = "" local errormsg = ""
local response = "" local response = ""
if command == "get-interface-version" then response = "interface-version"..msgseperator..connectorversion..msgterminator if command == "get-interface-version" then response = "interface-version"..msgseperator..connectorversion..msgterminator
elseif command == "get-duration" then response = "duration"..msgseperator..errormerge(get_duration())..msgterminator elseif command == "get-duration" then response = "duration"..msgseperator..errormerge(get_duration())..msgterminator
@ -428,43 +429,43 @@ function do_command ( command, argument)
elseif command == "set-playstate" then errormsg = set_playstate(argument) elseif command == "set-playstate" then errormsg = set_playstate(argument)
elseif command == "set-rate" then errormsg = set_var("rate", tonumber(argument)) elseif command == "set-rate" then errormsg = set_var("rate", tonumber(argument))
elseif command == "set-title" then errormsg = set_var("title", tonumber(argument)) elseif command == "set-title" then errormsg = set_var("title", tonumber(argument))
elseif command == "display-osd" then errormsg = display_osd(argument) elseif command == "display-osd" then errormsg = display_osd(argument)
elseif command == "load-file" then response = load_file(argument) elseif command == "load-file" then response = load_file(argument)
elseif command == "close-vlc" then quit_vlc() elseif command == "close-vlc" then quit_vlc()
else errormsg = unknowncommand else errormsg = unknowncommand
end end
if (errormsg ~= nil) and (errormsg ~= "") then if (errormsg ~= nil) and (errormsg ~= "") then
response = command..errormarker..msgseperator..tostring(errormsg)..msgterminator response = command..errormarker..msgseperator..tostring(errormsg)..msgterminator
end end
return response return response
end end
function errormerge(argument, errormsg) function errormerge(argument, errormsg)
-- Used to integrate 'no-input' error messages into command responses. -- Used to integrate 'no-input' error messages into command responses.
if (errormsg ~= nil) and (errormsg ~= "") then if (errormsg ~= nil) and (errormsg ~= "") then
do return errormsg end do return errormsg end
end end
return argument return argument
end end
function set_playstate(argument) function set_playstate(argument)
-- [Used by the set-playstate command] -- [Used by the set-playstate command]
local errormsg local errormsg
local input = vlc.object.input() local input = vlc.object.input()
local playstate local playstate
playstate, errormsg = get_play_state() playstate, errormsg = get_play_state()
if playstate ~= "playing" then playstate = "paused" end if playstate ~= "playing" then playstate = "paused" end
if ((errormsg ~= noinput) and (playstate ~= argument)) then if ((errormsg ~= noinput) and (playstate ~= argument)) then
vlc.playlist.pause() vlc.playlist.pause()
end end
return errormsg return errormsg
end end
@ -477,23 +478,24 @@ else
end end
-- main loop, which alternates between writing and reading -- main loop, which alternates between writing and reading
while running == true do while running == true do
--accept new connections and select active clients --accept new connections and select active clients
local fd = l:accept() local quitcheckcounter = 0
local buffer, inputbuffer, responsebuffer = "", "", "" local fd = l:accept()
local buffer, inputbuffer, responsebuffer = ""
while fd >= 0 and running == true do while fd >= 0 and running == true do
-- handle read mode -- handle read mode
local str = vlc.net.recv ( fd, 1000) local str = vlc.net.recv ( fd, 1000)
local responsebuffer local responsebuffer
if str == nil then str = "" end if str == nil then str = "" end
local safestr = string.gsub(tostring(str), "\r", "") local safestr = string.gsub(tostring(str), "\r", "")
if inputbuffer == nil then inputbuffer = "" end if inputbuffer == nil then inputbuffer = "" end
inputbuffer = inputbuffer .. safestr inputbuffer = inputbuffer .. safestr
while string.find(inputbuffer, msgterminator) and running == true do while string.find(inputbuffer, msgterminator) and running == true do
@ -507,11 +509,11 @@ while running == true do
index = string.find(request, msgseperator) index = string.find(request, msgseperator)
command = string.sub(request, 0, index - 1) command = string.sub(request, 0, index - 1)
argument = string.sub(request, index + string.len(msgseperator)) argument = string.sub(request, index + string.len(msgseperator))
else else
command = request command = request
end end
if (responsebuffer) then if (responsebuffer) then
responsebuffer = responsebuffer .. do_command(command,argument) responsebuffer = responsebuffer .. do_command(command,argument)
else else
@ -519,19 +521,31 @@ while running == true do
end end
end end
if (running == false) then if (running == false) then
net.close(fd) net.close(fd)
end end
-- handle write mode -- handle write mode
if (responsebuffer and running == true) then if (responsebuffer and running == true) then
vlc.net.send( fd, responsebuffer ) vlc.net.send( fd, responsebuffer )
responsebuffer = "" responsebuffer = ""
end end
vlc.misc.mwait(vlc.misc.mdate() + loopsleepduration) -- Don't waste processor time vlc.misc.mwait(vlc.misc.mdate() + loopsleepduration) -- Don't waste processor time
-- check if VLC has been closed
quitcheckcounter = quitcheckcounter + 1
if quitcheckcounter > quitcheckfrequency then
if vlc.volume.get() == -256 then
running = false
end
quitcheckcounter = 0
end
end end
end end

View File

@ -43,7 +43,7 @@ COMMANDS_ROOM = ["r", "room"]
COMMANDS_HELP = ['help', 'h', '?', '/?', r'\?'] COMMANDS_HELP = ['help', 'h', '?', '/?', r'\?']
MPC_MIN_VER = "1.6.4" MPC_MIN_VER = "1.6.4"
VLC_MIN_VERSION = "2.0.0" VLC_MIN_VERSION = "2.0.0"
VLC_INTERFACE_MIN_VERSION = "0.2.0" VLC_INTERFACE_MIN_VERSION = "0.2.1"
MPC_PATHS = [ MPC_PATHS = [
r"C:\Program Files (x86)\MPC-HC\mpc-hc.exe", r"C:\Program Files (x86)\MPC-HC\mpc-hc.exe",
r"C:\Program Files\MPC-HC\mpc-hc.exe", r"C:\Program Files\MPC-HC\mpc-hc.exe",