chiark / gitweb /
more control state fiddling, starts nicely when server down now
[disorder] / lib / eclient.c
index d0cf661841210c6534e4fadf0634b7103cbe8383..8efefb6f069783169d7e28ab3a7baf19e88fa511 100644 (file)
@@ -249,6 +249,9 @@ void disorder_eclient_close(disorder_eclient *c) {
   /* We'll need to resend all operations */
   for(op = c->ops; op; op = op->next)
     op->sent = 0;
+  /* Drop our use a hint that we're disconnected */
+  if(c->log_callbacks && c->log_callbacks->state)
+    c->log_callbacks->state(c->log_v, c->statebits);
 }
 
 /** @brief Return current state */
@@ -488,6 +491,8 @@ static void maybe_connected(disorder_eclient *c) {
     c->state = state_connected;
     byte_xasprintf(&r, "connected to %s", c->ident);
     c->callbacks->report(c->u, r);
+    /* If this is a log client we expect to get a bunch of updates from the
+     * server straight away */
   }
 }
 
@@ -1146,6 +1151,9 @@ int disorder_eclient_nop(disorder_eclient *c,
  * Once a client is being used for logging it cannot be used for anything else.
  * There is magic in authuser_opcallback() to re-submit the @c log command
  * after reconnection.
+ *
+ * NB that the @c state callback may be called from within this function,
+ * i.e. not solely later on from the event loop callback.
  */
 int disorder_eclient_log(disorder_eclient *c,
                          const disorder_eclient_log_callbacks *callbacks,
@@ -1153,6 +1161,9 @@ int disorder_eclient_log(disorder_eclient *c,
   if(c->log_callbacks) return -1;
   c->log_callbacks = callbacks;
   c->log_v = v;
+  /* Repoort initial state */
+  if(c->log_callbacks->state)
+    c->log_callbacks->state(c->log_v, c->statebits);
   stash_command(c, 0/*queuejump*/, log_opcallback, 0/*completed*/, v,
                 "log", (char *)0);
   return 0;
@@ -1200,7 +1211,7 @@ static void logline(disorder_eclient *c, const char *line) {
 static void logentry_completed(disorder_eclient *c,
                                int attribute((unused)) nvec, char **vec) {
   if(!c->log_callbacks->completed) return;
-  c->state &= ~DISORDER_PLAYING;
+  c->statebits &= ~DISORDER_PLAYING;
   c->log_callbacks->completed(c->log_v, vec[0]);
   if(c->log_callbacks->state)
     c->log_callbacks->state(c->log_v, c->statebits | DISORDER_CONNECTED);
@@ -1209,7 +1220,7 @@ static void logentry_completed(disorder_eclient *c,
 static void logentry_failed(disorder_eclient *c,
                             int attribute((unused)) nvec, char **vec) {
   if(!c->log_callbacks->failed)return;
-  c->state &= ~DISORDER_PLAYING;
+  c->statebits &= ~DISORDER_PLAYING;
   c->log_callbacks->failed(c->log_v, vec[0], vec[1]);
   if(c->log_callbacks->state)
     c->log_callbacks->state(c->log_v, c->statebits | DISORDER_CONNECTED);
@@ -1224,7 +1235,7 @@ static void logentry_moved(disorder_eclient *c,
 static void logentry_playing(disorder_eclient *c,
                              int attribute((unused)) nvec, char **vec) {
   if(!c->log_callbacks->playing) return;
-  c->state |= DISORDER_PLAYING;
+  c->statebits |= DISORDER_PLAYING;
   c->log_callbacks->playing(c->log_v, vec[0], vec[1]);
   if(c->log_callbacks->state)
     c->log_callbacks->state(c->log_v, c->statebits | DISORDER_CONNECTED);
@@ -1267,7 +1278,7 @@ static void logentry_removed(disorder_eclient *c,
 static void logentry_scratched(disorder_eclient *c,
                                int attribute((unused)) nvec, char **vec) {
   if(!c->log_callbacks->scratched) return;
-  c->state &= ~DISORDER_PLAYING;
+  c->statebits &= ~DISORDER_PLAYING;
   c->log_callbacks->scratched(c->log_v, vec[0], vec[1]);
   if(c->log_callbacks->state)
     c->log_callbacks->state(c->log_v, c->statebits | DISORDER_CONNECTED);
@@ -1313,6 +1324,45 @@ static void logentry_volume(disorder_eclient *c,
   c->log_callbacks->volume(c->log_v, (int)l, (int)r);
 }
 
+/** @brief Convert @p statebits to a string */
+char *disorder_eclient_interpret_state(unsigned long statebits) {
+  struct dynstr d[1];
+  size_t n;
+
+  static const struct {
+    unsigned long bit;
+    const char *name;
+  } bits[] = {
+    { DISORDER_PLAYING_ENABLED, "playing_enabled" },
+    { DISORDER_RANDOM_ENABLED, "random_enabled" },
+    { DISORDER_TRACK_PAUSED, "track_paused" },
+    { DISORDER_PLAYING, "playing" },
+    { DISORDER_CONNECTED, "connected" },
+  };
+#define NBITS (sizeof bits / sizeof *bits)
+
+  dynstr_init(d);
+  if(!statebits)
+    dynstr_append(d, '0');
+  for(n = 0; n < NBITS; ++n)
+    if(statebits & bits[n].bit) {
+      if(d->nvec)
+        dynstr_append(d, '|');
+      dynstr_append_string(d, bits[n].name);
+      statebits ^= bits[n].bit;
+    }
+  if(statebits) {
+    char s[20];
+
+    if(d->nvec)
+      dynstr_append(d, '|');
+    sprintf(s, "%#lx", statebits);
+    dynstr_append_string(d, s);
+  }
+  dynstr_terminate(d);
+  return d->vec;
+}
+
 /*
 Local Variables:
 c-basic-offset:2