Added prefetch logic
This commit is contained in:
@@ -444,11 +444,13 @@ class LibremsonicApp(Gtk.Application):
|
|||||||
self.state.song_progress = 0
|
self.state.song_progress = 0
|
||||||
|
|
||||||
def on_song_download_complete(_):
|
def on_song_download_complete(_):
|
||||||
# This will now return the local media.
|
# Switch to the local media if the player can hotswap (MPV can,
|
||||||
downloaded_filename = CacheManager.get_song_filename_or_stream(
|
# Chromecast cannot hotswap without lag).
|
||||||
song)[0]
|
if self.player.can_hotswap_source:
|
||||||
self.player.play_media(downloaded_filename,
|
downloaded_filename = (
|
||||||
self.state.song_progress, song)
|
CacheManager.get_song_filename_or_stream(song)[0])
|
||||||
|
self.player.play_media(downloaded_filename,
|
||||||
|
self.state.song_progress, song)
|
||||||
GLib.idle_add(self.update_window)
|
GLib.idle_add(self.update_window)
|
||||||
|
|
||||||
# If streaming, also download the song, unless configured not to,
|
# If streaming, also download the song, unless configured not to,
|
||||||
@@ -470,6 +472,23 @@ class LibremsonicApp(Gtk.Application):
|
|||||||
self.state.play_queue = play_queue
|
self.state.play_queue = play_queue
|
||||||
self.save_play_queue()
|
self.save_play_queue()
|
||||||
|
|
||||||
|
# Prefetch songs
|
||||||
|
if self.state.repeat_type != RepeatType.REPEAT_SONG:
|
||||||
|
song_idx = self.state.play_queue.index(song.id)
|
||||||
|
prefetch_idxs = []
|
||||||
|
for i in range(self.state.config.prefetch_amount):
|
||||||
|
prefetch_idx = song_idx + 1 + i
|
||||||
|
play_queue_len = len(self.state.play_queue)
|
||||||
|
if (prefetch_idx < play_queue_len or
|
||||||
|
self.state.repeat_type == RepeatType.REPEAT_QUEUE):
|
||||||
|
prefetch_idxs.append(prefetch_idx % play_queue_len)
|
||||||
|
CacheManager.batch_download_songs(
|
||||||
|
[self.state.play_queue[i] for i in prefetch_idxs],
|
||||||
|
before_download=lambda: GLib.idle_add(self.update_window),
|
||||||
|
on_song_download_complete=lambda _: GLib.idle_add(
|
||||||
|
self.update_window),
|
||||||
|
)
|
||||||
|
|
||||||
song_details_future = CacheManager.get_song_details(song)
|
song_details_future = CacheManager.get_song_details(song)
|
||||||
song_details_future.add_done_callback(
|
song_details_future.add_done_callback(
|
||||||
lambda f: GLib.idle_add(do_play_song, f.result()), )
|
lambda f: GLib.idle_add(do_play_song, f.result()), )
|
||||||
|
@@ -53,7 +53,7 @@ class ArtistsPanel(Gtk.Paned):
|
|||||||
self.pack2(self.artist_detail_panel, True, False)
|
self.pack2(self.artist_detail_panel, True, False)
|
||||||
|
|
||||||
def update(self, state: ApplicationState):
|
def update(self, state: ApplicationState):
|
||||||
self.artist_list.update()
|
self.artist_list.update(state)
|
||||||
if self.artist_id:
|
if self.artist_id:
|
||||||
self.artist_detail_panel.update(self.artist_id)
|
self.artist_detail_panel.update(self.artist_id)
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ class ArtistList(Gtk.Box):
|
|||||||
list_scroll_window.add(self.list)
|
list_scroll_window.add(self.list)
|
||||||
self.pack_start(list_scroll_window, True, True, 0)
|
self.pack_start(list_scroll_window, True, True, 0)
|
||||||
|
|
||||||
def update(self, force=False):
|
def update(self, state=None, force=False):
|
||||||
self.update_list(force=force)
|
self.update_list(force=force)
|
||||||
|
|
||||||
@util.async_callback(
|
@util.async_callback(
|
||||||
|
@@ -48,6 +48,10 @@ class Player:
|
|||||||
def song_loaded(self):
|
def song_loaded(self):
|
||||||
return self._song_loaded
|
return self._song_loaded
|
||||||
|
|
||||||
|
@property
|
||||||
|
def can_hotswap_source(self):
|
||||||
|
return self._can_hotswap_source
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def volume(self):
|
def volume(self):
|
||||||
return self._get_volume()
|
return self._get_volume()
|
||||||
@@ -104,6 +108,7 @@ class MPVPlayer(Player):
|
|||||||
self.mpv = mpv.MPV()
|
self.mpv = mpv.MPV()
|
||||||
self.progress_value_lock = threading.Lock()
|
self.progress_value_lock = threading.Lock()
|
||||||
self.progress_value_count = 0
|
self.progress_value_count = 0
|
||||||
|
self._can_hotswap_source = True
|
||||||
|
|
||||||
@self.mpv.property_observer('time-pos')
|
@self.mpv.property_observer('time-pos')
|
||||||
def time_observer(_name, value):
|
def time_observer(_name, value):
|
||||||
@@ -229,6 +234,8 @@ class ChromecastPlayer(Player):
|
|||||||
super().__init__(*args)
|
super().__init__(*args)
|
||||||
self._timepos = None
|
self._timepos = None
|
||||||
self.time_incrementor_running = False
|
self.time_incrementor_running = False
|
||||||
|
self._can_hotswap_source = False
|
||||||
|
|
||||||
ChromecastPlayer.cast_status_listener.on_new_cast_status = self.on_new_cast_status
|
ChromecastPlayer.cast_status_listener.on_new_cast_status = self.on_new_cast_status
|
||||||
ChromecastPlayer.media_status_listener.on_new_media_status = self.on_new_media_status
|
ChromecastPlayer.media_status_listener.on_new_media_status = self.on_new_media_status
|
||||||
|
|
||||||
|
@@ -234,7 +234,6 @@ class PlaylistsPanel(Gtk.Paned):
|
|||||||
|
|
||||||
self.playlist_songs = Gtk.TreeView(
|
self.playlist_songs = Gtk.TreeView(
|
||||||
model=self.playlist_song_model,
|
model=self.playlist_song_model,
|
||||||
headers_visible=False, # TODO use the config value for this
|
|
||||||
reorderable=True,
|
reorderable=True,
|
||||||
margin_top=15,
|
margin_top=15,
|
||||||
enable_search=True,
|
enable_search=True,
|
||||||
@@ -460,6 +459,8 @@ class PlaylistsPanel(Gtk.Paned):
|
|||||||
else:
|
else:
|
||||||
self.playlist_action_buttons.hide()
|
self.playlist_action_buttons.hide()
|
||||||
|
|
||||||
|
self.playlist_songs.set_headers_visible(state.config.show_headers)
|
||||||
|
|
||||||
def set_playlist_list_loading(self, loading_status):
|
def set_playlist_list_loading(self, loading_status):
|
||||||
if loading_status:
|
if loading_status:
|
||||||
self.playlist_list_loading.show()
|
self.playlist_list_loading.show()
|
||||||
|
Reference in New Issue
Block a user