[AD] ALSA RawMIDI fixes

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


Hi,

I noticed some behaviour in the ALSA rawmidi driver, which I think is wrong.
The alsa_rawmidi_output() method currently puts a detailed error message into
allegro_error when the call to snd_rawmidi_write() fails.  However, this
method is probably most often called from a timer interrupt, due to
play_midi().  The user might call some Allegro function and expect an error
message to be put in allegro_error, only to have it clobbered by the MIDI
playback running in the background.  Therefore I think it's best not to
modify allegro_error in alsa_rawmidi_output().

Also, if the ALSA MIDI driver is active but the user hasn't configured ALSA
properly, then the snd_rawmidi_write() will fail constantly.  The code that
sets allegro_error was non-trivial and causes the timer thread take up more
and more CPU time, eventually choking the main thread.  I've added code that
counts the number of times that snd_rawmidi_write() fails.  Once it fails
more than three times, we don't bother calling it any more.  It probably
not necessary after the previous change, but it saves some useless system
calls.

Okay?

Peter
--- src/unix/alsamidi.c	(revision 7756)
+++ src/unix/alsamidi.c	(local)
@@ -43,6 +43,9 @@
 #endif
 
 
+#define ALSA_RAWMIDI_MAX_ERRORS  3
+
+
 static int alsa_rawmidi_detect(int input);
 static int alsa_rawmidi_init(int input, int voices);
 static void alsa_rawmidi_exit(int input);
@@ -51,6 +54,7 @@ static void alsa_rawmidi_output(int data
 static char alsa_rawmidi_desc[256];
 
 static snd_rawmidi_t *rawmidi_handle = NULL;
+static int alsa_rawmidi_errors = 0;
 
 
 MIDI_DRIVER midi_alsa =
@@ -193,6 +197,7 @@ static int alsa_rawmidi_init(int input, 
       _al_sane_strncpy(alsa_rawmidi_desc, info.name, sizeof(alsa_rawmidi_desc));
 #endif
       midi_alsa.desc = alsa_rawmidi_desc;
+      alsa_rawmidi_errors = 0;
    }
 
    return ret;
@@ -227,10 +232,20 @@ static void alsa_rawmidi_output(int data
    int err;
    char temp[256];
 
+   /* If there are too many errors, just give up.  Otherwise the calling thread
+    * can end up consuming CPU time for no reason.  It probably means the user
+    * hasn't configured ALSA properly.
+    */
+   if (alsa_rawmidi_errors > ALSA_RAWMIDI_MAX_ERRORS) {
+      return;
+   }
+
    err = snd_rawmidi_write(rawmidi_handle, &data, sizeof(char));
    if (err) {
-      snprintf(temp, sizeof(temp), "Could not write to rawmidi port: %s", snd_strerror(err));
-      ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text(temp));
+      alsa_rawmidi_errors++;
+      if (alsa_rawmidi_errors == ALSA_RAWMIDI_MAX_ERRORS) {
+	  TRACE("al-alsamidi: too many errors, giving up\n");
+      }
    }
 }
 


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/