Continue reworking event infrastrucutre.
Note: We do not decode property values by default anymore.
This commit is contained in:
parent
f4c9f2fec4
commit
c90a5f692f
2 changed files with 66 additions and 33 deletions
83
mpv.py
83
mpv.py
|
|
@ -282,14 +282,14 @@ class MpvEventID(c_int):
|
|||
SEEK = 20
|
||||
PLAYBACK_RESTART = 21
|
||||
PROPERTY_CHANGE = 22
|
||||
EVENT_QUEUE_OVERFLOW = 24
|
||||
EVENT_HOOK = 25
|
||||
QUEUE_OVERFLOW = 24
|
||||
HOOK = 25
|
||||
|
||||
ANY = ( SHUTDOWN, LOG_MESSAGE, GET_PROPERTY_REPLY, SET_PROPERTY_REPLY, COMMAND_REPLY, START_FILE, END_FILE,
|
||||
FILE_LOADED, CLIENT_MESSAGE, VIDEO_RECONFIG, AUDIO_RECONFIG, SEEK, PLAYBACK_RESTART, PROPERTY_CHANGE)
|
||||
|
||||
def __repr__(self):
|
||||
return _mpv_event_name(self.value).decode()
|
||||
return f'<MpvEventID {self.value} (_mpv_event_name(self.value).decode("utf-8"))>'
|
||||
|
||||
@classmethod
|
||||
def from_str(kls, s):
|
||||
|
|
@ -383,15 +383,15 @@ class MpvEvent(Structure):
|
|||
def data(self):
|
||||
dtype = {
|
||||
MpvEventID.GET_PROPERTY_REPLY: MpvEventProperty,
|
||||
MpvEventID.PROPERTY_CHANGE: MpvEventProperty
|
||||
MpvEventID.PROPERTY_CHANGE: MpvEventProperty,
|
||||
MpvEventID.LOG_MESSAGE: MpvEventLogMessage,
|
||||
MpvEventID.CLIENT_MESSAGE: MpvEventClientMessage,
|
||||
MpvEventID.START_FILE: MpvEventStartFile,
|
||||
MpvEventID.END_FILE: MpvEventEndFile,
|
||||
MpvEventID.HOOK: MpvEventHook,
|
||||
MpvEventID.COMMAND_REPLY* MpvEventCommand,
|
||||
}.get(self.event_id)
|
||||
return cast(self.data, POINTER(dtype)).contents.as_dict(decoder=decoder)
|
||||
MpvEventID.COMMAND_REPLY: MpvEventCommand,
|
||||
}.get(self.event_id.value)
|
||||
return cast(self._data, POINTER(dtype)).contents if dtype else None
|
||||
|
||||
def as_dict(self, decoder=identity_decoder):
|
||||
out = cast(create_string_buffer(sizeof(MpvNode)), POINTER(MpvNode))
|
||||
|
|
@ -400,15 +400,39 @@ class MpvEvent(Structure):
|
|||
_mpv_free_node_contents(out)
|
||||
return rv
|
||||
|
||||
def __str__(self):
|
||||
d = self.data
|
||||
return f'<{type(d).__name__} ({self.event_id.value}) err={self.error} p={self.reply_userdata:016x} d={self.as_dict()}>'
|
||||
|
||||
class MpvEventProperty(Structure):
|
||||
_fields_ = [('name', c_char_p),
|
||||
_fields_ = [('_name', c_char_p),
|
||||
('format', MpvFormat),
|
||||
('data', MpvNodeUnion)]
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name.decode("utf-8")
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
return MpvNode.node_cast_value(self.data, self.format.value)
|
||||
|
||||
class MpvEventLogMessage(Structure):
|
||||
_fields_ = [('prefix', c_char_p),
|
||||
('level', c_char_p),
|
||||
('text', c_char_p)]
|
||||
_fields_ = [('_prefix', c_char_p),
|
||||
('_level', c_char_p),
|
||||
('_text', c_char_p)]
|
||||
|
||||
@property
|
||||
def prefix(self):
|
||||
return self._prefix.decode("utf-8")
|
||||
|
||||
@property
|
||||
def level(self):
|
||||
return self._level.decode("utf-8")
|
||||
|
||||
@property
|
||||
def text(self):
|
||||
return self._text
|
||||
|
||||
class MpvEventEndFile(Structure):
|
||||
_fields_ = [('reason', c_int),
|
||||
|
|
@ -421,30 +445,32 @@ class MpvEventEndFile(Structure):
|
|||
ERROR = 4
|
||||
REDIRECT = 5
|
||||
|
||||
# For backwards-compatibility
|
||||
@property
|
||||
def value(self):
|
||||
return self.reason
|
||||
|
||||
class MpvEventStartFile(Structure):
|
||||
_fields_ = [('playlist_entry_id', c_ulonglong),]
|
||||
|
||||
class MpvEventScriptInputDispatch(Structure):
|
||||
_fields_ = [('arg0', c_int),
|
||||
('type', c_char_p)]
|
||||
|
||||
class MpvEventClientMessage(Structure):
|
||||
_fields_ = [('num_args', c_int),
|
||||
('args', POINTER(c_char_p))]
|
||||
_fields_ = [('_num_args', c_int),
|
||||
('_args', POINTER(c_char_p))]
|
||||
|
||||
@property
|
||||
def args(self):
|
||||
return [ self._args[i] for i in range(self._num_args) ]
|
||||
|
||||
class MpvEventCommand(Structure):
|
||||
_fields_ = [('result', MpvNode)]
|
||||
_fields_ = [('_result', MpvNode)]
|
||||
|
||||
def result(self):
|
||||
return self._result.node_value()
|
||||
|
||||
class MpvEventHook(Structure):
|
||||
_fields_ = [('name', c_char_p),
|
||||
_fields_ = [('_name', c_char_p),
|
||||
('id', c_ulonglong),]
|
||||
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name.decode("utf-8")
|
||||
|
||||
StreamReadFn = CFUNCTYPE(c_int64, c_void_p, POINTER(c_char), c_uint64)
|
||||
StreamSeekFn = CFUNCTYPE(c_int64, c_void_p, c_int64)
|
||||
StreamSizeFn = CFUNCTYPE(c_int64, c_void_p)
|
||||
|
|
@ -856,13 +882,15 @@ class MPV(object):
|
|||
for event in _event_generator(self._event_handle):
|
||||
try:
|
||||
eid = event.event_id.value
|
||||
if not eid == MpvEventID.LOG_MESSAGE:
|
||||
print(event)
|
||||
|
||||
with self._event_handler_lock:
|
||||
if eid == MpvEventID.SHUTDOWN:
|
||||
self._core_shutdown = True
|
||||
|
||||
for callback in self._event_callbacks:
|
||||
callback(devent)
|
||||
callback(event)
|
||||
|
||||
if eid == MpvEventID.PROPERTY_CHANGE:
|
||||
pc = event.data
|
||||
|
|
@ -877,6 +905,7 @@ class MPV(object):
|
|||
if eid == MpvEventID.CLIENT_MESSAGE:
|
||||
# {'event': {'args': ['key-binding', 'foo', 'u-', 'g']}, 'reply_userdata': 0, 'error': 0, 'event_id': 16}
|
||||
target, *args = event.data.args
|
||||
target = target.decode("utf-8")
|
||||
if target in self._message_handlers:
|
||||
self._message_handlers[target](*args)
|
||||
|
||||
|
|
@ -1659,6 +1688,10 @@ class MPV(object):
|
|||
self.command('enable-section', binding_name, 'allow-hide-cursor+allow-vo-dragging')
|
||||
|
||||
def _handle_key_binding_message(self, binding_name, key_state, key_name=None, key_char=None):
|
||||
binding_name = binding_name.decode('utf-8')
|
||||
key_state = key_state.decode('utf-8')
|
||||
key_name = key_name.decode('utf-8') if key_name is not None else None
|
||||
key_char = key_char.decode('utf-8') if key_char is not None else None
|
||||
self._key_binding_handlers[binding_name](key_state, key_name, key_char)
|
||||
|
||||
def unregister_key_binding(self, keydef):
|
||||
|
|
|
|||
|
|
@ -243,7 +243,7 @@ class ObservePropertyTest(MpvTestCase):
|
|||
|
||||
time.sleep(0.1) #couple frames
|
||||
m.terminate() # needed for synchronization of event thread
|
||||
handler.assert_has_calls([mock.call('vid', 'auto')])
|
||||
handler.assert_has_calls([mock.call('vid', b'auto')])
|
||||
|
||||
def test_property_observer_decorator(self):
|
||||
handler = mock.Mock()
|
||||
|
|
@ -380,7 +380,7 @@ class KeyBindingTest(MpvTestCase):
|
|||
def test_wait_for_property_error_forwarding(self):
|
||||
def run():
|
||||
nonlocal self
|
||||
self.m.wait_until_playing()
|
||||
self.m.wait_until_playing(timeout=2)
|
||||
self.m.mute = True
|
||||
t = threading.Thread(target=run, daemon=True)
|
||||
t.start()
|
||||
|
|
@ -396,7 +396,7 @@ class KeyBindingTest(MpvTestCase):
|
|||
def test_register_simple_decorator_fun_chaining(self):
|
||||
self.m.loop = 'inf'
|
||||
self.m.play(TESTVID)
|
||||
self.m.wait_until_playing()
|
||||
self.m.wait_until_playing(timeout=2)
|
||||
|
||||
handler1, handler2 = mock.Mock(), mock.Mock()
|
||||
|
||||
|
|
@ -412,7 +412,7 @@ class KeyBindingTest(MpvTestCase):
|
|||
self.assertEqual(reg_test_fun.mpv_key_bindings, ['b', 'a'])
|
||||
|
||||
def keypress_and_sync(key):
|
||||
with self.m.prepare_and_wait_for_event('client_message'):
|
||||
with self.m.prepare_and_wait_for_event('client_message', timeout=2):
|
||||
self.m.keypress(key)
|
||||
|
||||
keypress_and_sync('a')
|
||||
|
|
@ -610,7 +610,7 @@ class TestLifecycle(unittest.TestCase):
|
|||
handler()
|
||||
t = threading.Thread(target=run, daemon=True)
|
||||
t.start()
|
||||
m.wait_until_playing()
|
||||
m.wait_until_playing(timeout=2)
|
||||
m.mute = True
|
||||
t.join()
|
||||
m.terminate()
|
||||
|
|
@ -682,7 +682,7 @@ class TestLifecycle(unittest.TestCase):
|
|||
m = mpv.MPV(vo=testvo, log_handler=handler)
|
||||
m.play(TESTVID)
|
||||
# Wait for playback to start
|
||||
m.wait_until_playing()
|
||||
m.wait_until_playing(timeout=2)
|
||||
m.command("print-text", 'This is a python-mpv test')
|
||||
m.wait_for_playback()
|
||||
m.terminate()
|
||||
|
|
@ -713,7 +713,7 @@ class CommandTests(MpvTestCase):
|
|||
time.sleep(0.5)
|
||||
|
||||
self.m.loadfile(TESTVID)
|
||||
self.m.wait_until_playing()
|
||||
self.m.wait_until_playing(timeout=2)
|
||||
self.m.sub_add(TESTSRT)
|
||||
|
||||
self.m.wait_for_playback()
|
||||
|
|
@ -727,7 +727,7 @@ class CommandTests(MpvTestCase):
|
|||
time.sleep(0.5)
|
||||
|
||||
self.m.loadfile(TESTVID)
|
||||
self.m.wait_until_playing()
|
||||
self.m.wait_until_playing(timeout=2)
|
||||
self.m.command_async('sub_add', TESTSRT, callback=callback)
|
||||
reply = self.m.command_async('expand-text', 'test ${mute}')
|
||||
assert reply.result() == 'test no'
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue