@@ 725,6 725,17 @@ def get_last_feed_refresh() -> int:
return app_conf["news-feed-refresh"]
return None
+def get_video_duration(server_id:str, video_id:str) -> (float|None):
+ conn = connect_to_db()
+ results = conn.execute("""
+ SELECT duration
+ FROM playback
+ WHERE video_id = ? AND video_server = ?
+ """, (video_id, server_id)).fetchone()
+ if results is None:
+ return None
+ return results[0]
+
def get_video_playback_position(server_id:str, video_id:str) -> (float|None):
conn = connect_to_db()
results = conn.execute("""
@@ 15,7 15,7 @@ from melon.widgets.feeditem import AdaptiveFeedItem
from melon.widgets.preferencerow import PreferenceRow, PreferenceType, Preference
from melon.widgets.iconbutton import IconButton
from melon.models import get_app_settings, add_to_history, register_callback
-from melon.models import get_video_playback_position, set_video_playback_position, set_video_playback_position_force
+from melon.models import get_video_playback_position, set_video_playback_position, set_video_playback_position_force, get_video_duration
from melon.utils import pass_me
class PlayerScreen(Adw.NavigationPage):
@@ 63,10 63,8 @@ class PlayerScreen(Adw.NavigationPage):
# do not autoplay
self.player.pause()
self.box.append(self.player)
- # TODO: stop + kill player on hide
- # TODO: connect this to navpage close
- def on_close(self):
+ def on_hide(self):
self.disconnect_player()
def disconnect_player(self):
@@ 79,7 77,7 @@ class PlayerScreen(Adw.NavigationPage):
# we only want to save valid datasets
return
set_video_playback_position(self.video, self.position, self.duration)
- self.disconnect_player()
+
def on_player_data(self, position, duration):
if position is None or duration is None:
# we only want to save valid datasets
@@ 151,6 149,9 @@ class PlayerScreen(Adw.NavigationPage):
self.scrollview = Gtk.ScrolledWindow()
self.wrapper.set_child(self.scrollview)
+ # connect to events
+ self.connect("hiding", lambda _: self.on_hide())
+
self.init_video(server_id, video_id)
def init_video(self, server_id, video_id):
@@ 158,6 159,9 @@ class PlayerScreen(Adw.NavigationPage):
self.position = None
self.duration = None
+ # disconnect old player
+ self.disconnect_player()
+
self.video_id = video_id
# get instance handle
server = get_servers_list()[server_id]
@@ 170,7 174,7 @@ class PlayerScreen(Adw.NavigationPage):
# reset playback position if video was nearly completely watched
pos = get_video_playback_position(server_id, video_id)
- dur = get_video_playback_position(server_id, video_id)
+ dur = get_video_duration(server_id, video_id)
if not pos is None and not dur is None:
# TODO consider moving this to the settings panel
consider_done = 0.99*dur
@@ 291,16 291,24 @@ class Peertube(Server):
results = []
if r.ok:
for item in r.json()["data"]:
- item = item["video"]
- video_host = instance
- video_slug = item["uuid"]
- video_id=f"{video_host}::{video_slug}"
- thumb_path = item["thumbnailPath"]
- thumb = f"{instance}{thumb_path}"
- channel_name = item["channel"]["displayName"]
- channel_slug = item["channel"]["name"]
- channel_host = item["channel"]["host"]
- channel_id = f"https://{channel_host}::{channel_slug}"
+ try:
+ item = item["video"]
+ video_host = instance
+ video_slug = item["uuid"]
+ video_id=f"{video_host}::{video_slug}"
+ thumb_path = item["thumbnailPath"]
+ thumb = f"{instance}{thumb_path}"
+ channel_name = item["channel"]["displayName"]
+ channel_slug = item["channel"]["name"]
+ channel_host = item["channel"]["host"]
+ channel_id = f"https://{channel_host}::{channel_slug}"
+ except Exception as e:
+ # skip invalid entries
+ # peertube keeps deleted videos in the playlist
+ # but doesn't set all attributes
+ # melon doesn't have a way to display deleted videos
+ # so we can just skip them
+ continue
v = Video(
self.id,
item["url"],