From f62f104c8d2548226ab59afb3246a72ea2f09940 Mon Sep 17 00:00:00 2001 From: DYefremov Date: Wed, 2 Oct 2019 14:44:58 +0300 Subject: [PATCH] added rewind support to the player --- app/tools/media.py | 17 ++++++- app/ui/main_app_window.py | 29 +++++++++++- app/ui/main_window.glade | 98 ++++++++++++++++++++++++++++----------- 3 files changed, 114 insertions(+), 30 deletions(-) diff --git a/app/tools/media.py b/app/tools/media.py index cef65066..fc76ec69 100644 --- a/app/tools/media.py +++ b/app/tools/media.py @@ -1,13 +1,25 @@ from app.commons import run_task from app.tools import vlc +from app.tools.vlc import EventType class Player: _VLC_INSTANCE = None - def __init__(self): + def __init__(self, rewind_callback=None, position_callback=None): self._is_playing = False self._player = self.get_vlc_instance() + ev_mgr = self._player.event_manager() + + if rewind_callback: + # TODO look other EventType options + ev_mgr.event_attach(EventType.MediaPlayerBuffering, + lambda e, p: rewind_callback(p.get_media().get_duration()), + self._player) + if position_callback: + ev_mgr.event_attach(EventType.MediaPlayerTimeChanged, + lambda e, p: position_callback(p.get_time()), + self._player) @staticmethod def get_vlc_instance(): @@ -32,6 +44,9 @@ class Player: def pause(self): self._player.pause() + def set_time(self, time): + self._player.set_time(time) + @run_task def release(self): if self._player: diff --git a/app/ui/main_app_window.py b/app/ui/main_app_window.py index f2523f25..850a901b 100644 --- a/app/ui/main_app_window.py +++ b/app/ui/main_app_window.py @@ -138,6 +138,7 @@ class Application(Gtk.Application): "on_player_stop": self.on_player_stop, "on_player_previous": self.on_player_previous, "on_player_next": self.on_player_next, + "on_player_rewind": self.on_player_rewind, "on_player_close": self.on_player_close, "on_player_press": self.on_player_press, "on_full_screen": self.on_full_screen, @@ -239,6 +240,10 @@ class Application(Gtk.Application): self._filter_only_free_button = builder.get_object("filter_only_free_button") # Player self._player_box = builder.get_object("player_box") + self._player_scale = builder.get_object("player_scale") + self._player_full_time_label = builder.get_object("player_full_time_label") + self._player_current_time_label = builder.get_object("player_current_time_label") + self._player_rewind_box = builder.get_object("player_rewind_box") self._player_drawing_area = builder.get_object("player_drawing_area") self._player_tool_bar = builder.get_object("player_tool_bar") self._player_prev_button = builder.get_object("player_prev_button") @@ -1528,7 +1533,8 @@ class Application(Gtk.Application): def play(self, url): if not self._player: try: - self._player = Player() + self._player = Player(rewind_callback=self.on_player_duration_changed, + position_callback=self.on_player_time_changed) except (NameError, AttributeError): self.show_error_dialog("No VLC is found. Check that it is installed!") return @@ -1560,6 +1566,9 @@ class Application(Gtk.Application): if self._fav_view.do_move_cursor(self._fav_view, Gtk.MovementStep.DISPLAY_LINES, 1): self.on_play_stream() + def on_player_rewind(self, scale, scroll_type, value): + self._player.set_time(int(value)) + def update_player_buttons(self): if self._player: path, column = self._fav_view.get_cursor() @@ -1573,6 +1582,24 @@ class Application(Gtk.Application): self._player = None GLib.idle_add(self._player_box.set_visible, False, priority=GLib.PRIORITY_LOW) + @lru_cache(maxsize=1) + def on_player_duration_changed(self, duration): + self._player_scale.set_value(0) + self._player_scale.get_adjustment().set_upper(duration) + GLib.idle_add(self._player_rewind_box.set_visible, duration > 0) + GLib.idle_add(self._player_current_time_label.set_text, "0") + GLib.idle_add(self._player_full_time_label.set_text, self.get_time_str(duration)) + + def on_player_time_changed(self, t): + if not self._full_screen and self._player_rewind_box.get_visible(): + GLib.idle_add(self._player_current_time_label.set_text, self.get_time_str(t), priority=GLib.PRIORITY_LOW) + + def get_time_str(self, duration): + """ returns a string representation of time from duration in milliseconds """ + m, s = divmod(duration // 1000, 60) + h, m = divmod(m, 60) + return "{}{:02d}:{:02d}".format(str(h) + ":" if h else "", m, s) + def on_drawing_area_realize(self, widget): self._drawing_area_xid = widget.get_window().get_xid() self._player.set_xwindow(self._drawing_area_xid) diff --git a/app/ui/main_window.glade b/app/ui/main_window.glade index de47dcfb..e1c21ae7 100644 --- a/app/ui/main_window.glade +++ b/app/ui/main_window.glade @@ -612,6 +612,11 @@ Author: Dmitriy Yefremov False gtk-new + + 100 + 1 + 10 + True False @@ -1367,17 +1372,20 @@ Author: Dmitriy Yefremov True False + 15 + 15 - + True False - - - + Previous stream in the list + True + gtk-media-previous + - True - True + False + False @@ -1390,7 +1398,7 @@ Author: Dmitriy Yefremov False - True + False @@ -1404,21 +1412,7 @@ Author: Dmitriy Yefremov False - True - - - - - True - False - Previous stream in the list - True - gtk-media-previous - - - - False - True + False @@ -1432,15 +1426,64 @@ Author: Dmitriy Yefremov False - True + False - + True False - + + False + 15 + 15 + 2 + + + True + False + 0 + + + False + True + 0 + + + + + True + True + 5 + 5 + player_scale_adjustment + False + 0 + 1 + False + False + + + + True + True + 1 + + + + + True + False + 0 + + + False + True + 2 + + + @@ -1459,7 +1502,7 @@ Author: Dmitriy Yefremov False - True + False @@ -1467,14 +1510,13 @@ Author: Dmitriy Yefremov True False Close - 15 True gtk-close False - True + False