Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Callback on source end example #651

Open
dvdsk opened this issue Dec 3, 2024 · 5 comments
Open

Callback on source end example #651

dvdsk opened this issue Dec 3, 2024 · 5 comments

Comments

@dvdsk
Copy link
Collaborator

dvdsk commented Dec 3, 2024

Would have helped with: #600 (see last few messages there)

@geeseofbeverlyroad
Copy link

geeseofbeverlyroad commented Dec 6, 2024

Hi! Just came here to ask about something I assume might be similar. I am looking for a way to assign some Fn to call when the current Source has reached its end. For pausable / seekable sources, just "sleep until end" isn't enough, as it's useful to have the thread responsive to controls.

My current approach is getting get_pos and comparing to total_duration on a constant loop, but I assume there's a better way. Would love to be able to do something like source.on_end(|| println!("Sink ended")); or sink.on_current_source_ended(/* closure */); that can be assigned once on source creation.

Is there a way to do this already, or is it a planned feature?

@geeseofbeverlyroad
Copy link

OK seems like this works:

let actual_source = /* your actual source */;
sink.append(actual_source);
let callback_source = EmptyCallback::<f32>::new(Box::new(|| println!("actual source has ended!")));
sink.append(callback_source);

It's quite a strange approach to me, since statistics like number of sources added to the sink's queue, are then "wrong", let's say I added 10 actual audio sources, but getting sound_count would return 20.

It's possible to live with that and manage the queue separately somewhere of course. But wondering about the reasons you chose to go for this API specifically. Seems more "direct" to have the Sink itself notify of it progressing through its sources, in the "my current source changed (ended, skipped, etc), here's next source if any".

@dvdsk
Copy link
Collaborator Author

dvdsk commented Dec 6, 2024

there is, we really need an example of that (which is what this issue is for)

To run a function once a source end you append a second source of type EmptyCallback it takes as argument: Box<dyn Send + Fn()>. That is rust speak for a Boxed function that can be send from one thread to another.

Once your first source ends the queue 'plays' emptycallback. It does not make sound but runs your function. Once your function is done the queue immediately moves to the next source.

@dvdsk
Copy link
Collaborator Author

dvdsk commented Dec 6, 2024

lol you found out about the same time as I typed my explanation.

But wondering about the reasons you chose to go for this API specifically

Its an old choice from before my time as maintainer. It does however make things internally easier. We are designing a more high level API to rodio (its probably going to be called Player and replace the current Sink that will make this easier.

If you have time please let us know what you need: #626

@ch3pjw
Copy link

ch3pjw commented Jan 1, 2025

there is, we really need an example of that (which is what this issue is for)

That would be super useful - I hit exactly the same question.

dvdsk added a commit that referenced this issue Jan 2, 2025
Has an explicit comment instructing the user in the use of `move` since thats something people struggle with. I could have made the example nicer and more functional. It could be refactored with a function that generates the callback. Then we would have something like:
```rust
fn new_playlist_pos_callback() -> impl Fn() + Send {
    ...
}

sink.append(song);
sink.append(new_playlist_pos_callback());
sink.append(song);
sink.append(new_playlist_pos_callback());
sink.append(song);
sink.append(new_playlist_pos_callback());
```

I chose instead to keep it as short and simple as possible, even though
the example code on its own is not as usefull now.
dvdsk added a commit that referenced this issue Jan 2, 2025
Has an explicit comment instructing the user in the use of `move` since thats something people struggle with. I could have made the example nicer and more functional. It could be refactored with a function that generates the callback. Then we would have something like:
```rust
fn new_playlist_pos_callback() -> impl Fn() + Send {
    ...
}

sink.append(song);
sink.append(new_playlist_pos_callback());
sink.append(song);
sink.append(new_playlist_pos_callback());
sink.append(song);
sink.append(new_playlist_pos_callback());
```

I chose instead to keep it as short and simple as possible, even though
the example code on its own is not as usefull now. Functions returning a generic boxed closure are hard to understand and that distracts from what we are trying to show here (how to use the emptycallback source).
dvdsk added a commit that referenced this issue Jan 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants