mirror of https://github.com/wb2osz/direwolf.git
Fix transmit failures when using virtual devices
Direwolf does not send a continuous stream to the audio device. It merely sends samples when it has a transmission to accomplish. This seems to work okay on hardware devices, but is causing an issue when working against a virtual device like plug or dmix because the vitual device seems to get into a weird state while direwolf is not sending samples. This causes it to error out with -EBADFD on every transmission after the first. Direwolf tries to recover from this error by running snd_pcm_recover() on the output device. Inspecting the code of this function revealed that it was a noop on any errors other than -EPIPE or -ESTRPIPE, so it had no hope of fixing any issues other than a buffer underrun or a suspended device. This patch breaks things out so that we only run snd_pcm_recover() on -EPIPE or -ESTRPIPE, and for any other error we go ahead and just try to prepare the device again. This appears to work to make transmissions subsequent to the first work correctly on virtual devices. We handle -EBADFD differently merely so that we don't print the error message for a quasi-expected condition. This problem could also possibly be solved by unprotecting the snd_pcm_prepare() on line 1174 of audio.c and just preparing the device whether it apparently needs it or not, but I'm wary of the unintended consequences of doing so in cases where the code is currently working. Much more testing would be necessary for that solution. This solution should only touch cases that are not working currently regardless.
This commit is contained in:
parent
b915842c9f
commit
91d5b90e2a
16
audio.c
16
audio.c
|
@ -1204,6 +1204,17 @@ int audio_flush (int a)
|
||||||
|
|
||||||
snd_pcm_recover (adev[a].audio_out_handle, k, 1);
|
snd_pcm_recover (adev[a].audio_out_handle, k, 1);
|
||||||
}
|
}
|
||||||
|
else if (k == -ESTRPIPE) {
|
||||||
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
dw_printf ("Driver suspended, recovering\n");
|
||||||
|
snd_pcm_recover(adev[a].audio_out_handle, k, 1);
|
||||||
|
}
|
||||||
|
else if (k == -EBADFD) {
|
||||||
|
k = snd_pcm_prepare (adev[a].audio_out_handle);
|
||||||
|
if(k < 0) {
|
||||||
|
dw_printf ("Error preparing after bad state: %s\n", snd_strerror(k));
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (k < 0) {
|
else if (k < 0) {
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
dw_printf ("Audio write error: %s\n", snd_strerror(k));
|
dw_printf ("Audio write error: %s\n", snd_strerror(k));
|
||||||
|
@ -1211,7 +1222,10 @@ int audio_flush (int a)
|
||||||
/* Some other error condition. */
|
/* Some other error condition. */
|
||||||
/* Try again. What do we have to lose? */
|
/* Try again. What do we have to lose? */
|
||||||
|
|
||||||
snd_pcm_recover (adev[a].audio_out_handle, k, 1);
|
k = snd_pcm_prepare (adev[a].audio_out_handle);
|
||||||
|
if(k < 0) {
|
||||||
|
dw_printf ("Error preparing after error: %s\n", snd_strerror(k));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (k != adev[a].outbuf_len / adev[a].bytes_per_frame) {
|
else if (k != adev[a].outbuf_len / adev[a].bytes_per_frame) {
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
|
Loading…
Reference in New Issue