Index: roard/clients.c
===================================================================
--- roard/clients.c	(revision 5452)
+++ roard/clients.c	(revision 5567)
@@ -32,20 +32,22 @@
 // declared 'extern'
 struct roar_client_server * g_clients[ROAR_CLIENTS_MAX];
-struct roard_proto g_proto[MAX_PROTOS];
-
-
-struct roard_proto g_proto[MAX_PROTOS] = {
-#ifndef ROAR_WITHOUT_DCOMP_EMUL_ESD
-#ifdef ROAR_HAVE_H_ESD
- {ROAR_PROTO_ESOUND, ROAR_SUBSYS_WAVEFORM, "EsounD emulation", NULL, NULL, NULL, emul_esd_check_client, NULL, NULL},
-#endif
+
+static struct roard_proto_handle __protos[MAX_PROTOS] = {
+ {.proto = ROAR_PROTO_ROARAUDIO, .lhandle = NULL, .type = ROARD_PROTO_TYPE_BUILDIN,
+ .impl = {.buildin = 0}},
+#if !defined(ROAR_WITHOUT_DCOMP_EMUL_ESD) && defined(ROAR_HAVE_H_ESD)
+ {.proto = ROAR_PROTO_ESOUND, .lhandle = NULL, .type = ROARD_PROTO_TYPE_ROARDPROTO,
+ .impl = {.roardproto = {ROAR_PROTO_ESOUND, ROAR_SUBSYS_WAVEFORM, "EsounD emulation", NULL, NULL, NULL, emul_esd_check_client, NULL, NULL}}},
 #endif
 #ifndef ROAR_WITHOUT_DCOMP_EMUL_RPLAY
- {ROAR_PROTO_RPLAY, ROAR_SUBSYS_WAVEFORM, "RPlay emulation", NULL, NULL, NULL, emul_rplay_check_client, NULL, NULL},
+ {.proto = ROAR_PROTO_RPLAY, .lhandle = NULL, .type = ROARD_PROTO_TYPE_ROARDPROTO,
+ .impl = {.roardproto = {ROAR_PROTO_RPLAY, ROAR_SUBSYS_WAVEFORM, "RPlay emulation", NULL, NULL, NULL, emul_rplay_check_client, NULL, NULL}}},
 #endif
 #ifndef ROAR_WITHOUT_DCOMP_EMUL_GOPHER
- {ROAR_PROTO_GOPHER, ROAR_SUBSYS_WAVEFORM, "The Internet Gopher Protocol", NULL, NULL, NULL, emul_gopher_check_client, NULL, emul_gopher_flushed_client},
-#endif
- {-1, 0, NULL, NULL, NULL, NULL, NULL, NULL}
+ {.proto = ROAR_PROTO_GOPHER, .lhandle = NULL, .type = ROARD_PROTO_TYPE_ROARDPROTO,
+ .impl = {.roardproto = {ROAR_PROTO_GOPHER, ROAR_SUBSYS_WAVEFORM, "The Internet Gopher Protocol", NULL, NULL, NULL, emul_gopher_check_client, NULL,
+ emul_gopher_flushed_client}}},
+#endif
+ {.proto = -1}
 };
 
@@ -59,8 +61,8 @@
   g_clients[i] = NULL;
 
- for (i = 0; g_proto[i].proto != -1; i++);
+ for (i = 0; __protos[i].proto != -1; i++);
 
  for (; i < MAX_PROTOS; i++)
-  g_proto[i].proto = -1;
+  __protos[i].proto = -1;
 
  return 0;
@@ -164,4 +166,5 @@
 int clients_delete (int id) {
  struct roar_client_server * cs;
+ const struct roard_proto_handle * proto;
  int i;
  int close_client_fh = 1;
@@ -173,9 +176,14 @@
  cs = g_clients[id];
 
- for (i = 0; g_proto[i].proto != -1; i++) {
-  if ( g_proto[i].proto == ROAR_CLIENT(cs)->proto ) {
-   if ( g_proto[i].delete_client != NULL ) {
-    g_proto[i].delete_client(id);
-   }
+ proto = clients_get_protohandle(ROAR_CLIENT(cs)->proto);
+ if ( proto != NULL ) {
+  switch (proto->type) {
+   case ROARD_PROTO_TYPE_BUILDIN:
+     /* noop */
+    break;
+   case ROARD_PROTO_TYPE_ROARDPROTO:
+     if ( proto->impl.roardproto.delete_client != NULL )
+      proto->impl.roardproto.delete_client(id);
+    break;
   }
  }
@@ -558,4 +566,5 @@
  struct roar_vio_calls  vio;
  struct roar_error_state errstate;
+ const struct roard_proto_handle * proto;
  int command_error;
  char * data = NULL;
@@ -565,5 +574,4 @@
  uint32_t flags[2] = {COMMAND_FLAG_NONE, COMMAND_FLAG_NONE};
  uint32_t event;
- size_t i;
 
  ROAR_DBG("clients_check(id=%i) = ?", id);
@@ -655,13 +663,22 @@
   default:
     rv = -1;
-    for (i = 0; g_proto[i].proto != -1; i++) {
-     if ( g_proto[i].proto == c->proto ) {
-      roar_vio_open_fh_socket(&vio, clients_get_fh(id));
-      if ( g_proto[i].lhandle != NULL )
-       roar_dl_context_restore(g_proto[i].lhandle);
-      rv = g_proto[i].check_client(id, &vio);
-      if ( g_proto[i].lhandle != NULL )
-       roar_dl_context_store(g_proto[i].lhandle);
+    proto = clients_get_protohandle(c->proto);
+    if ( proto != NULL ) {
+     roar_vio_open_fh_socket(&vio, clients_get_fh(id));
+     if ( proto->lhandle != NULL )
+      roar_dl_context_restore(proto->lhandle);
+
+     switch (proto->type) {
+      case ROARD_PROTO_TYPE_BUILDIN:
+        ROAR_WARN("clients_check(id=%i): proto(%i) marked as buildin but isn't. BAD.", id, proto->proto);
+       break;
+      case ROARD_PROTO_TYPE_ROARDPROTO:
+        if ( proto->impl.roardproto.check_client != NULL )
+         rv = proto->impl.roardproto.check_client(id, &vio);
+       break;
      }
+
+     if ( proto->lhandle != NULL )
+      roar_dl_context_store(proto->lhandle);
     }
  }
@@ -675,12 +692,12 @@
 
 int clients_flush      (int id) {
- struct roar_vio_calls         vio;
- struct roar_client_server   * cs;
- struct roar_client          * c;
- struct roard_proto          * p = NULL;
- size_t i;
+ struct roar_vio_calls             vio;
+ struct roar_client_server       * cs;
+ struct roar_client              * c;
+ const struct roard_proto_handle * p;
  size_t len;
  ssize_t ret;
  void * buf;
+ int rv;
 
  _CHECK_CID(id);
@@ -688,22 +705,25 @@
  c = ROAR_CLIENT(cs = g_clients[id]);
 
- for (i = 0; g_proto[i].proto != -1; i++) {
-  if ( g_proto[i].proto == c->proto ) {
-   p = &(g_proto[i]);
+ p = clients_get_protohandle(c->proto);
+
+ if ( p == NULL )
+  return -1;
+
+ roar_vio_open_fh_socket(&vio, clients_get_fh(id));
+
+ switch (p->type) {
+  case ROARD_PROTO_TYPE_BUILDIN:
+    /* noop */
    break;
-  }
- }
-
- if ( p == NULL )
-  return -1;
-
- roar_vio_open_fh_socket(&vio, clients_get_fh(id));
-
- if ( p->flush_client != NULL ) {
-  if ( p->lhandle != NULL )
-   roar_dl_context_restore(p->lhandle);
-  return p->flush_client(id, &vio);
-  if ( p->lhandle != NULL )
-   roar_dl_context_store(p->lhandle);
+  case ROARD_PROTO_TYPE_ROARDPROTO:
+    if ( p->impl.roardproto.flush_client != NULL ) {
+     if ( p->lhandle != NULL )
+      roar_dl_context_restore(p->lhandle);
+     rv = p->impl.roardproto.flush_client(id, &vio);
+     if ( p->lhandle != NULL )
+      roar_dl_context_store(p->lhandle);
+     return rv;
+    }
+   break;
  }
 
@@ -734,10 +754,18 @@
 
  if ( cs->outbuf == NULL ) {
-  if ( p->flushed_client != NULL ) {
-   if ( p->lhandle != NULL )
-    roar_dl_context_restore(p->lhandle);
-   return p->flushed_client(id, &vio);
-   if ( p->lhandle != NULL )
-    roar_dl_context_store(p->lhandle);
+  switch (p->type) {
+   case ROARD_PROTO_TYPE_BUILDIN:
+     /* noop */
+    break;
+   case ROARD_PROTO_TYPE_ROARDPROTO:
+     if ( p->impl.roardproto.flushed_client != NULL ) {
+      if ( p->lhandle != NULL )
+       roar_dl_context_restore(p->lhandle);
+      rv = p->impl.roardproto.flushed_client(id, &vio);
+      if ( p->lhandle != NULL )
+       roar_dl_context_store(p->lhandle);
+      return rv;
+     }
+    break;
   }
  }
@@ -836,6 +864,22 @@
 
 // proto support
+const struct roard_proto_handle * clients_get_protohandle(const int proto) {
+ size_t i;
+
+ if ( proto < 0 ) {
+  roar_err_set(ROAR_ERROR_INVAL);
+  return NULL;
+ }
+
+ for (i = 0; i < (sizeof(__protos)/sizeof(*__protos)); i++)
+  if ( __protos[i].proto == proto )
+   return &(__protos[i]);
+
+ roar_err_set(ROAR_ERROR_NOENT);
+ return NULL;
+}
+
 int clients_register_proto(struct roard_proto * proto, struct roar_dl_lhandle * lhandle) {
- const size_t len = sizeof(g_proto)/sizeof(*g_proto);
+ const size_t len = sizeof(__protos)/sizeof(*__protos);
  size_t i;
 
@@ -843,5 +887,5 @@
   return -1;
 
- for (i = 0; g_proto[i].proto != -1; i++);
+ for (i = 0; __protos[i].proto != -1; i++);
 
  // i is now at pos of current EOS entry.
@@ -851,7 +895,11 @@
   return -1;
 
- memcpy(&(g_proto[i]), proto, sizeof(*g_proto));
-
- g_proto[i].lhandle = lhandle;
+ memcpy(&(__protos[i].impl.roardproto), proto, sizeof(__protos[i].impl.roardproto));
+
+ __protos[i].impl.roardproto.lhandle = lhandle;
+
+ __protos[i].proto   = proto->proto;
+ __protos[i].type    = ROARD_PROTO_TYPE_ROARDPROTO;
+ __protos[i].lhandle = lhandle;
 
  return 0;
@@ -859,5 +907,4 @@
 
 int clients_unregister_proto(int proto) {
- const size_t len = sizeof(g_proto)/sizeof(*g_proto);
  size_t i;
 
@@ -867,8 +914,8 @@
  }
 
- for (i = 0; i < len; i++) {
-  if ( g_proto[i].proto == proto ) {
-   memset(&(g_proto[i]), 0, sizeof(*g_proto));
-   g_proto[i].proto = -1;
+ for (i = 0; i < (sizeof(__protos)/sizeof(*__protos)); i++) {
+  if ( __protos[i].proto == proto ) {
+   memset(&(__protos[i]), 0, sizeof(*__protos));
+   __protos[i].proto = -1;
    return 0;
   }
@@ -880,7 +927,7 @@
 
 void print_protolist        (enum output_format format) {
- const size_t len = sizeof(g_proto)/sizeof(*g_proto);
- struct roard_proto * p;
+ struct roard_proto_handle * p;
  char subsys[7] = "      ";
+ const char * description;
  size_t i;
 
@@ -922,33 +969,38 @@
  }
 
- for (i = 0; i < len; i++) {
-  p = &(g_proto[i]);
+ for (i = 0; i < (sizeof(__protos)/sizeof(*__protos)); i++) {
+  p = &(__protos[i]);
   if ( p->proto == -1 )
    continue;
 
   strncpy(subsys, "      ", 6);
-
-  if ( p->subsystems & ROAR_SUBSYS_WAVEFORM )
-   subsys[0] = 'W';
-  if ( p->subsystems & ROAR_SUBSYS_MIDI )
-   subsys[1] = 'M';
-  if ( p->subsystems & ROAR_SUBSYS_CB )
-   subsys[2] = 'C';
-  if ( p->subsystems & ROAR_SUBSYS_LIGHT )
-   subsys[3] = 'L';
-  if ( p->subsystems & ROAR_SUBSYS_RAW )
-   subsys[4] = 'R';
-  if ( p->subsystems & ROAR_SUBSYS_COMPLEX )
-   subsys[5] = 'X';
+  description = "(none)";
+
+  if ( p->type == ROARD_PROTO_TYPE_ROARDPROTO ) {
+   if ( p->impl.roardproto.subsystems & ROAR_SUBSYS_WAVEFORM )
+    subsys[0] = 'W';
+   if ( p->impl.roardproto.subsystems & ROAR_SUBSYS_MIDI )
+    subsys[1] = 'M';
+   if ( p->impl.roardproto.subsystems & ROAR_SUBSYS_CB )
+    subsys[2] = 'C';
+   if ( p->impl.roardproto.subsystems & ROAR_SUBSYS_LIGHT )
+    subsys[3] = 'L';
+   if ( p->impl.roardproto.subsystems & ROAR_SUBSYS_RAW )
+    subsys[4] = 'R';
+   if ( p->impl.roardproto.subsystems & ROAR_SUBSYS_COMPLEX )
+    subsys[5] = 'X';
+
+   description = p->impl.roardproto.description;
+  }
 
   switch (format) {
    case FORMAT_NATIVE:
-     printf("  %-13s %s - %s\n", roar_proto2str(p->proto), subsys, p->description);
+     printf("  %-13s %s - %s\n", roar_proto2str(p->proto), subsys, description);
     break;
    case FORMAT_WIKI:
-     printf("||%s || ||%s ||%s ||\n", roar_proto2str(p->proto), subsys, p->description);
+     printf("||%s || ||%s ||%s ||\n", roar_proto2str(p->proto), subsys, description);
     break;
    case FORMAT_CSV:
-     printf("%s,,%s,%s\n", roar_proto2str(p->proto), subsys, p->description);
+     printf("%s,,%s,%s\n", roar_proto2str(p->proto), subsys, description);
     break;
   }
