cheofusi / just_playback

A small library for playing audio files in python, with essential playback functionality.
MIT License
70 stars 7 forks source link

Callback at end of song #27

Closed nhansendev closed 7 months ago

nhansendev commented 1 year ago

Is there any built-in functionality that would allow a callback to be executed when a song ends? I can replicate the behavior by using a loop to check if the player status has changed and if the curr_pos has reset itself to 0, but it's a little sketchy.

My main use-case is to have it auto-play the next song once the previous one ends, so it seems like a useful built-in feature if it doesn't exist already.

Edit: I found this in the miniaudio documentation:

Use ma_sound_at_end() to determine whether or not a sound is currently at the end. For a looping sound this should never return true. Alternatively, you can configure a callback that will be fired when the sound reaches the end. Note that the callback is fired from the audio thread which means you cannot be uninitializing sound from the callback. To set the callback you can use ma_sound_set_end_callback(). Alternatively, if you're using ma_sound_init_ex(), you can pass it into the config like so:

soundConfig.endCallback = my_end_callback;
soundConfig.pEndCallbackUserData = pMyEndCallbackUserData;

Since the callback is triggered from the audio thread it may not be as simple as I was thinking...

cheofusi commented 7 months ago

just-playback's goal is to be as simple as possible. Adding this feature would probably require that we schedule the execution of a Python function from the C extension. Things then quickly become unnecessarily complicated.

A while p.active: ... is the easiest solution for now. Another could be to use Python's event scheduler to schedule your callback to be called after a period t, where t is the length of the active audio file.

tomhaines commented 7 months ago

I am using just_playback in a Pyglet app, and I use their scheduler to regularly fire this method that I’ve monkey-patched into just_playback

Monkey patch an eos_reached property

def eos_reached(self): """ Check if the playback has reached the end of the stream """ return self._Playback__ma_attrs.audio_stream_ended_naturally

Built in functionality would be fantastic

On Wed, Mar 13, 2024 at 8:01 AM Cheo Fusi @.***> wrote:

just-playback's goal is to be as simple as possible. Adding this feature would probably require that we schedule the execution of a Python function from the C extension. Things then quickly become unnecessarily complicated.

A while p.active: ... is the easiest solution for now. Another could be to use Python's event scheduler https://docs.python.org/3/library/sched.html to schedule your callback to be called after a period t, where t is the length of the active audio file.

— Reply to this email directly, view it on GitHub https://github.com/cheofusi/just_playback/issues/27#issuecomment-1994604540, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABF6EZSL72IHUM6EYTBFLLYYBS5RAVCNFSM6AAAAAAWXB7MN6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSOJUGYYDINJUGA . You are receiving this because you are subscribed to this thread.Message ID: @.***>

cheofusi commented 7 months ago

@tomhaines your solution seems not work when Playback::loops_at_end is true.

Why not check instead if Playback::active is set ?

tomhaines commented 7 months ago

Yeah. It’s not a perfect solution, which is why an official way to check would be great. I am not looping in my application, so it has worked but I’ll update with the approach you mention.

On Wed, Mar 13, 2024 at 3:08 PM Cheo Fusi @.***> wrote:

@tomhaines https://github.com/tomhaines your solution seems not work when Playback::loops_at_end is true.

— Reply to this email directly, view it on GitHub https://github.com/cheofusi/just_playback/issues/27#issuecomment-1995973202, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABF6EZ7EA2GTB4YEA4H5MDYYDE7XAVCNFSM6AAAAAAWXB7MN6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSOJVHE3TGMRQGI . You are receiving this because you were mentioned.Message ID: @.***>