wineoss.drv: Only write as much data as will fit into the OSS buffer.

This commit is contained in:
Andrew Eikum 2011-10-11 15:31:28 -05:00 committed by Alexandre Julliard
parent 296b795655
commit 1ed42313a9
1 changed files with 31 additions and 16 deletions

View File

@ -1253,51 +1253,66 @@ static void oss_silence_buffer(ACImpl *This, BYTE *buf, UINT32 frames)
static void oss_write_data(ACImpl *This) static void oss_write_data(ACImpl *This)
{ {
ssize_t written; ssize_t written_bytes;
UINT32 written_frames; UINT32 written_frames;
size_t to_write; size_t to_write_frames, to_write_bytes;
audio_buf_info bi;
BYTE *buf = BYTE *buf =
This->local_buffer + (This->lcl_offs_frames * This->fmt->nBlockAlign); This->local_buffer + (This->lcl_offs_frames * This->fmt->nBlockAlign);
if(This->lcl_offs_frames + This->held_frames > This->bufsize_frames) if(This->lcl_offs_frames + This->held_frames > This->bufsize_frames)
to_write = This->bufsize_frames - This->lcl_offs_frames; to_write_frames = This->bufsize_frames - This->lcl_offs_frames;
else else
to_write = This->held_frames; to_write_frames = This->held_frames;
to_write_bytes = to_write_frames * This->fmt->nBlockAlign;
if(ioctl(This->fd, SNDCTL_DSP_GETOSPACE, &bi) < 0){
WARN("GETOSPACE failed: %d (%s)\n", errno, strerror(errno));
return;
}
if(bi.bytes < to_write_bytes){
to_write_frames = bi.bytes / This->fmt->nBlockAlign;
to_write_bytes = to_write_frames * This->fmt->nBlockAlign;
}
if(This->session->mute) if(This->session->mute)
oss_silence_buffer(This, buf, to_write); oss_silence_buffer(This, buf, to_write_frames);
written = write(This->fd, buf, to_write * This->fmt->nBlockAlign); written_bytes = write(This->fd, buf, to_write_bytes);
if(written < 0){ if(written_bytes < 0){
/* EAGAIN is OSS buffer full, log that too */ /* EAGAIN is OSS buffer full, log that too */
WARN("write failed: %d (%s)\n", errno, strerror(errno)); WARN("write failed: %d (%s)\n", errno, strerror(errno));
return; return;
} }
written_frames = written / This->fmt->nBlockAlign; written_frames = written_bytes / This->fmt->nBlockAlign;
This->lcl_offs_frames += written_frames; This->lcl_offs_frames += written_frames;
This->lcl_offs_frames %= This->bufsize_frames; This->lcl_offs_frames %= This->bufsize_frames;
This->held_frames -= written_frames; This->held_frames -= written_frames;
This->inbuf_frames += written_frames; This->inbuf_frames += written_frames;
if(written_frames < to_write){ if(written_frames < to_write_frames){
/* OSS buffer probably full */ /* OSS buffer probably full */
return; return;
} }
if(This->held_frames){ bi.bytes -= written_bytes;
if(This->held_frames && bi.bytes >= This->fmt->nBlockAlign){
/* wrapped and have some data back at the start to write */ /* wrapped and have some data back at the start to write */
if(This->session->mute) to_write_frames = bi.bytes / This->fmt->nBlockAlign;
oss_silence_buffer(This, This->local_buffer, This->held_frames); to_write_bytes = to_write_frames * This->fmt->nBlockAlign;
written = write(This->fd, This->local_buffer, if(This->session->mute)
This->held_frames * This->fmt->nBlockAlign); oss_silence_buffer(This, This->local_buffer, to_write_frames);
if(written < 0){
written_bytes = write(This->fd, This->local_buffer, to_write_bytes);
if(written_bytes < 0){
WARN("write failed: %d (%s)\n", errno, strerror(errno)); WARN("write failed: %d (%s)\n", errno, strerror(errno));
return; return;
} }
written_frames = written / This->fmt->nBlockAlign; written_frames = written_bytes / This->fmt->nBlockAlign;
This->lcl_offs_frames += written_frames; This->lcl_offs_frames += written_frames;
This->lcl_offs_frames %= This->bufsize_frames; This->lcl_offs_frames %= This->bufsize_frames;