mediathek-viewer/src/gtk_mediathek_player/player_widget.py

184 lines
5.5 KiB
Python

from . import tools
from . import gst_widget
from gi.repository import Gtk, GLib, Gst, Gdk
import gi
gi.require_version("Gtk", "3.0")
gi.require_version('Gst', '1.0')
class PlayerWidget(Gtk.Overlay):
@staticmethod
def create_player_for_uri(uri: str):
widget = PlayerWidget()
widget.play_from_uri(uri)
return widget
def __init__(self) -> None:
Gtk.Overlay.__init__(self)
self._videoarea = gst_widget.GstWidget()
self._create_controls()
self.add(self._videoarea)
self.add_overlay(self._controls)
self._duration = None
self._is_update = False
self._seconds_after_mouse_move = 0
self._slider.connect("value-changed", self._on_user_slider_change)
def update_controls(self):
self._is_update = True
state = self.get_state()
if state == Gst.State.PLAYING or state == Gst.State.PAUSED:
self._duration = self._videoarea.get_duration()
self._slider.set_range(0, self._duration)
if self._duration is not None:
position = self._videoarea.get_position()
self._slider.set_value(position)
position_string = tools.seconds_to_timestring(int(position))
duration_string = tools.seconds_to_timestring(int(self._duration))
self._duration_text.set_markup(
f"{position_string}/{duration_string}")
self._is_update = False
if self._seconds_after_mouse_move > 3:
self._controls.set_reveal_child(False)
self._seconds_after_mouse_move += 1
return True
def _on_user_slider_change(self, range):
if self._is_update:
return
value = self._slider.get_value()
self._videoarea.set_position(value)
def _create_controls(self) -> Gtk.Box:
self._slider = Gtk.Scale.new_with_range(orientation=Gtk.Orientation.HORIZONTAL,
min=0,
max=100,
step=1)
self._slider.props.draw_value = False
self._play_button = tools.new_button_with_icon('media-playback-start')
self._stop_button = tools.new_button_with_icon('media-playback-stop')
self._play_pause_button = tools.new_button_with_icon(
'media-playback-pause')
bbox = Gtk.ButtonBox(orientation=Gtk.Orientation.HORIZONTAL)
bbox.set_layout(Gtk.ButtonBoxStyle.EXPAND)
box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
self._controls = Gtk.Revealer()
self._duration_text = Gtk.Label("--/--")
bbox.pack_start(self._play_pause_button,
expand=False,
fill=False,
padding=0)
box.pack_start(bbox,
expand=False,
fill=False,
padding=0)
box.pack_end(self._duration_text,
expand=False,
fill=False,
padding=0)
box.pack_end(self._slider,
expand=True,
fill=True,
padding=0)
# TODO: replace this deprecated (honestly, i find it disturbing that there is no container or css template)
# already there to do this, such that you are forced to create a custom css
# snippet and override the default gtk scheme)
box.override_background_color(
Gtk.StateType.NORMAL, Gdk.RGBA(.0, .0, .0, .8))
self._controls.add(box)
self._controls.set_valign(Gtk.Align.END)
self._controls.set_transition_type(Gtk.RevealerTransitionType.SLIDE_UP)
self._controls.set_reveal_child(True)
style_context = self._controls.get_style_context()
style_context.add_class(Gtk.STYLE_CLASS_OSD)
self._play_pause_button.connect("clicked", self.toogle_play)
def play_from_uri(self, uri: str):
self._videoarea.load_from_uri(uri)
def play(self, _=None):
if self.get_state() != Gst.State.PLAYING:
new_icon = tools.get_icon("media-playback-pause")
self._play_pause_button.props.image = new_icon
self._videoarea.play()
def stop(self, _=None):
state = self.get_state()
self._videoarea.stop()
if state == Gst.State.PLAYING or state == Gst.State.PAUSED:
new_icon = tools.get_icon("media-playback-start")
self._play_pause_button.props.image = new_icon
self._duration = None
def toogle_play(self, _=None):
state = self.get_state()
if state == Gst.State.NULL:
# do nothing
return
if state == Gst.State.PLAYING:
self.pause()
elif state == Gst.State.PAUSED:
self.play()
def pause(self, _=None):
if self.get_state() == Gst.State.PLAYING:
new_icon = tools.get_icon("media-playback-start")
self._play_pause_button.props.image = new_icon
self._videoarea.pause()
def get_state(self):
return self._videoarea.get_state()
def is_playing(self) -> bool:
return self.get_state() == Gst.State.PLAYING
def is_stopped(self) -> bool:
return self.get_state() == Gst.State.NULL
def is_paused(self) -> bool:
return self.get_state() == Gst.State.PAUSED
def show_controls(self):
self._controls.set_reveal_child(True)
self._seconds_after_mouse_move = 0