Mercurial > audlegacy-plugins
comparison src/alsa/audio.c @ 1727:9d6de95dd7ed
Clean up and rework xrun/suspend handling, and add myself to Copyright holders.
Closes Ubuntu #123571.
author | William Pitcock <nenolod@atheme.org> |
---|---|
date | Tue, 18 Sep 2007 09:47:41 -0500 |
parents | f9856ca98943 |
children | 63feceeb3799 |
comparison
equal
deleted
inserted
replaced
1726:0a689ca43d7a | 1727:9d6de95dd7ed |
---|---|
2 * Copyright (C) 2001-2003 Matthieu Sozeau <mattam@altern.org> | 2 * Copyright (C) 2001-2003 Matthieu Sozeau <mattam@altern.org> |
3 * Copyright (C) 1998-2003 Peter Alm, Mikael Alm, Olle Hallnas, | 3 * Copyright (C) 1998-2003 Peter Alm, Mikael Alm, Olle Hallnas, |
4 * Thomas Nilsson and 4Front Technologies | 4 * Thomas Nilsson and 4Front Technologies |
5 * Copyright (C) 1999-2006 Haavard Kvaalen | 5 * Copyright (C) 1999-2006 Haavard Kvaalen |
6 * Copyright (C) 2005 Takashi Iwai | 6 * Copyright (C) 2005 Takashi Iwai |
7 * Copyright (C) 2007 William Pitcock | |
7 * | 8 * |
8 * This program is free software; you can redistribute it and/or modify | 9 * This program is free software; you can redistribute it and/or modify |
9 * it under the terms of the GNU General Public License as published by | 10 * it under the terms of the GNU General Public License as published by |
10 * the Free Software Foundation; either version 2 of the License, or | 11 * the Free Software Foundation; either version 2 of the License, or |
11 * (at your option) any later version. | 12 * (at your option) any later version. |
130 return FALSE; | 131 return FALSE; |
131 | 132 |
132 return snd_pcm_state(alsa_pcm) == SND_PCM_STATE_RUNNING; | 133 return snd_pcm_state(alsa_pcm) == SND_PCM_STATE_RUNNING; |
133 } | 134 } |
134 | 135 |
135 static int xrun_recover(void) | 136 static int |
136 { | 137 alsa_recovery(int err) |
138 { | |
139 int err2; | |
140 | |
141 /* if debug mode is enabled, dump ALSA state to console */ | |
137 if (alsa_cfg.debug) | 142 if (alsa_cfg.debug) |
138 { | 143 { |
139 snd_pcm_status_t *alsa_status; | 144 snd_pcm_status_t *alsa_status; |
140 snd_pcm_status_alloca(&alsa_status); | 145 snd_pcm_status_alloca(&alsa_status); |
141 if (snd_pcm_status(alsa_pcm, alsa_status) < 0) | 146 if (snd_pcm_status(alsa_pcm, alsa_status) < 0) |
144 { | 149 { |
145 printf("Status:\n"); | 150 printf("Status:\n"); |
146 snd_pcm_status_dump(alsa_status, logs); | 151 snd_pcm_status_dump(alsa_status, logs); |
147 } | 152 } |
148 } | 153 } |
149 return snd_pcm_prepare(alsa_pcm); | 154 |
150 } | 155 /* |
151 | 156 * specifically handle -EPIPE and -ESTRPIPE to recover |
152 static int suspend_recover(void) | 157 * PCM fragment periods without losing data. |
153 { | 158 */ |
154 int err; | 159 switch (err) |
155 | 160 { |
156 while ((err = snd_pcm_resume(alsa_pcm)) == -EAGAIN) | 161 case -ESTRPIPE: /* "suspend": wait until ALSA is "running" again. */ |
157 /* wait until suspend flag is released */ | 162 while ((err2 = snd_pcm_resume(alsa_pcm)) == -EAGAIN) |
158 g_usleep(1000000); | 163 g_usleep(100000); |
159 if (err < 0) | 164 |
160 { | 165 if (err2 < 0) |
161 g_warning("alsa_handle_error(): " | 166 return snd_pcm_prepare(alsa_pcm); |
162 "snd_pcm_resume() failed."); | 167 |
168 break; | |
169 | |
170 case -EPIPE: /* under-run and the I/O pipe closed on us */ | |
163 return snd_pcm_prepare(alsa_pcm); | 171 return snd_pcm_prepare(alsa_pcm); |
164 } | 172 break; |
165 return err; | 173 |
166 } | 174 default: |
167 | 175 g_warning("Unhandled ALSA exception code %d (%s), trying hard restart.", err, snd_strerror(err)); |
168 /* handle generic errors */ | 176 return snd_pcm_prepare(alsa_pcm); |
169 static int alsa_handle_error(int err) | 177 break; |
170 { | 178 } |
171 switch (err) | 179 |
172 { | 180 return 0; |
173 case -EPIPE: | |
174 return xrun_recover(); | |
175 case -ESTRPIPE: | |
176 return suspend_recover(); | |
177 } | |
178 | |
179 return err; | |
180 } | 181 } |
181 | 182 |
182 /* update and get the available space on h/w buffer (in frames) */ | 183 /* update and get the available space on h/w buffer (in frames) */ |
183 static snd_pcm_sframes_t alsa_get_avail(void) | 184 static snd_pcm_sframes_t alsa_get_avail(void) |
184 { | 185 { |
187 if (alsa_pcm == NULL) | 188 if (alsa_pcm == NULL) |
188 return 0; | 189 return 0; |
189 | 190 |
190 while ((ret = snd_pcm_avail_update(alsa_pcm)) < 0) | 191 while ((ret = snd_pcm_avail_update(alsa_pcm)) < 0) |
191 { | 192 { |
192 ret = alsa_handle_error(ret); | 193 ret = alsa_recovery(ret); |
193 if (ret < 0) | 194 if (ret < 0) |
194 { | 195 { |
195 g_warning("alsa_get_avail(): snd_pcm_avail_update() failed: %s", | 196 g_warning("alsa_get_avail(): snd_pcm_avail_update() failed: %s", |
196 snd_strerror(ret)); | 197 snd_strerror(ret)); |
197 return 0; | 198 return 0; |
762 data += written; | 763 data += written; |
763 alsa_hw_written += written; | 764 alsa_hw_written += written; |
764 } | 765 } |
765 else | 766 else |
766 { | 767 { |
767 int err = alsa_handle_error((int)written_frames); | 768 int err = alsa_recovery((int)written_frames); |
768 if (err < 0) | 769 if (err < 0) |
769 { | 770 { |
770 g_warning("alsa_write_audio(): write error: %s", | 771 g_warning("alsa_write_audio(): write error: %s", |
771 snd_strerror(err)); | 772 snd_strerror(err)); |
772 break; | 773 break; |
818 { | 819 { |
819 alsa_write_out_thread_data(); | 820 alsa_write_out_thread_data(); |
820 } | 821 } |
821 else if (wr < 0) | 822 else if (wr < 0) |
822 { | 823 { |
823 alsa_handle_error(wr); | 824 alsa_recovery(wr); |
824 } | 825 } |
825 } | 826 } |
826 else | 827 else |
827 g_usleep(10000); | 828 g_usleep(10000); |
828 | 829 |