From 6255b604537b3a2588d6d3c83036e075dfadb4c9 Mon Sep 17 00:00:00 2001 From: DYefremov Date: Thu, 4 May 2023 21:55:58 +0300 Subject: [PATCH] loading screen to playback * some playback refactoring --- app/tools/media.py | 58 +++++++++++++------------------------------ app/ui/playback.glade | 42 +++++++++++++++++++++++++------ app/ui/playback.py | 55 +++++++++++++++++++++++++++++----------- app/ui/style.css | 5 ++++ 4 files changed, 97 insertions(+), 63 deletions(-) diff --git a/app/tools/media.py b/app/tools/media.py index a1b6fae5..e9e62630 100644 --- a/app/tools/media.py +++ b/app/tools/media.py @@ -30,19 +30,20 @@ import os import sys from datetime import datetime -from gi.repository import Gdk, Gtk, GObject +from gi.repository import GObject -from app.commons import run_task, log, LOG_DATE_FORMAT, run_with_delay +from app.commons import run_task, log, LOG_DATE_FORMAT from app.settings import IS_DARWIN, IS_LINUX, IS_WIN -class Player(Gtk.DrawingArea): +class Player(GObject.GObject): """ Base player class. Also used as a factory. """ def __init__(self, mode, widget, **kwargs): super().__init__(**kwargs) self._mode = mode self._is_playing = False + self._handle = self.get_window_handle(widget.playback_widget) GObject.signal_new("error", self, GObject.SIGNAL_RUN_LAST, GObject.TYPE_PYOBJECT, (GObject.TYPE_PYOBJECT,)) @@ -57,16 +58,9 @@ class Player(Gtk.DrawingArea): GObject.signal_new("subtitle-track", self, GObject.SIGNAL_RUN_LAST, GObject.TYPE_PYOBJECT, (GObject.TYPE_PYOBJECT,)) - self.connect("draw", self.on_draw) - self.connect("motion-notify-event", self.on_mouse_motion) - self.set_events(Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.POINTER_MOTION_MASK) - widget.add(self) - - parent = widget.get_parent() - parent.connect("play", self.on_play) - parent.connect("stop", self.on_stop) - parent.connect("pause", self.on_pause) - self.show() + widget.connect("play", self.on_play) + widget.connect("stop", self.on_stop) + widget.connect("pause", self.on_pause) def get_play_mode(self): pass @@ -116,14 +110,14 @@ class Player(Gtk.DrawingArea): def on_release(self, widget, state): self.release() - def get_window_handle(self): + def get_window_handle(self, widget): """ Returns the identifier [pointer] for the window. Based on gtkvlc.py[get_window_pointer] example from here: https://github.com/oaubert/python-vlc/tree/master/examples """ if IS_LINUX: - return self.get_window().get_xid() + return widget.get_window().get_xid() else: try: import ctypes @@ -135,31 +129,13 @@ class Player(Gtk.DrawingArea): # https://gitlab.gnome.org/GNOME/pygobject/-/issues/112 ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.c_void_p ctypes.pythonapi.PyCapsule_GetPointer.argtypes = [ctypes.py_object] - gpointer = ctypes.pythonapi.PyCapsule_GetPointer(self.get_window().__gpointer__, None) + gpointer = ctypes.pythonapi.PyCapsule_GetPointer(widget.get_window().__gpointer__, None) get_pointer = libgdk.gdk_quartz_window_get_nsview if IS_DARWIN else libgdk.gdk_win32_window_get_handle get_pointer.restype = ctypes.c_void_p get_pointer.argtypes = [ctypes.c_void_p] return get_pointer(gpointer) - def on_draw(self, widget, cr): - """ Used for black background drawing in the player drawing area. """ - cr.set_source_rgb(0, 0, 0) - cr.paint() - - def on_mouse_motion(self, widget, event): - display = widget.get_display() - window = widget.get_window() - cursor = Gdk.Cursor.new_from_name(display, "default") - window.set_cursor(cursor) - - self.hide_mouse_cursor(window, display) - - @run_with_delay(3) - def hide_mouse_cursor(self, window, display): - cursor = Gdk.Cursor.new_for_display(display, Gdk.CursorType.BLANK_CURSOR) - window.set_cursor(cursor) - @staticmethod def make(name, mode, widget): """ Factory method. We will not use a separate factory to return a specific implementation. @@ -192,7 +168,7 @@ class MpvPlayer(Player): try: from app.tools import mpv - self._player = mpv.MPV(wid=str(self.get_window_handle()), + self._player = mpv.MPV(wid=str(self._handle), input_default_bindings=False, input_cursor=False, cursor_autohide="no") @@ -292,7 +268,7 @@ class GstPlayer(Player): self.STAT_RETURN = Gst.StateChangeReturn self._player = Gst.ElementFactory.make("playbin", "player") - self._player.set_window_handle(self.get_window_handle()) + self._player.set_window_handle(self._handle) bus = self._player.get_bus() bus.add_signal_watch() @@ -427,7 +403,7 @@ class VlcPlayer(Player): lambda et: self.emit("position", self._player.get_time())) ev_mgr.event_attach(EventType.MediaPlayerEncounteredError, lambda et: self.emit("error", "Can't Playback!")) - self.init_video_widget(widget) + self.init_video_widget() @classmethod def get_instance(cls, mode, widget): @@ -490,13 +466,13 @@ class VlcPlayer(Player): s_desc = self._player.video_get_spu_description() self.emit("subtitle-track", [(s[0], s[1].decode(encoding="utf-8", errors="ignore")) for s in s_desc]) - def init_video_widget(self, widget): + def init_video_widget(self): if IS_LINUX: - self._player.set_xwindow(self.get_window_handle()) + self._player.set_xwindow(self._handle) elif IS_DARWIN: - self._player.set_nsobject(self.get_window_handle()) + self._player.set_nsobject(self._handle) else: - self._player.set_hwnd(self.get_window_handle()) + self._player.set_hwnd(self._handle) class Recorder: diff --git a/app/ui/playback.glade b/app/ui/playback.glade index 19b664f4..78cae129 100644 --- a/app/ui/playback.glade +++ b/app/ui/playback.glade @@ -28,19 +28,43 @@ Author: Dmitriy Yefremov --> + - + True False - - + + True + False + + + + + playback + Playback + + + + True + False + True + + + load + Load + 1 + + + True @@ -142,6 +166,7 @@ Author: Dmitriy Yefremov + 175 False 5 5 @@ -151,6 +176,9 @@ Author: Dmitriy Yefremov True False 0 + + + False @@ -179,6 +207,9 @@ Author: Dmitriy Yefremov True False 0 + + + False @@ -188,7 +219,7 @@ Author: Dmitriy Yefremov - False + True True 4 @@ -316,8 +347,5 @@ Author: Dmitriy Yefremov 7 - diff --git a/app/ui/playback.py b/app/ui/playback.py index cc77d4f8..be2c64b9 100644 --- a/app/ui/playback.py +++ b/app/ui/playback.py @@ -71,9 +71,11 @@ class PlayerBox(Gtk.Overlay): self._playback_window = None self._audio_track_menu = None self._subtitle_track_menu = None - self._play_mode = self._app.app_settings.play_streams_mode + self._play_mode = PlayStreamsMode(self._app.app_settings.play_streams_mode) handlers = {"on_realize": self.on_realize, + "on_draw": self.on_draw, + "on_mouse_motion": self.on_mouse_motion, "on_press": self.on_press, "on_pause": self.on_pause, "on_stop": self.on_stop, @@ -84,8 +86,11 @@ class PlayerBox(Gtk.Overlay): "on_close": self.on_close} builder = get_builder(UI_RESOURCES_PATH + "playback.glade", handlers) - self._event_box = builder.get_object("event_box") - self.add(self._event_box) + self._stack = builder.get_object("stack") + self._playback_area = builder.get_object("playback_area") + self._playback_area.set_events(Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.POINTER_MOTION_MASK) + self._playback_area.connect("motion-notify-event", self.on_mouse_motion) + self.add(self._stack) if not IS_DARWIN: self.add_overlay(builder.get_object("tool_bar")) @@ -105,6 +110,10 @@ class PlayerBox(Gtk.Overlay): self.connect("delete-event", self.on_delete) self.connect("show", self.set_player_area_size) + @property + def playback_widget(self): + return self._playback_area + def on_fav_clicked(self, app, mode): if mode is not FavClickMode.STREAM and not self._app.http_api: return @@ -112,7 +121,7 @@ class PlayerBox(Gtk.Overlay): if len(self._fav_view.get_model()) == 0: return - self._fav_view.set_sensitive(False) + self._stack.set_visible_child_name("load") if mode is FavClickMode.STREAM: self.on_play_stream() elif mode is FavClickMode.ZAP_PLAY: @@ -166,20 +175,18 @@ class PlayerBox(Gtk.Overlay): self.on_close() self.set_visible(False) - def on_realize(self, box): + def on_realize(self, area): if not self._player: settings = self._app.app_settings + self._stack.set_visible_child_name("load") try: - self._player = Player.make(settings.stream_lib, settings.play_streams_mode, self._event_box) + self._player = Player.make(settings.stream_lib, settings.play_streams_mode, self) except (ImportError, NameError) as e: self._app.show_error_message(str(e)) return True else: self.init_playback_elements() - self.emit("play", self._current_mrl) - finally: - if settings.play_streams_mode is PlayStreamsMode.BUILT_IN: - self.set_player_area_size(box) + GLib.idle_add(self.emit, "play", self._current_mrl) def init_playback_elements(self): self._player.connect("error", self.on_error) @@ -313,7 +320,7 @@ class PlayerBox(Gtk.Overlay): @run_with_delay(1) def set_player_action(self): click_mode = FavClickMode(self._app.app_settings.fav_click_mode) - self._fav_view.set_sensitive(False) + self._stack.set_visible_child_name("load") if click_mode is FavClickMode.PLAY: self.on_play_service() elif click_mode is FavClickMode.ZAP_PLAY: @@ -351,6 +358,7 @@ class PlayerBox(Gtk.Overlay): def set_player_area_size(self, widget): w, h = self._app.app_window.get_size() widget.set_size_request(w * 0.6, -1) + self._stack.set_visible_child_name("playback") @run_idle def show_playback_window(self, title=None): @@ -369,7 +377,7 @@ class PlayerBox(Gtk.Overlay): self._playback_window.connect("delete-event", self.on_close) self._playback_window.connect("key-press-event", self.on_key_press) - self._playback_window.bind_property("visible", self._event_box, "visible") + self._playback_window.bind_property("visible", self._stack, "visible") if not IS_DARWIN: self._prev_button.set_visible(False) @@ -451,19 +459,36 @@ class PlayerBox(Gtk.Overlay): else: self._current_mrl = url - self._fav_view.set_sensitive(True) self._fav_view.grab_focus() @run_idle def on_played(self, player, duration): - self._fav_view.set_sensitive(True) + self._stack.set_visible_child_name("playback") if not IS_DARWIN: self.on_duration_changed(duration) @run_idle def on_error(self, player, msg): self._app.show_error_message(msg) - self._fav_view.set_sensitive(True) + self._stack.set_visible_child_name("playback") + + def on_draw(self, widget, cr): + """ Used for black background drawing in the player drawing area. """ + cr.set_source_rgb(0, 0, 0) + cr.paint() + + def on_mouse_motion(self, widget, event): + display = widget.get_display() + window = widget.get_window() + cursor = Gdk.Cursor.new_from_name(display, "default") + window.set_cursor(cursor) + + self.hide_mouse_cursor(window, display) + + @run_with_delay(3) + def hide_mouse_cursor(self, window, display): + cursor = Gdk.Cursor.new_for_display(display, Gdk.CursorType.BLANK_CURSOR) + window.set_cursor(cursor) if __name__ == "__main__": diff --git a/app/ui/style.css b/app/ui/style.css index affd0fcc..7f74b477 100644 --- a/app/ui/style.css +++ b/app/ui/style.css @@ -104,3 +104,8 @@ paned.vertical > separator { padding-right: 5px; min-width: 50px; } + +.playback { + background-color: #000000; + color: #ffffff; +}