python-mpv-jsonipc 1.2.0__py3-none-any.whl → 1.2.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_mpv_jsonipc-1.2.0.dist-info → python_mpv_jsonipc-1.2.2.dist-info}/METADATA +7 -10
- python_mpv_jsonipc-1.2.2.dist-info/RECORD +6 -0
- {python_mpv_jsonipc-1.2.0.dist-info → python_mpv_jsonipc-1.2.2.dist-info}/WHEEL +1 -1
- python_mpv_jsonipc.py +35 -23
- python_mpv_jsonipc-1.2.0.dist-info/RECORD +0 -6
- {python_mpv_jsonipc-1.2.0.dist-info → python_mpv_jsonipc-1.2.2.dist-info/licenses}/LICENSE.md +0 -0
- {python_mpv_jsonipc-1.2.0.dist-info → python_mpv_jsonipc-1.2.2.dist-info}/top_level.txt +0 -0
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: python-mpv-jsonipc
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.2
|
|
4
4
|
Summary: Python API to MPV using JSON IPC
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
License: Apache-2.0
|
|
9
|
-
Platform: UNKNOWN
|
|
5
|
+
Author-email: Izzie Walton <izzie@iwalton.com>
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/iwalton3/python-mpv-jsonipc
|
|
10
8
|
Classifier: Programming Language :: Python :: 3
|
|
11
|
-
Classifier: License :: OSI Approved :: Apache Software License
|
|
12
9
|
Classifier: Operating System :: OS Independent
|
|
13
10
|
Requires-Python: >=3.6
|
|
14
11
|
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE.md
|
|
13
|
+
Dynamic: license-file
|
|
15
14
|
|
|
16
15
|
# Python MPV JSONIPC
|
|
17
16
|
|
|
@@ -69,5 +68,3 @@ def handle_eof(name, value):
|
|
|
69
68
|
# Or simply wait for the value to change once.
|
|
70
69
|
mpv.wait_for_property("duration")
|
|
71
70
|
```
|
|
72
|
-
|
|
73
|
-
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
python_mpv_jsonipc.py,sha256=McfALK21Mp48Ekpg8wszSnHlSExtlrpsrw90i9syvng,24041
|
|
2
|
+
python_mpv_jsonipc-1.2.2.dist-info/licenses/LICENSE.md,sha256=7GQBUOA3dNG1Jk-yaPOCncNnRVURCRMev23QpZ1ew-s,10495
|
|
3
|
+
python_mpv_jsonipc-1.2.2.dist-info/METADATA,sha256=AjVHMMb5-bKwYuf89xM3J9jLRPX17v-iXkMvuft8AF0,2277
|
|
4
|
+
python_mpv_jsonipc-1.2.2.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
5
|
+
python_mpv_jsonipc-1.2.2.dist-info/top_level.txt,sha256=nGk4yjpVHKmIrL39XdGD2PhCeWF0oMjwey0nsNOd2TM,19
|
|
6
|
+
python_mpv_jsonipc-1.2.2.dist-info/RECORD,,
|
python_mpv_jsonipc.py
CHANGED
|
@@ -38,7 +38,7 @@ class MPVError(Exception):
|
|
|
38
38
|
class WindowsSocket(threading.Thread):
|
|
39
39
|
"""
|
|
40
40
|
Wraps a Windows named pipe in a high-level interface. (Internal)
|
|
41
|
-
|
|
41
|
+
|
|
42
42
|
Data is automatically encoded and decoded as JSON. The callback
|
|
43
43
|
function will be called for each inbound message.
|
|
44
44
|
"""
|
|
@@ -52,7 +52,8 @@ class WindowsSocket(threading.Thread):
|
|
|
52
52
|
ipc_socket = "\\\\.\\pipe\\" + ipc_socket
|
|
53
53
|
self.callback = callback
|
|
54
54
|
self.quit_callback = quit_callback
|
|
55
|
-
|
|
55
|
+
self._stopping = False
|
|
56
|
+
|
|
56
57
|
access = _winapi.GENERIC_READ | _winapi.GENERIC_WRITE
|
|
57
58
|
limit = 5 # Connection may fail at first. Try 5 times.
|
|
58
59
|
for _ in range(limit):
|
|
@@ -72,9 +73,11 @@ class WindowsSocket(threading.Thread):
|
|
|
72
73
|
self.callback = lambda data: None
|
|
73
74
|
|
|
74
75
|
threading.Thread.__init__(self)
|
|
76
|
+
self.daemon = True
|
|
75
77
|
|
|
76
78
|
def stop(self, join=True):
|
|
77
79
|
"""Terminate the thread."""
|
|
80
|
+
self._stopping = True
|
|
78
81
|
if self.socket is not None:
|
|
79
82
|
try:
|
|
80
83
|
self.socket.close()
|
|
@@ -116,14 +119,16 @@ class WindowsSocket(threading.Thread):
|
|
|
116
119
|
if self.quit_callback:
|
|
117
120
|
self.quit_callback()
|
|
118
121
|
except Exception as ex:
|
|
119
|
-
log
|
|
122
|
+
# Only log if not intentionally stopping
|
|
123
|
+
if not self._stopping:
|
|
124
|
+
log.error("Pipe connection died.", exc_info=1)
|
|
120
125
|
if self.quit_callback:
|
|
121
126
|
self.quit_callback()
|
|
122
127
|
|
|
123
128
|
class UnixSocket(threading.Thread):
|
|
124
129
|
"""
|
|
125
130
|
Wraps a Unix/Linux socket in a high-level interface. (Internal)
|
|
126
|
-
|
|
131
|
+
|
|
127
132
|
Data is automatically encoded and decoded as JSON. The callback
|
|
128
133
|
function will be called for each inbound message.
|
|
129
134
|
"""
|
|
@@ -137,6 +142,7 @@ class UnixSocket(threading.Thread):
|
|
|
137
142
|
self.ipc_socket = ipc_socket
|
|
138
143
|
self.callback = callback
|
|
139
144
|
self.quit_callback = quit_callback
|
|
145
|
+
self._stopping = False
|
|
140
146
|
self.socket = socket.socket(socket.AF_UNIX)
|
|
141
147
|
self.socket.connect(self.ipc_socket)
|
|
142
148
|
|
|
@@ -144,9 +150,11 @@ class UnixSocket(threading.Thread):
|
|
|
144
150
|
self.callback = lambda data: None
|
|
145
151
|
|
|
146
152
|
threading.Thread.__init__(self)
|
|
153
|
+
self.daemon = True
|
|
147
154
|
|
|
148
155
|
def stop(self, join=True):
|
|
149
156
|
"""Terminate the thread."""
|
|
157
|
+
self._stopping = True
|
|
150
158
|
if self.socket is not None:
|
|
151
159
|
try:
|
|
152
160
|
self.socket.shutdown(socket.SHUT_WR)
|
|
@@ -184,7 +192,9 @@ class UnixSocket(threading.Thread):
|
|
|
184
192
|
self.callback(json_data)
|
|
185
193
|
data = b''
|
|
186
194
|
except Exception as ex:
|
|
187
|
-
log
|
|
195
|
+
# Only log if not intentionally stopping
|
|
196
|
+
if not self._stopping:
|
|
197
|
+
log.error("Socket connection died.", exc_info=1)
|
|
188
198
|
if self.quit_callback:
|
|
189
199
|
self.quit_callback()
|
|
190
200
|
|
|
@@ -206,7 +216,7 @@ class MPVProcess:
|
|
|
206
216
|
mpv_location = "mpv.exe"
|
|
207
217
|
else:
|
|
208
218
|
mpv_location = "mpv"
|
|
209
|
-
|
|
219
|
+
|
|
210
220
|
log.debug("Staring MPV from {0}.".format(mpv_location))
|
|
211
221
|
ipc_socket_name = ipc_socket
|
|
212
222
|
if os.name == 'nt':
|
|
@@ -248,7 +258,7 @@ class MPVProcess:
|
|
|
248
258
|
else:
|
|
249
259
|
self.process.terminate()
|
|
250
260
|
raise MPVError("MPV start timed out.")
|
|
251
|
-
|
|
261
|
+
|
|
252
262
|
if not ipc_exists or self.process.returncode is not None:
|
|
253
263
|
self.process.terminate()
|
|
254
264
|
raise MPVError("MPV not started.")
|
|
@@ -290,7 +300,7 @@ class MPVInter:
|
|
|
290
300
|
self.quit_callback = quit_callback
|
|
291
301
|
if self.callback is None:
|
|
292
302
|
self.callback = lambda event, data: None
|
|
293
|
-
|
|
303
|
+
|
|
294
304
|
self.socket = Socket(ipc_socket, self.event_callback, self.quit_callback)
|
|
295
305
|
self.socket.start()
|
|
296
306
|
self.command_id = 1
|
|
@@ -298,7 +308,7 @@ class MPVInter:
|
|
|
298
308
|
self.socket_lock = threading.Lock()
|
|
299
309
|
self.cid_result = {}
|
|
300
310
|
self.cid_wait = {}
|
|
301
|
-
|
|
311
|
+
|
|
302
312
|
def stop(self, join=True):
|
|
303
313
|
"""Terminate the underlying connection."""
|
|
304
314
|
self.socket.stop(join)
|
|
@@ -310,11 +320,11 @@ class MPVInter:
|
|
|
310
320
|
self.cid_wait[data["request_id"]].set()
|
|
311
321
|
elif "event" in data:
|
|
312
322
|
self.callback(data["event"], data)
|
|
313
|
-
|
|
323
|
+
|
|
314
324
|
def command(self, command, *args):
|
|
315
325
|
"""
|
|
316
326
|
Issue a command to MPV. Will block until completed or timeout is reached.
|
|
317
|
-
|
|
327
|
+
|
|
318
328
|
*command* is the name of the MPV command
|
|
319
329
|
|
|
320
330
|
All further arguments are forwarded to the MPV command.
|
|
@@ -356,13 +366,14 @@ class EventHandler(threading.Thread):
|
|
|
356
366
|
"""Create an instance of the thread."""
|
|
357
367
|
self.queue = queue.Queue()
|
|
358
368
|
threading.Thread.__init__(self)
|
|
359
|
-
|
|
369
|
+
self.daemon = True
|
|
370
|
+
|
|
360
371
|
def put_task(self, func, *args):
|
|
361
372
|
"""
|
|
362
373
|
Put a new task to the thread.
|
|
363
|
-
|
|
374
|
+
|
|
364
375
|
*func* is the function to call
|
|
365
|
-
|
|
376
|
+
|
|
366
377
|
All further arguments are forwarded to *func*.
|
|
367
378
|
"""
|
|
368
379
|
self.queue.put((func, args))
|
|
@@ -386,15 +397,15 @@ class EventHandler(threading.Thread):
|
|
|
386
397
|
class MPV:
|
|
387
398
|
"""
|
|
388
399
|
The main MPV interface class. Use this to control MPV.
|
|
389
|
-
|
|
400
|
+
|
|
390
401
|
This will expose all mpv commands as callable methods and all properties.
|
|
391
402
|
You can set properties and call the commands directly.
|
|
392
|
-
|
|
403
|
+
|
|
393
404
|
Please note that if you are using a really old MPV version, a fallback command
|
|
394
405
|
list is used. Not all commands may actually work when this fallback is used.
|
|
395
406
|
"""
|
|
396
407
|
def __init__(self, start_mpv=True, ipc_socket=None, mpv_location=None,
|
|
397
|
-
log_handler=None, loglevel=None, quit_callback=None, **kwargs):
|
|
408
|
+
log_handler=None, loglevel=None, quit_callback=None, start_retries=5, start_retry_delay_ms=1000, **kwargs):
|
|
398
409
|
"""
|
|
399
410
|
Create the interface to MPV and process instance.
|
|
400
411
|
|
|
@@ -424,13 +435,14 @@ class MPV:
|
|
|
424
435
|
ipc_socket = "/tmp/{0}".format(rand_file)
|
|
425
436
|
|
|
426
437
|
if start_mpv:
|
|
427
|
-
# Attempt to start MPV
|
|
428
|
-
for i in range(
|
|
438
|
+
# Attempt to start MPV multiple times.
|
|
439
|
+
for i in range(start_retries):
|
|
429
440
|
try:
|
|
430
441
|
self.mpv_process = MPVProcess(ipc_socket, mpv_location, **kwargs)
|
|
431
442
|
break
|
|
432
443
|
except MPVError:
|
|
433
444
|
log.warning("MPV start failed.", exc_info=1)
|
|
445
|
+
time.sleep(start_retry_delay_ms / 1000)
|
|
434
446
|
continue
|
|
435
447
|
else:
|
|
436
448
|
raise MPVError("MPV process retry limit reached.")
|
|
@@ -455,7 +467,7 @@ class MPV:
|
|
|
455
467
|
self.observer_lock = threading.Lock()
|
|
456
468
|
self.keybind_id = 1
|
|
457
469
|
self.keybind_lock = threading.Lock()
|
|
458
|
-
|
|
470
|
+
|
|
459
471
|
if log_handler is not None and loglevel is not None:
|
|
460
472
|
self.command("request_log_messages", loglevel)
|
|
461
473
|
@self.on_event("log-message")
|
|
@@ -582,7 +594,7 @@ class MPV:
|
|
|
582
594
|
self.bind_property_observer(name, func)
|
|
583
595
|
return func
|
|
584
596
|
return wrapper
|
|
585
|
-
|
|
597
|
+
|
|
586
598
|
def wait_for_property(self, name):
|
|
587
599
|
"""
|
|
588
600
|
Waits for the value of a property to change.
|
|
@@ -630,11 +642,11 @@ class MPV:
|
|
|
630
642
|
"""
|
|
631
643
|
Send a command to MPV. All commands are bound to the class by default,
|
|
632
644
|
except JSON IPC specific commands. This may also be useful to retain
|
|
633
|
-
compatibility with python-mpv, as it does not bind all of the commands.
|
|
645
|
+
compatibility with python-mpv, as it does not bind all of the commands.
|
|
634
646
|
|
|
635
647
|
*command* is the command name.
|
|
636
648
|
|
|
637
|
-
All further arguments are forwarded to the MPV command.
|
|
649
|
+
All further arguments are forwarded to the MPV command.
|
|
638
650
|
"""
|
|
639
651
|
return self.mpv_inter.command(command, *args)
|
|
640
652
|
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
python_mpv_jsonipc.py,sha256=F6rSnv0QKkqR1XKYkao0aXFqsXGr-22EV9gkXU7dHCA,23629
|
|
2
|
-
python_mpv_jsonipc-1.2.0.dist-info/LICENSE.md,sha256=7GQBUOA3dNG1Jk-yaPOCncNnRVURCRMev23QpZ1ew-s,10495
|
|
3
|
-
python_mpv_jsonipc-1.2.0.dist-info/METADATA,sha256=1gom4VqEf_32RzxScob2OuXe3cAnNAeDHktQwjLK-eA,2295
|
|
4
|
-
python_mpv_jsonipc-1.2.0.dist-info/WHEEL,sha256=ewwEueio1C2XeHTvT17n8dZUJgOvyCWCt0WVNLClP9o,92
|
|
5
|
-
python_mpv_jsonipc-1.2.0.dist-info/top_level.txt,sha256=nGk4yjpVHKmIrL39XdGD2PhCeWF0oMjwey0nsNOd2TM,19
|
|
6
|
-
python_mpv_jsonipc-1.2.0.dist-info/RECORD,,
|
{python_mpv_jsonipc-1.2.0.dist-info → python_mpv_jsonipc-1.2.2.dist-info/licenses}/LICENSE.md
RENAMED
|
File without changes
|
|
File without changes
|