Help with in-screen audio player issues (restarting music, unable to truly 'pause') [SOLVED]

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Post Reply
Message
Author
User avatar
KINJA
Newbie
Posts: 7
Joined: Mon May 13, 2024 5:14 pm
Contact:

Help with in-screen audio player issues (restarting music, unable to truly 'pause') [SOLVED]

#1 Post by KINJA »

PREMISE:

Hello!

I made a previous post about making a fake in-game radio for my horror game. How it works is that the radio is a composite of a few screens for display, with a slider bar that "tunes" the radio, either playing static or music. The station number cooresponds to a track that plays on the radio, which displays as you move the slider. Also, there's a button that will either become a play or pause button, and a button to leave the screen. So far, it works! The audio changes when you slide the bar, and the station changes in real time above it, which has been cool so far. Here's what it looks like all together (doesn't look pretty yet lmao):

Image

Aaaaaand here's the code I made for it:

Code: Select all

screen Leave:
    frame:
        align (.6,.9)
        padding (20,10)
        textbutton "CLOSE" action Jump("AnotherDay"):
            activate_sound "audio/typeClick.mp3"

init python:
    global signal
    import renpy.audio.music as music

    music.register_channel("music_room", mixer="music_room_mixer", loop=True)

    pausedstate = True
    
    def playSignal():
        global pausedstate
        if pausedstate == False:
            if persistent.signal == 2:
                renpy.music.play("audio/signal1.ogg", channel="music_room", loop=True, fadein=1.0)
            elif persistent.signal == 5:
                renpy.music.play("audio/signal2.ogg", channel="music_room", loop=True, fadein=1.0)
            elif persistent.signal == 11:
                renpy.music.play("audio/signal3.ogg", channel="music_room", loop=True, fadein=1.0)
            elif persistent.signal == 14:
                renpy.music.play("audio/signal4.ogg", channel="music_room", loop=True, fadein=1.0)
            elif persistent.signal == 9:
                sig.Play("audio/signal5.ogg")
                renpy.music.play("audio/signal5a.ogg", channel="music_room", loop=True, fadein=1.0)
            else:
                renpy.music.play("audio/signal-static.ogg", channel="music_room", loop=True)
        return

    def pauseSignal():
        global pausedstate
        music.stop(channel='music_room', fadeout=1.0)

define signals = [
    101.1, 101.2, 101.3, 101.4,
    102.1, 102.2, 102.3, 102.4,
    103.1, 103.2, 103.3, 103.4,
    104.1, 104.2, 104.3, 104.4
    ]
    
default persistent.signal = 0
default stationNum = persistent.signal
default currentSignal = signals[stationNum]
default current_signal = None

transform gestaltButton:
    on hover:
        alpha 1
    on idle:
        alpha .5

screen radioBar:
    bar:
        value FieldValue(persistent, "signal", 15, style="radio_slider", step=1, force_step = False)
        align (.5,.5)
        xsize 300
        ysize 35
        thumb "gui/slider/rad_thumb.png"
        thumb_offset 32
        left_gutter 13
        right_gutter 13

screen playpause():
    if pausedstate:
        imagebutton:
            at gestaltButton
            xalign .5
            idle buttonPlay
            hover buttonPlay
            action ToggleVariable("pausedstate"), PauseAudio(channel='music_room', value=False)
    if not pausedstate:
        imagebutton:
            at gestaltButton
            xalign .5
            idle buttonPause
            hover buttonPause
            action ToggleVariable("pausedstate"), PauseAudio(channel='music_room', value=True)

screen cellRadio():
    $ stationNum = persistent.signal
    $ currentSignal = signals[stationNum]
    if not pausedstate:
        $ playSignal()
    frame:
        align (0.5,0.5)
        padding (50,150)
        vbox:
            ypos -50
            spacing 30
            frame:
                padding (50,10)
                align (.5,.5)
                text "S I G N A L"
            frame:
                align (.5,.5)
                padding (50,20)
                text "[currentSignal]" size 100 font "fonts/digital-7.ttf"
            use radioBar
            use playpause
    use Leave

label radioScreen:
    call screen cellRadio
    return
THE PROBLEM:

Here's my issue: Whenever I leave this screen, or do anything else really, the music that's playing from the radio replays itself automatically. If I pause the game (normal right click) and unpause, the track playing will restart. Other times, it will restart from the very start of the track list (101.1, in this case) without me touching it. This is an issue because I need the music to continue to play after closing the screen, and while checking other screens. The only way I want this to change is with the play/pause button (it becomes one or the other when pressed), and while it successfully turns off/on the radio, the issue is that it's not a true pause, and will instead stop the music when paused, and play it from the beginning when played. Basically, the same issue.

TROUBLESHOOTING:

I think it may be an issue with me running the $ playSignal() command in my screen, and why it's restarting every time. However, I want the tracks to change in real time with the slider, so I need something there that tracks and changes what is playing, which is what that function does. Also, I'm trying to use the traditional PauseAudio() action for the play/pause button (was using 'stop' actions before), but it essentially does nothing so far. The same thing goes for the pauseSignal() function, which does the same thing whether it's using a 'stop' or 'pause' command (which is why it's not being used right now). I really think the issue is either with the channel the radio uses ('music_room' in this case), or the fact that the playSignal() function uses renpy.music.play to play the tracks when called, which may be why it restarts everytime I come back to this screen? The problem is, I don't know what other action to use here, nor do I know how to get a proper pause that stops the track rather than replaying it. I'm a little stuck, haha.

