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