use named pipes for mpv on windows

currently using non-blocking mode which involves a sleep in the read
loop - overlapped i/o might be a better option in the future
This commit is contained in:
Damien Elmes 2017-09-30 19:32:48 +10:00
parent 7dc8f82906
commit e8b4d276b4

View file

@ -54,6 +54,9 @@ class MPVCommandError(MPVError):
class MPVTimeoutError(MPVError):
pass
from anki.utils import isWin
if isWin:
import win32file, win32pipe, pywintypes, winerror
class MPVBase:
"""Base class for communication with the mpv media player via unix socket
@ -64,7 +67,9 @@ class MPVBase:
default_argv = [
"--idle",
"--no-terminal"
"--no-terminal",
"--force-window=no",
"--ontop",
]
def __init__(self, window_id=None, debug=False):
@ -119,6 +124,9 @@ class MPVBase:
"""Create a random socket filename which we pass to mpv with the
--input-unix-socket option.
"""
if isWin:
self._sock_filename = "ankimpv"
return
fd, self._sock_filename = tempfile.mkstemp(prefix="mpv.")
os.close(fd)
os.remove(self._sock_filename)
@ -132,6 +140,14 @@ class MPVBase:
time.sleep(0.1)
try:
if isWin:
self._sock = win32file.CreateFile(r'\\.\pipe\ankimpv',
win32file.GENERIC_READ | win32file.GENERIC_WRITE,
0, None, win32file.OPEN_EXISTING, 0, None)
win32pipe.SetNamedPipeHandleState(self._sock,
1, # PIPE_NOWAIT
None, None)
else:
self._sock = socket.socket(socket.AF_UNIX)
self._sock.connect(self._sock_filename)
except (FileNotFoundError, ConnectionRefusedError):
@ -179,6 +195,19 @@ class MPVBase:
"""
buf = b""
while not self._stop_event.is_set():
if isWin:
try:
(n, b) = win32file.ReadFile(self._sock, 4096)
buf += b
except pywintypes.error as err:
if err.args[0] == winerror.ERROR_NO_DATA:
time.sleep(0.1)
continue
elif err.args[0] == winerror.ERROR_BROKEN_PIPE:
return
else:
raise
else:
r, w, e = select.select([self._sock], [], [], 1)
if r:
b = self._sock.recv(1024)
@ -264,6 +293,9 @@ class MPVBase:
raise MPVTimeoutError("unable to put request")
# Write the message data to the socket.
if isWin:
win32file.WriteFile(self._sock, data)
else:
while data:
size = self._sock.send(data)
if size == 0: