Add observe_property support
This commit is contained in:
parent
a1c170d6ff
commit
694a2c2c62
1 changed files with 138 additions and 111 deletions
249
mpv.py
249
mpv.py
|
|
@ -69,6 +69,10 @@ class MpvFormat(c_int):
|
||||||
NODE = 6
|
NODE = 6
|
||||||
NODE_ARRAY = 7
|
NODE_ARRAY = 7
|
||||||
NODE_MAP = 8
|
NODE_MAP = 8
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return ['NONE', 'STRING', 'OSD_STRING', 'FLAG', 'INT64', 'DOUBLE', 'NODE', 'NODE_ARRAY', 'NODE_MAP'][self.value]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class MpvEventID(c_int):
|
class MpvEventID(c_int):
|
||||||
|
|
@ -125,8 +129,17 @@ 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():
|
def as_dict(self):
|
||||||
pass # FIXME
|
if self.format.value == MpvFormat.STRING:
|
||||||
|
proptype, _access = ALL_PROPERTIES.get(self.name, (str, None))
|
||||||
|
return {'name': self.name.decode(),
|
||||||
|
'format': self.format,
|
||||||
|
'data': self.data,
|
||||||
|
'value': proptype(cast(self.data, POINTER(c_char_p)).contents.value.decode())}
|
||||||
|
else:
|
||||||
|
return {'name': self.name.decode(),
|
||||||
|
'format': self.format,
|
||||||
|
'data': self.data}
|
||||||
|
|
||||||
class MpvEventLogMessage(Structure):
|
class MpvEventLogMessage(Structure):
|
||||||
_fields_ = [('prefix', c_char_p),
|
_fields_ = [('prefix', c_char_p),
|
||||||
|
|
@ -266,6 +279,7 @@ class MPV:
|
||||||
self.handle = _mpv_create()
|
self.handle = _mpv_create()
|
||||||
|
|
||||||
self.event_callbacks = []
|
self.event_callbacks = []
|
||||||
|
self._property_handlers = {}
|
||||||
self._playback_cond = threading.Condition()
|
self._playback_cond = threading.Condition()
|
||||||
def event_loop():
|
def event_loop():
|
||||||
for event in _event_generator(self.handle):
|
for event in _event_generator(self.handle):
|
||||||
|
|
@ -273,6 +287,8 @@ class MPV:
|
||||||
if devent['event_id'] in (MpvEventID.SHUTDOWN, MpvEventID.END_FILE, MpvEventID.PAUSE):
|
if devent['event_id'] in (MpvEventID.SHUTDOWN, MpvEventID.END_FILE, MpvEventID.PAUSE):
|
||||||
with self._playback_cond:
|
with self._playback_cond:
|
||||||
self._playback_cond.notify_all()
|
self._playback_cond.notify_all()
|
||||||
|
if devent['event_id'] == MpvEventID.PROPERTY_CHANGE:
|
||||||
|
self._property_handlers[devent['reply_userdata']](devent['event'])
|
||||||
for callback in self.event_callbacks:
|
for callback in self.event_callbacks:
|
||||||
callback.call()
|
callback.call()
|
||||||
self._event_thread = threading.Thread(target=event_loop, daemon=True)
|
self._event_thread = threading.Thread(target=event_loop, daemon=True)
|
||||||
|
|
@ -398,14 +414,24 @@ class MPV:
|
||||||
|
|
||||||
def script_message_to(self, target, *args):
|
def script_message_to(self, target, *args):
|
||||||
self.command('script_message_to', target, *args)
|
self.command('script_message_to', target, *args)
|
||||||
|
|
||||||
|
def observe_property(self, name, handler):
|
||||||
|
self._property_handlers[hash(handler)] = handler
|
||||||
|
_mpv_observe_property(self.handle, hash(handler), name.encode(), MpvFormat.STRING)
|
||||||
|
|
||||||
|
def unobserve_property(self, handler):
|
||||||
|
_mpv_observe_property(self.handle, hash(handler))
|
||||||
|
del self._property_handlers[hash(handler)]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def metadata(self):
|
def metadata(self):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@property
|
||||||
def chapter_metadata(self):
|
def chapter_metadata(self):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@property
|
||||||
def vf_metadata(self):
|
def vf_metadata(self):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
@ -468,7 +494,115 @@ class MPV:
|
||||||
# TODO: edition-list
|
# TODO: edition-list
|
||||||
# TODO property-mapped options
|
# TODO property-mapped options
|
||||||
|
|
||||||
|
ALL_PROPERTIES = {
|
||||||
|
'osd-level': (int, 'rw'),
|
||||||
|
'osd-scale': (float, 'rw'),
|
||||||
|
'loop': (str, 'rw'),
|
||||||
|
'loop-file': (str, 'rw'),
|
||||||
|
'speed': (float, 'rw'),
|
||||||
|
'filename': (str, 'r'),
|
||||||
|
'file-size': (int, 'r'),
|
||||||
|
'path': (str, 'r'),
|
||||||
|
'media-title': (str, 'r'),
|
||||||
|
'stream-pos': (int, 'rw'),
|
||||||
|
'stream-end': (int, 'r'),
|
||||||
|
'length': (float, 'r'),
|
||||||
|
'avsync': (float, 'r'),
|
||||||
|
'total-avsync-change': (float, 'r'),
|
||||||
|
'drop-frame-count': (int, 'r'),
|
||||||
|
'percent-pos': (int, 'rw'),
|
||||||
|
'ratio-pos': (float, 'rw'),
|
||||||
|
'time-pos': (float, 'rw'),
|
||||||
|
'time-start': (float, 'r'),
|
||||||
|
'time-remaining': (float, 'r'),
|
||||||
|
'playtime-remaining': (float, 'r'),
|
||||||
|
'chapter': (int, 'rw'),
|
||||||
|
'edition': (int, 'rw'),
|
||||||
|
'disc-titles': (int, 'r'),
|
||||||
|
'disc-title': (str, 'rw'),
|
||||||
|
'disc-menu-active': (ynbool, 'r'),
|
||||||
|
'chapters': (int, 'r'),
|
||||||
|
'editions': (int, 'r'),
|
||||||
|
'angle': (int, 'rw'),
|
||||||
|
'pause': (ynbool, 'rw'),
|
||||||
|
'core-idle': (ynbool, 'r'),
|
||||||
|
'cache': (int, 'r'),
|
||||||
|
'cache-size': (int, 'rw'),
|
||||||
|
'pause-for-cache': (ynbool, 'r'),
|
||||||
|
'eof-reached': (ynbool, 'r'),
|
||||||
|
'pts-association-mode': (str, 'rw'),
|
||||||
|
'hr-seek': (ynbool, 'rw'),
|
||||||
|
'volume': (float, 'rw'),
|
||||||
|
'mute': (ynbool, 'rw'),
|
||||||
|
'audio-delay': (float, 'rw'),
|
||||||
|
'audio-format': (str, 'r'),
|
||||||
|
'audio-codec': (str, 'r'),
|
||||||
|
'audio-bitrate': (float, 'r'),
|
||||||
|
'audio-samplerate': (int, 'r'),
|
||||||
|
'audio-channels': (str, 'r'),
|
||||||
|
'aid': (int, 'rw'),
|
||||||
|
'audio': (int, 'rw'),
|
||||||
|
'balance': (int, 'rw'),
|
||||||
|
'fullscreen': (ynbool, 'rw'),
|
||||||
|
'deinterlace': (str, 'rw'),
|
||||||
|
'colormatrix': (str, 'rw'),
|
||||||
|
'colormatrix-input-range': (str, 'rw'),
|
||||||
|
'colormatrix-output-range': (str, 'rw'),
|
||||||
|
'colormatrix-primaries': (str, 'rw'),
|
||||||
|
'ontop': (ynbool, 'rw'),
|
||||||
|
'border': (ynbool, 'rw'),
|
||||||
|
'framedrop': (str, 'rw'),
|
||||||
|
'gamma': (float, 'rw'),
|
||||||
|
'brightness': (int, 'rw'),
|
||||||
|
'contrast': (int, 'rw'),
|
||||||
|
'saturation': (int, 'rw'),
|
||||||
|
'hue': (int, 'rw'),
|
||||||
|
'hwdec': (ynbool, 'rw'),
|
||||||
|
'panscan': (float, 'rw'),
|
||||||
|
'video-format': (str, 'r'),
|
||||||
|
'video-codec': (str, 'r'),
|
||||||
|
'video-bitrate': (float, 'r'),
|
||||||
|
'width': (int, 'r'),
|
||||||
|
'height': (int, 'r'),
|
||||||
|
'dwidth': (int, 'r'),
|
||||||
|
'dheight': (int, 'r'),
|
||||||
|
'fps': (float, 'r'),
|
||||||
|
'estimated-vf-fps': (float, 'r'),
|
||||||
|
'window-scale': (float, 'rw'),
|
||||||
|
'video-aspect': (str, 'rw'),
|
||||||
|
'osd-width': (int, 'r'),
|
||||||
|
'osd-height': (int, 'r'),
|
||||||
|
'osd-par': (float, 'r'),
|
||||||
|
'vid': (int, 'rw'),
|
||||||
|
'video': (int, 'rw'),
|
||||||
|
'video-align-x': (float, 'rw'),
|
||||||
|
'video-align-y': (float, 'rw'),
|
||||||
|
'video-pan-x': (int, 'rw'),
|
||||||
|
'video-pan-y': (int, 'rw'),
|
||||||
|
'video-zoom': (float, 'rw'),
|
||||||
|
'video-unscaled': (ynbool, 'w'),
|
||||||
|
'program': (int, 'w'),
|
||||||
|
'sid': (int, 'rw'),
|
||||||
|
'secondary-sid': (int, 'rw'),
|
||||||
|
'sub': (int, 'rw'),
|
||||||
|
'sub-delay': (float, 'rw'),
|
||||||
|
'sub-pos': (int, 'rw'),
|
||||||
|
'sub-visibility': (ynbool, 'rw'),
|
||||||
|
'sub-forced-only': (ynbool, 'rw'),
|
||||||
|
'sub-scale': (float, 'rw'),
|
||||||
|
'ass-use-margins': (ynbool, 'rw'),
|
||||||
|
'ass-vsfilter-aspect-compat': (ynbool, 'rw'),
|
||||||
|
'ass-style-override': (str, 'rw'),
|
||||||
|
'stream-capture': (str, 'rw'),
|
||||||
|
'tv-brightness': (int, 'rw'),
|
||||||
|
'tv-contrast': (int, 'rw'),
|
||||||
|
'tv-saturation': (int, 'rw'),
|
||||||
|
'tv-hue': (int, 'rw'),
|
||||||
|
'playlist-pos': (int, 'rw'),
|
||||||
|
'playlist-count': (int, 'r'),
|
||||||
|
'quvi-format': (str, 'rw'),
|
||||||
|
'seekable': (ynbool, 'r')}
|
||||||
|
|
||||||
def bindproperty(MPV, name, proptype, access):
|
def bindproperty(MPV, name, proptype, access):
|
||||||
def getter(self):
|
def getter(self):
|
||||||
return proptype(_ensure_encoding(_mpv_get_property_string(self.handle, name.encode())))
|
return proptype(_ensure_encoding(_mpv_get_property_string(self.handle, name.encode())))
|
||||||
|
|
@ -478,113 +612,6 @@ def bindproperty(MPV, name, proptype, access):
|
||||||
raise NotImplementedError('Access denied')
|
raise NotImplementedError('Access denied')
|
||||||
setattr(MPV, name.replace('-', '_'), property(getter if 'r' in access else barf, setter if 'w' in access else barf))
|
setattr(MPV, name.replace('-', '_'), property(getter if 'r' in access else barf, setter if 'w' in access else barf))
|
||||||
|
|
||||||
for name, proptype, access in (
|
for name, (proptype, access) in ALL_PROPERTIES.items():
|
||||||
('osd-level', int, 'rw'),
|
|
||||||
('osd-scale', float, 'rw'),
|
|
||||||
('loop', str, 'rw'),
|
|
||||||
('loop-file', str, 'rw'),
|
|
||||||
('speed', float, 'rw'),
|
|
||||||
('filename', str, 'r'),
|
|
||||||
('file-size', int, 'r'),
|
|
||||||
('path', str, 'r'),
|
|
||||||
('media-title', str, 'r'),
|
|
||||||
('stream-pos', int, 'rw'),
|
|
||||||
('stream-end', int, 'r'),
|
|
||||||
('length', float, 'r'),
|
|
||||||
('avsync', float, 'r'),
|
|
||||||
('total-avsync-change', float, 'r'),
|
|
||||||
('drop-frame-count', int, 'r'),
|
|
||||||
('percent-pos', int, 'rw'),
|
|
||||||
('ratio-pos', float, 'rw'),
|
|
||||||
('time-pos', float, 'rw'),
|
|
||||||
('time-start', float, 'r'),
|
|
||||||
('time-remaining', float, 'r'),
|
|
||||||
('playtime-remaining', float, 'r'),
|
|
||||||
('chapter', int, 'rw'),
|
|
||||||
('edition', int, 'rw'),
|
|
||||||
('disc-titles', int, 'r'),
|
|
||||||
('disc-title', str, 'rw'),
|
|
||||||
('disc-menu-active', ynbool, 'r'),
|
|
||||||
('chapters', int, 'r'),
|
|
||||||
('editions', int, 'r'),
|
|
||||||
('angle', int, 'rw'),
|
|
||||||
('pause', ynbool, 'rw'),
|
|
||||||
('core-idle', ynbool, 'r'),
|
|
||||||
('cache', int, 'r'),
|
|
||||||
('cache-size' , int, 'rw'),
|
|
||||||
('pause-for-cache', ynbool, 'r'),
|
|
||||||
('eof-reached', ynbool, 'r'),
|
|
||||||
('pts-association-mode', str, 'rw'),
|
|
||||||
('hr-seek', ynbool, 'rw'),
|
|
||||||
('volume', float, 'rw'),
|
|
||||||
('mute', ynbool, 'rw'),
|
|
||||||
('audio-delay', float, 'rw'),
|
|
||||||
('audio-format', str, 'r'),
|
|
||||||
('audio-codec', str, 'r'),
|
|
||||||
('audio-bitrate', float, 'r'),
|
|
||||||
('audio-samplerate', int, 'r'),
|
|
||||||
('audio-channels', str, 'r'),
|
|
||||||
('aid', int, 'rw'),
|
|
||||||
('audio', int, 'rw'),
|
|
||||||
('balance', int, 'rw'),
|
|
||||||
('fullscreen', ynbool, 'rw'),
|
|
||||||
('deinterlace', str, 'rw'),
|
|
||||||
('colormatrix', str, 'rw'),
|
|
||||||
('colormatrix-input-range', str, 'rw'),
|
|
||||||
('colormatrix-output-range', str, 'rw'),
|
|
||||||
('colormatrix-primaries', str, 'rw'),
|
|
||||||
('ontop', ynbool, 'rw'),
|
|
||||||
('border', ynbool, 'rw'),
|
|
||||||
('framedrop', str, 'rw'),
|
|
||||||
('gamma', float, 'rw'),
|
|
||||||
('brightness', int, 'rw'),
|
|
||||||
('contrast', int, 'rw'),
|
|
||||||
('saturation', int, 'rw'),
|
|
||||||
('hue', int, 'rw'),
|
|
||||||
('hwdec', ynbool, 'rw'),
|
|
||||||
('panscan', float, 'rw'),
|
|
||||||
('video-format', str, 'r'),
|
|
||||||
('video-codec', str, 'r'),
|
|
||||||
('video-bitrate', float, 'r'),
|
|
||||||
('width', int, 'r'),
|
|
||||||
('height', int, 'r'),
|
|
||||||
('dwidth', int, 'r'),
|
|
||||||
('dheight', int, 'r'),
|
|
||||||
('fps', float, 'r'),
|
|
||||||
('estimated-vf-fps', float, 'r'),
|
|
||||||
('window-scale', float, 'rw'),
|
|
||||||
('video-aspect', str, 'rw'),
|
|
||||||
('osd-width', int, 'r'),
|
|
||||||
('osd-height', int, 'r'),
|
|
||||||
('osd-par', float, 'r'),
|
|
||||||
('vid', int, 'rw'),
|
|
||||||
('video', int, 'rw'),
|
|
||||||
('video-align-x', float, 'rw'),
|
|
||||||
('video-align-y', float, 'rw'),
|
|
||||||
('video-pan-x', int, 'rw'),
|
|
||||||
('video-pan-y', int, 'rw'),
|
|
||||||
('video-zoom', float, 'rw'),
|
|
||||||
('video-unscaled', ynbool, 'w'),
|
|
||||||
('program', int, 'w'),
|
|
||||||
('sid', int, 'rw'),
|
|
||||||
('secondary-sid', int, 'rw'),
|
|
||||||
('sub', int, 'rw'),
|
|
||||||
('sub-delay', float, 'rw'),
|
|
||||||
('sub-pos', int, 'rw'),
|
|
||||||
('sub-visibility', ynbool, 'rw'),
|
|
||||||
('sub-forced-only', ynbool, 'rw'),
|
|
||||||
('sub-scale', float, 'rw'),
|
|
||||||
('ass-use-margins', ynbool, 'rw'),
|
|
||||||
('ass-vsfilter-aspect-compat', ynbool, 'rw'),
|
|
||||||
('ass-style-override', str, 'rw'),
|
|
||||||
('stream-capture', str, 'rw'),
|
|
||||||
('tv-brightness', int, 'rw'),
|
|
||||||
('tv-contrast', int, 'rw'),
|
|
||||||
('tv-saturation', int, 'rw'),
|
|
||||||
('tv-hue', int, 'rw'),
|
|
||||||
('playlist-pos', int, 'rw'),
|
|
||||||
('playlist-count', int, 'r'),
|
|
||||||
('quvi-format', str, 'rw'),
|
|
||||||
('seekable', ynbool, 'r')):
|
|
||||||
bindproperty(MPV, name, proptype, access)
|
bindproperty(MPV, name, proptype, access)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue