From 7943565a6ec0585a351f4f054ab472e50ac0535c Mon Sep 17 00:00:00 2001 From: yumoqing Date: Sat, 23 Apr 2022 19:57:11 +0800 Subject: [PATCH] bugfix --- kivyblocks/blocks.py | 89 +++++++++++++++++++++++++++++++++-- kivyblocks/hack_ffpyplayer.py | 40 ++++++++++------ kivyblocks/newvideo.py | 3 +- 3 files changed, 112 insertions(+), 20 deletions(-) diff --git a/kivyblocks/blocks.py b/kivyblocks/blocks.py index 44b15b1..5f252be 100755 --- a/kivyblocks/blocks.py +++ b/kivyblocks/blocks.py @@ -270,8 +270,9 @@ class Blocks(EventDispatcher): widget.widget_id = id widget.build_desc = desc - self.build_attributes(widget,desc) - self.build_rest(widget,desc) + self.build_attributes(widget, desc) + self.build_rest(widget, desc) + self.buildBinds(widget, desc) return widget def build_attributes(self, widget:Widget,desc,t=None): @@ -297,17 +298,26 @@ class Blocks(EventDispatcher): pos = 0 for pos,sw in enumerate(desc.get('subwidgets',[])): b = Blocks() + if isinstance(sw, str): + w = Blocks.getWidgetById(sw, from_widget=widget) + if w: + widget.add_widget(w) + continue + kw = self.valueExpr(sw.copy(), localnamespace={'self':widget}) w = b.widgetBuild(kw) - widget.add_widget(w) + if w: + widget.add_widget(w) + + def buildBinds(self, widget:Widget, desc:dict): for b in desc.get('binds',[]): kw = self.valueExpr(b.copy(), \ localnamespace={'self':widget}) self.buildBind(widget,kw) - def buildBind(self, widget:Widget, desc): + def buildBind(self, widget:Widget, desc:dict): wid = desc.get('wid','self') w = Blocks.getWidgetById(desc.get('wid','self'),from_widget=widget) if not w: @@ -533,7 +543,7 @@ class Blocks(EventDispatcher): w = args[0] target = desc.get('target') if target: - w = self.getWidgetById(target, from_widget=widget) + w = Blocks.getWidgetById(target, from_widget=widget) if w is None: print('get_rtdata():w is None', desc) return {} @@ -663,6 +673,75 @@ class Blocks(EventDispatcher): return None return doit(desc) + @classmethod + def findWidget(self, id:str, from_widget:Widget=None) -> Widget: + """ + -:find up direct, find widget in ancestor + + or empty: find down direct, find widget in descendant + @:find widget by class + $ or empty:find widget by id + .:more than one step. + + """ + def find_widget_by_id(id, from_widget): + if id=='self': + return from_widget + if hasattr(from_widget,'widget_id'): + if from_widget.widget_id == id: + return from_widget + if hasattr(from_widget, id): + w = getattr(from_widget,id) + return w + return None + + def find_widget_by_class(klass, from_widget) + if from_widget.__class__.__name__ == klass: + return from_widget + for k, v in from_widget.__dict__.items(): + if isinstance(v, Widget): + if v.__class__.__name__ == klass: + return v + retur None + + def _find_widget(name, from_widget, dir='down', + find_func=find_widget_by_id): + w = ff(name, from_widget) + if w: + return w + if dir == 'down': + children = [i for i in from_widget.children] + if hasattr(from_widget, 'get_subwidgets'): + children = from_widget.get_subwidgets() + for c in children: + ret = ff(id,from_widget=c) + if ret: + return ret + else: + if isinstance(from_widget, WindowBase): + return None + if from_widget.parent: + return ff(id, from_widget=from_widget.parent) + return None + + def find_widget(step, from_widget): + dir = 'down' + if step[0:1] == '-': + dir = 'up' + step = step[1:] + find_func = find_widget_by_id + if step[0:1] == '@': + find_func = find_widget_by_class + return _find_widget(step, from_widget=from_widget, + dir=dir, find_func=find_func) + + steps = id.split('.') + w = from_widget + for s in steps: + w = find_widget(s, w) + if not w: + return None + return w + @classmethod def getWidgetById(self, id:str, from_widget:Widget=None) -> Widget: def find_widget_by_id(id, from_widget): diff --git a/kivyblocks/hack_ffpyplayer.py b/kivyblocks/hack_ffpyplayer.py index e90fbf2..eaefb0e 100644 --- a/kivyblocks/hack_ffpyplayer.py +++ b/kivyblocks/hack_ffpyplayer.py @@ -1,8 +1,33 @@ from functools import partial -from ffpyplayer.player import MediaPlayer +from ffpyplayer.player import MediaPlayer as OldMediaPlayer from threading import Thread from kivy.core.video.video_ffpyplayer import VideoFFPy +from kivy.core.video import video_ffpyplayer + +external_ff_opts = {} +external_lib_opts = {} + +def set_external_ff_opts(dic): + external_ff_opts = dic + +def set_external_lib_opts(dic): + external_lib_opts = dic + +def MediaPlayer(filename, *args, ff_opts={}, lib_opts={}, **kw): + ff_opts.update(external_ff_opts) + lib_opts.update(external_lib_opts) + if filename.startswith('http://') or \ + filename.startswith('https://'): + headers = get_spec_headers(filename) + if headers is not None: + lib_opts['headers'] = "$'%s'" % headers + + return OldMediaPlayer(filename, *args, ff_opts=ff_opts, + lib_opts=lib_opts, **kw) + +def hack_mediaplayer(): + video_ffpyplayer.MediaPlayer = MediaPlayer headers_pattern = { } @@ -15,16 +40,3 @@ def get_spec_headers(filename): if p in filename: return headers_pattern[p] return None - -old_init = getattr(MediaPlayer, '__init__') - -def mediaplayer_init(self, filename, *args, lib_opts={}, **kw): - print('******************** MediaPlayer __init__ hacked *****') - if self._filename.startswith('http://') or \ - self._filename.startswith('https://'): - headers = get_spec_headers(self._filename) - if headers is not None: - lib_opts['headers'] = "$'%s'" % headers - old_init(self, file, *args, lib_opts=lib_opts, **kw) - -# setattr(MediaPlayer, '__init__', mediaplayer_init) diff --git a/kivyblocks/newvideo.py b/kivyblocks/newvideo.py index 15db750..7a8cd8c 100644 --- a/kivyblocks/newvideo.py +++ b/kivyblocks/newvideo.py @@ -8,7 +8,7 @@ from kivy.clock import Clock from ffpyplayer.tools import set_log_callback -from .hack_ffpyplayer import set_headers_pattern +from .hack_ffpyplayer import set_headers_pattern, hack_mediaplayer logger_func = {'quiet': Logger.critical, 'panic': Logger.critical, 'fatal': Logger.critical, 'error': Logger.error, 'warning': Logger.warning, 'info': Logger.info, @@ -19,6 +19,7 @@ class NewVideo(Video): center_screen = BooleanProperty(False) h_pattern = DictProperty(None) def __init__(self, **kw): + hack_mediaplayer() Video.__init__(self, **kw) Window.allow_screensaver = False set_log_callback(self.ffplayerLog)