mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-05 13:29:57 -05:00
oss: support hot-unplug on FreeBSD
Patch by Hans Petter Selasky <hselasky@FreeBSD.org> ref: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=194727#c27 Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/277>
This commit is contained in:
parent
a9d1afbefd
commit
ef8fa7c997
2 changed files with 67 additions and 52 deletions
|
|
@ -126,6 +126,8 @@ struct userdata {
|
||||||
|
|
||||||
int nfrags, frag_size, orig_frag_size;
|
int nfrags, frag_size, orig_frag_size;
|
||||||
|
|
||||||
|
bool shutdown;
|
||||||
|
|
||||||
bool use_mmap;
|
bool use_mmap;
|
||||||
unsigned out_mmap_current, in_mmap_current;
|
unsigned out_mmap_current, in_mmap_current;
|
||||||
void *in_mmap, *out_mmap;
|
void *in_mmap, *out_mmap;
|
||||||
|
|
@ -843,14 +845,10 @@ static void sink_set_volume(pa_sink *s) {
|
||||||
pa_assert(u->mixer_devmask & (SOUND_MASK_VOLUME|SOUND_MASK_PCM));
|
pa_assert(u->mixer_devmask & (SOUND_MASK_VOLUME|SOUND_MASK_PCM));
|
||||||
|
|
||||||
if (u->mixer_devmask & SOUND_MASK_VOLUME)
|
if (u->mixer_devmask & SOUND_MASK_VOLUME)
|
||||||
if (pa_oss_set_volume(u->mixer_fd, SOUND_MIXER_WRITE_VOLUME, &s->sample_spec, &s->real_volume) >= 0)
|
(void) pa_oss_set_volume(u->mixer_fd, SOUND_MIXER_WRITE_VOLUME, &s->sample_spec, &s->real_volume);
|
||||||
return;
|
|
||||||
|
|
||||||
if (u->mixer_devmask & SOUND_MASK_PCM)
|
if (u->mixer_devmask & SOUND_MASK_PCM)
|
||||||
if (pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_WRITE_PCM, &s->sample_spec, &s->real_volume) >= 0)
|
(void) pa_oss_set_volume(u->mixer_fd, SOUND_MIXER_WRITE_PCM, &s->sample_spec, &s->real_volume);
|
||||||
return;
|
|
||||||
|
|
||||||
pa_log_info("Device doesn't support writing mixer settings: %s", pa_cstrerror(errno));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void source_get_volume(pa_source *s) {
|
static void source_get_volume(pa_source *s) {
|
||||||
|
|
@ -858,7 +856,7 @@ static void source_get_volume(pa_source *s) {
|
||||||
|
|
||||||
pa_assert_se(u = s->userdata);
|
pa_assert_se(u = s->userdata);
|
||||||
|
|
||||||
pa_assert(u->mixer_devmask & (SOUND_MASK_IGAIN|SOUND_MASK_RECLEV));
|
pa_assert(u->mixer_devmask & (SOUND_MASK_MIC|SOUND_MASK_IGAIN|SOUND_MASK_RECLEV));
|
||||||
|
|
||||||
if (u->mixer_devmask & SOUND_MASK_IGAIN)
|
if (u->mixer_devmask & SOUND_MASK_IGAIN)
|
||||||
if (pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_READ_IGAIN, &s->sample_spec, &s->real_volume) >= 0)
|
if (pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_READ_IGAIN, &s->sample_spec, &s->real_volume) >= 0)
|
||||||
|
|
@ -868,6 +866,10 @@ static void source_get_volume(pa_source *s) {
|
||||||
if (pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_READ_RECLEV, &s->sample_spec, &s->real_volume) >= 0)
|
if (pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_READ_RECLEV, &s->sample_spec, &s->real_volume) >= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (u->mixer_devmask & SOUND_MASK_MIC)
|
||||||
|
if (pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_READ_MIC, &s->sample_spec, &s->real_volume) >= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
pa_log_info("Device doesn't support reading mixer settings: %s", pa_cstrerror(errno));
|
pa_log_info("Device doesn't support reading mixer settings: %s", pa_cstrerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -876,17 +878,16 @@ static void source_set_volume(pa_source *s) {
|
||||||
|
|
||||||
pa_assert_se(u = s->userdata);
|
pa_assert_se(u = s->userdata);
|
||||||
|
|
||||||
pa_assert(u->mixer_devmask & (SOUND_MASK_IGAIN|SOUND_MASK_RECLEV));
|
pa_assert(u->mixer_devmask & (SOUND_MASK_MIC|SOUND_MASK_IGAIN|SOUND_MASK_RECLEV));
|
||||||
|
|
||||||
if (u->mixer_devmask & SOUND_MASK_IGAIN)
|
if (u->mixer_devmask & SOUND_MASK_IGAIN)
|
||||||
if (pa_oss_set_volume(u->mixer_fd, SOUND_MIXER_WRITE_IGAIN, &s->sample_spec, &s->real_volume) >= 0)
|
(void) pa_oss_set_volume(u->mixer_fd, SOUND_MIXER_WRITE_IGAIN, &s->sample_spec, &s->real_volume);
|
||||||
return;
|
|
||||||
|
|
||||||
if (u->mixer_devmask & SOUND_MASK_RECLEV)
|
if (u->mixer_devmask & SOUND_MASK_RECLEV)
|
||||||
if (pa_oss_get_volume(u->mixer_fd, SOUND_MIXER_WRITE_RECLEV, &s->sample_spec, &s->real_volume) >= 0)
|
(void) pa_oss_set_volume(u->mixer_fd, SOUND_MIXER_WRITE_RECLEV, &s->sample_spec, &s->real_volume);
|
||||||
return;
|
|
||||||
|
|
||||||
pa_log_info("Device doesn't support writing mixer settings: %s", pa_cstrerror(errno));
|
if (u->mixer_devmask & SOUND_MASK_MIC)
|
||||||
|
(void) pa_oss_set_volume(u->mixer_fd, SOUND_MIXER_WRITE_MIC, &s->sample_spec, &s->real_volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void thread_func(void *userdata) {
|
static void thread_func(void *userdata) {
|
||||||
|
|
@ -1127,15 +1128,22 @@ static void thread_func(void *userdata) {
|
||||||
pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
|
pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
|
||||||
pollfd->events = (short)
|
pollfd->events = (short)
|
||||||
(((u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state)) ? POLLIN : 0) |
|
(((u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state)) ? POLLIN : 0) |
|
||||||
((u->sink && PA_SINK_IS_OPENED(u->sink->thread_info.state)) ? POLLOUT : 0));
|
((u->sink && PA_SINK_IS_OPENED(u->sink->thread_info.state)) ? POLLOUT : 0) |
|
||||||
|
POLLHUP);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hmm, nothing to do. Let's sleep */
|
/* set a watchdog timeout of one second */
|
||||||
if ((ret = pa_rtpoll_run(u->rtpoll)) < 0)
|
pa_rtpoll_set_timer_relative(u->rtpoll, 1000000);
|
||||||
goto fail;
|
|
||||||
|
|
||||||
if (ret == 0)
|
/* Hmm, nothing to do. Let's sleep */
|
||||||
goto finish;
|
if ((ret = pa_rtpoll_run(u->rtpoll)) < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for shutdown */
|
||||||
|
if (u->shutdown) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
if (u->rtpoll_item) {
|
if (u->rtpoll_item) {
|
||||||
struct pollfd *pollfd;
|
struct pollfd *pollfd;
|
||||||
|
|
@ -1150,6 +1158,16 @@ static void thread_func(void *userdata) {
|
||||||
revents = pollfd->revents;
|
revents = pollfd->revents;
|
||||||
} else
|
} else
|
||||||
revents = 0;
|
revents = 0;
|
||||||
|
|
||||||
|
/* check for mixer shutdown, if any */
|
||||||
|
if ((revents & (POLLOUT | POLLIN)) == 0) {
|
||||||
|
int mixer_fd = u->mixer_fd;
|
||||||
|
int devmask;
|
||||||
|
if (mixer_fd > -1 && ioctl(mixer_fd, SOUND_MIXER_READ_DEVMASK, &devmask) < 0) {
|
||||||
|
pa_log("Mixer shutdown.");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
|
@ -1157,9 +1175,6 @@ fail:
|
||||||
* processing messages until we received PA_MESSAGE_SHUTDOWN */
|
* processing messages until we received PA_MESSAGE_SHUTDOWN */
|
||||||
pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
|
pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL);
|
||||||
pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN);
|
pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN);
|
||||||
|
|
||||||
finish:
|
|
||||||
pa_log_debug("Thread shutting down");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int pa__init(pa_module*m) {
|
int pa__init(pa_module*m) {
|
||||||
|
|
@ -1448,7 +1463,7 @@ int pa__init(pa_module*m) {
|
||||||
do_close = false;
|
do_close = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (u->source && (u->mixer_devmask & (SOUND_MASK_RECLEV|SOUND_MASK_IGAIN))) {
|
if (u->source && (u->mixer_devmask & (SOUND_MASK_MIC|SOUND_MASK_RECLEV|SOUND_MASK_IGAIN))) {
|
||||||
pa_log_debug("Found hardware mixer track for recording.");
|
pa_log_debug("Found hardware mixer track for recording.");
|
||||||
pa_source_set_get_volume_callback(u->source, source_get_volume);
|
pa_source_set_get_volume_callback(u->source, source_get_volume);
|
||||||
pa_source_set_set_volume_callback(u->source, source_set_volume);
|
pa_source_set_set_volume_callback(u->source, source_set_volume);
|
||||||
|
|
@ -1533,6 +1548,7 @@ void pa__done(pa_module*m) {
|
||||||
pa_source_unlink(u->source);
|
pa_source_unlink(u->source);
|
||||||
|
|
||||||
if (u->thread) {
|
if (u->thread) {
|
||||||
|
u->shutdown = true;
|
||||||
pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
|
pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
|
||||||
pa_thread_free(u->thread);
|
pa_thread_free(u->thread);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@
|
||||||
#include "oss-util.h"
|
#include "oss-util.h"
|
||||||
|
|
||||||
int pa_oss_open(const char *device, int *mode, int* pcaps) {
|
int pa_oss_open(const char *device, int *mode, int* pcaps) {
|
||||||
|
static const int nonblock_io = 1;
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
int caps;
|
int caps;
|
||||||
char *t;
|
char *t;
|
||||||
|
|
@ -89,6 +90,10 @@ int pa_oss_open(const char *device, int *mode, int* pcaps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
success:
|
success:
|
||||||
|
if (ioctl(fd, FIONBIO, &nonblock_io) < 0) {
|
||||||
|
pa_log("FIONBIO: %s", pa_cstrerror(errno));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
t = pa_sprintf_malloc(
|
t = pa_sprintf_malloc(
|
||||||
"%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
|
"%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
|
||||||
|
|
@ -295,41 +300,35 @@ int pa_oss_set_volume(int fd, unsigned long mixer, const pa_sample_spec *ss, con
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_device_number(const char *dev) {
|
static int get_device_number(const char *dev) {
|
||||||
const char *p, *e;
|
const char *p;
|
||||||
|
const char *e;
|
||||||
char *rp = NULL;
|
char *rp = NULL;
|
||||||
int r;
|
int r = -1;
|
||||||
|
|
||||||
if (!(p = rp = pa_readlink(dev))) {
|
if (!(p = rp = pa_readlink(dev))) {
|
||||||
#ifdef ENOLINK
|
if (errno != EINVAL && errno != ENOLINK)
|
||||||
if (errno != EINVAL && errno != ENOLINK) {
|
return -2;
|
||||||
#else
|
|
||||||
if (errno != EINVAL) {
|
|
||||||
#endif
|
|
||||||
r = -1;
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
p = dev;
|
p = dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((e = strrchr(p, '/')))
|
/* find the last forward slash */
|
||||||
p = e+1;
|
while ((e = strrchr(p, '/')))
|
||||||
|
p = e + 1;
|
||||||
if (p == 0) {
|
|
||||||
r = 0;
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
p = strchr(p, 0) -1;
|
|
||||||
|
|
||||||
|
/* collect unit number at end, if any */
|
||||||
|
while (*p) {
|
||||||
if (*p >= '0' && *p <= '9') {
|
if (*p >= '0' && *p <= '9') {
|
||||||
r = *p - '0';
|
if (r < 0)
|
||||||
goto finish;
|
r = 0;
|
||||||
|
else
|
||||||
|
r *= 10;
|
||||||
|
r += *p - '0';
|
||||||
|
} else {
|
||||||
|
r = -1;
|
||||||
|
}
|
||||||
|
p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = -1;
|
|
||||||
|
|
||||||
finish:
|
|
||||||
pa_xfree(rp);
|
pa_xfree(rp);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
@ -339,7 +338,7 @@ int pa_oss_get_hw_description(const char *dev, char *name, size_t l) {
|
||||||
int n, r = -1;
|
int n, r = -1;
|
||||||
int b = 0;
|
int b = 0;
|
||||||
|
|
||||||
if ((n = get_device_number(dev)) < 0)
|
if ((n = get_device_number(dev)) == -2)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (!(f = pa_fopen_cloexec("/dev/sndstat", "r")) &&
|
if (!(f = pa_fopen_cloexec("/dev/sndstat", "r")) &&
|
||||||
|
|
@ -405,10 +404,10 @@ int pa_oss_open_mixer_for_device(const char *device) {
|
||||||
char *fn;
|
char *fn;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
if ((n = get_device_number(device)) < 0)
|
if ((n = get_device_number(device)) == -2)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (n == 0)
|
if (n == -1)
|
||||||
if ((fd = open_mixer("/dev/mixer")) >= 0)
|
if ((fd = open_mixer("/dev/mixer")) >= 0)
|
||||||
return fd;
|
return fd;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue