[gnome-music/mcatanzaro/random-shuffle] Make random shuffle actually random




commit e17c8e24f15bd0f8781244719e3157ee85ab1b84
Author: Michael Catanzaro <mcatanzaro redhat com>
Date:   Thu Aug 19 12:12:07 2021 -0500

    Make random shuffle actually random
    
    Currently the randomness in the random shuffle is implemented by
    returning a random result in a sort function, which is not very random
    at all. In practice, it results in songs close to the start of the list
    being sorted first.
    
    To fix this, we can simply assign a random integer to each song and
    compare them in the sorting function, to make the results consistent.
    
    Fixes #369

 gnomemusic/coresong.py | 7 +++++++
 gnomemusic/player.py   | 7 ++++---
 2 files changed, 11 insertions(+), 3 deletions(-)
---
diff --git a/gnomemusic/coresong.py b/gnomemusic/coresong.py
index ad397960b..585f28e8d 100644
--- a/gnomemusic/coresong.py
+++ b/gnomemusic/coresong.py
@@ -24,6 +24,7 @@
 
 from __future__ import annotations
 from enum import IntEnum
+from random import randint
 from typing import Optional
 import typing
 
@@ -52,6 +53,7 @@ class CoreSong(GObject.GObject):
     media = GObject.Property(type=Grl.Media)
     grlid = GObject.Property(type=str, default=None)
     play_count = GObject.Property(type=int)
+    shuffle_pos = GObject.Property(type=int)
     state = GObject.Property()  # FIXME: How to set an IntEnum type?
     title = GObject.Property(type=str)
     track_number = GObject.Property(type=int)
@@ -84,6 +86,7 @@ class CoreSong(GObject.GObject):
         self._is_tracker: bool = media.get_source() == "grl-tracker3-source"
         self.props.validation = CoreSong.Validation.PENDING
         self.update(media)
+        self.update_shuffle_pos()
 
     def __eq__(self, other: object) -> bool:
         return (isinstance(other, CoreSong)
@@ -180,3 +183,7 @@ class CoreSong(GObject.GObject):
         self.props.media.set_last_played(GLib.DateTime.new_now_utc())
         self._coregrilo.writeback_tracker(
             self.props.media, "last-played")
+
+    def update_shuffle_pos(self) -> None:
+        """Randomizes the shuffle position of this song"""
+        self.props.shuffle_pos = randint(1, 1_000_000)
diff --git a/gnomemusic/player.py b/gnomemusic/player.py
index 7e6ddf289..2c3d2ae44 100644
--- a/gnomemusic/player.py
+++ b/gnomemusic/player.py
@@ -24,7 +24,7 @@
 
 from enum import Enum, IntEnum
 from gettext import gettext as _
-from random import randint, randrange
+from random import randrange
 import time
 import typing
 
@@ -277,11 +277,12 @@ class PlayerPlaylist(GObject.GObject):
         self._model_recent.set_offset(offset)
 
     def _on_repeat_mode_changed(self, klass, param):
-        # FIXME: This shuffle is too simple.
         def _shuffle_sort(song_a, song_b):
-            return randint(-1, 1)
+            return song_a.shuffle_pos < song_b.shuffle_pos
 
         if self.props.repeat_mode == RepeatMode.SHUFFLE:
+            for _, coresong in enumerate(self._model):
+                coresong.update_shuffle_pos()
             self._model.set_sort_func(
                 utils.wrap_list_store_sort_func(_shuffle_sort))
         elif self.props.repeat_mode in [RepeatMode.NONE, RepeatMode.ALL]:


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]