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

Removing sources that are at the end of the Sink #636

Open
callum-jones19 opened this issue Nov 11, 2024 · 3 comments
Open

Removing sources that are at the end of the Sink #636

callum-jones19 opened this issue Nov 11, 2024 · 3 comments

Comments

@callum-jones19
Copy link

Hi there!

I just had a brief issue dealing with the following situation:

  1. You create a new sink.
  2. You open two sources from files.
  3. Both sources are appended to the sink
  4. During playback of source 1, you decide that you want to remove source 2, and append a new source in its place.

However, I want to do this without interrupting the flow of playback. This is for a music player, so the possibility of the next upcoming song changing (say, because of a queue change) without interrupting the current playback (stutters, moment of silence, etc) is quite important. I would also like to keep the gapless playback functionality.

Right now, the only solution I could think of is having a secondary sink which is switched out, but this seems a bit cumbersome and likely to cause one of the issues I mentioned above. The way my player works right now is there is a Vec of song file paths (my 'lightweight' queue). When you add a song to this file path queue, it checks to see if the sink contains < 4 song sources in it. If it does, then it opens the file path into an actual source, and adds it to the sink. An EmptyCallback that sits after this then runs whenever the song source ends, and opens the next song path in the file path vec into a Decoder, which is then appended to the sink.

I do this so that I can have a very large queue that is easy to control (plus has song struct info in it) with minimal open file pointers, etc, but then the sink is constantly kept at 2 songs ready to go (unless there is only 1 left to play) so gapless playback works. This works well, but like I said, if I want to change the next song in the queue during playback of the first source, I am not sure how to remove the second source from the sink and append a new one in its place.

Thanks for all the hard work on Rodio - it's been incredibly helpful, and I've learnt a lot working with the library. Hopefully when I understand it a bit more fully I can contribute back to it too :)

@dvdsk
Copy link
Collaborator

dvdsk commented Nov 11, 2024

Hi callum,

First off all thank you for your very clear description. We are currently in the process of redesigning the Sink API you have worked with. I am going to copy your description/use case it to the list of user stories.

If I understand correctly your question is: how do I remove the last item in the Sink queue. It might be good to know that you can use rodio completely without Sink. We should have some examples on that, we currently do not :( Thats something we should and do want to change. I recently explained how to create your own Sink in this issue: #634 it might be a useful read.

To easiest way to address your usecase: you can make any source in rodio abort early by wrapping the source in a Stoppable. Now you might wonder how to control that stoppable once the source is moved into the Sink. The answer to that is wrapping the source yet again, this time with PeriodicAccess. For more detail on that see the linked issue and the example linked in it.

If you have any issue let us know here. It is useful info. And if you wish to contribute back, please think back to now and what would have helped you find the solution. It can be difficult as maintainer to look at the library the same way as a new user. That makes it difficult to decide what would be the best example or place to put some extra documentation such that it helps out new users at the right moment.

@callum-jones19
Copy link
Author

Thank you so much for the detailed reply! I will take a look at all of that and see how it goes (although it might take me a while to get around to it haha).

Something I also was hoping to clarify was the functionality of PeriodicAccess. I've had my eye on it for a while, just from reading through Sink.rs, but I wanted to ask if it had any performance implications at all? This question is stemming purely from ignorance - there's just a part of my brain that makes it feel like switching to execute the periodic callback every, say, 5ms, would potentially slow down the app, just from the overhead of managing async stuff? Is this true (or is there any similar sort of performance concern to keep in mind), if I were to wrap sources in Stoppable, and then run a periodic check every 5ms to see whether they should be marked as such? Or is such a concern negligible?

Thanks again for the help!

@dvdsk
Copy link
Collaborator

dvdsk commented Nov 12, 2024

there's just a part of my brain that makes it feel like switching to execute the periodic callback every, say, 5ms, would potentially slow down the app

Its the fastest way we have figured out to control a running stream. If you make the period longer if becomes more efficient though that should not be needed. You do want to be conscious that you do as few things as possible in the callback (no heavy calculations or IO). The fastest is probably setting the controls by copying over the values of a bunch of shared atomicbools. But as always with performance test it if your worried.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants