https://bugs.winehq.org/show_bug.cgi?id=53475
--- Comment #11 from Zeb Figura z.figura12@gmail.com --- (In reply to ilkka.prusi from comment #9)
Created attachment 72847 [details] Simplify end of stream and flush event handling
Flush event handling has bogus error message: it is normal that WaitForSingleObject() returns 0 when event has been signalled. Also at that point it is expected that code will stop blocking so expedited return would be preferred instead of continuing in SendSampleData(). This has a case-check in the patch.
The problem with this diff is that under normal operation we really shouldn't be getting there in the first place. If flush_event is signaled then the sink should be flushing or stopped. In either case the upstream filter that's driving the graph (i.e. the parser) should have waited for the streaming thread to finish before un-flushing or restarting the graph.
The code is awful and doesn't make this clear, of course.
In dsound_render_sink_eos(), when stream is finished resetting should buffer have no meaningful purpose: a) buffer will be destroyed and sample no longer matters b) buffer could be reused and rewritten with new sample Zeroing serves no purpose in either case and is removed in the patch.
The buffer may not be destroyed or refilled immediately; it may take an arbitrary amount of time, during which time dsound will continue to loop over it. If we don't zero the buffer the user will hear the last second of audio repeat.
Additionally, in dsound_render_sink_eos() there is a waiting loop which seems to have no purpose and causes bogus "underrun" message when sample playing is supposed to end already. Code does other things that seem to have no useful meaning when stream is ending. The lines that may have use are lifter up the call chain in the patch.
It's waiting for the buffer to finish playing, so that the aforementioned zeroing won't overwrite data that hasn't been written out to the audio device yet.
Finally, filter->state_event should only be set after all modifying of the state is done, so ensure that is the last. This is also in the patch.
That's not necessary; there's nothing that needs to actually be synchronized there. The point of state_event is to signal preroll; usually it's signaled on a sample rather than EOS.