Ren'Py A deeper understanding of renpy audio queue

Playstorepers

Member
May 24, 2020
160
79
Hey everyone,

Right now, I'm struggling with a very weird problem concerning renpy.audio.queue

Let's say I have 2 kinds of music playlists:

Python:
define list1 = [track1, track2, track3, ..., track100]
default list2 = [track1, track2, track3, ..., track100]
And in my game script both get at one point or another queued up, but one is random:
It would look like this:

stop music
$ renpy.music.queue(list1, loop=True)

and

stop music
$renpy.random.shuffle(list2)
$ renpy.music.queue(list2, loop=True)

it works nicely.

However, the shuffle only happens in the "beginning " of the script, when you queue it up. So if you reload the game, you always hear the same songs in the same sequence.
To shuffle them, I decided to go with:

label after_load:
$renpy.random.shuffle(list2)

It works perfectly: Every time you reload your game, another song from the list gets played.
just what I wanted.

Now the problem part: let's say you want to add or remove a song from your lists with a patch:

Python:
label after_load:
    #optional if-clause for patches, but for testing purposes not necessary
    $list2 = [track1, track4, ..., track100, track101,track2000]
    $renpy.random.shuffle(list2)

list1 goes down without a hitch. Define does its job nicely. The new songs, that are played are from the patched list.
Whenever you load up the game, you always start with the first song on your list, but whatever, that's what you wanted: nice.

list2 on the other hand...
list2 gets weird af, once you load a savefile, that's playing the list already.
you always start with the same song. despite $renpy.random.shuffle(list2) also being in the after_load and despite $renpy.random.shuffle(list2) in after_load working before.
The music queue is also fixed.

Why? Because it assumes the weirdest shit:
It takes the old queue, but your list2 is different.

Meaning:
if you open up the console and type: list2, it shows you: [track1, track4, ..., track100, track101,track2000], however your queued music is track1-100 shuffled, just like the one before. It even has track2 and 3, which were removed but not track 101 and 2000 which were added.

So my questions are kinda simple, even though the problem was difficult to describe:
1) Why does renpy play the old playlist, and how can I make it stop that.

2) Is there a more elegant way to have random-music-queue, with appliable patches?


Thanks for everyone, who was willing to read such a giant wall of text.
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,611
2,258
I'd need to do a bit of digging for some of your question, but I can cover one aspect...

renpy.random.shuffle() may play the same songs each time because it honors RenPy's rollback system.
It IS random, but perhaps not in the way you imagine.

RenPy's random functions were adapted so that if the game generates a random number, and then the player rolls back before it and then plays forward again... it still generates the same random number. It's to keep the VN game mechanics and stop the player just rolling back and forward to get a result they like. The same is true for save/load - to stop a player save scumming their way through encounters they don't like.

I tend to think of it like "the random numbers are predetermined" - though it probably is more complicated than that.

The other thing... best guess without me checking anything... Your $ renpy.music.queue() is adding the "new" list2 to the existing queue. So "track3" which was originally on the list, is still there - but you might find "track4" is in there twice now. Best guess, the same stop music you had earlier is needed to clear the queue despite no music currently playing, before you recreate it. It could be tested relatively easily by having list2 only being 3 tracks rather than hundreds and only 2 as part of the after_load: - you'll see either 5 or 2 tracks, depending on if I'm guessing right or not.

In fact, based on my random guess... the first part I quoted about renpy.random.shuffle() may not actually apply here. Still, knowledge is knowledge.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,979
16,236
The other thing... best guess without me checking anything... Your $ renpy.music.queue() is adding the "new" list2 to the existing queue.
Not according to the code (renpy/audio/music.py):
Code:
def queue(filenames, channel="music", loop=None, clear_queue=True, fadein=0, tight=None):
    [...]
            if clear_queue:
                c.dequeue(True)
Since he don't use clear_queue in his arguments, the queue is automatically cleared.


Now the problem part: let's say you want to add or remove a song from your lists with a patch:

Python:
label after_load:
    #optional if-clause for patches, but for testing purposes not necessary
    $list2 = [track1, track4, ..., track100, track101,track2000]
    $renpy.random.shuffle(list2)
It's a stupid question, but there's a $ renpy.music.queue(list2, loop=True) right after those lines, right ?
 
  • Like
Reactions: Playstorepers

Playstorepers

Member
May 24, 2020
160
79
Not according to the code (renpy/audio/music.py):
Code:
def queue(filenames, channel="music", loop=None, clear_queue=True, fadein=0, tight=None):
    [...]
            if clear_queue:
                c.dequeue(True)
Since he don't use clear_queue in his arguments, the queue is automatically cleared.




It's a stupid question, but there's a $ renpy.music.queue(list2, loop=True) right after those lines, right ?
Here's the fun part: No there isn't.

Yet still, if I use the shuffle without (!) the

$list2 = [track1, track4, ..., track100, track101,track2000]

, then it plays a random song each time, you reload your save-file (((((((if the music playing right now is NOT on your list, otherwise it just continues with the music and everything gets weird ( To elaborate, let's say your list has track 1-5 and you save your file (It absolutely doesn't matter which one of the 5 songs is playing while you save btw). Then you load your save file, while your music channel is playing track 3 from another list, that has track 3 to 16 on it. Renpy will continue to play your list, that has track 3 to 16 on it, not the 1-5 list))))))))).




The answer 79flavors gave me is kinda wrong?

If you use the shuffle in the after_load, and the queue(list) in the script, then your music gets randomized every time you load the file. But if you overwrite the list, it stays fixed on the old list even though the list, that's playing shouldn't exist anymore.
Weird, right?

EDIT:
Oh, right, I forgot to type it here, but logically speaking the real problem is this: If you change your list in after_load, you splice your music list in two lists.
The old one, that continues to play and can't be randomized anymore, since it isn't called list2 anymore for some reason.
And the new one which gets shuffled with each load, but never played. Big question: why?

And thanks anne, I'll look into music.py, maybe I'll find my answers there.
 
Last edited:

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,979
16,236
Here's the fun part: No there isn't.
Then you've the answer.

Firstly, in Python everything is an object (even numbers and strings).
This lead to a specific behavior. When you assign a variable to another variable, you're in fact creating a new reference to the same object. This also apply to arguments/parameters, and for Ren'py it (most of the time) survive the save process:
You don't have permission to view the spoiler content. Log in or register now.

Secondly, random.shuffle break the unmutability rule of Python variables.
Technically, the content of the list have changed (it have been shuffled) but praticaly, the list stay the same. This imply that the link created by the assignation of a variable to another one, continue to exist ; what is probably the reason of this particular behavior of random.shuffle. Therefore, if you pass the list to an object (I use a function as example, just because it's easier), then shuffle it, the list as seen from the object will also have new order:
You don't have permission to view the spoiler content. Log in or register now.

Thirdly, but the default behavior of Python variable is to be unmutable.
This mean that, when you assign a direct new value to a variable, you are creating a totally new variable. This break all links that could have previously existed:
You don't have permission to view the spoiler content. Log in or register now.

And it's where is the flaw in your "after_load" code:
Code:
label after_load:
    $list2 = [track1, track4, ..., track100, track101,track2000]
    $renpy.random.shuffle(list2)
If you just shuffling the list, it works, because the link between list2 and the variable used by Ren'py to store the queue still exist. They both point to the same "list" object.
But here, you started by assigning a new value to list2, what break the link. list2 and the audio queue become two different objects ; list2 having your new values, while Ren'py audio queue still have the old values.

Just use renpy.music.queue once again (right after the shuffle, because it's cleaner this way) to link the queue with the new list2 and it will works.
 

Playstorepers

Member
May 24, 2020
160
79
Then you've the answer.

Firstly, in Python everything is an object (even numbers and strings).
This lead to a specific behavior. When you assign a variable to another variable, you're in fact creating a new reference to the same object. This also apply to arguments/parameters, and for Ren'py it (most of the time) survive the save process:
You don't have permission to view the spoiler content. Log in or register now.

Secondly, random.shuffle break the unmutability rule of Python variables.
Technically, the content of the list have changed (it have been shuffled) but praticaly, the list stay the same. This imply that the link created by the assignation of a variable to another one, continue to exist ; what is probably the reason of this particular behavior of random.shuffle. Therefore, if you pass the list to an object (I use a function as example, just because it's easier), then shuffle it, the list as seen from the object will also have new order:
You don't have permission to view the spoiler content. Log in or register now.

Thirdly, but the default behavior of Python variable is to be unmutable.
This mean that, when you assign a direct new value to a variable, you are creating a totally new variable. This break all links that could have previously existed:
You don't have permission to view the spoiler content. Log in or register now.

And it's where is the flaw in your "after_load" code:
Code:
label after_load:
    $list2 = [track1, track4, ..., track100, track101,track2000]
    $renpy.random.shuffle(list2)
If you just shuffling the list, it works, because the link between list2 and the variable used by Ren'py to store the queue still exist. They both point to the same "list" object.
But here, you started by assigning a new value to list2, what break the link. list2 and the audio queue become two different objects ; list2 having your new values, while Ren'py audio queue still have the old values.

Just use renpy.music.queue once again (right after the shuffle, because it's cleaner this way) to link the queue with the new list2 and it will works.

That's a very good insight. And I do understand now a lot more and the problem.

But that's sadly not the way, I can patch my game, is it?
I can't queue songs in after_load, since they'd play every time the player loads the game, right? Even when it's a completely different part of the game.
And I can't add another variable in hindsight, that checks whether a patch with a new renpy.music.queue needs to be applied...

So how do I implement my patch?
Do I just have to accept the loss: Players, who have a savefile, that's exactly saved, while the old playlist runs are screwed, right?
 
Jul 22, 2019
247
369
Firstly, in Python everything is an object (even numbers and strings).
This lead to a specific behavior. When you assign a variable to another variable, you're in fact creating a new reference to the same object.
Yeah this caused me a number of headaches back in the day when I started out with python. A point to note about this though as you pointed out, is that immutable objects (strings, numbers etc.) are effectively pass-by-value. Under the hood you are creating a new reference, however, as immutable objects cannot be changed in-place, the behavior is the same as if you copied the value i.e. changing its value in a function will not be reflected anywhere else. It is not true for mutable objects though.
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,611
2,258
As previously stated, I'm no python expert. On a good day, I'm barely a python beginner.
But by random chance, I came across an alternative to renpy.random.shuffle() during another thread, that being renpy.random.sample().

Where shuffle random shuffles an existing list, sample creates a new list (equally shuffled). Does that solve your immutable problems?

I'm thinking something like:

$ renpy.music.queue ( renpy.random.sample(list2, len(list2)) )

Seriously, I'm out of my depth here. But even I get lucky sometimes.
 
  • Like
Reactions: Playstorepers
Jul 22, 2019
247
369
This is weird, idk what your code looks like where you're actually queuing the songs (I am assuming it happens at some point after the player loads a save, if it happens before and you're only calling "play" or something afterwards then there's your issue, you're creating a new list that the queue isn't aware of, you'll have to re-queue it). However the issue does seem to have to do with re-assigning a new list.

Maybe try out list2.append("new-song") and list2.remove("old-song") in the after_load label to add and remove songs instead of re-assigning the whole list and see if it works??

I can't queue songs in after_load, since they'd play every time the player loads the game, right? Even when it's a completely different part of the game.
Not exactly aware of how this works but don't you have to call play or something for the queue to start playing? Or does it just immediately start playing after adding songs to the queue? Otherwise anonymous' solution should work.
 
  • Like
Reactions: Playstorepers

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,979
16,236
Does that solve your immutable problems?
The result is returned, by opposition to random.shuffle that alter the content of the list. Therefore yes, it solve the immutable problem, since it lead to the creation of a new list.
But, in the same time, it don't solve the problem he had, since both solution need to call renpy.music.queue with the new list.
 
  • Like
Reactions: Playstorepers

Playstorepers

Member
May 24, 2020
160
79
First of all: Thanks to all of you for helping.

Second:
This is weird, idk what your code looks like where you're actually queuing the songs (I am assuming it happens at some point after the player loads a save, if it happens before and you're only calling "play" or something afterwards then there's your issue, you're creating a new list that the queue isn't aware of, you'll have to re-queue it). However the issue does seem to have to do with re-assigning a new list.

Maybe try out list2.append("new-song") and list2.remove("old-song") in the after_load label to add and remove songs instead of re-assigning the whole list and see if it works??



Not exactly aware of how this works but don't you have to call play or something for the queue to start playing? Or does it just immediately start playing after adding songs to the queue? Otherwise anonymous' solution should work.
At some point in the script I'll do this:
stop music
$renpy.random.shuffle(list2)
$ renpy.music.queue(list2, loop=True)

So technically a fixed playlist, after an initial shuffle, gets queued. If I'd leave it like that, on leaving the game and reload, the same order of songs get played always starting with the first song, that got shuffled to position 1.

If I add:

$renpy.random.shuffle(list2) in the after_load a random song gets played every time the player reloads the game.

Reason for that as Anne explained already, is the fact, that renpy doesn't treat shuffle as creating a new object.

Now I want to patch my playlist, but I simply put can't, because overwriting it does jack shit, since renpy sees it as creating a new list, which is therefore not queued.

I'll try remove and append next, but I wager, that it doesn't follow the shuffle behavior, but rather the: YOU CHANGED SOMETHING, now I'm a completely new object.

And to be honest, it looks like I'm gonna take the hit, because I have no idea here. Some players might get an error message, because I want to delete a few songs from the older version, but what can I do about it?
I can't queue up a new list and I can't have a variable checked in hindsight to mark all parts, which require a new overwritten playlist, so i can add the new renpy.music.queue.
 
Jul 22, 2019
247
369
Ah I see, so adding it to the queue does immediately start playing it.

I'll try remove and append next, but I wager, that it doesn't follow the shuffle behavior, but rather the: YOU CHANGED SOMETHING, now I'm a completely new object.
No, appending and removing doesn't create a new object, you're not reassigning anything, all the previous references to this list object will stay valid. If you're problem is indeed due to you not updating the original list and just creating a new one, then append() and remove() should fix it.

And to be honest, it looks like I'm gonna take the hit, because I have no idea here. Some players might get an error message
I think as long as you're properly checking the version of the save and then modifying the list accordingly I don't think there should be any problems. But then again you should test all cases out first just to make sure you're not hitting any edge cases.
 
  • Like
Reactions: Playstorepers

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,611
2,258
Another random thought for the moment...

If lists using define work just fine and you want to be able to remove music as much as add it... why not just use define for both list1 and list2?

I'm assuming the equivalent of default list2 = [ [...] ] is already in your game (and therefore stored in players' save files). So my guess would be that it'd be easier to just use a separate variable called list3 and ignore list2 in the future.

I'm thinking:

Python:
# --- script.rpy ---
define list3 = [track1, track2, track3, track4, [...], track100]

label after_load:

    $ renpy.music.queue ( renpy.random.sample(list3), len(list3)), loop=True )
    return

label start:

    $ renpy.music.queue ( renpy.random.sample(list3), len(list3)), loop=True )

    # game continues with the basic playlist playing.

Python:
# --- music_patch.rpy ---
init 1:
    define list3 = [track1, track2, track101, track4, [...], track100]

Where the init 1: runs after the normal init: and replaces list3 with a new version. I've used renpy.random.sample() here to avoid changing a variable created using define.
 

Playstorepers

Member
May 24, 2020
160
79
Ah I see, so adding it to the queue does immediately start playing it.



No, appending and removing doesn't create a new object, you're not reassigning anything, all the previous references to this list object will stay valid. If you're problem is indeed due to you not updating the original list and just creating a new one, then append() and remove() should fix it.



I think as long as you're properly checking the version of the save and then modifying the list accordingly I don't think there should be any problems. But then again you should test all cases out first just to make sure you're not hitting any edge cases.
I'm gonna check this out, when I get home.

Another random thought for the moment...

If lists using define work just fine and you want to be able to remove music as much as add it... why not just use define for both list1 and list2?

I'm assuming the equivalent of default list2 = [ [...] ] is already in your game (and therefore stored in players' save files). So my guess would be that it'd be easier to just use a separate variable called list3 and ignore list2 in the future.

I'm thinking:

Python:
# --- script.rpy ---
define list3 = [track1, track2, track3, track4, [...], track100]

label after_load:

    $ renpy.music.queue ( renpy.random.sample(list3), len(list3)), loop=True )
    return

