mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-04 13:29:59 -05:00
handle hot-remeving of OSS devices properly
git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1221 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
parent
3cfed301d9
commit
4c9c4269bb
2 changed files with 81 additions and 35 deletions
|
|
@ -117,6 +117,42 @@ static void update_usage(struct userdata *u) {
|
|||
(u->source ? pa_idxset_size(u->source->outputs) : 0));
|
||||
}
|
||||
|
||||
static void clear_up(struct userdata *u) {
|
||||
assert(u);
|
||||
|
||||
if (u->sink) {
|
||||
pa_sink_disconnect(u->sink);
|
||||
pa_sink_unref(u->sink);
|
||||
u->sink = NULL;
|
||||
}
|
||||
|
||||
if (u->source) {
|
||||
pa_source_disconnect(u->source);
|
||||
pa_source_unref(u->source);
|
||||
u->source = NULL;
|
||||
}
|
||||
|
||||
if (u->in_mmap && u->in_mmap != MAP_FAILED) {
|
||||
munmap(u->in_mmap, u->in_mmap_length);
|
||||
u->in_mmap = NULL;
|
||||
}
|
||||
|
||||
if (u->out_mmap && u->out_mmap != MAP_FAILED) {
|
||||
munmap(u->out_mmap, u->out_mmap_length);
|
||||
u->out_mmap = NULL;
|
||||
}
|
||||
|
||||
if (u->io_event) {
|
||||
u->core->mainloop->io_free(u->io_event);
|
||||
u->io_event = NULL;
|
||||
}
|
||||
|
||||
if (u->fd >= 0) {
|
||||
close(u->fd);
|
||||
u->fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void out_fill_memblocks(struct userdata *u, unsigned n) {
|
||||
assert(u && u->out_memblocks);
|
||||
|
||||
|
|
@ -154,6 +190,9 @@ static void do_write(struct userdata *u) {
|
|||
|
||||
if (ioctl(u->fd, SNDCTL_DSP_GETOPTR, &info) < 0) {
|
||||
pa_log(__FILE__": SNDCTL_DSP_GETOPTR: %s", pa_cstrerror(errno));
|
||||
|
||||
clear_up(u);
|
||||
pa_module_unload_request(u->module);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -217,6 +256,9 @@ static void do_read(struct userdata *u) {
|
|||
|
||||
if (ioctl(u->fd, SNDCTL_DSP_GETIPTR, &info) < 0) {
|
||||
pa_log(__FILE__": SNDCTL_DSP_GETIPTR: %s", pa_cstrerror(errno));
|
||||
|
||||
clear_up(u);
|
||||
pa_module_unload_request(u->module);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -234,6 +276,12 @@ static void io_callback(pa_mainloop_api *m, pa_io_event *e, PA_GCC_UNUSED int fd
|
|||
struct userdata *u = userdata;
|
||||
assert (u && u->core->mainloop == m && u->io_event == e);
|
||||
|
||||
if (f & PA_IO_EVENT_ERROR) {
|
||||
clear_up(u);
|
||||
pa_module_unload_request(u->module);
|
||||
return;
|
||||
}
|
||||
|
||||
if (f & PA_IO_EVENT_INPUT)
|
||||
do_read(u);
|
||||
if (f & PA_IO_EVENT_OUTPUT)
|
||||
|
|
@ -393,7 +441,7 @@ int pa__init(pa_core *c, pa_module*m) {
|
|||
if ((u->fd = pa_oss_open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), &mode, &caps)) < 0)
|
||||
goto fail;
|
||||
|
||||
if (!(caps & DSP_CAP_MMAP) || !(caps & DSP_CAP_REALTIME) || !(caps & DSP_CAP_TRIGGER)) {
|
||||
if (!(caps & DSP_CAP_MMAP) || !(caps & DSP_CAP_TRIGGER)) {
|
||||
pa_log(__FILE__": OSS device not mmap capable.");
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -539,6 +587,8 @@ void pa__done(pa_core *c, pa_module*m) {
|
|||
if (!(u = m->userdata))
|
||||
return;
|
||||
|
||||
clear_up(u);
|
||||
|
||||
if (u->out_memblocks) {
|
||||
unsigned i;
|
||||
for (i = 0; i < u->out_fragments; i++)
|
||||
|
|
@ -555,27 +605,5 @@ void pa__done(pa_core *c, pa_module*m) {
|
|||
pa_xfree(u->in_memblocks);
|
||||
}
|
||||
|
||||
if (u->in_mmap && u->in_mmap != MAP_FAILED)
|
||||
munmap(u->in_mmap, u->in_mmap_length);
|
||||
|
||||
if (u->out_mmap && u->out_mmap != MAP_FAILED)
|
||||
munmap(u->out_mmap, u->out_mmap_length);
|
||||
|
||||
if (u->sink) {
|
||||
pa_sink_disconnect(u->sink);
|
||||
pa_sink_unref(u->sink);
|
||||
}
|
||||
|
||||
if (u->source) {
|
||||
pa_source_disconnect(u->source);
|
||||
pa_source_unref(u->source);
|
||||
}
|
||||
|
||||
if (u->io_event)
|
||||
u->core->mainloop->io_free(u->io_event);
|
||||
|
||||
if (u->fd >= 0)
|
||||
close(u->fd);
|
||||
|
||||
pa_xfree(u);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,6 +107,27 @@ static void update_usage(struct userdata *u) {
|
|||
(u->source ? pa_idxset_size(u->source->outputs) : 0));
|
||||
}
|
||||
|
||||
static void clear_up(struct userdata *u) {
|
||||
assert(u);
|
||||
|
||||
if (u->sink) {
|
||||
pa_sink_disconnect(u->sink);
|
||||
pa_sink_unref(u->sink);
|
||||
u->sink = NULL;
|
||||
}
|
||||
|
||||
if (u->source) {
|
||||
pa_source_disconnect(u->source);
|
||||
pa_source_unref(u->source);
|
||||
u->source = NULL;
|
||||
}
|
||||
|
||||
if (u->io) {
|
||||
pa_iochannel_free(u->io);
|
||||
u->io = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void do_write(struct userdata *u) {
|
||||
pa_memchunk *memchunk;
|
||||
ssize_t r;
|
||||
|
|
@ -148,6 +169,9 @@ static void do_write(struct userdata *u) {
|
|||
|
||||
if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, memchunk->length)) < 0) {
|
||||
pa_log(__FILE__": write() failed: %s", pa_cstrerror(errno));
|
||||
|
||||
clear_up(u);
|
||||
pa_module_unload_request(u->module);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -199,8 +223,11 @@ static void do_read(struct userdata *u) {
|
|||
assert(memchunk.memblock);
|
||||
if ((r = pa_iochannel_read(u->io, memchunk.memblock->data, memchunk.memblock->length)) < 0) {
|
||||
pa_memblock_unref(memchunk.memblock);
|
||||
if (errno != EAGAIN)
|
||||
if (errno != EAGAIN) {
|
||||
pa_log(__FILE__": read() failed: %s", pa_cstrerror(errno));
|
||||
clear_up(u);
|
||||
pa_module_unload_request(u->module);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -502,21 +529,12 @@ void pa__done(pa_core *c, pa_module*m) {
|
|||
if (!(u = m->userdata))
|
||||
return;
|
||||
|
||||
clear_up(u);
|
||||
|
||||
if (u->memchunk.memblock)
|
||||
pa_memblock_unref(u->memchunk.memblock);
|
||||
if (u->silence.memblock)
|
||||
pa_memblock_unref(u->silence.memblock);
|
||||
|
||||
if (u->sink) {
|
||||
pa_sink_disconnect(u->sink);
|
||||
pa_sink_unref(u->sink);
|
||||
}
|
||||
|
||||
if (u->source) {
|
||||
pa_source_disconnect(u->source);
|
||||
pa_source_unref(u->source);
|
||||
}
|
||||
|
||||
pa_iochannel_free(u->io);
|
||||
pa_xfree(u);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue