#include <pulsecore/thread-mq.h>
#include <pulsecore/rtpoll.h>
+#if defined(__NetBSD__) && !defined(SNDCTL_DSP_GETODELAY)
+#include <sys/audioio.h>
+#include <sys/syscall.h>
+#endif
+
#include "oss-util.h"
#include "module-oss-symdef.h"
int mixer_fd;
int mixer_devmask;
- int nfrags, frag_size;
+ int nfrags, frag_size, orig_frag_size;
pa_bool_t use_mmap;
unsigned out_mmap_current, in_mmap_current;
if (u->use_getodelay) {
int arg;
-
+#if defined(__NetBSD__) && !defined(SNDCTL_DSP_GETODELAY)
+#if defined(AUDIO_GETBUFINFO)
+ struct audio_info info;
+ if (syscall(SYS_ioctl, u->fd, AUDIO_GETBUFINFO, &info) < 0) {
+ pa_log_info("Device doesn't support AUDIO_GETBUFINFO: %s", pa_cstrerror(errno));
+ u->use_getodelay = 0;
+ } else {
+ arg = info.play.seek + info.blocksize / 2;
+ r = pa_bytes_to_usec((size_t) arg, &u->sink->sample_spec);
+ }
+#else
+ pa_log_info("System doesn't support AUDIO_GETBUFINFO");
+ u->use_getodelay = 0;
+#endif
+#else
if (ioctl(u->fd, SNDCTL_DSP_GETODELAY, &arg) < 0) {
pa_log_info("Device doesn't support SNDCTL_DSP_GETODELAY: %s", pa_cstrerror(errno));
u->use_getodelay = 0;
} else
r = pa_bytes_to_usec((size_t) arg, &u->sink->sample_spec);
-
+#endif
}
if (!u->use_getodelay && u->use_getospace) {
return r;
}
-
static pa_usec_t io_source_get_latency(struct userdata *u) {
pa_usec_t r = 0;
return 0;
}
-static int sink_get_volume(pa_sink *s);
-static int source_get_volume(pa_source *s);
-
static int unsuspend(struct userdata *u) {
int m;
pa_sample_spec ss, *ss_original;
}
if (u->nfrags >= 2 && u->frag_size >= 1)
- if (pa_oss_set_fragments(u->fd, u->nfrags, u->frag_size) < 0) {
+ if (pa_oss_set_fragments(u->fd, u->nfrags, u->orig_frag_size) < 0) {
pa_log_warn("Resume failed, couldn't set original fragment settings.");
goto fail;
}
build_pollfd(u);
- if (u->sink && u->sink->get_volume)
- u->sink->get_volume(u->sink);
- if (u->source && u->source->get_volume)
- u->source->get_volume(u->source);
+ if (u->sink)
+ pa_sink_get_volume(u->sink, TRUE);
+ if (u->source)
+ pa_source_get_volume(u->source, TRUE);
pa_log_info("Resumed successfully...");
break;
+ case PA_SINK_INVALID_STATE:
case PA_SINK_UNLINKED:
case PA_SINK_INIT:
;
case PA_SOURCE_UNLINKED:
case PA_SOURCE_INIT:
+ case PA_SOURCE_INVALID_STATE:
;
}
return ret;
}
-static int sink_get_volume(pa_sink *s) {
+static void sink_get_volume(pa_sink *s) {
struct userdata *u;
- int r;
pa_assert_se(u = s->userdata);
pa_assert(u->mixer_devmask & (SOUND_MASK_VOLUME|SOUND_MASK_PCM));
if (u->mixer_devmask & SOUND_MASK_VOLUME)
- if ((r = pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_READ_VOLUME, &s->sample_spec, &s->volume)) >= 0)
- return r;
+ if (pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_READ_VOLUME, &s->sample_spec, &s->virtual_volume) >= 0)
+ return;
if (u->mixer_devmask & SOUND_MASK_PCM)
- if ((r = pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_READ_PCM, &s->sample_spec, &s->volume)) >= 0)
- return r;
+ if (pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_READ_PCM, &s->sample_spec, &s->virtual_volume) >= 0)
+ return;
pa_log_info("Device doesn't support reading mixer settings: %s", pa_cstrerror(errno));
- return -1;
}
-static int sink_set_volume(pa_sink *s) {
+static void sink_set_volume(pa_sink *s) {
struct userdata *u;
- int r;
pa_assert_se(u = s->userdata);
pa_assert(u->mixer_devmask & (SOUND_MASK_VOLUME|SOUND_MASK_PCM));
if (u->mixer_devmask & SOUND_MASK_VOLUME)
- if ((r = pa_oss_set_volume(u->mixer_fd, SOUND_MIXER_WRITE_VOLUME, &s->sample_spec, &s->volume)) >= 0)
- return r;
+ if (pa_oss_set_volume(u->mixer_fd, SOUND_MIXER_WRITE_VOLUME, &s->sample_spec, &s->virtual_volume) >= 0)
+ return;
if (u->mixer_devmask & SOUND_MASK_PCM)
- if ((r = pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_WRITE_PCM, &s->sample_spec, &s->volume)) >= 0)
- return r;
+ if (pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_WRITE_PCM, &s->sample_spec, &s->virtual_volume) >= 0)
+ return;
pa_log_info("Device doesn't support writing mixer settings: %s", pa_cstrerror(errno));
- return -1;
}
-static int source_get_volume(pa_source *s) {
+static void source_get_volume(pa_source *s) {
struct userdata *u;
- int r;
pa_assert_se(u = s->userdata);
pa_assert(u->mixer_devmask & (SOUND_MASK_IGAIN|SOUND_MASK_RECLEV));
if (u->mixer_devmask & SOUND_MASK_IGAIN)
- if ((r = pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_READ_IGAIN, &s->sample_spec, &s->volume)) >= 0)
- return r;
+ if (pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_READ_IGAIN, &s->sample_spec, &s->virtual_volume) >= 0)
+ return;
if (u->mixer_devmask & SOUND_MASK_RECLEV)
- if ((r = pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_READ_RECLEV, &s->sample_spec, &s->volume)) >= 0)
- return r;
+ if (pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_READ_RECLEV, &s->sample_spec, &s->virtual_volume) >= 0)
+ return;
pa_log_info("Device doesn't support reading mixer settings: %s", pa_cstrerror(errno));
- return -1;
}
-static int source_set_volume(pa_source *s) {
+static void source_set_volume(pa_source *s) {
struct userdata *u;
- int r;
pa_assert_se(u = s->userdata);
pa_assert(u->mixer_devmask & (SOUND_MASK_IGAIN|SOUND_MASK_RECLEV));
if (u->mixer_devmask & SOUND_MASK_IGAIN)
- if ((r = pa_oss_set_volume(u->mixer_fd, SOUND_MIXER_WRITE_IGAIN, &s->sample_spec, &s->volume)) >= 0)
- return r;
+ if (pa_oss_set_volume(u->mixer_fd, SOUND_MIXER_WRITE_IGAIN, &s->sample_spec, &s->virtual_volume) >= 0)
+ return;
if (u->mixer_devmask & SOUND_MASK_RECLEV)
- if ((r = pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_WRITE_RECLEV, &s->sample_spec, &s->volume)) >= 0)
- return r;
+ if (pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_WRITE_RECLEV, &s->sample_spec, &s->virtual_volume) >= 0)
+ return;
pa_log_info("Device doesn't support writing mixer settings: %s", pa_cstrerror(errno));
- return -1;
}
static void thread_func(void *userdata) {
/* pa_log("loop"); */
- if (PA_SINK_IS_OPENED(u->sink->thread_info.state))
+ if (u->sink && PA_SINK_IS_OPENED(u->sink->thread_info.state))
if (u->sink->thread_info.rewind_requested)
pa_sink_process_rewind(u->sink, 0);
struct userdata *u = NULL;
const char *dev;
int fd = -1;
- int nfrags, frag_size;
+ int nfrags, orig_frag_size, frag_size;
int mode, caps;
pa_bool_t record = TRUE, playback = TRUE, use_mmap = TRUE;
pa_sample_spec ss;
pa_log_info("Device opened in %s mode.", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR"));
+ orig_frag_size = frag_size;
if (nfrags >= 2 && frag_size >= 1)
if (pa_oss_set_fragments(fd, nfrags, frag_size) < 0)
goto fail;
u->device_name = pa_xstrdup(dev);
u->in_nfrags = u->out_nfrags = (uint32_t) (u->nfrags = nfrags);
u->out_fragment_size = u->in_fragment_size = (uint32_t) (u->frag_size = frag_size);
+ u->orig_frag_size = orig_frag_size;
u->use_mmap = use_mmap;
u->rtpoll = pa_rtpoll_new();
pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
u->sink->flags |= PA_SINK_HW_VOLUME_CTRL;
u->sink->get_volume = sink_get_volume;
u->sink->set_volume = sink_set_volume;
+ u->sink->n_volume_steps = 101;
do_close = FALSE;
}
u->source->flags |= PA_SOURCE_HW_VOLUME_CTRL;
u->source->get_volume = source_get_volume;
u->source->set_volume = source_set_volume;
+ u->source->n_volume_steps = 101;
do_close = FALSE;
}
}