player refactoring

This commit is contained in:
DYefremov
2019-12-16 09:57:27 +03:00
parent a4800ace14
commit a8b4047239
2 changed files with 57 additions and 29 deletions

View File

@@ -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)

View File

@@ -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.