This commit is contained in:
yumoqing 2022-11-19 15:47:55 +08:00
parent f380aadf94
commit f4e8d384c5
24 changed files with 97 additions and 54 deletions

0
kivyblocks/baseWidget.py Executable file → Normal file
View File

0
kivyblocks/blocks.py Executable file → Normal file
View File

0
kivyblocks/dg.py Executable file → Normal file
View File

0
kivyblocks/externalwidgetmanager.py Executable file → Normal file
View File

View File

@ -1,4 +1,5 @@
from traceback import print_exc
import time
import numpy as np
from ffpyplayer.player import MediaPlayer
@ -16,7 +17,32 @@ from kivy.graphics.texture import Texture
from kivy.graphics import Color, Line
from kivyblocks.ready import WidgetReady
from kivyblocks.baseWidget import Running
from kivyblocks.videobehavior import VideoBehavior
vhks = ['v_src',
'play_mode',
'header_callback',
'audio_id',
'duration',
'position',
'volume',
'timeout',
'in_center_focus',
'renderto',
'auto_play',
'repeat'
]
class FFVideo(WidgetReady, VideoBehavior, Widget):
def __init__(self, **kw):
kw1 = {k:v for k,v in kw.items() if k in vhks}
kw1['renderto'] = 'background'
kw2 = {k:v for k,v in kw.items() if k not in vhks}
Widget.__init__(self, **kw2)
VideoBehavior.__init__(self, **kw1)
WidgetReady.__init__(self)
"""
class FFVideo(WidgetReady, Image):
v_src = StringProperty(None)
status = OptionProperty('stop', \
@ -130,7 +156,8 @@ class FFVideo(WidgetReady, Image):
def on_parent(self, *args):
if self.parent:
return
self._play_stop()
# self._play_stop()
print('on_parent() called -----------')
def on_startplay(self, *args):
pass
@ -228,7 +255,9 @@ class FFVideo(WidgetReady, Image):
print('ff_opts=', ff_opts)
print('lib_opts=', lib_opts)
# self._player = MediaPlayer(self.v_src)
print('EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEe')
print_exc()
print('EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEe')
self._player = MediaPlayer(self.v_src, ff_opts=ff_opts, \
lib_opts=lib_opts)
# self._play_start()
@ -403,3 +432,4 @@ class FFVideo(WidgetReady, Image):
self.vh_task = Clock.schedule_once(self.video_handle, 0)
self.block_task = Clock.schedule_once(self.video_blocked, self.timeout)
"""

0
kivyblocks/imgs/bullet_arrow_down.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 201 B

After

Width:  |  Height:  |  Size: 201 B

0
kivyblocks/imgs/bullet_arrow_right.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 315 B

After

Width:  |  Height:  |  Size: 315 B

0
kivyblocks/imgs/folder.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 537 B

After

Width:  |  Height:  |  Size: 537 B

0
kivyblocks/imgs/picture_empty.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 463 B

After

Width:  |  Height:  |  Size: 463 B

View File

@ -2,9 +2,8 @@
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.widget import Widget
from kivyblocks.bgcolorbehavior import BGColorBehavior
from kivyblocks.utils import SUPER
from kivyblocks.utils import widget_build
from kivyblocks.mixin import get_mixins, filter_mixin
from kivyblocks.register import widget_build
class LandscopeHide(FloatLayout):
def __init__(self, fix_desc=None, float_desc=None, **kw):

View File

@ -47,10 +47,12 @@ from .pyinterpreter import PyInterpreter
from .circle_progress import CircleProgress
from .modalbehavior import ModalBehavior
from .videobehavior import VideoBehavior
from .landscopehide import LandscopeHide
r = Factory.register
# if kivy.platform in ['win','linux', 'macosx']:
# r('ScreenWithMic', ScreenWithMic)
r('LandscopeHide', LandscopeHide)
r('VideoBehavior', VideoBehavior)
r('ModalBehavior', ModalBehavior)
r('CircleProgress', CircleProgress)
@ -155,8 +157,4 @@ def register_blocks(name, value):
except:
Logger.info(f'plugin : register_blocks():{name} register error')
def widget_build(desc):
b = Factory.Blocks()
w = b.widgetBuild(desc)
return w

View File

@ -27,6 +27,8 @@ class Script:
def __init__(self):
config = getConfig()
self.root = config.script_root
if sep != '/':
self.root = self.root.replace(sep, '/')
# print('Script.root=', self.root)
self.env = {}
self.env['uihome'] = config.uihome
@ -38,8 +40,13 @@ class Script:
def url2filepath(self, url):
if url.startswith('file://'):
url = url[7:]
ret = join(self.root, *url.split('/'))
print('url2filepath():root=', self.root, url, ret)
parts = self.root.split('/')
if url[0] == '/':
url = url[1:]
parts += url.split('/')
ret = '/'.join(parts)
# ret = join(self.root, *url.split('/'))
print('url2filepath():root=', self.root, url, parts, ret)
return ret
def show_info(self, env):
@ -67,12 +74,13 @@ class Script:
env['root_path'] = self.root
env['url'] = url
env['filepath'] = filepath
h = handler(env)
h = handler(self, env)
d = h.render()
try:
return json.loads(d)
except:
return d
return filepath
def register(self, suffix, handler):
self.handlers[suffix] = handler
@ -81,6 +89,10 @@ class Script:
self.env.update({n:v})
class BaseHandler:
def real_filepath(self, url):
myurl = self.entire_url(url)
return self.script.url2filepath(myurl)
def entire_url(self, url):
if url.startswith('file://') or \
url.startswith('http://') or \
@ -89,38 +101,42 @@ class BaseHandler:
tokens = url.split('/')
if tokens[0] == '':
root = self.env['uihome']
tokens[0] = root
return '/'.join(tokens)
if root[-1] == '/':
return root + url[1:]
else:
tokens[0] = root
return '/'.join(tokens)
p1 = self.env['url'].split('/')[:-1]
ret = '/'.join(p1+tokens)
"""
print('entire_url(): org_url=', self.env['url'],
'url=', url,
'p1=', p1,
'tokens=', tokens,
'ret=', ret)
"""
return ret
def __init__(self, env):
def __init__(self, script, env):
self.script = script
self.env = env
self.env['entire_url'] = self.entire_url
self.env['real_filepath'] = self.real_filepath
class TemplateHandler(BaseHandler):
def __init__(self, env):
super().__init__(env)
def __init__(self, script, env):
super().__init__(script, env)
root = env['root_path']
paths = [root]
fp = env['filepath'][len(root):]
plst = fp.split(sep)[:-1]
fp = env['filepath'][len(root)+1:]
plst = fp.split('/')[:-1]
self.templ_file = basename(env['filepath'])
cpath = root
for p in plst:
cpath = join(cpath, p)
cpath = f'{cpath}/{p}'
paths.append(cpath)
paths.reverse()
print(f'paths={paths}')
self.engine = MyTemplateEngine(paths)
def render(self):
@ -132,8 +148,8 @@ class TemplateHandler(BaseHandler):
traceback.print_exc()
class DspyHandler(BaseHandler):
def __init__(self, env):
super().__init__(env)
def __init__(self, script, env):
super().__init__(script, env)
def loadScript(self, path):
data = ''

0
kivyblocks/ttf/DroidSansFallback.ttf Executable file → Normal file
View File

View File

@ -3,13 +3,14 @@ from traceback import print_exc
from traceback import print_exc
from kivy.app import App
from kivy.logger import Logger
from appPublic.jsonConfig import getConfig
from kivy.factory import Factory
from kivy.uix.popup import Popup
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.modalview import ModalView
from kivy.uix.image import AsyncImage
from appPublic.jsonConfig import getConfig
from appPublic.dictObject import DictObject
from .mixin import filter_mixin, get_mixins, mixin_behaviors
@ -244,3 +245,9 @@ def show_widget_info(w, tag='DEBUG'):
id = getattr(w, 'widget_id', 'null')
msg=f"""{tag}:size_hint={w.size_hint},size={w.size},pos={w.pos},widget_id={id},{w}"""
Logger.info(msg)
def widget_build(desc):
b = Factory.Blocks()
w = b.widgetBuild(desc)
return w

View File

@ -1,4 +1,5 @@
from traceback import print_exc
import time
import numpy as np
from ffpyplayer.player import MediaPlayer
@ -32,10 +33,11 @@ class VideoBehavior(object):
auto_play=BooleanProperty(True)
repeat=BooleanProperty(False)
in_center_focus = BooleanProperty(False)
render_to = OptionProperty('foreground', options=['background', 'foreground', 'cover'])
renderto = OptionProperty('foreground', options=['background', 'foreground', 'cover'])
def __init__(self, **kwargs):
self._player = None
self.change_size_task = None
self._update_task = None
self.running = None
self.vh_task = None
@ -56,7 +58,7 @@ class VideoBehavior(object):
self.register_event_type('on_load_success')
self.register_event_type('on_startplay')
self.bind(size=self.set_video_size)
self.bind(parent=self.stop_when_remove)
# self.bind(parent=self.stop_when_remove)
for k, v in kwargs.items():
setattr(self, k, v)
@ -142,6 +144,7 @@ class VideoBehavior(object):
pass
def on_frame(self, *args):
return
w = self.get_root_window()
if w is None:
self.status = 'stop'
@ -149,12 +152,6 @@ class VideoBehavior(object):
if self._player is None:
return
if not self.playing:
self.dispatch('on_startplay')
self._player.request_channel( \
'audio', 'open', self.audio_id)
self.seek(self.position)
self.playing = True
def __del__(self):
self._play_stop()
@ -205,34 +202,27 @@ class VideoBehavior(object):
self._player.request_channel('audio', action='cycle')
def on_v_src(self, o, src):
# self.running = Running(self)
self.status = 'stop'
self.playing = False
ff_opts = {
'pause':False
}
if self.play_mode == 'preview':
ff_opts['lowres'] = 2 # 1/4 size
ff_opts['an'] = True
elif self.play_mode == 'audioonly':
ff_opts['vn'] = True
ff_opts.update(self.ff_opts)
lib_opts = {
}
lib_opts.update(self.lib_opts)
heads = self._get_spec_headers(self.v_src)
if heads:
lib_opts.update({'headers':heads})
ff_opts.update({'headers':heads})
# ff_opts.update({'headers':heads})
print('ff_opts=', ff_opts)
print('lib_opts=', lib_opts)
# self._player = MediaPlayer(self.v_src)
self._player = MediaPlayer(self.v_src, ff_opts=ff_opts, \
lib_opts=lib_opts)
self.playing = False
if self.auto_play:
self.play()
@ -257,13 +247,11 @@ class VideoBehavior(object):
self.status = 'pause'
def _get_video_info(self):
if not self.playing:
self.playing = True
meta = self._player.get_metadata()
self.duration = meta['duration']
self._out_fmt = meta['src_pix_fmt']
self.frame_rate = meta['frame_rate']
self.videosize = meta['src_vid_size']
meta = self._player.get_metadata()
self.duration = meta['duration']
self._out_fmt = meta['src_pix_fmt']
self.frame_rate = meta['frame_rate']
self.videosize = meta['src_vid_size']
def _play_stop(self):
if self._player:
@ -287,6 +275,10 @@ class VideoBehavior(object):
self.videosize = None
def set_video_size(self, *args):
if self.change_size_task:
self.change_size_task.cancel()
self.change_size_task = Clock.schedule_once(self._set_video_size, 0.1)
def _set_video_size(self, *args):
if self._player is None:
return
if self.videosize == None:
@ -294,10 +286,13 @@ class VideoBehavior(object):
w, h = self.videosize
r = w / h
r1 = self.width / self.height
# position = self.position
if r1 >= r:
self._player.set_size(-1, self.height)
else:
self._player.set_size(self.width, -1)
# self.seek(position)
# print('_set_video_size():position=', position)
def set_black(self):
if self.is_black:
@ -365,7 +360,6 @@ class VideoBehavior(object):
canvas.clear()
with canvas:
Rectangle(texture=texture, pos=pos, size=(w, h))
self.canvas.after.clear()
Color(1,1,1,1)
Line(points=[0, 1, self.width, 1], width=2)
Color(1,0,0,1)
@ -397,7 +391,6 @@ class VideoBehavior(object):
self.vh_task = Clock.schedule_once(self.video_handle, 0.1)
return
self. _get_video_info()
self.last_frame = frame
self.video_ts = val
if self.last_val is None:
@ -416,10 +409,10 @@ class VideoBehavior(object):
self.start_task = None
if self.block_task:
self.block_task.cancel()
# if self.running:
# print('runnung dismiss ........')
# self.running.dismiss()
# self.running = None
if not self.playing:
self.playing = True
self._get_video_info()
self.dispatch('on_startplay')
self.position = self._player.get_pts()
self.volume = self._player.get_volume()
img, t = self.last_frame

0
kivyblocks/widgetExt/__init__.py Executable file → Normal file
View File

0
kivyblocks/widgetExt/androidwebview.py Executable file → Normal file
View File

0
kivyblocks/widgetExt/binstateimage.py Executable file → Normal file
View File

0
kivyblocks/widgetExt/dataloader.py Executable file → Normal file
View File

0
kivyblocks/widgetExt/inputext.py Executable file → Normal file
View File

0
kivyblocks/widgetExt/jsoncodeinput.py Executable file → Normal file
View File

0
kivyblocks/widgetExt/scrollwidget.py Executable file → Normal file
View File

0
kivyblocks/widgetExt/sqldataloadder.py Executable file → Normal file
View File

0
setup.py Executable file → Normal file
View File