Bugzilla – Bug 2551
Prevent songs being played twice in random mixes
Last modified: 2008-09-15 14:39:24 UTC
Currently Random Mix does nothing to prevent songs being played twice. I believe it should be possible to do this simply by noting the time when the mix started, then only playing tracks whose last played time is before this time.
I was going to assign this to myself but can't edit the assigned to field. Please feel free to do the necessary, Dan.
It doesn't look like DataModel.pm allows where clauses with operators other than =, like and in. It therefore needs extending to allow < and > searches. Could someone suggest how the external interface should be changed to allow this?
Pulling Dan in as it turns out I'm talking to myself. ;-)
Looking at code for AdvancedSearch, it looks like I should be able to say something like: 'lastPlayed' => { '<' => $startTime }
Commited first stab at this in R6002. Not entirely certain this will work in album/year/artist mode and no idea at all what will happen when all the songs have been played!
This approach may be doomed. lastplayed is only updated when tracks are played, not when they are added to a playlist. This will therefore stop a lot of tracks from being played twice, but won't stop songs from being added again when they are in the upcoming playlist. This assumedly means that random mix will go into a loop when it reaches the end of a user's collection, with the same tracks being added again and again. Solution to this? Could perhaps maintain a "lastqueued" column as well that is updated when tracks are added to the playlist?
on the basis that Rnadom is made for loading a small queue, it might be failry quick to simply toss a track if it matches one of the id's already in the queue and go grab another.
I started thinking on the same lines whilst trying to get to sleep last night (curse you, SlimDevices!). I can probably get the ids of the tracks ahead of the current one in the playlist and add a not in (...) to the query. I don't want to start comparing against the whole playlist as this could get nasty when the user keeps all played tracks. Would still be more elegant to simply compare against a time stamp, though. How much work would it be to add a new db column? Would this be considered? Might be fun to use such a column to give stats on "tracks you almost played" and such like. ;-)
Could this be made as an optional feature? People with large collection might want to allow same songs played multiple times. (ok... at least I do :-)
Ah yes, more options - just what the world needs! ;-) Yes, this could easily be made an optional feature. I'll get it working first though!
Current version seems to be broken. Please see: http://forums.slimdevices.com/showthread.php?t=20771
It seems that songs are now being duplicated a lot in the current playlist. I've noticed this myself.
I'd inadvertently inserted a lastPlayed is null into the initial mix selection. Fixed in R6084?
There is still something strange with R6084 (not very random). My usual setting for random mix are show 10 upcoming and 39 played songs. When I start random mix, 10 songs looks random to me. If I jump to 10th song and wait for random mix to add new 10 songs, they are not so random anymore. They are songs that I have listened recently. If I jump to last song again, I get similar results. If I stop random mix and start it again, I get partly the same songs from the previous try.
Ah, I think I might know what's going on. As it now says lastPlayed < x, this stops it selecting tunes that have never been played. I need to say (lastPlayed IS NULL OR lastPlayed < x). Sadly, I have no idea how to do this through the db api. Thoughts anyone? If anyone wants to go back to the old behaviour, just comment out line 236 (or thereabouts) in Plugins/RandomPlay/Plugin.pm, which should be: $find->{'lastPlayed'} = {'<' => $mixInfo{$client}->{'startTime'}};
I've commited a change that comments out the line mentioned in the comment above as I don't have the time to work on this at the moment.
Just to provide some further data on comment 15. I'm afraid that I'm going by dim recollection here, so it's a bit vague. I found that the problem with writing the type of query that I described is that the db abstraction API is actually broken by some code in SlimServer. There's a line somewhere that has a comment above it saying something like "optimize queries by turning long strings of ORs into in statements" i.e. x = A OR x=B becomes x in (a,b). Sadly, this code isn't terribly well written, and stomps all over genuine attempts to use OR such as abstraction code that ends up churning out queries such as (lastPlayed IS NULL OR lastPlayed < x).
Max, have you looked at the new DB code?
Not at all, I'm afraid. I'm generally a busy man in the summer months! I added that info just in case it was useful to someone else (or me in the future - mind like a sieve etc).
Fixed in change 8855
Not sure this should be resolved fix yet, but your call obviously, Dan. At the moment, tracks that are in the upcoming songs list can still be added again, as lastPlayed only reflects tracks that have been played. Need some way of keeping track of queued tracks as well. Additionally (as you know), this will also fail with multiple clients doing random mixes.