Got a killer response from the forums last time, so I'm hoping for some good luck again by posting the issue here. Hopefully someone may know what to do here, I'm an animator first and foremost and still getting the hang writing code like this lol. Big thanks in advance!
Last edited by KINJA on Wed May 15, 2024 4:40 pm, edited 1 time in total.
None of the Avengers help Blade out with the literal hordes of vampires that walk the Earth and that's genuinely insane to me.

philat
Eileen-Class Veteran
Posts: 1926
Joined: Wed Dec 04, 2013 12:33 pm
Contact:

Re: Help with in-screen audio player issues (restarting music, unable to truly 'pause'))

#2 Post by philat »

Conceptually, given that this is a radio, it seems like the track shouldn't be pausable in the first place. Would it make more sense to simply have separate registered channels for all the signals, which are muted on/off instead? (I don't know what this would look like performance wise, I'm just throwing it out there.)

User avatar
KINJA
Newbie
Posts: 7
Joined: Mon May 13, 2024 5:14 pm
Contact:

Re: Help with in-screen audio player issues (restarting music, unable to truly 'pause'))

#3 Post by KINJA »

philat wrote: Wed May 15, 2024 1:11 am Conceptually, given that this is a radio, it seems like the track shouldn't be pausable in the first place. Would it make more sense to simply have separate registered channels for all the signals, which are muted on/off instead? (I don't know what this would look like performance wise, I'm just throwing it out there.)
Possibly yeah! A mute button that pauses music that's always going would be cool too, and I agree it makes sense for a radio. I'd still like to fix this first issue, and if I can get that fixed I think this would be an easy adjustment to make.
None of the Avengers help Blade out with the literal hordes of vampires that walk the Earth and that's genuinely insane to me.

User avatar
Ocelot
Lemma-Class Veteran
Posts: 2428
Joined: Tue Aug 23, 2016 10:35 am
Github: MiiNiPaa
Discord: MiiNiPaa#4384
Contact:

Re: Help with in-screen audio player issues (restarting music, unable to truly 'pause'))

#4 Post by Ocelot »

KINJA wrote: Tue May 14, 2024 5:58 pm I think it may be an issue with me running the $ playSignal() command in my screen, and why it's restarting every time. However, I want the tracks to change in real time with the slider, so I need something there that tracks and changes what is playing, which is what that function does.
Your function is run every interaction, every time something updateas and just occasionly over time. SO it should expect that.
If you want it to run when bar value changes then run it when bar value changes:
https://www.renpy.org/doc/html/screens.html#bar
changed
If given, this should be a Python function. The function is called with the value of the adjustment when the adjustment is changed.
< < insert Rick Cook quote here > >

User avatar
KINJA
Newbie
Posts: 7
Joined: Mon May 13, 2024 5:14 pm
Contact:

Re: Help with in-screen audio player issues (restarting music, unable to truly 'pause'))

#5 Post by KINJA »

