aboutsummaryrefslogtreecommitdiffstats
path: root/Alc
diff options
context:
space:
mode:
Diffstat (limited to 'Alc')
-rw-r--r--Alc/backends/pulseaudio.c52
1 files changed, 37 insertions, 15 deletions
diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c
index 79ca38e5..0eda2abd 100644
--- a/Alc/backends/pulseaudio.c
+++ b/Alc/backends/pulseaudio.c
@@ -626,6 +626,11 @@ static void ALCpulsePlayback_bufferAttrCallback(pa_stream *stream, void *pdata)
self->attr = *pa_stream_get_buffer_attr(stream);
TRACE("minreq=%d, tlength=%d, prebuf=%d\n", self->attr.minreq, self->attr.tlength, self->attr.prebuf);
+ /* FIXME: Update the device's UpdateSize (and/or NumUpdates) using the new
+ * buffer attributes? Changing UpdateSize will change the ALC_REFRESH
+ * property, which probably shouldn't change between device resets. But
+ * leaving it alone means ALC_REFRESH will be off.
+ */
}
static void ALCpulsePlayback_contextStateCallback(pa_context *context, void *pdata)
@@ -797,7 +802,6 @@ static int ALCpulsePlayback_mixerProc(void *ptr)
ALCpulsePlayback *self = ptr;
ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
ALuint buffer_size;
- ALint update_size;
size_t frame_size;
ssize_t len;
@@ -806,18 +810,30 @@ static int ALCpulsePlayback_mixerProc(void *ptr)
pa_threaded_mainloop_lock(self->loop);
frame_size = pa_frame_size(&self->spec);
- update_size = device->UpdateSize * frame_size;
-
- /* Sanitize buffer metrics, in case we actually have less than what we
- * asked for. */
- buffer_size = minu(update_size*device->NumUpdates, self->attr.tlength);
- update_size = minu(update_size, buffer_size/2);
- do {
- len = pa_stream_writable_size(self->stream) - self->attr.tlength +
- buffer_size;
- if(len < update_size)
+ buffer_size = device->UpdateSize * device->NumUpdates * frame_size;
+
+ while(!self->killNow && device->Connected)
+ {
+ len = pa_stream_writable_size(self->stream);
+ if(len < 0)
{
- if(pa_stream_is_corked(self->stream) == 1)
+ ERR("Failed to get writable size: %ld", (long)len);
+ aluHandleDisconnect(device);
+ break;
+ }
+
+ /* Make sure we're going to write at least 2 'periods' (minreqs), in
+ * case the server increased it since starting playback.
+ */
+ buffer_size = maxu(buffer_size, self->attr.minreq*2);
+
+ /* NOTE: This assumes pa_stream_writable_size returns between 0 and
+ * tlength, else there will be more latency than intended.
+ */
+ len = mini(len - (ssize_t)self->attr.tlength, 0) + buffer_size;
+ if(len < self->attr.minreq)
+ {
+ if(pa_stream_is_corked(self->stream))
{
pa_operation *o;
o = pa_stream_cork(self->stream, 0, NULL, NULL);
@@ -826,11 +842,12 @@ static int ALCpulsePlayback_mixerProc(void *ptr)
pa_threaded_mainloop_wait(self->loop);
continue;
}
- len -= len%update_size;
+ len -= len%self->attr.minreq;
while(len > 0)
{
size_t newlen = len;
+ int ret;
void *buf;
pa_free_cb_t free_func = NULL;
@@ -842,10 +859,15 @@ static int ALCpulsePlayback_mixerProc(void *ptr)
aluMixData(device, buf, newlen/frame_size);
- pa_stream_write(self->stream, buf, newlen, free_func, 0, PA_SEEK_RELATIVE);
+ ret = pa_stream_write(self->stream, buf, newlen, free_func, 0, PA_SEEK_RELATIVE);
+ if(ret != PA_OK)
+ {
+ ERR("Failed to write to stream: %d, %s\n", ret, pa_strerror(ret));
+ break;
+ }
len -= newlen;
}
- } while(!self->killNow && device->Connected);
+ }
pa_threaded_mainloop_unlock(self->loop);
return 0;