[pulseaudio-commits] r1194 - in /trunk/src/modules: module-alsa-sink.c module-alsa-source.c
svnmailer-noreply at 0pointer.de
svnmailer-noreply at 0pointer.de
Fri Aug 11 08:08:13 PDT 2006
Author: lennart
Date: Fri Aug 11 17:08:09 2006
New Revision: 1194
URL: http://0pointer.de/cgi-bin/viewcvs.cgi?rev=1194&root=pulseaudio&view=rev
Log:
ALSA: handle write()/read() errors properly by unloading the driver module. This should fix problems when removing USB audio device while pulseaudio is running.
Modified:
trunk/src/modules/module-alsa-sink.c
trunk/src/modules/module-alsa-source.c
Modified: trunk/src/modules/module-alsa-sink.c
URL: http://0pointer.de/cgi-bin/viewcvs.cgi/trunk/src/modules/module-alsa-sink.c?rev=1194&root=pulseaudio&r1=1193&r2=1194&view=diff
==============================================================================
--- trunk/src/modules/module-alsa-sink.c (original)
+++ trunk/src/modules/module-alsa-sink.c Fri Aug 11 17:08:09 2006
@@ -96,13 +96,49 @@
(u->sink ? pa_idxset_size(u->sink->monitor_source->outputs) : 0));
}
-static void xrun_recovery(struct userdata *u) {
+static void clear_up(struct userdata *u) {
assert(u);
-
- pa_log(__FILE__": *** ALSA-XRUN (playback) ***");
-
- if (snd_pcm_prepare(u->pcm_handle) < 0)
- pa_log(__FILE__": snd_pcm_prepare() failed");
+
+ if (u->sink) {
+ pa_sink_disconnect(u->sink);
+ pa_sink_unref(u->sink);
+ u->sink = NULL;
+ }
+
+ if (u->pcm_fdl)
+ pa_alsa_fdlist_free(u->pcm_fdl);
+ if (u->mixer_fdl)
+ pa_alsa_fdlist_free(u->mixer_fdl);
+
+ u->pcm_fdl = u->mixer_fdl = NULL;
+
+ if (u->mixer_handle) {
+ snd_mixer_close(u->mixer_handle);
+ u->mixer_handle = NULL;
+ }
+
+ if (u->pcm_handle) {
+ snd_pcm_drop(u->pcm_handle);
+ snd_pcm_close(u->pcm_handle);
+ u->pcm_handle = NULL;
+ }
+}
+
+static int xrun_recovery(struct userdata *u) {
+ int ret;
+ assert(u);
+
+ pa_log_info(__FILE__": *** ALSA-XRUN (playback) ***");
+
+ if ((ret = snd_pcm_prepare(u->pcm_handle)) < 0) {
+ pa_log(__FILE__": snd_pcm_prepare() failed: %s", snd_strerror(-ret));
+
+ clear_up(u);
+ pa_module_unload_request(u->module);
+ return -1;
+ }
+
+ return ret;
}
static void do_write(struct userdata *u) {
@@ -130,11 +166,16 @@
return;
if (frames == -EPIPE) {
- xrun_recovery(u);
+ if (xrun_recovery(u) < 0)
+ return;
+
continue;
}
- pa_log(__FILE__": snd_pcm_writei() failed: %s", snd_strerror(frames));
+ pa_log(__FILE__": snd_pcm_writei() failed: %s", snd_strerror(-frames));
+
+ clear_up(u);
+ pa_module_unload_request(u->module);
return;
}
@@ -159,7 +200,8 @@
assert(u);
if (snd_pcm_state(u->pcm_handle) == SND_PCM_STATE_XRUN)
- xrun_recovery(u);
+ if (xrun_recovery(u) < 0)
+ return;
do_write(u);
}
@@ -480,25 +522,9 @@
if (!(u = m->userdata))
return;
-
- if (u->sink) {
- pa_sink_disconnect(u->sink);
- pa_sink_unref(u->sink);
- }
-
- if (u->pcm_fdl)
- pa_alsa_fdlist_free(u->pcm_fdl);
- if (u->mixer_fdl)
- pa_alsa_fdlist_free(u->mixer_fdl);
-
- if (u->mixer_handle)
- snd_mixer_close(u->mixer_handle);
-
- if (u->pcm_handle) {
- snd_pcm_drop(u->pcm_handle);
- snd_pcm_close(u->pcm_handle);
- }
-
+
+ clear_up(u);
+
if (u->memchunk.memblock)
pa_memblock_unref(u->memchunk.memblock);
if (u->silence.memblock)
Modified: trunk/src/modules/module-alsa-source.c
URL: http://0pointer.de/cgi-bin/viewcvs.cgi/trunk/src/modules/module-alsa-source.c?rev=1194&root=pulseaudio&r1=1193&r2=1194&view=diff
==============================================================================
--- trunk/src/modules/module-alsa-source.c (original)
+++ trunk/src/modules/module-alsa-source.c Fri Aug 11 17:08:09 2006
@@ -96,13 +96,50 @@
(u->source ? pa_idxset_size(u->source->outputs) : 0));
}
-static void xrun_recovery(struct userdata *u) {
+static void clear_up(struct userdata *u) {
assert(u);
-
- pa_log(__FILE__": *** ALSA-XRUN (capture) ***");
-
- if (snd_pcm_prepare(u->pcm_handle) < 0)
- pa_log(__FILE__": snd_pcm_prepare() failed");
+
+ if (u->source) {
+ pa_source_disconnect(u->source);
+ pa_source_unref(u->source);
+ u->source = NULL;
+ }
+
+ if (u->pcm_fdl)
+ pa_alsa_fdlist_free(u->pcm_fdl);
+ if (u->mixer_fdl)
+ pa_alsa_fdlist_free(u->mixer_fdl);
+
+ u->pcm_fdl = u->mixer_fdl = NULL;
+
+ if (u->mixer_handle) {
+ snd_mixer_close(u->mixer_handle);
+ u->mixer_handle = NULL;
+ }
+
+ if (u->pcm_handle) {
+ snd_pcm_drop(u->pcm_handle);
+ snd_pcm_close(u->pcm_handle);
+ u->pcm_handle = NULL;
+ }
+}
+
+static int xrun_recovery(struct userdata *u) {
+ int ret;
+ assert(u);
+
+ pa_log_info(__FILE__": *** ALSA-XRUN (capture) ***");
+
+ if ((ret = snd_pcm_prepare(u->pcm_handle)) < 0) {
+ pa_log(__FILE__": snd_pcm_prepare() failed: %s", snd_strerror(-ret));
+
+ clear_up(u);
+ pa_module_unload_request(u->module);
+
+ return -1;
+ }
+
+ return 0;
}
static void do_read(struct userdata *u) {
@@ -131,11 +168,16 @@
return;
if (frames == -EPIPE) {
- xrun_recovery(u);
+ if (xrun_recovery(u) < 0)
+ return;
+
continue;
}
- pa_log(__FILE__": snd_pcm_readi() failed: %s", pa_cstrerror(-frames));
+ pa_log(__FILE__": snd_pcm_readi() failed: %s", snd_strerror(-frames));
+
+ clear_up(u);
+ pa_module_unload_request(u->module);
return;
}
@@ -164,7 +206,8 @@
assert(u);
if (snd_pcm_state(u->pcm_handle) == SND_PCM_STATE_XRUN)
- xrun_recovery(u);
+ if (xrun_recovery(u) < 0)
+ return;
do_read(u);
}
@@ -182,6 +225,7 @@
u->source->get_hw_volume(u->source);
if (u->source->get_hw_mute)
u->source->get_hw_mute(u->source);
+
pa_subscription_post(u->source->core,
PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE,
u->source->index);
@@ -468,24 +512,8 @@
if (!(u = m->userdata))
return;
-
- if (u->source) {
- pa_source_disconnect(u->source);
- pa_source_unref(u->source);
- }
-
- if (u->pcm_fdl)
- pa_alsa_fdlist_free(u->pcm_fdl);
- if (u->mixer_fdl)
- pa_alsa_fdlist_free(u->mixer_fdl);
-
- if (u->mixer_handle)
- snd_mixer_close(u->mixer_handle);
-
- if (u->pcm_handle) {
- snd_pcm_drop(u->pcm_handle);
- snd_pcm_close(u->pcm_handle);
- }
+
+ clear_up(u);
if (u->memchunk.memblock)
pa_memblock_unref(u->memchunk.memblock);
More information about the pulseaudio-commits
mailing list