From a8b40472390a7a7c7e48f9e151eb81f4dcffe8d3 Mon Sep 17 00:00:00 2001 From: DYefremov Date: Mon, 16 Dec 2019 09:57:27 +0300 Subject: [PATCH] player refactoring --- app/tools/media.py | 71 ++++++++++++++++++++++++++------------- app/ui/main_app_window.py | 15 +++++---- 2 files changed, 57 insertions(+), 29 deletions(-) diff --git a/app/tools/media.py b/app/tools/media.py index fc76ec69..2df7c3ea 100644 --- a/app/tools/media.py +++ b/app/tools/media.py @@ -1,32 +1,37 @@ -from app.commons import run_task -from app.tools import vlc -from app.tools.vlc import EventType +import sys +from app.commons import run_task, log class Player: - _VLC_INSTANCE = None + __VLC_INSTANCE = None - 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() + def __init__(self, rewind_callback, position_callback): + try: + from app.tools import vlc + from app.tools.vlc import EventType + except OSError as e: + log("{}: Load library error: {}".format(__class__.__name__, e)) + else: + self._is_playing = False + args = "--quiet {}".format("" if sys.platform == "darwin" else "--no-xlib") + self._player = vlc.Instance(args).media_player_new() + 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) + if rewind_callback: + # TODO look other EventType options + ev_mgr.event_attach(EventType.MediaPlayerBuffering, + lambda et, p: rewind_callback(p.get_media().get_duration()), + self._player) + if position_callback: + ev_mgr.event_attach(EventType.MediaPlayerTimeChanged, + lambda et, p: position_callback(p.get_time()), + self._player) - @staticmethod - def get_vlc_instance(): - if Player._VLC_INSTANCE: - return Player._VLC_INSTANCE - _VLC_INSTANCE = vlc.Instance("--quiet --no-xlib").media_player_new() - return _VLC_INSTANCE + @classmethod + def get_instance(cls, rewind_callback=None, position_callback=None): + if not cls.__VLC_INSTANCE: + cls.__VLC_INSTANCE = Player(rewind_callback, position_callback) + return cls.__VLC_INSTANCE @run_task def play(self, mrl=None): @@ -57,6 +62,26 @@ class Player: def set_xwindow(self, xid): self._player.set_xwindow(xid) + def set_nso(self, widget): + """ Used on MacOS to set NSObject. + + Based on gtkvlc.py[get_window_pointer] example from here: + https://github.com/oaubert/python-vlc/tree/master/examples + """ + try: + import ctypes + g_dll = ctypes.CDLL("libgdk-3.0.dylib") + except OSError as e: + log("{}: Load library error: {}".format(__class__.__name__, e)) + else: + get_nsview = g_dll.gdk_quartz_window_get_nsview + get_nsview.restype, get_nsview.argtypes = ctypes.c_void_p, [ctypes.c_void_p] + ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.c_void_p + ctypes.pythonapi.PyCapsule_GetPointer.argtypes = [ctypes.py_object] + # Get the C void* pointer to the window + pointer = ctypes.pythonapi.PyCapsule_GetPointer(widget.get_window().__gpointer__, None) + self._player.set_nsobject(get_nsview(pointer)) + def set_mrl(self, mrl): self._player.set_mrl(mrl) diff --git a/app/ui/main_app_window.py b/app/ui/main_app_window.py index 80bb5157..0a9ed14e 100644 --- a/app/ui/main_app_window.py +++ b/app/ui/main_app_window.py @@ -1554,8 +1554,8 @@ class Application(Gtk.Application): def play(self, url): if not self._player: try: - self._player = Player(rewind_callback=self.on_player_duration_changed, - position_callback=self.on_player_time_changed) + self._player = Player.get_instance(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 @@ -1592,8 +1592,7 @@ class Application(Gtk.Application): def on_player_close(self, item=None): if self._player: - self._player.release() - self._player = None + self._player.stop() GLib.idle_add(self._player_box.set_visible, False, priority=GLib.PRIORITY_LOW) @lru_cache(maxsize=1) @@ -1615,8 +1614,12 @@ class Application(Gtk.Application): 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) + if sys.platform == "darwin": + self._player.set_nso(widget) + else: + self._drawing_area_xid = widget.get_window().get_xid() + print(self._drawing_area_xid) + self._player.set_xwindow(self._drawing_area_xid) def on_player_drawing_area_draw(self, widget, cr): """ Used for black background drawing in the player drawing area.