Index: ChangeLog
===================================================================
--- ChangeLog	(revision 5086)
+++ ChangeLog	(revision 5089)
@@ -1,2 +1,5 @@
+v. 0.4beta8 - ?
+	* Fixed endlessloop in MIDI subsystem (Closes: #137)
+
 v. 0.4beta7 - Sun Jul 10 2011 13:26 CEST
 	Prereleases: 0: Mon Jun 20 2011 18:36 CEST
Index: configure
===================================================================
--- configure	(revision 5059)
+++ configure	(revision 5089)
@@ -648,5 +648,5 @@
  :
 else
- WITHOUT_DCOMP="$WITHOUT_DCOMP"' cb midi rdtcs'
+ WITHOUT_DCOMP="$WITHOUT_DCOMP"' rdtcs'
  no_lib_gcrypt=true
  no_lib_jack=true
Index: roard/midi.c
===================================================================
--- roard/midi.c	(revision 5053)
+++ roard/midi.c	(revision 5089)
@@ -213,4 +213,170 @@
 }
 
+#if 1
+static int _cache_to_mes(struct midi_message * mes, unsigned char * data, size_t len,
+                         int id, struct roar_stream_server * ss) {
+ unsigned char type = *data;
+
+ ROAR_DBG("_cache_to_mes(*): type=0x%.2X", (unsigned int)type);
+
+ if (type == MIDI_TYPE_CLOCK_TICK || type == MIDI_TYPE_CLOCK_START || type == MIDI_TYPE_CLOCK_STOP ) {
+  if ( len != 1 )
+   return -1;
+
+  mes->type = type;
+
+  if ( type == MIDI_TYPE_CLOCK_TICK ) {
+// TODO:
+   ROAR_STREAM(ss)->pos = ROAR_MATH_OVERFLOW_ADD(ROAR_STREAM(ss)->pos, 1);
+  }
+ } else {
+  mes->type    = type & 0xF0;
+  mes->channel = type & 0x0F;
+
+  switch (mes->type) {
+   case MIDI_TYPE_NOTE_ON:
+   case MIDI_TYPE_NOTE_OFF:
+     if ( len != 3 )
+      return -1;
+     roar_midi_note_from_midiid(&(mes->d.note), data[1]);
+
+     // if velocity is zero we have a NOTE OFF event
+     if ( data[2] == 0 )
+      mes->type = MIDI_TYPE_NOTE_OFF;
+   case MIDI_TYPE_PA:
+   case MIDI_TYPE_CONTROLER:
+     mes->kk = data[1];
+     mes->vv = data[2];
+    break;
+   case MIDI_TYPE_PROGRAM:
+   case MIDI_TYPE_MA:
+     if ( len != 2 )
+      return -1;
+     mes->vv = data[1];
+    break;
+   case MIDI_TYPE_PB:
+   case MIDI_TYPE_SYSEX:
+     ROAR_WARN("_cache_to_mes(id=%i): Message of Type 0x%.2X (PB or SysEx) not yet supported", id, (unsigned int)type);
+     return -1;
+    break;
+  }
+ }
+
+ switch (mes->type) {
+  case MIDI_TYPE_CONTROLER:
+    switch (mes->kk) {
+     case MIDI_CCE_MAIN_VOL:
+       if ( (516 * mes->vv) > 65100 ) { // max volume
+        ss->mixer.mixer[mes->channel] = 65535;
+       } else {
+        ss->mixer.mixer[mes->channel] = 516 * mes->vv;
+       }
+      break;
+    }
+   break;
+ }
+
+ ROAR_DBG("_cache_to_mes(*) = 0");
+ return 0;
+}
+
+int midi_conv_midi2mes (int id) {
+ struct roar_stream        *   s;
+ struct roar_stream_server *  ss;
+ size_t have;
+ void * bufdata;
+ unsigned char * data;
+ unsigned char   cache[3];
+ size_t cachepos = 0;
+ int sync = 1;
+ struct roar_buffer        * buf = NULL;
+ struct midi_message       * mes = NULL;
+
+ if ( g_streams[id] == NULL )
+  return -1;
+
+ ROAR_DBG("midi_conv_midi2mes(id=%i) = ?", id);
+
+ s = ROAR_STREAM(ss = g_streams[id]);
+
+ while (ss->buffer != NULL) {
+  if ( roar_buffer_get_len(ss->buffer, &have) == -1 )
+   return -1;
+  if ( roar_buffer_get_data(ss->buffer, &bufdata) == -1 )
+   return -1;
+  data = bufdata;
+
+  while (have) {
+   if ( !sync ) {
+    if ( *data & 0x80 ) {
+     cachepos = 0;
+     sync = 1;
+    } else {
+     data++;
+     have--;
+     continue;
+    }
+   }
+
+   if ( (*data & 0x80) && cachepos != 0 ) {
+    // submit cache.
+
+    if ( midi_new_bufmes(&buf, &mes) == -1 ) {
+     // this is bad.
+     // TODO: handle better.
+     return -1;
+    }
+
+    if ( _cache_to_mes(mes, cache, cachepos, id, ss) == -1 ) {
+     ROAR_WARN("midi_conv_midi2mes(id=%i): Message can not be parsed.", id);
+     roar_buffer_free(buf);
+    } else {
+     midi_add_buf(id, buf); // FIXME: don't we need error handling here?
+    }
+
+    cachepos = 0;
+   } else if ( cachepos == sizeof(cache) ) {
+    // lost sync.
+    sync = 0;
+    continue;
+   }
+
+   ROAR_DBG("midi_conv_midi2mes(id=%i): cache[%u] = 0x%.2X", id, (unsigned int)cachepos, (unsigned int)*data);
+   cache[cachepos++] = *data;
+   data++;
+   have--;
+  }
+
+  roar_buffer_next(&(ss->buffer));
+ }
+
+ if ( cachepos ) {
+  if ( midi_new_bufmes(&buf, &mes) == -1 ) {
+   // this is bad.
+   // TODO: handle better.
+   return -1;
+  }
+
+  if ( _cache_to_mes(mes, cache, cachepos, id, ss) == -1 ) {
+   ROAR_WARN("midi_conv_midi2mes(id=%i): Message can not be parsed.", id);
+   roar_buffer_free(buf);
+  } else {
+   midi_add_buf(id, buf); // FIXME: don't we need error handling here?
+   cachepos = 0;
+  }
+ }
+
+ if ( cachepos ) {
+  if ( roar_buffer_new_data(&buf, cachepos, &bufdata) == -1 )
+   return -1;
+
+  memcpy(bufdata, cache, cachepos);
+
+  ss->buffer = buf;
+ }
+
+ return 0;
+}
+#else
 int midi_conv_midi2mes (int id) {
  void          * bufdata;
@@ -377,4 +543,5 @@
  return 0;
 }
+#endif
 
 #define _nb  len++; *(d++)
