Update python-mpv-jsonipc to v1.1.11

This commit is contained in:
et0h 2020-05-13 22:46:20 +01:00
parent 956ba07e0a
commit 532a991692
3 changed files with 61 additions and 28 deletions

View File

@ -31,7 +31,7 @@ function will be called for each inbound message.
#### \_\_init\_\_
``` python
| __init__(ipc_socket, callback=None)
| __init__(ipc_socket, callback=None, quit_callback=None)
```
Create the wrapper.
@ -87,7 +87,7 @@ function will be called for each inbound message.
#### \_\_init\_\_
``` python
| __init__(ipc_socket, callback=None)
| __init__(ipc_socket, callback=None, quit_callback=None)
```
Create the wrapper.
@ -175,7 +175,7 @@ Low-level interface to MPV. Does NOT manage an mpv process. (Internal)
#### \_\_init\_\_
``` python
| __init__(ipc_socket, callback=None)
| __init__(ipc_socket, callback=None, quit_callback=None)
```
Create the wrapper.
@ -293,7 +293,7 @@ list is used. Not all commands may actually work when this fallback is used.
#### \_\_init\_\_
``` python
| __init__(start_mpv=True, ipc_socket=None, mpv_location=None, log_handler=None, loglevel=None, ****kwargs)
| __init__(start_mpv=True, ipc_socket=None, mpv_location=None, log_handler=None, loglevel=None, quit_callback=None, ****kwargs)
```
Create the interface to MPV and process instance.
@ -407,7 +407,7 @@ Remove callback to an MPV property change.
Decorator to bind a callback to an MPV property change.
@on\_key\_press(property\_name)
@property\_observer(property\_name)
def my\_callback(name, data):
pass
@ -441,7 +441,7 @@ Play the specified URL. An alias to loadfile().
| terminate()
```
Terminate the connection to MPV and process (if started by this module).
Terminate the connection to MPV and process (if **start\_mpv** is used).
<a name=".python_mpv_jsonipc.MPV.command"></a>

View File

@ -42,14 +42,16 @@ class WindowsSocket(threading.Thread):
Data is automatically encoded and decoded as JSON. The callback
function will be called for each inbound message.
"""
def __init__(self, ipc_socket, callback=None):
def __init__(self, ipc_socket, callback=None, quit_callback=None):
"""Create the wrapper.
*ipc_socket* is the pipe name. (Not including \\\\.\\pipe\\)
*callback(json_data)* is the function for recieving events.
*quit_callback* is called when the socket connection dies.
"""
ipc_socket = "\\\\.\\pipe\\" + ipc_socket
self.callback = callback
self.quit_callback = quit_callback
access = _winapi.GENERIC_READ | _winapi.GENERIC_WRITE
limit = 5 # Connection may fail at first. Try 5 times.
@ -71,15 +73,21 @@ class WindowsSocket(threading.Thread):
threading.Thread.__init__(self)
def stop(self):
def stop(self, join=True):
"""Terminate the thread."""
if self.socket is not None:
self.socket.close()
self.join()
if join:
self.join()
def send(self, data):
"""Send *data* to the pipe, encoded as JSON."""
self.socket.send_bytes(json.dumps(data).encode('utf-8') + b'\n')
try:
self.socket.send_bytes(json.dumps(data).encode('utf-8') + b'\n')
except OSError as ex:
if len(ex.args) == 1 and ex.args[0] == "handle is closed":
raise BrokenPipeError("handle is closed")
raise ex
def run(self):
"""Process pipe events. Do not run this directly. Use *start*."""
@ -102,7 +110,8 @@ class WindowsSocket(threading.Thread):
self.callback(json_data)
data = b''
except EOFError:
pass
if self.quit_callback:
self.quit_callback()
class UnixSocket(threading.Thread):
"""
@ -111,14 +120,16 @@ class UnixSocket(threading.Thread):
Data is automatically encoded and decoded as JSON. The callback
function will be called for each inbound message.
"""
def __init__(self, ipc_socket, callback=None):
def __init__(self, ipc_socket, callback=None, quit_callback=None):
"""Create the wrapper.
*ipc_socket* is the path to the socket.
*callback(json_data)* is the function for recieving events.
*quit_callback* is called when the socket connection dies.
"""
self.ipc_socket = ipc_socket
self.callback = callback
self.quit_callback = quit_callback
self.socket = socket.socket(socket.AF_UNIX)
self.socket.connect(self.ipc_socket)
@ -127,15 +138,22 @@ class UnixSocket(threading.Thread):
threading.Thread.__init__(self)
def stop(self):
def stop(self, join=True):
"""Terminate the thread."""
if self.socket is not None:
self.socket.shutdown(socket.SHUT_WR)
self.socket.close()
self.join()
try:
self.socket.shutdown(socket.SHUT_WR)
self.socket.close()
self.socket = None
except OSError:
pass # Ignore socket close failure.
if join:
self.join()
def send(self, data):
"""Send *data* to the socket, encoded as JSON."""
if self.socket is None:
raise BrokenPipeError("socket is closed")
self.socket.send(json.dumps(data).encode('utf-8') + b'\n')
def run(self):
@ -157,6 +175,8 @@ class UnixSocket(threading.Thread):
json_data = json.loads(item)
self.callback(json_data)
data = b''
if self.quit_callback:
self.quit_callback()
class MPVProcess:
"""
@ -236,21 +256,23 @@ class MPVInter:
"""
Low-level interface to MPV. Does NOT manage an mpv process. (Internal)
"""
def __init__(self, ipc_socket, callback=None):
def __init__(self, ipc_socket, callback=None, quit_callback=None):
"""Create the wrapper.
*ipc_socket* is the path to the Unix/Linux socket or name of the Windows pipe.
*callback(event_name, data)* is the function for recieving events.
*quit_callback* is called when the socket connection to MPV dies.
"""
Socket = UnixSocket
if os.name == 'nt':
Socket = WindowsSocket
self.callback = callback
self.quit_callback = quit_callback
if self.callback is None:
self.callback = lambda event, data: None
self.socket = Socket(ipc_socket, self.event_callback)
self.socket = Socket(ipc_socket, self.event_callback, self.quit_callback)
self.socket.start()
self.command_id = 1
self.rid_lock = threading.Lock()
@ -258,9 +280,9 @@ class MPVInter:
self.cid_result = {}
self.cid_wait = {}
def stop(self):
def stop(self, join=True):
"""Terminate the underlying connection."""
self.socket.stop()
self.socket.stop(join)
def event_callback(self, data):
"""Internal callback for recieving events from MPV."""
@ -326,10 +348,10 @@ class EventHandler(threading.Thread):
"""
self.queue.put((func, args))
def stop(self):
def stop(self, join=True):
"""Terminate the thread."""
self.queue.put("quit")
self.join()
self.join(join)
def run(self):
"""Process socket events. Do not run this directly. Use *start*."""
@ -352,7 +374,8 @@ class MPV:
Please note that if you are using a really old MPV version, a fallback command
list is used. Not all commands may actually work when this fallback is used.
"""
def __init__(self, start_mpv=True, ipc_socket=None, mpv_location=None, log_handler=None, loglevel=None, **kwargs):
def __init__(self, start_mpv=True, ipc_socket=None, mpv_location=None,
log_handler=None, loglevel=None, quit_callback=None, **kwargs):
"""
Create the interface to MPV and process instance.
@ -361,6 +384,7 @@ class MPV:
*mpv_location* is the location of MPV for *start_mpv*. (Default: Use MPV in PATH)
*log_handler(level, prefix, text)* is an optional handler for log events. (Default: Disabled)
*loglevel* is the level for log messages. Levels are fatal, error, warn, info, v, debug, trace. (Default: Disabled)
*quit_callback* is called when the socket connection to MPV dies.
All other arguments are forwarded to MPV as command-line arguments if *start_mpv* is used.
"""
@ -370,6 +394,7 @@ class MPV:
self.property_bindings = {}
self.mpv_process = None
self.mpv_inter = None
self.quit_callback = quit_callback
self.event_handler = EventHandler()
self.event_handler.start()
if ipc_socket is None:
@ -391,7 +416,7 @@ class MPV:
else:
raise MPVError("MPV process retry limit reached.")
self.mpv_inter = MPVInter(ipc_socket, self._callback)
self.mpv_inter = MPVInter(ipc_socket, self._callback, self._quit_callback)
self.properties = set(x.replace("-", "_") for x in self.command("get_property", "property-list"))
try:
command_list = [x["name"] for x in self.command("get_property", "command-list")]
@ -426,6 +451,14 @@ class MPV:
if len(args) == 2 and args[0] == "custom-bind":
self.event_handler.put_task(self.key_bindings[args[1]])
def _quit_callback(self):
"""
Internal handler for quit events.
"""
if self.quit_callback:
self.quit_callback()
self.terminate(join=False)
def bind_event(self, name, callback):
"""
Bind a callback to an MPV event.
@ -563,13 +596,13 @@ class MPV:
def __del__(self):
self.terminate()
def terminate(self):
def terminate(self, join=True):
"""Terminate the connection to MPV and process (if *start_mpv* is used)."""
if self.mpv_process:
self.mpv_process.stop()
if self.mpv_inter:
self.mpv_inter.stop()
self.event_handler.stop()
self.mpv_inter.stop(join)
self.event_handler.stop(join)
def command(self, command, *args):
"""

View File

@ -6,7 +6,7 @@ with open("README.md", "r") as fh:
setup(
name='python-mpv-jsonipc',
version='1.1.10',
version='1.1.11',
author="Ian Walton",
author_email="iwalton3@gmail.com",
description="Python API to MPV using JSON IPC",