Allow retrieving the queue signal in a sink when using crossbeam-channel feature
Hi,
This commit creates a new Sink::append_with_signal method and make Sink::append a wrapper function without breaking change.
It only "works" with the crossbeam-channel feature flag because crossbeam::channel::Receiver implements Clone but not std::sync::mpsc::Receiver .
append_with_signal will be useful in case we have to do something at the end of a Source inside a Sink.
Hi,
Thanks for the PR. This Pr exposes more of Rodio's internals which will make it harder to make changes to rodio in the future, which makes me hesitant to merge this. Maybe there is another way. Could you explain why you need this?
Hi @dvdsk,
Thank you for your response, there are two cases, and I use both:
- With the current Sink API, we can't wait the end of a source which is not the last append
Currently, if I use Sink::sleep_until_end and then load and process data for this file, I get silences between my sources, due the time spent between Sink::sleep_until_end and Sink::append.
The new function Sink::append_with_signal become useful to lazily load the music file and process data for this file only when the sink will "soon" be ended (in my case when less than two sources are remaining).
It becomes faster starting up the program and make the program less memory consuming than loading all files at startup.
- With the current Sink API, we can't use
crossbeam::channel::select!
crossbeam allows to do something with the fastest ready receiver (https://docs.rs/crossbeam/latest/crossbeam/channel/struct.Select.html).
In my case, I can now use Sink::append_with_signal with my source, and then do, for example:
crossbeam::channel::select! {
recv(receiver_from_append_with_signal) -> msg => receiver_from_append_with_signal = my_sink.append_with_signal(MySource::load()),
recv(receiver_from_another_thread_sending_messages) -> msg => my_sink.set_volume(0.5),
}
In this case, it is possible to block the thread as with Sink::sleep_until_end, while still being able to communicate.
This also means we could have two sinks, in two different threads, where the first could send a message to the second to lower the volume of the second until the first ended playing.
Your first use case (a good one) is in the same category to https://github.com/RustAudio/rodio/pull/506. It seems a good idea to overhaul/redesign the Sink to better support these use-cases.
Regarding the second use-case, can you give me a a little more information? Are you trying to do a cross-fade effect?
Ok, I will explain my own use case if it helps understand it better.
First of all, this is not to do a cross-fade effect, I already use Sink::take_crossfade_with to cross-fade between my sources.
My application works with at least two Sinks working in different threads (It can't be synchronous for reasons not linked with rodio).
The first thread will handle music in the background, the Sink will continuously play.
The second thread will handle the "event" music, the Sink will play only several sounds and will last like 30 seconds each time when something is triggered by my users.
The "event"s are more important than the music in the background, therefore I want at this moment, the first thread Sink volume can be set to 0.5, but not stopping playing, and at the end of the "event", the background can be set back to volume 1.0.
In fact, my overall issue is to make both first case and second case work together, I need both in my project, and I found out the little change I made here made it easy.
Hope it is more understandable with that case !
@AlbanWS would adding an https://docs.rs/rodio/latest/rodio/source/struct.EmptyCallback.html source after your sound effect work? The empty callback could send a message using an mpsc for example
(Same person, different account)
Indeed ! It would fit well, thank you for all !
Yes, EmptyCallaback may do the trick but it is not obvious that this may be a solution, I think a usage example (with it and a crossbeam channel) should help.
Yes,
EmptyCallabackmay do the trick but it is not obvious that this may be a solution, I think a usage example (with it and a crossbeam channel) should help.
Agreed an example is needed. I would suggest leaving out crossbeam though. If a user really dislikes the std::mpsc they can always switch it out themselves. In the future this need will largly be served by the to be designed Player struct.
@dvdsk I wonder if good old callbacks instead can do the trick. So if someone wants to use a channel they can add a message to it in a callback function. It is a bit more verbose but makes no assumptions on how event handling would be implemented.
@dvdsk I wonder if good old callbacks instead can do the trick.
Yeah that is what we should have in the example. Since the most common use-case is probably to have a receiver somewhere receive a message once a song ends.