Ocelot wrote: Wed May 15, 2024 12:27 pm
KINJA wrote: Tue May 14, 2024 5:58 pm I think it may be an issue with me running the $ playSignal() command in my screen, and why it's restarting every time. However, I want the tracks to change in real time with the slider, so I need something there that tracks and changes what is playing, which is what that function does.
Your function is run every interaction, every time something updateas and just occasionly over time. SO it should expect that.
If you want it to run when bar value changes then run it when bar value changes:
https://www.renpy.org/doc/html/screens.html#bar
changed
If given, this should be a Python function. The function is called with the value of the adjustment when the adjustment is changed.
I added the 'changed' property to the radioBar screen that runs the playSignal() function now, and removed it from the cellRadio screen. However, I'm still experiencing the issue, and the music keeps replaying if you leave the screen, pause/unpause, or interact with anything. Basically, it helped clean up the code a bit (thank you for that), but the issue hasn't changed unfortunately.

Here's the updated radioBar for anyone that may need to see it:

Code: Select all

screen radioBar:
    bar:
        value FieldValue(persistent, "signal", 15, style="radio_slider", step=1, force_step = False)
        align (.5,.5)
        xsize 300
        ysize 35
        changed playSignal()
        thumb "gui/slider/rad_thumb.png"
        thumb_offset 32
        left_gutter 13
        right_gutter 13
None of the Avengers help Blade out with the literal hordes of vampires that walk the Earth and that's genuinely insane to me.

User avatar
Ocelot
Lemma-Class Veteran
Posts: 2428
Joined: Tue Aug 23, 2016 10:35 am
Github: MiiNiPaa
Discord: MiiNiPaa#4384
Contact:

Re: Help with in-screen audio player issues (restarting music, unable to truly 'pause'))

#6 Post by Ocelot »

Code: Select all

changed playSignal()
is equivalent to

Code: Select all

$ x = playSignal()
changed x
Which is equvalent to

Code: Select all

$ playSignal()
changed None
You need to pass a function, not call it and pass result of its execution.

TL;DR:
Remove () from playSignal()
< < insert Rick Cook quote here > >

User avatar
KINJA
Newbie
Posts: 7
Joined: Mon May 13, 2024 5:14 pm
Contact:

Re: Help with in-screen audio player issues (restarting music, unable to truly 'pause'))

#7 Post by KINJA »

Ocelot wrote: Wed May 15, 2024 2:58 pm

Code: Select all

changed playSignal()
is equivalent to

Code: Select all

$ x = playSignal()
changed x
Which is equvalent to

Code: Select all

$ playSignal()
changed None
You need to pass a function, not call it and pass result of its execution.

TL;DR:
Remove () from playSignal()
Unfortunately, removing () doesn't seem to run the function at all. But, the good news is that I solved the issue! I'm going to make a post in a bit here about how I did it, but thanks a bunch for the tips.
None of the Avengers help Blade out with the literal hordes of vampires that walk the Earth and that's genuinely insane to me.

User avatar
KINJA
Newbie
Posts: 7
Joined: Mon May 13, 2024 5:14 pm
Contact:

Re: Help with in-screen audio player issues (restarting music, unable to truly 'pause'))

#8 Post by KINJA »

I solved the issue in a strange but cool way!

So the main problem was that I didn't want the music on the radio restarting when you interact with anything, or open/close other screens. Basically, I want it to play nonstop until you stop it with the radio player or the game stops it for you. Here's how the fix I came up with:

First, I figured the best way to go about this was to have every signal (track) on a different channel, BUT, keep them on the same mixer. So while all the signals have their own channel now, they all share the "music_room_mixer" mixer property. After that, I split everything into three different functions (which is a lot), but it managed to run everything how I need it to. Here's the first function within the init python block:

Code: Select all

def Signals():
        global pausedstate
        muteSignal()
        renpy.music.play("audio/signal1.ogg", channel="signal1", loop=True, fadein=1.0, synchro_start=True)
        renpy.music.play("audio/signal2.ogg", channel="signal2", loop=True, fadein=1.0, synchro_start=True)
        renpy.music.play("audio/signal3.ogg", channel="signal3", loop=True, fadein=1.0, synchro_start=True)
        renpy.music.play("audio/signal4.ogg", channel="signal4", loop=True, fadein=1.0, synchro_start=True)
        renpy.music.play("audio/signal5a.ogg", channel="signal5a", loop=True, fadein=1.0, synchro_start=True)
        renpy.music.play("audio/educational.ogg", channel="babble_signal", loop=True, fadein=1.0, synchro_start=True)
        renpy.music.play("audio/i still remember you after all these years.ogg", channel="his_signal", loop=True, fadein=1.0, synchro_start=True)
        renpy.music.play("audio/audiobook.ogg", channel="book_signal", loop=True, fadein=1.0, synchro_start=True)
        renpy.music.play("audio/NOTYET.ogg", channel="find_me", loop=True, fadein=1.0, synchro_start=True)
        renpy.music.play("audio/signal-static.ogg", channel="null_signal", loop=True, synchro_start=True)
        return
This first function plays the tracks all at once, at the start of the scenario. As you can see, they've all got individual channels, but the same mixer. Also! They all use synchro_start set to True, meaning they'll all be playing at once, which is what I want. With this being separate now, the tracks won't keep replaying every time the radio screen is open/closed/clicked away from, because it's out of the callRadio screen entirely now. I also have a muteSignal() function running at the very top, which is the second function I made:

Code: Select all

def muteSignal():
        global pausedstate
        music.set_volume(0, channel="signal1")
        music.set_volume(0, channel="signal2")
        music.set_volume(0, channel="babble_signal")
        music.set_volume(0, channel="find_me")
        music.set_volume(0, channel="signal5a")
        music.set_volume(0, channel="signal3")
        music.set_volume(0, channel="book_signal")
        music.set_volume(0, channel="signal4")
        music.set_volume(0, channel="his_signal")
        music.set_volume(0, channel="null_signal")
        return
This second function sets every signal's channel volume to 0, effectively muting it while it plays. This way, all of the tracks will be initially silenced, unless the radio is used to turn it on and unmuted. This happens when the radioBar screen runs the third function with it's channel value set to playSignal():

Code: Select all

    def playSignal():
        global pausedstate
        muteSignal()
        if persistent.signal == 2:
            renpy.music.set_volume(1, channel="signal1")
        elif persistent.signal == 5:  
            renpy.music.set_volume(1, channel="signal2")
        elif persistent.signal == 7:  
            renpy.music.set_volume(1, channel="babble_signal")
        elif persistent.signal == 10:
            renpy.music.set_volume(1, channel="find_me")
        elif persistent.signal == 9:
            renpy.music.set_volume(1, channel="signal5a")
        elif persistent.signal == 11:  
            renpy.music.set_volume(1, channel="signal3")
        elif persistent.signal == 12:
            renpy.music.set_volume(1, channel="book_signal")
        elif persistent.signal == 14: 
           renpy.music.set_volume(1, channel="signal4")
        elif persistent.signal == 15:
            renpy.music.set_volume(1, channel="his_signal")
        else:
            renpy.music.set_volume(1, channel="null_signal")
        return
        
      screen radioBar:
    	bar:
        	value FieldValue(persistent, "signal", 15, style="radio_slider", step=1, force_step = False)
        	align (.5,.5)
        	xsize 300
        	ysize 35
        	changed playSignal()
        	thumb "gui/slider/rad_thumb.png"
        	thumb_offset 32
        	left_gutter 13
        	right_gutter 13
When the slider of the bar is moved, it will run playSignal(), which unmutes the channel of a signal's track based the bar's value (in this case, 'persisten.signal' for me). The playSignal() function also starts with muteSignal(), meaning whatever track that was playing will have its channel muted, and playSignal will unmute a different channel.

In combination, it all works! I can navigate other parts of the game while the music plays from the radio, and it doesn't replay because I set the Signals() function way back at the start of the scenario. For anyone curious, I put the channels all on the same mixer because the pause/play button uses ToggleMute('music_room_mixer'), meaning that it will mute/unmute the mixer when pressed, which mutes all of the tracks attatched to it (in this case, all of the signals), which is exactly what I want. Right now, the button itself is a little finnicky, but as for the main issue of the thread I managed to find the solution this way!

I hope this helps anyone else with a similar issue! This took frikkin forever!!! ✌😬✨
None of the Avengers help Blade out with the literal hordes of vampires that walk the Earth and that's genuinely insane to me.

Post Reply

Who is online

Users browsing this forum: No registered users