label start:

    $ renpy.music.queue ( renpy.random.sample(list3), len(list3)), loop=True )

    # game continues with the basic playlist playing.

Python:
# --- music_patch.rpy ---
init 1:
    define list3 = [track1, track2, track101, track4, [...], track100]

Where the init 1: runs after the normal init: and replaces list3 with a new version. I've used renpy.random.sample() here to avoid changing a variable created using define.
Sadly, define doesn't even allow shuffle to happen, so I can't use it for my random playlists.
It works nicely for non-randomized lists, though.

And I think, I didn't explain my usage of the music playlist well enough:
At one point in the game the randomized list gets used.

So
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,611
2,258
Sadly, define doesn't even allow shuffle to happen, so I can't use it for my random playlists.

Which was why suggested I changing it to renpy.random.sample()... which creates a separate list object - which can be passed to renpy.music.queue() already randomized - but remaining separate from the original define.

It may not work. But and work both differently and the same - in certain specific ways I already described earlier.

And yeah, it's not uncommon for me to miss specific points in the original post while replying. But it seemed you wanted to create a predefined (but random) playlist, which can be replaced via a patch/DLC. One define replacing itself via a different init: level might do that for you.

At one point in the game the randomized list gets used.

Yeah. I did kinda latch onto the label after_load:, thinking it was actively changing the playing music.
But IF renpy.random.sample() works how I hope it does... then you'd only need the $ renpy.music.queue ( renpy.random.sample(list3), len(list3)), loop=True ) line at the point you want to start the music - without the need for the after_load:. Unless you want to cope with someone loading a save file during a period where the music was already playing... in which case, you'd probably need to check if music was already playing and re-queue things accordingly.
 
Last edited:
  • Like
Reactions: Playstorepers

Playstorepers

Member
May 24, 2020
160
79
Which was why suggested I changing it to renpy.random.sample()... which creates a separate list object - which can be passed to renpy.music.queue() already randomized - but remaining separate from the original define.

It may not work. But and work both differently and the same - in certain specific ways I already described earlier.

And yeah, it's not uncommon for me to miss specific points in the original post while replying. But it seemed you wanted to create a predefined (but random) playlist, which can be replaced via a patch/DLC. One define replacing itself via a different init: level might do that for you.




Yeah. I did kinda latch onto the label after_load:, thinking it was actively changing the playing music.
But IF renpy.random.sample() works how I hope it does... then you'd only need the $ renpy.music.queue ( renpy.random.sample(list3), len(list3)), loop=True ) line at the point you want to start the music - without the need for the after_load:. Unless you want to cope with someone loading a save file during a period where the music was already playing... in which case, you'd probably need to check if music was already playing and re-queue things accordingly.
Exactly. I want the latter. However it gets really complicated, since I can't add check variable in hindsight for the patch, so the only option, I would have is go deeper into music.py and find out, how it spits out the entire queue and then do a check on the queued songs.

And I just checked. .remove does squat for the music playing. If the music list, that's playing, is one active song it doesn't get removed. It just splices the lists again... So remove isn't the same as shuffle, I guess.

Which is unlucky, but hey it really is an edge case. So thank you all anyways for trying to help me.
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,611
2,258
So... I decided to test my recommendation of using define, init 1: and renpy.random.sample()... and I think I ended up with what you were aiming for.

The only problem I had to solve not previously considered in this thread was figuring out which playlist was currently active during label after_load:. I decided to just have a variable that is set at the same time renpy.music.queue() is executed (or set to None when the music is stopped).

My test script has 2 play lists, list1 and list3.

list1 plays sequentially 1 -> 2 -> 3 -> 1 [rinse and repeat].
list3 plays randomly (random order of 4, 5 or 6, repeated).

If a saved game is loaded that is currently playing list3, it requeues list3 - just in case the list of tracks has been overridden by a patch script.

I also have a file in the game folder called patch_music.notrpy. If it is renamed to patch_music.rpy before the game is run, list3 plays a completely different set of tracks.

I've tested it by saving when track 2 is playing (as part of list1), when there is no music is playing and during the second random track of list3. It works how I expected it to.

It's a testbench script, intended to demonstrate the concept... but I think it achieves what you originally wanted.
Download here:


