BREAKING: Move property observation API to NODE format
This commit is contained in:
parent
303eedbb3b
commit
c47bd2a2c6
2 changed files with 25 additions and 44 deletions
|
|
@ -151,7 +151,7 @@ class ObservePropertyTest(unittest.TestCase):
|
||||||
m.loop = 'no'
|
m.loop = 'no'
|
||||||
m.loop = 'inf'
|
m.loop = 'inf'
|
||||||
m.terminate() # needed for synchronization of event thread
|
m.terminate() # needed for synchronization of event thread
|
||||||
handler.assert_has_calls([mock.call('no'), mock.call('inf')])
|
handler.assert_has_calls([mock.call('loop', False), mock.call('loop', 'inf')])
|
||||||
|
|
||||||
|
|
||||||
class TestLifecycle(unittest.TestCase):
|
class TestLifecycle(unittest.TestCase):
|
||||||
|
|
|
||||||
67
mpv.py
67
mpv.py
|
|
@ -228,17 +228,13 @@ class MpvEventProperty(Structure):
|
||||||
_fields_ = [('name', c_char_p),
|
_fields_ = [('name', c_char_p),
|
||||||
('format', MpvFormat),
|
('format', MpvFormat),
|
||||||
('data', c_void_p)]
|
('data', c_void_p)]
|
||||||
def as_dict(self):
|
def as_dict(self, decode_str=False):
|
||||||
if self.format.value == MpvFormat.STRING:
|
proptype, _access = ALL_PROPERTIES.get(self.name, (str, None))
|
||||||
proptype, _access = ALL_PROPERTIES.get(self.name, (str, None))
|
value = MpvNode.node_cast_value(self.data, self.format.value, decode_str or proptype in (str, _commalist))
|
||||||
return {'name': self.name.decode('utf-8'),
|
return {'name': self.name.decode('utf-8'),
|
||||||
'format': self.format,
|
'format': self.format,
|
||||||
'data': self.data,
|
'data': self.data,
|
||||||
'value': proptype(cast(self.data, POINTER(c_char_p)).contents.value.decode('utf-8'))}
|
'value': value}
|
||||||
else:
|
|
||||||
return {'name': self.name.decode('utf-8'),
|
|
||||||
'format': self.format,
|
|
||||||
'data': self.data}
|
|
||||||
|
|
||||||
class MpvEventLogMessage(Structure):
|
class MpvEventLogMessage(Structure):
|
||||||
_fields_ = [('prefix', c_char_p),
|
_fields_ = [('prefix', c_char_p),
|
||||||
|
|
@ -394,21 +390,10 @@ def _event_loop(event_handle, playback_cond, event_callbacks, message_handlers,
|
||||||
playback_cond.notify_all()
|
playback_cond.notify_all()
|
||||||
if eid == MpvEventID.PROPERTY_CHANGE:
|
if eid == MpvEventID.PROPERTY_CHANGE:
|
||||||
pc = devent['event']
|
pc = devent['event']
|
||||||
name = pc['name']
|
name, value = pc['name'], pc['value']
|
||||||
|
|
||||||
if 'value' in pc:
|
|
||||||
proptype, _access = ALL_PROPERTIES[name]
|
|
||||||
if proptype is bytes:
|
|
||||||
args = (pc['value'],)
|
|
||||||
else:
|
|
||||||
args = (proptype(_ensure_encoding(pc['value'])),)
|
|
||||||
elif pc['format'] == MpvFormat.NONE:
|
|
||||||
args = (None,)
|
|
||||||
else:
|
|
||||||
args = (pc['data'], pc['format'])
|
|
||||||
|
|
||||||
for handler in property_handlers[name]:
|
for handler in property_handlers[name]:
|
||||||
handler(*args)
|
handler(name, value)
|
||||||
if eid == MpvEventID.LOG_MESSAGE and log_handler is not None:
|
if eid == MpvEventID.LOG_MESSAGE and log_handler is not None:
|
||||||
ev = devent['event']
|
ev = devent['event']
|
||||||
log_handler(ev['level'], ev['prefix'], ev['text'])
|
log_handler(ev['level'], ev['prefix'], ev['text'])
|
||||||
|
|
@ -479,7 +464,7 @@ class MPV(object):
|
||||||
```idle_active``` indicating the player is done with regular playback
|
```idle_active``` indicating the player is done with regular playback
|
||||||
and just idling around """
|
and just idling around """
|
||||||
sema = threading.Semaphore(value=0)
|
sema = threading.Semaphore(value=0)
|
||||||
def observer(val):
|
def observer(name, val):
|
||||||
if cond(val):
|
if cond(val):
|
||||||
sema.release()
|
sema.release()
|
||||||
self.observe_property(name, observer)
|
self.observe_property(name, observer)
|
||||||
|
|
@ -655,37 +640,33 @@ class MPV(object):
|
||||||
""" Mapped mpv seek command, see man mpv(1). """
|
""" Mapped mpv seek command, see man mpv(1). """
|
||||||
self.command('script_message_to', target, *args)
|
self.command('script_message_to', target, *args)
|
||||||
|
|
||||||
def observe_property(self, name, handler=None):
|
def observe_property(self, name, handler):
|
||||||
""" Register an observer on the named property. An observer is a
|
""" Register an observer on the named property. An observer is a function that is called with the new property
|
||||||
function that is called with the new property value every time the
|
value every time the property's value is changed. The basic function signature is ```fun(property_name,
|
||||||
property's value is changed. The basic function signature is
|
new_value)``` with new_value being the decoded property value as a python object. This function can be used as a
|
||||||
```fun(new_value)``` with new_value being the decoded property value as
|
function decorator if no handler is given.
|
||||||
a python object. This function can be used as a function decorator if
|
|
||||||
no handler is given.
|
|
||||||
|
|
||||||
To uunregister the observer, call either of ```mpv.unobserve_property(name, handler)```,
|
To uunregister the observer, call either of ```mpv.unobserve_property(name, handler)```,
|
||||||
```mpv.unobserve_all_properties(handler)``` or the handler's ```unregister_mpv_properties``` attribute:
|
```mpv.unobserve_all_properties(handler)``` or the handler's ```unregister_mpv_properties``` attribute:
|
||||||
|
|
||||||
```
|
```
|
||||||
@player.observe_property('volume')
|
@player.observe_property('volume')
|
||||||
def my_handler(new_volume):
|
def my_handler(new_volume, *):
|
||||||
print("It's loud!", volume)
|
print("It's loud!", volume)
|
||||||
|
|
||||||
my_handler.unregister_mpv_properties()
|
my_handler.unregister_mpv_properties()
|
||||||
``` """
|
``` """
|
||||||
if handler is None:
|
|
||||||
def wrapper(fun):
|
|
||||||
self._observe_property_internal(name, handler)
|
|
||||||
return fun
|
|
||||||
return wrapper
|
|
||||||
else:
|
|
||||||
self._observe_property_internal(name, handler)
|
|
||||||
|
|
||||||
def _observe_property_internal(self, name, handler):
|
|
||||||
handler.observed_mpv_properties = getattr(handler, 'observed_mpv_properties', []) + [name]
|
handler.observed_mpv_properties = getattr(handler, 'observed_mpv_properties', []) + [name]
|
||||||
handler.unregister_mpv_properties = lambda: self.unobserve_property(None, handler)
|
handler.unregister_mpv_properties = lambda: self.unobserve_property(None, handler)
|
||||||
self._property_handlers[name].append(handler)
|
self._property_handlers[name].append(handler)
|
||||||
_mpv_observe_property(self._event_handle, hash(name)&0xffffffffffffffff, name.encode('utf-8'), MpvFormat.STRING)
|
_mpv_observe_property(self._event_handle, hash(name)&0xffffffffffffffff, name.encode('utf-8'), MpvFormat.NODE)
|
||||||
|
|
||||||
|
def property_observer(self, name):
|
||||||
|
""" Function decorator to register a property observer. See ```MPV.observe_property``` for details. """
|
||||||
|
def wrapper(fun):
|
||||||
|
self.observe_property(name, fun)
|
||||||
|
return fun
|
||||||
|
return wrapper
|
||||||
|
|
||||||
def unobserve_property(self, name, handler):
|
def unobserve_property(self, name, handler):
|
||||||
""" Unregister a property observer. This requires both the observed property's name and the handler function
|
""" Unregister a property observer. This requires both the observed property's name and the handler function
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue