Loading audio/ossaudio.c +96 −176 Original line number Diff line number Diff line Loading @@ -40,19 +40,15 @@ typedef struct OSSVoiceOut { HWVoiceOut hw; void *pcm_buf; int fd; int wpos; int nfrags; int fragsize; int mmapped; int pending; Audiodev *dev; } OSSVoiceOut; typedef struct OSSVoiceIn { HWVoiceIn hw; void *pcm_buf; int fd; int nfrags; int fragsize; Loading Loading @@ -371,98 +367,87 @@ static int oss_open(int in, struct oss_params *req, audsettings *as, return -1; } static void oss_write_pending (OSSVoiceOut *oss) static size_t oss_get_available_bytes(OSSVoiceOut *oss) { HWVoiceOut *hw = &oss->hw; int err; struct count_info cntinfo; assert(oss->mmapped); if (oss->mmapped) { return; err = ioctl(oss->fd, SNDCTL_DSP_GETOPTR, &cntinfo); if (err < 0) { oss_logerr(errno, "SNDCTL_DSP_GETOPTR failed\n"); return 0; } while (oss->pending) { int samples_written; ssize_t bytes_written; int samples_till_end = hw->samples - oss->wpos; int samples_to_write = MIN (oss->pending, samples_till_end); int bytes_to_write = samples_to_write << hw->info.shift; void *pcm = advance (oss->pcm_buf, oss->wpos << hw->info.shift); return audio_ring_dist(cntinfo.ptr, oss->hw.pos_emul, oss->hw.size_emul); } bytes_written = write (oss->fd, pcm, bytes_to_write); if (bytes_written < 0) { if (errno != EAGAIN) { oss_logerr (errno, "failed to write %d bytes\n", bytes_to_write); static void *oss_get_buffer_out(HWVoiceOut *hw, size_t *size) { OSSVoiceOut *oss = (OSSVoiceOut *) hw; if (oss->mmapped) { *size = MIN(oss_get_available_bytes(oss), hw->size_emul - hw->pos_emul); return hw->buf_emul + hw->pos_emul; } else { return audio_generic_get_buffer_out(hw, size); } break; } if (bytes_written & hw->info.align) { dolog ("misaligned write asked for %d, but got %zd\n", bytes_to_write, bytes_written); return; } static size_t oss_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size) { OSSVoiceOut *oss = (OSSVoiceOut *) hw; if (oss->mmapped) { assert(buf == hw->buf_emul + hw->pos_emul && size < hw->size_emul); samples_written = bytes_written >> hw->info.shift; oss->pending -= samples_written; oss->wpos = (oss->wpos + samples_written) % hw->samples; if (bytes_written - bytes_to_write) { break; } hw->pos_emul = (hw->pos_emul + size) % hw->size_emul; return size; } else { return audio_generic_put_buffer_out(hw, buf, size); } } static size_t oss_run_out(HWVoiceOut *hw, size_t live) static size_t oss_write(HWVoiceOut *hw, void *buf, size_t len) { OSSVoiceOut *oss = (OSSVoiceOut *) hw; int err; size_t decr; struct audio_buf_info abinfo; struct count_info cntinfo; size_t bufsize; bufsize = hw->samples << hw->info.shift; size_t pos; if (oss->mmapped) { int bytes, pos; size_t total_len; len = MIN(len, oss_get_available_bytes(oss)); err = ioctl (oss->fd, SNDCTL_DSP_GETOPTR, &cntinfo); if (err < 0) { oss_logerr (errno, "SNDCTL_DSP_GETOPTR failed\n"); return 0; } total_len = len; while (len) { size_t to_copy = MIN(len, hw->size_emul - hw->pos_emul); memcpy(hw->buf_emul + hw->pos_emul, buf, to_copy); pos = hw->rpos << hw->info.shift; bytes = audio_ring_dist (cntinfo.ptr, pos, bufsize); decr = MIN (bytes >> hw->info.shift, live); hw->pos_emul = (hw->pos_emul + to_copy) % hw->pos_emul; buf += to_copy; len -= to_copy; } else { err = ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &abinfo); if (err < 0) { oss_logerr (errno, "SNDCTL_DSP_GETOPTR failed\n"); return 0; return total_len; } if (abinfo.bytes > bufsize) { trace_oss_invalid_available_size(abinfo.bytes, bufsize); abinfo.bytes = bufsize; } pos = 0; while (len) { ssize_t bytes_written; void *pcm = advance(buf, pos); if (abinfo.bytes < 0) { trace_oss_invalid_available_size(abinfo.bytes, bufsize); return 0; bytes_written = write(oss->fd, pcm, len); if (bytes_written < 0) { if (errno != EAGAIN) { oss_logerr(errno, "failed to write %zu bytes\n", len); } return pos; } decr = MIN (abinfo.bytes >> hw->info.shift, live); if (!decr) { return 0; pos += bytes_written; if (bytes_written < len) { break; } len -= bytes_written; } decr = audio_pcm_hw_clip_out (hw, oss->pcm_buf, decr, oss->pending); oss->pending += decr; oss_write_pending (oss); return decr; return pos; } static void oss_fini_out (HWVoiceOut *hw) Loading @@ -473,18 +458,13 @@ static void oss_fini_out (HWVoiceOut *hw) ldebug ("oss_fini\n"); oss_anal_close (&oss->fd); if (oss->pcm_buf) { if (oss->mmapped) { err = munmap (oss->pcm_buf, hw->samples << hw->info.shift); if (oss->mmapped && hw->buf_emul) { err = munmap(hw->buf_emul, hw->size_emul); if (err) { oss_logerr(errno, "Failed to unmap buffer %p, size %zu\n", oss->pcm_buf, hw->samples << hw->info.shift); hw->buf_emul, hw->size_emul); } } else { g_free (oss->pcm_buf); } oss->pcm_buf = NULL; hw->buf_emul = NULL; } } Loading Loading @@ -535,19 +515,20 @@ static int oss_init_out(HWVoiceOut *hw, struct audsettings *as, oss->mmapped = 0; if (oopts->has_try_mmap && oopts->try_mmap) { oss->pcm_buf = mmap ( hw->size_emul = hw->samples << hw->info.shift; hw->buf_emul = mmap( NULL, hw->samples << hw->info.shift, hw->size_emul, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 ); if (oss->pcm_buf == MAP_FAILED) { if (hw->buf_emul == MAP_FAILED) { oss_logerr(errno, "Failed to map %zu bytes of DAC\n", hw->samples << hw->info.shift); } else { hw->size_emul); hw->buf_emul = NULL; } else { int err; int trig = 0; if (ioctl (fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { Loading @@ -567,30 +548,16 @@ static int oss_init_out(HWVoiceOut *hw, struct audsettings *as, } if (!oss->mmapped) { err = munmap (oss->pcm_buf, hw->samples << hw->info.shift); err = munmap(hw->buf_emul, hw->size_emul); if (err) { oss_logerr(errno, "Failed to unmap buffer %p size %zu\n", oss->pcm_buf, hw->samples << hw->info.shift); hw->buf_emul, hw->size_emul); } hw->buf_emul = NULL; } } } if (!oss->mmapped) { oss->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift); if (!oss->pcm_buf) { dolog ( "Could not allocate DAC buffer (%zu samples, each %d bytes)\n", hw->samples, 1 << hw->info.shift ); oss_anal_close (&fd); return -1; } } oss->fd = fd; oss->dev = dev; return 0; Loading Loading @@ -618,7 +585,7 @@ static int oss_ctl_out (HWVoiceOut *hw, int cmd, ...) return 0; } audio_pcm_info_clear_buf (&hw->info, oss->pcm_buf, hw->samples); audio_pcm_info_clear_buf(&hw->info, hw->buf_emul, hw->samples); trig = PCM_ENABLE_OUTPUT; if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { oss_logerr ( Loading Loading @@ -692,13 +659,6 @@ static int oss_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) } hw->samples = (obt.nfrags * obt.fragsize) >> hw->info.shift; oss->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift); if (!oss->pcm_buf) { dolog("Could not allocate ADC buffer (%zu samples, each %d bytes)\n", hw->samples, 1 << hw->info.shift); oss_anal_close (&fd); return -1; } oss->fd = fd; oss->dev = dev; Loading @@ -710,78 +670,36 @@ static void oss_fini_in (HWVoiceIn *hw) OSSVoiceIn *oss = (OSSVoiceIn *) hw; oss_anal_close (&oss->fd); g_free(oss->pcm_buf); oss->pcm_buf = NULL; } static size_t oss_run_in(HWVoiceIn *hw) static size_t oss_read(HWVoiceIn *hw, void *buf, size_t len) { OSSVoiceIn *oss = (OSSVoiceIn *) hw; int hwshift = hw->info.shift; int i; size_t live = audio_pcm_hw_get_live_in (hw); size_t dead = hw->samples - live; size_t read_samples = 0; struct { size_t add; size_t len; } bufs[2] = { { .add = hw->wpos, .len = 0 }, { .add = 0, .len = 0 } }; if (!dead) { return 0; } size_t pos = 0; if (hw->wpos + dead > hw->samples) { bufs[0].len = (hw->samples - hw->wpos) << hwshift; bufs[1].len = (dead - (hw->samples - hw->wpos)) << hwshift; } else { bufs[0].len = dead << hwshift; } for (i = 0; i < 2; ++i) { while (len) { ssize_t nread; if (bufs[i].len) { void *p = advance (oss->pcm_buf, bufs[i].add << hwshift); nread = read (oss->fd, p, bufs[i].len); void *dst = advance(buf, pos); nread = read(oss->fd, dst, len); if (nread > 0) { if (nread & hw->info.align) { dolog("warning: Misaligned read %zd (requested %zu), " "alignment %d\n", nread, bufs[i].add << hwshift, hw->info.align + 1); } read_samples += nread >> hwshift; hw->conv (hw->conv_buf + bufs[i].add, p, nread >> hwshift); } if (bufs[i].len - nread) { if (nread == -1) { switch (errno) { case EINTR: case EAGAIN: break; default: oss_logerr( errno, "Failed to read %zu bytes of audio (to %p)\n", bufs[i].len, p ); break; } } oss_logerr(errno, "Failed to read %zu bytes of audio (to %p)\n", len, dst); break; } } pos += nread; len -= nread; } hw->wpos = (hw->wpos + read_samples) % hw->samples; return read_samples; return pos; } static int oss_ctl_in (HWVoiceIn *hw, int cmd, ...) Loading Loading @@ -845,12 +763,14 @@ static void oss_audio_fini (void *opaque) static struct audio_pcm_ops oss_pcm_ops = { .init_out = oss_init_out, .fini_out = oss_fini_out, .run_out = oss_run_out, .write = oss_write, .get_buffer_out = oss_get_buffer_out, .put_buffer_out = oss_put_buffer_out, .ctl_out = oss_ctl_out, .init_in = oss_init_in, .fini_in = oss_fini_in, .run_in = oss_run_in, .read = oss_read, .ctl_in = oss_ctl_in }; Loading Loading
audio/ossaudio.c +96 −176 Original line number Diff line number Diff line Loading @@ -40,19 +40,15 @@ typedef struct OSSVoiceOut { HWVoiceOut hw; void *pcm_buf; int fd; int wpos; int nfrags; int fragsize; int mmapped; int pending; Audiodev *dev; } OSSVoiceOut; typedef struct OSSVoiceIn { HWVoiceIn hw; void *pcm_buf; int fd; int nfrags; int fragsize; Loading Loading @@ -371,98 +367,87 @@ static int oss_open(int in, struct oss_params *req, audsettings *as, return -1; } static void oss_write_pending (OSSVoiceOut *oss) static size_t oss_get_available_bytes(OSSVoiceOut *oss) { HWVoiceOut *hw = &oss->hw; int err; struct count_info cntinfo; assert(oss->mmapped); if (oss->mmapped) { return; err = ioctl(oss->fd, SNDCTL_DSP_GETOPTR, &cntinfo); if (err < 0) { oss_logerr(errno, "SNDCTL_DSP_GETOPTR failed\n"); return 0; } while (oss->pending) { int samples_written; ssize_t bytes_written; int samples_till_end = hw->samples - oss->wpos; int samples_to_write = MIN (oss->pending, samples_till_end); int bytes_to_write = samples_to_write << hw->info.shift; void *pcm = advance (oss->pcm_buf, oss->wpos << hw->info.shift); return audio_ring_dist(cntinfo.ptr, oss->hw.pos_emul, oss->hw.size_emul); } bytes_written = write (oss->fd, pcm, bytes_to_write); if (bytes_written < 0) { if (errno != EAGAIN) { oss_logerr (errno, "failed to write %d bytes\n", bytes_to_write); static void *oss_get_buffer_out(HWVoiceOut *hw, size_t *size) { OSSVoiceOut *oss = (OSSVoiceOut *) hw; if (oss->mmapped) { *size = MIN(oss_get_available_bytes(oss), hw->size_emul - hw->pos_emul); return hw->buf_emul + hw->pos_emul; } else { return audio_generic_get_buffer_out(hw, size); } break; } if (bytes_written & hw->info.align) { dolog ("misaligned write asked for %d, but got %zd\n", bytes_to_write, bytes_written); return; } static size_t oss_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size) { OSSVoiceOut *oss = (OSSVoiceOut *) hw; if (oss->mmapped) { assert(buf == hw->buf_emul + hw->pos_emul && size < hw->size_emul); samples_written = bytes_written >> hw->info.shift; oss->pending -= samples_written; oss->wpos = (oss->wpos + samples_written) % hw->samples; if (bytes_written - bytes_to_write) { break; } hw->pos_emul = (hw->pos_emul + size) % hw->size_emul; return size; } else { return audio_generic_put_buffer_out(hw, buf, size); } } static size_t oss_run_out(HWVoiceOut *hw, size_t live) static size_t oss_write(HWVoiceOut *hw, void *buf, size_t len) { OSSVoiceOut *oss = (OSSVoiceOut *) hw; int err; size_t decr; struct audio_buf_info abinfo; struct count_info cntinfo; size_t bufsize; bufsize = hw->samples << hw->info.shift; size_t pos; if (oss->mmapped) { int bytes, pos; size_t total_len; len = MIN(len, oss_get_available_bytes(oss)); err = ioctl (oss->fd, SNDCTL_DSP_GETOPTR, &cntinfo); if (err < 0) { oss_logerr (errno, "SNDCTL_DSP_GETOPTR failed\n"); return 0; } total_len = len; while (len) { size_t to_copy = MIN(len, hw->size_emul - hw->pos_emul); memcpy(hw->buf_emul + hw->pos_emul, buf, to_copy); pos = hw->rpos << hw->info.shift; bytes = audio_ring_dist (cntinfo.ptr, pos, bufsize); decr = MIN (bytes >> hw->info.shift, live); hw->pos_emul = (hw->pos_emul + to_copy) % hw->pos_emul; buf += to_copy; len -= to_copy; } else { err = ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &abinfo); if (err < 0) { oss_logerr (errno, "SNDCTL_DSP_GETOPTR failed\n"); return 0; return total_len; } if (abinfo.bytes > bufsize) { trace_oss_invalid_available_size(abinfo.bytes, bufsize); abinfo.bytes = bufsize; } pos = 0; while (len) { ssize_t bytes_written; void *pcm = advance(buf, pos); if (abinfo.bytes < 0) { trace_oss_invalid_available_size(abinfo.bytes, bufsize); return 0; bytes_written = write(oss->fd, pcm, len); if (bytes_written < 0) { if (errno != EAGAIN) { oss_logerr(errno, "failed to write %zu bytes\n", len); } return pos; } decr = MIN (abinfo.bytes >> hw->info.shift, live); if (!decr) { return 0; pos += bytes_written; if (bytes_written < len) { break; } len -= bytes_written; } decr = audio_pcm_hw_clip_out (hw, oss->pcm_buf, decr, oss->pending); oss->pending += decr; oss_write_pending (oss); return decr; return pos; } static void oss_fini_out (HWVoiceOut *hw) Loading @@ -473,18 +458,13 @@ static void oss_fini_out (HWVoiceOut *hw) ldebug ("oss_fini\n"); oss_anal_close (&oss->fd); if (oss->pcm_buf) { if (oss->mmapped) { err = munmap (oss->pcm_buf, hw->samples << hw->info.shift); if (oss->mmapped && hw->buf_emul) { err = munmap(hw->buf_emul, hw->size_emul); if (err) { oss_logerr(errno, "Failed to unmap buffer %p, size %zu\n", oss->pcm_buf, hw->samples << hw->info.shift); hw->buf_emul, hw->size_emul); } } else { g_free (oss->pcm_buf); } oss->pcm_buf = NULL; hw->buf_emul = NULL; } } Loading Loading @@ -535,19 +515,20 @@ static int oss_init_out(HWVoiceOut *hw, struct audsettings *as, oss->mmapped = 0; if (oopts->has_try_mmap && oopts->try_mmap) { oss->pcm_buf = mmap ( hw->size_emul = hw->samples << hw->info.shift; hw->buf_emul = mmap( NULL, hw->samples << hw->info.shift, hw->size_emul, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 ); if (oss->pcm_buf == MAP_FAILED) { if (hw->buf_emul == MAP_FAILED) { oss_logerr(errno, "Failed to map %zu bytes of DAC\n", hw->samples << hw->info.shift); } else { hw->size_emul); hw->buf_emul = NULL; } else { int err; int trig = 0; if (ioctl (fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { Loading @@ -567,30 +548,16 @@ static int oss_init_out(HWVoiceOut *hw, struct audsettings *as, } if (!oss->mmapped) { err = munmap (oss->pcm_buf, hw->samples << hw->info.shift); err = munmap(hw->buf_emul, hw->size_emul); if (err) { oss_logerr(errno, "Failed to unmap buffer %p size %zu\n", oss->pcm_buf, hw->samples << hw->info.shift); hw->buf_emul, hw->size_emul); } hw->buf_emul = NULL; } } } if (!oss->mmapped) { oss->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift); if (!oss->pcm_buf) { dolog ( "Could not allocate DAC buffer (%zu samples, each %d bytes)\n", hw->samples, 1 << hw->info.shift ); oss_anal_close (&fd); return -1; } } oss->fd = fd; oss->dev = dev; return 0; Loading Loading @@ -618,7 +585,7 @@ static int oss_ctl_out (HWVoiceOut *hw, int cmd, ...) return 0; } audio_pcm_info_clear_buf (&hw->info, oss->pcm_buf, hw->samples); audio_pcm_info_clear_buf(&hw->info, hw->buf_emul, hw->samples); trig = PCM_ENABLE_OUTPUT; if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { oss_logerr ( Loading Loading @@ -692,13 +659,6 @@ static int oss_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque) } hw->samples = (obt.nfrags * obt.fragsize) >> hw->info.shift; oss->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift); if (!oss->pcm_buf) { dolog("Could not allocate ADC buffer (%zu samples, each %d bytes)\n", hw->samples, 1 << hw->info.shift); oss_anal_close (&fd); return -1; } oss->fd = fd; oss->dev = dev; Loading @@ -710,78 +670,36 @@ static void oss_fini_in (HWVoiceIn *hw) OSSVoiceIn *oss = (OSSVoiceIn *) hw; oss_anal_close (&oss->fd); g_free(oss->pcm_buf); oss->pcm_buf = NULL; } static size_t oss_run_in(HWVoiceIn *hw) static size_t oss_read(HWVoiceIn *hw, void *buf, size_t len) { OSSVoiceIn *oss = (OSSVoiceIn *) hw; int hwshift = hw->info.shift; int i; size_t live = audio_pcm_hw_get_live_in (hw); size_t dead = hw->samples - live; size_t read_samples = 0; struct { size_t add; size_t len; } bufs[2] = { { .add = hw->wpos, .len = 0 }, { .add = 0, .len = 0 } }; if (!dead) { return 0; } size_t pos = 0; if (hw->wpos + dead > hw->samples) { bufs[0].len = (hw->samples - hw->wpos) << hwshift; bufs[1].len = (dead - (hw->samples - hw->wpos)) << hwshift; } else { bufs[0].len = dead << hwshift; } for (i = 0; i < 2; ++i) { while (len) { ssize_t nread; if (bufs[i].len) { void *p = advance (oss->pcm_buf, bufs[i].add << hwshift); nread = read (oss->fd, p, bufs[i].len); void *dst = advance(buf, pos); nread = read(oss->fd, dst, len); if (nread > 0) { if (nread & hw->info.align) { dolog("warning: Misaligned read %zd (requested %zu), " "alignment %d\n", nread, bufs[i].add << hwshift, hw->info.align + 1); } read_samples += nread >> hwshift; hw->conv (hw->conv_buf + bufs[i].add, p, nread >> hwshift); } if (bufs[i].len - nread) { if (nread == -1) { switch (errno) { case EINTR: case EAGAIN: break; default: oss_logerr( errno, "Failed to read %zu bytes of audio (to %p)\n", bufs[i].len, p ); break; } } oss_logerr(errno, "Failed to read %zu bytes of audio (to %p)\n", len, dst); break; } } pos += nread; len -= nread; } hw->wpos = (hw->wpos + read_samples) % hw->samples; return read_samples; return pos; } static int oss_ctl_in (HWVoiceIn *hw, int cmd, ...) Loading Loading @@ -845,12 +763,14 @@ static void oss_audio_fini (void *opaque) static struct audio_pcm_ops oss_pcm_ops = { .init_out = oss_init_out, .fini_out = oss_fini_out, .run_out = oss_run_out, .write = oss_write, .get_buffer_out = oss_get_buffer_out, .put_buffer_out = oss_put_buffer_out, .ctl_out = oss_ctl_out, .init_in = oss_init_in, .fini_in = oss_fini_in, .run_in = oss_run_in, .read = oss_read, .ctl_in = oss_ctl_in }; Loading