It makes use of renpy.music.get_loop(), which was introduced as part of . Older versions won't be able to execute this code.

I'd suggest downloading it, then just playing it. Check if it does what you were aiming for and if it does... take a look at the code. When you've had a bit of a mess, rename the .notrpy file to .rpy to see what happens when the list3 playlist is overridden using a patch file.

You don't have permission to view the spoiler content. Log in or register now.
 
Last edited:

Playstorepers

Member
May 24, 2020
160
79
So... I decided to test my recommendation of using define, init 1: and renpy.random.sample()... and I think I ended up with what you were aiming for.

The only problem I had to solve not previously considered in this thread was figuring out which playlist was currently active during label after_load:. I decided to just have a variable that is set at the same time renpy.music.queue() is executed (or set to None when the music is stopped).

My test script has 2 play lists, list1 and list3.

list1 plays sequentially 1 -> 2 -> 3 -> 1 [rinse and repeat].
list3 plays randomly (random order of 4, 5 or 6, repeated).

If a saved game is loaded that is currently playing list3, it requeues list3 - just in case the list of tracks has been overridden by a patch script.

I also have a file in the game folder called patch_music.notrpy. If it is renamed to patch_music.rpy before the game is run, list3 plays a completely different set of tracks.

I've tested it by saving when track 2 is playing (as part of list1), when there is no music is playing and during the second random track of list3. It works how I expected it to.

It's a testbench script, intended to demonstrate the concept... but I think it achieves what you originally wanted.
Download here:


It makes use of renpy.music.get_loop(), which was introduced as part of . Older versions won't be able to execute this code.

I'd suggest downloading it, then just playing it. Check if it does what you were aiming for and if it does... take a look at the code. When you've had a bit of a mess, rename the .notrpy file to .rpy to see what happens when the list3 playlist is overridden using a patch file.

You don't have permission to view the spoiler content. Log in or register now.
Dude, you're amazing! I'm gonna look at the code in detail this weekend, but wow. Thank you so much for all the effort.

From a first skim, it's everything, I need.

Thank you so much again.
 

Playstorepers

Member
May 24, 2020
160
79
Addendum:

So I really like your idea with the variables, however, it's not possible to add the variable in hindsight and therefore not possible to patch my shit with this method.

The only option, I'm left with, is renpy.music.get_loop to get me the playlist and then check on it, to decide, whether I have to queue a new list. Luckily, I can check for a few core songs, that will only play in this playlist, instead of checking every song of the currently played playlist.

I really thank you all for your efforts, though. Especially you 79flavors.
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,611
2,258
[...] however, it's not possible to add the variable in hindsight and therefore not possible to patch my shit with this method.

Of course it is.

I assume you're talking about introducing the variable active_playlist into an existing game, where the game has already been released... and therefore players already have savefiles without the variable set to a meaningful value. That's kinda the point of default and label after_load:.

Option1:

Don't worry about it.​
By using default active_playlist = None, the value will be None when the player loads a save file. My current after_load: code won't match and the existing queue will continue playing (or not). As long as you don't actually delete any music files from the disk - it won't actually crash the game and the only consequence is that for a period the wrong playlist will be playing. However, once the game finally hits a stop music - the problem goes away. The next time a playlist is queued... it'll be the right playlist and the variable will be set. Is it perfect...? No. But it's not terrible either.​

Option2:

Use label after_load: as it is intended, to fix things for you.​
I presume each of the playlists includes at least one track that is unique - otherwise why have separate playlists?​
So use that to figure out the correct value of active_playlist and set it appropriately.​
This code would do it:​
Python:
label after_load:

    if renpy.music.get_loop() is not None and new_active_playlist == None:        # a music queue is active, but we don't know which one.
        if "music/three.mp3" in renpy.music.get_loop():
            $ new_active_playlist = "list1"
        if "music/six.mp3" in renpy.music.get_loop():
            $ new_active_playlist = "list3"
        if "music/ten.mp3" in renpy.music.get_loop():
            $ new_active_playlist = "list3"

    if new_active_playlist == "list3":          # list3 might have changed... so if it was active... requeue it.
        stop music
        $ renpy.music.queue( renpy.random.sample( list3, len(list3) ), loop=True)

    return
 
Last edited: