[PATCH] winepulse.drv: Add PulseAudio driver

Andrew Eikum aeikum at codeweavers.com
Mon Jun 18 09:31:04 CDT 2012

On Fri, Jun 15, 2012 at 06:23:57PM -0700, Chris Robinson wrote:
> The update_size is only relevant if mmdevapi updates in period-sized chunks. 
> If it doesn't, you can just remove it and the rounding. The tlength should be 
> kept updated using pa_stream_set_buffer_attr_callback, in case the server 
> tries to increase it more during runtime.

We chatted a little on IRC this weekend, but thanks again for the

Mmdevapi sends it data to the lower systems in period-sized chunks,
and the reported buffer fill level decreases in period-sized chunks.
But the audio clock position is more accurate than that, returning
some value between periods, and taking into account latency.

Unfortunately, PulseAudio (and, apparently, every Linux audio API)
refuses to make any guarantees at all with regard to things like
buffer sizes, period sizes, callback regularity, and latencies. So in
Wine we have to build an emulation layer, involving a buffer in the
driver itself, and lie about buffer drain behavior and latencies.  I
really don't understand why the audio APIs refuse to do this heavy
lifting, instead pushing it off to applications. What is the API for
if I have to do all the hard work anyway?

It'd be handy if there was some page explaining how PulseAudio's data
model works. Stuff like where the data is stored, when and how it's
transfered, when callbacks are triggered, what the members of
pa_buffer_attr actually mean (their documentation is useless), how the
stream flags affect stream operation and the callbacks, when the
buffer attributes might change and how applications should deal with
those changes. This stuff is all unclear to me, and I think it's a big
source of my frustration with the API.

> When creating the stream, I set minreq to the period size, and tlength to the 
> requested buffer size. I also set the flags PA_STREAM_INTERPOLATE_TIMING, 
> The most important part is to not rely on PA_STREAM_EARLY_REQUESTS or the 
> write callback to tell you when some space is free for writing, since as noted 
> above, PulseAudio can set unreasonably large values.

Yeah, I experimented with ADJUST_LATENCY, as it seems to be the trick
to getting lower latencies. Then we have to maintain our own buffer,
which is why I switched to using the write callback, to have Pulse
tell us when it's ready for more data from our internal buffer.  But
then I couldn't get the callbacks to actually trigger without
supplying EARLY_REQUESTS, which invalidates our latency request,
causing the high latency problem... wonderful API, isn't it?

Your mail makes me think I should go back to the pulse-independent
timer setup. That is, write to Pulse during the
CreateTimerQueueTimer() callback. I have a strong feeling I've been
down that path before, but I could give it another shot.

Thanks again,

More information about the wine-devel mailing list