diff --git a/kivyblocks/blocks.py b/kivyblocks/blocks.py index 8783844..92a6f24 100755 --- a/kivyblocks/blocks.py +++ b/kivyblocks/blocks.py @@ -769,7 +769,7 @@ x = ClassX{klass_cnt}() children = [i for i in from_widget.children] if hasattr(from_widget, 'get_subwidgets'): children = from_widget.get_subwidgets() - # Logger.info('children=%s', str(children)) + Logger.info('children=%s', str(children)) for c in children: ret = _find_widget(name, from_widget=c, dir=dir) if ret: @@ -781,8 +781,16 @@ x = ClassX{klass_cnt}() return _find_widget(name, from_widget=from_widget.parent, dir=dir) - Logger.info('Block:_find_widget(), %s, %s %s return None', - name, from_widget.__class__.__name__, dir) + wid = None + if hasattr(from_widget, 'widget_id'): + wid = getattr(from_widget, 'widget_id') + if wid == 'channel_list': + print('channel_list=', from_widget.__class__.__name__, 'children cnt=', len(from_widget.children)) + for c in children: + cid = None + if hasattr(c, 'widget_id'): + cid = getattr(c, 'widget_id') + print('channel_list children:', c.__class__.__name__, cid) return None def find_widget(step, from_widget): diff --git a/kivyblocks/dg.py b/kivyblocks/dg.py index e951294..ecce274 100755 --- a/kivyblocks/dg.py +++ b/kivyblocks/dg.py @@ -58,7 +58,7 @@ class Cell(ButtonBehavior, WidgetCSS, BoxLayout): self.row = row width = self.desc['width'] height = self.row.part.datagrid.rowHeight() - print(f'Cell:{width=}, {height=},value={desc["value"]}') + # print(f'Cell:{width=}, {height=},value={desc["value"]}') super().__init__(size_hint=(None,None), width=width, bgcolor=[0.1,0.5,0.5], @@ -173,7 +173,6 @@ class Body(WidgetReady, ScrollPanel): row.row_id = id self.add_widget(row,index=index) self.idRow[id] = row - print(f'row size={row.size}, hint={row.size_hint}') return row def clearRows(self): @@ -531,6 +530,10 @@ class DataGrid(VBox): idx = -1 recs1 = recs[:self.show_rows] recs2 = recs[self.show_rows:] + for r in recs1: + id = self.addRow(r,index=idx) + ids.append(id) + """ self._fbo = Fbo(size=self.size) with self._fbo: self._background_color = Color(0,0,0,1) @@ -541,6 +544,7 @@ class DataGrid(VBox): with self.canvas: self._fbo_rect = Rectangle(size=self.size, texture=self._fbo.texture) + """ data['idx'] = idx data['ids'] = ids diff --git a/kivyblocks/ffpyplayer_video.py b/kivyblocks/ffpyplayer_video.py index 7a074e2..a7d122e 100755 --- a/kivyblocks/ffpyplayer_video.py +++ b/kivyblocks/ffpyplayer_video.py @@ -35,7 +35,6 @@ vhks = ['v_src', ] class FFVideo(WidgetReady, VideoBehavior, BoxLayout): -# class FFVideo(VideoBehavior, BoxLayout): def __init__(self, **kw): kw1 = {k:v for k,v in kw.items() if k in vhks} kw1['renderto'] = 'background' @@ -44,402 +43,8 @@ class FFVideo(WidgetReady, VideoBehavior, BoxLayout): BoxLayout.__init__(self, **kw2) VideoBehavior.__init__(self, **kw1) WidgetReady.__init__(self) - # self.msg_w = Label(text='Hello') - # self.add_widget(self.msg_w) - # self.bind(on_frame=self.show_info) def show_info(self, o, d): txt = f"size={d['size']}, vpos={d['pos']}, vsize={d['texture_size']}" self.msg_w.text = txt -""" -class FFVideo(WidgetReady, Image): - v_src = StringProperty(None) - status = OptionProperty('stop', \ - options=['stop', 'play', 'pause']) - play_mode = OptionProperty('normal', \ - options=['normal', 'preview', 'audioonly']) - header_callback = StringProperty(None) - audio_id = NumericProperty(None) - duration = NumericProperty(-1) - position = NumericProperty(-1) - volume = NumericProperty(-1) - timeout = NumericProperty(5) - in_center_focus = BooleanProperty(False) - - def __init__(self, **kwargs): - self._player = None - self._update_task = None - self.running = None - self.vh_task = None - self.is_black = False - self.videosize = None - self.ff_opts = { - "framedrop":True - } - self.lib_opts = {} - self.headers_pattern = {} - super(FFVideo, self).__init__(**kwargs) - self.set_black() - self.start_task = None - self.block_task = None - self.register_event_type('on_frame') - self.register_event_type('on_open_failed') - self.register_event_type('on_leave_focus') - self.register_event_type('on_enter_focus') - self.register_event_type('on_load_success') - self.register_event_type('on_startplay') - - def video_blocked(self, *args): - self._play_stop() - self.on_v_src(None, None) - - def on_open_failed(self, source): - print(f'{source} open failed') - - def on_load_success(self, *args): - pass - - def on_enter_focus(self, *args): - pass - - def on_leave_focus(self, *args): - pass - - def check_focus(self,*args): - if not self.parent: - self.in_center_screen = False - return - if not self.get_root_window(): - self.in_center_screen = False - - w = self.parent - pos = w.to_widget(*Window.center) - if self.collide_point(*pos): - self.in_center_screen = True - else: - self.in_center_screen = False - - def set_ff_opt(self, k,v): - self.ff_opts.update({k:v}) - - def set_lib_opt(self, k, v): - self.lib_opts.update({k:v}) - - def set_pattern_header(self, pattern, k,v): - dic = self.headers_pattern.get(pattern,{}) - dic.update({k:v}) - self.headers_pattern[pattern] = dic - - def _get_spec_headers(self, filename): - for p in self.headers_pattern.keys(): - if filename.startswith(p): - headers = self.headers_pattern[p] - headers_str = ''.join([f'{k}:{v}\r\n' for k,v in headers.items()]) - return headers_str - return None - - def on_volume(self, *args): - if self._player is None: - return - - self._player.set_volume(self.volume) - - def on_status(self, *args): - print('on_status called, ', self.status) - if self._player is None: - print('no _player, do nothing') - return - - Window.allow_screensaver = True - if self.status == 'play': - Window.allow_screensaver = False - self._player.set_pause(False) - self.video_handle() - elif self.status == 'pause': - self._player.set_pause(True) - elif self.status == 'stop': - self._play_stop() - else: - pass - - def on_parent(self, *args): - if self.parent: - return - # self._play_stop() - print('on_parent() called -----------') - - def on_startplay(self, *args): - pass - - def on_frame(self, *args): - 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 - if self.duration > 0: - p = self.position / self.duration * self.width - self.canvas.after.clear() - with self.canvas.after: - Color(1,1,1,1) - Line() - Line(points=[0, 0, self.width, 0], width=1) - Color(1,0,0,1) - Line(points=[0,1,p,1], width=1) - - def __del__(self): - self._play_stop() - - def set_volume(self, v): - if self.play_mode == 'preview': - return - if self._player is None: - return - if self.status != 'play': - return - if v > 1.0: - v = 1.0 - if v < 0.0: - v = 0.0 - self.volume = v - - def seek(self, pts): - self.vsync = False - if self.play_mode == 'preview': - return - if self._player is None: - return - if self.status != 'play': - return - self._player.seek(pts, relative=False) - self.position = self._player.get_pts() - self.last_val = None - - def mute(self, flag=None): - if self.play_mode == 'preview': - return - if self._player is None: - return - if self.status != 'play': - return - x = self._player.get_mute() - print('Video(), mute=', x) - self._player.set_mute(not x) - - def switch_audio(self): - if self.play_mode == 'preview': - return - if self._player is None: - return - if self.status != 'play': - return - 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}) - - print('ff_opts=', ff_opts) - print('lib_opts=', lib_opts) - print('EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEe') - print_exc() - print('EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEe') - self._player = MediaPlayer(self.v_src, ff_opts=ff_opts, \ - lib_opts=lib_opts) - # self._play_start() - self.status = 'play' - self.start_task = Clock.schedule_once(self.open_failed, self.timeout) - - def open_failed(self, *args): - self.dispatch('on_open_failed', self.v_src) - - def on_open_failed(self, source): - print(f'{source} open failed') - - def file_opened(self, files): - self.v_src = files[0] - - def play(self): - if self._player is None: - return - self.status = 'play' - - def pause(self): - if self._player is None: - return - # self._player.set_pause(True) - self.status = 'pause' - - def _play_start(self): - self.last_frame = None - self.is_black = False - self.vsync = False - - 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'] - - def _play_stop(self): - if self._player: - self._player.close_player() - self._player = None - if self._update_task: - self._update_task.cancel() - self._update_task = None - if self.vh_task: - self.vh_task.cancel() - self.vh_task = None - self.next_frame = None - self.duration = -1 - self.position = 0 - self.videosize = None - - def on_size(self, *args): - if self._player is None: - return - if self.videosize == None: - return - w, h = self.videosize - r = w / h - r1 = self.width / self.height - if r1 >= r: - self._player.set_size(-1, self.height) - else: - self._player.set_size(self.width, -1) - - def set_black(self): - if self.is_black: - return - image_texture = Texture.create( - size=self.size, colorfmt='rgb') - buf = b'\x00' * int(self.width * self.height * 3) - image_texture.blit_buffer(buf, colorfmt='rgb', bufferfmt='ubyte') - self.texture = image_texture - self.is_black = True - - def show_yuv420(self, img): - w, h = img.get_size() - w2 = int(w / 2) - h2 = int(h / 2) - self._tex_y = Texture.create( - size=(w, h), colorfmt='luminance') - self._tex_u = Texture.create( - size=(w2, h2), colorfmt='luminance') - self._tex_v = Texture.create( - size=(w2, h2), colorfmt='luminance') - self._fbo = fbo = Fbo(size=(w, h)) - with fbo: - BindTexture(texture=self._tex_u, index=1) - BindTexture(texture=self._tex_v, index=2) - Rectangle(size=fbo.size, texture=self._tex_y) - fbo.shader.fs = VideoFFPy.YUV_RGB_FS - fbo['tex_y'] = 0 - fbo['tex_u'] = 1 - fbo['tex_v'] = 2 - dy, du, dv, _ = img.to_memoryview() - if dy and du and dv: - self._tex_y.blit_buffer(dy, colorfmt='luminance') - self._tex_u.blit_buffer(du, colorfmt='luminance') - self._tex_v.blit_buffer(dv, colorfmt='luminance') - self._fbo.ask_update() - self._fbo.draw() - texture.flip_vertical() - self.texture = texture - - def show_others(self, img): - w, h = img.get_size() - texture = Texture.create(size=(w, h), colorfmt='rgb') - texture.blit_buffer( - img.to_memoryview()[0], colorfmt='rgb', - bufferfmt='ubyte') - texture.flip_vertical() - self.texture = texture - # print('img_size=', w, h, 'window size=', self.size) - - def video_handle(self, *args): - if self._update_task: - self._update_task.cancel() - self._update_task = None - if self._player is None: - return - frame, val = self._player.get_frame() - if val == 'eof': - self.status = 'stop' - self.set_black() - self.last_val = None - return - if val == 'pause': - self.status = 'pause' - self.last_val = None - return - if frame is None: - self.set_black() - self.last_val = None - 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: - self.last_val = val - self._update_task = Clock.schedule_once(self.do_update, 0) - else: - t = val - self.last_val - if t > 0: - self._update_task = Clock.schedule_once(self.do_update, t) - else: - self._update_task = Clock.schedule_once(self.do_update, 0) - - def do_update(self, *args): - if self.start_task: - self.start_task.cancel() - self.start_task = None - if self.block_task: - self.block_task.cancel() - # if self.running: - # print('runnung dismiss ........') - # self.running.dismiss() - # self.running = None - self.position = self._player.get_pts() - self.volume = self._player.get_volume() - img, t = self.last_frame - if self._out_fmt == 'yuv420p': - self.show_yuv420(img) - else: - self.show_others(img) - self.dispatch('on_frame', self.last_frame) - self.last_frame = None - self.vh_task = Clock.schedule_once(self.video_handle, 0) - self.block_task = Clock.schedule_once(self.video_blocked, self.timeout) - -""" diff --git a/kivyblocks/newvideo.py b/kivyblocks/newvideo.py index 7a8cd8c..a5bf5c5 100755 --- a/kivyblocks/newvideo.py +++ b/kivyblocks/newvideo.py @@ -40,6 +40,9 @@ class NewVideo(Video): def on_enter_focus(self, v=None): pass + def set_source(self, source): + self.source = source + def on_leave_focus(self, v=None): pass diff --git a/kivyblocks/videobehavior.py b/kivyblocks/videobehavior.py index 0f5353a..72c15e1 100755 --- a/kivyblocks/videobehavior.py +++ b/kivyblocks/videobehavior.py @@ -126,6 +126,8 @@ class VideoBehavior(object): return None def on_volume(self, *args): + if not hasattr(self, '_player'): + return if self._player is None: return @@ -261,6 +263,8 @@ class VideoBehavior(object): self.videosize = meta['src_vid_size'] def _play_stop(self): + if not hasattr(self, '_player'): + return if self._player: self._player.close_player() self._player = None