File jack2-PR_435-484_merged.patch of Package jack
diff --git a/linux/alsa/JackAlsaDriver.cpp b/linux/alsa/JackAlsaDriver.cpp
index 62d9f43..06be2dc 100644
--- a/linux/alsa/JackAlsaDriver.cpp
+++ b/linux/alsa/JackAlsaDriver.cpp
@@ -406,6 +406,7 @@ int JackAlsaDriver::Read()
int wait_status;
jack_nframes_t nframes;
fDelayedUsecs = 0.f;
+ int retry_cnt = 0;
retry:
@@ -420,6 +421,11 @@ retry:
*/
jack_log("ALSA XRun wait_status = %d", wait_status);
NotifyXRun(fBeginDateUst, fDelayedUsecs);
+ if(retry_cnt >= MAX_RECOVERY_RETRY) {
+ jack_error("ALSA Device not recovering, tried Xrun recovery for %d times", retry_cnt);
+ return -1;
+ }
+ retry_cnt++;
goto retry; /* recoverable error*/
}
@@ -920,10 +926,14 @@ void SetTime(jack_time_t time)
g_alsa_driver->SetTimetAux(time);
}
-int Restart()
+int Restart(int delay)
{
int res;
+
if ((res = g_alsa_driver->Stop()) == 0) {
+ if(delay > 0) {
+ usleep(delay * MS_TO_US);
+ }
res = g_alsa_driver->Start();
}
return res;
diff --git a/linux/alsa/JackAlsaDriver.h b/linux/alsa/JackAlsaDriver.h
index c62ff54..afc0a3f 100644
--- a/linux/alsa/JackAlsaDriver.h
+++ b/linux/alsa/JackAlsaDriver.h
@@ -26,6 +26,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "JackTime.h"
#include "alsa_driver.h"
+/* Milli Seconds represented in Micro seconds */
+#define MS_TO_US 1000
+/* Max re-try count for Alsa XRUNs */
+#define MAX_RECOVERY_RETRY 10
+
namespace Jack
{
diff --git a/linux/alsa/alsa_driver.c b/linux/alsa/alsa_driver.c
index 9573001..d9da869 100644
--- a/linux/alsa/alsa_driver.c
+++ b/linux/alsa/alsa_driver.c
@@ -58,6 +58,10 @@ char* strcasestr(const char* haystack, const char* needle);
#define XRUN_REPORT_DELAY 0
/* Max re-try count for Alsa poll timeout handling */
#define MAX_RETRY_COUNT 5
+/* Max re-try count for Alsa poll timeout handling */
+#define MAX_RETRY_COUNT 5
+/* Delay in initiating the second xrun recovery */
+#define RECOVER_DELAY_MS 20
void
jack_driver_init (jack_driver_t *driver)
@@ -1168,7 +1172,7 @@ alsa_driver_stop (alsa_driver_t *driver)
}
static int
-alsa_driver_restart (alsa_driver_t *driver)
+alsa_driver_restart (alsa_driver_t *driver, int delay)
{
int res;
@@ -1178,7 +1182,7 @@ alsa_driver_restart (alsa_driver_t *driver)
if ((res = driver->nt_stop((struct _jack_driver_nt *) driver))==0)
res = driver->nt_start((struct _jack_driver_nt *) driver);
*/
- res = Restart();
+ res = Restart(delay);
driver->xrun_recovery = 0;
if (res && driver->midi)
@@ -1192,6 +1196,7 @@ alsa_driver_xrun_recovery (alsa_driver_t *driver, float *delayed_usecs)
{
snd_pcm_status_t *status;
int res;
+ int delay = 0;
snd_pcm_status_alloca(&status);
@@ -1224,10 +1229,11 @@ alsa_driver_xrun_recovery (alsa_driver_t *driver, float *delayed_usecs)
}
}
+ driver->xrun_count++;
+
if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN
&& driver->process_count > XRUN_REPORT_DELAY) {
struct timeval now, diff, tstamp;
- driver->xrun_count++;
snd_pcm_status_get_tstamp(status,&now);
snd_pcm_status_get_trigger_tstamp(status, &tstamp);
timersub(&now, &tstamp, &diff);
@@ -1247,7 +1253,12 @@ alsa_driver_xrun_recovery (alsa_driver_t *driver, float *delayed_usecs)
}
}
- if (alsa_driver_restart (driver)) {
+ /* Try the first xrun recovery without delay and the subsequent ones with delay */
+ if(driver->xrun_count > 1) {
+ delay = RECOVER_DELAY_MS;
+ }
+
+ if (alsa_driver_restart (driver, delay)) {
return -1;
}
return 0;
@@ -1277,6 +1288,7 @@ alsa_driver_set_clock_sync_status (alsa_driver_t *driver, channel_t chn,
ClockSyncStatus status)
{
driver->clock_sync_data[chn] = status;
+ int retry_cnt = 0;
alsa_driver_clock_sync_notify (driver, chn, status);
}
@@ -1536,6 +1548,10 @@ alsa_driver_wait (alsa_driver_t *driver, int extra_fd, int *status, float
if (xrun_detected) {
*status = alsa_driver_xrun_recovery (driver, delayed_usecs);
return 0;
+ } else {
+ if(driver->xrun_count > 0) {
+ driver->xrun_count = 0;
+ }
}
*status = 0;
diff --git a/linux/alsa/alsa_driver.h b/linux/alsa/alsa_driver.h
index efe93de..36a0d01 100644
--- a/linux/alsa/alsa_driver.h
+++ b/linux/alsa/alsa_driver.h
@@ -278,7 +278,7 @@ void MonitorInput();
void ClearOutput();
void WriteOutput(jack_nframes_t orig_nframes, snd_pcm_sframes_t contiguous, snd_pcm_sframes_t nwritten);
void SetTime(jack_time_t time);
-int Restart();
+int Restart(int delay);
#ifdef __cplusplus
}