chiark / gitweb /
detect ALSA capability automatically
[disorder] / lib / eclient.c
index e33cb7cce41024b2a9a936c0ab1cc8df457f96e5..e175c221e96b1f67e862b4fb2991d22ca818ee88 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * This file is part of DisOrder.
- * Copyright (C) 2006 Richard Kettlewell
+ * Copyright (C) 2006, 2007 Richard Kettlewell
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -170,6 +170,7 @@ static void logentry_removed(disorder_eclient *c, int nvec, char **vec);
 static void logentry_scratched(disorder_eclient *c, int nvec, char **vec);
 static void logentry_state(disorder_eclient *c, int nvec, char **vec);
 static void logentry_volume(disorder_eclient *c, int nvec, char **vec);
+static void logentry_rescanned(disorder_eclient *c, int nvec, char **vec);
 
 /* Tables ********************************************************************/
 
@@ -194,6 +195,7 @@ static const struct logentry_handler logentry_handlers[] = {
   LE(recent_added, 2, INT_MAX),
   LE(recent_removed, 1, 1),
   LE(removed, 1, 2),
+  LE(rescanned, 0, 0),
   LE(scratched, 2, 2),
   LE(state, 1, 1),
   LE(volume, 2, 2)
@@ -503,16 +505,31 @@ static void authbanner_opcallback(disorder_eclient *c,
   size_t nonce_len;
   const unsigned char *nonce;
   const char *res;
+  char **rvec;
+  int nrvec;
+  const char *algo = "SHA1";
   
   D(("authbanner_opcallback"));
-  if(c->rc / 100 != 2) {
-    /* Banner told us to go away.  We cannot proceed. */
+  if(c->rc / 100 != 2
+     || !(rvec = split(c->line + 4, &nrvec, SPLIT_QUOTES, 0, 0))
+     || nrvec < 1) {
+    /* Banner told us to go away, or was malformed.  We cannot proceed. */
     protocol_error(c, op, c->rc, "%s: %s", c->ident, c->line);
     disorder_eclient_close(c);
     return;
   }
-  nonce = unhex(c->line +  4, &nonce_len);
-  res = authhash(nonce, nonce_len, config->password);
+  if(nrvec > 1) {
+    algo = *rvec++;
+    --nrvec;
+  }
+  nonce = unhex(rvec[0], &nonce_len);
+  res = authhash(nonce, nonce_len, config->password, algo);
+  if(!res) {
+    protocol_error(c, op, c->rc, "%s: unknown authentication algorithm '%s'",
+                   c->ident, algo);
+    disorder_eclient_close(c);
+    return;
+  }
   stash_command(c, 1/*queuejump*/, authuser_opcallback, 0/*completed*/, 0/*v*/,
                 "user", quoteutf8(config->username), quoteutf8(res),
                 (char *)0);
@@ -634,7 +651,7 @@ static void process_line(disorder_eclient *c, char *line) {
     case 3:
       /* We need to collect the body. */
       c->state = state_body;
-      c->vec.nvec = 0;
+      vector_init(&c->vec);
       break;
     case 4:
       assert(c->log_callbacks != 0);
@@ -1141,6 +1158,25 @@ int disorder_eclient_nop(disorder_eclient *c,
                 "nop", (char *)0);
 }
 
+/** @brief Get the last @p max added tracks
+ * @param c Client
+ * @param completed Called with list
+ * @param max Number of tracks to get, 0 for all
+ * @param v Passed to @p completed
+ *
+ * The first track in the list is the most recently added.
+ */
+int disorder_eclient_new_tracks(disorder_eclient *c,
+                                disorder_eclient_list_response *completed,
+                                int max,
+                                void *v) {
+  char limit[32];
+
+  sprintf(limit, "%d", max);
+  return simple(c, list_response_opcallback, (void (*)())completed, v,
+                "new", limit, (char *)0);
+}
+
 /* Log clients ***************************************************************/
 
 /** @brief Monitor the server log
@@ -1275,6 +1311,13 @@ static void logentry_removed(disorder_eclient *c,
   c->log_callbacks->removed(c->log_v, vec[0], vec[1]);
 }
 
+static void logentry_rescanned(disorder_eclient *c,
+                               int attribute((unused)) nvec,
+                               char attribute((unused)) **vec) {
+  if(!c->log_callbacks->rescanned) return;
+  c->log_callbacks->rescanned(c->log_v);
+}
+
 static void logentry_scratched(disorder_eclient *c,
                                int attribute((unused)) nvec, char **vec) {
   if(!c->log_callbacks->scratched) return;
@@ -1292,6 +1335,9 @@ static const struct {
   { DISORDER_PLAYING_ENABLED, "enable_play", "disable_play" },
   { DISORDER_RANDOM_ENABLED, "enable_random", "disable_random" },
   { DISORDER_TRACK_PAUSED, "pause", "resume" },
+  { DISORDER_PLAYING, "playing", "completed" },
+  { DISORDER_PLAYING, 0, "scratched" },
+  { DISORDER_PLAYING, 0, "failed" },
 };
 #define NSTATES (int)(sizeof statestrings / sizeof *statestrings)
 
@@ -1300,10 +1346,10 @@ static void logentry_state(disorder_eclient *c,
   int n;
 
   for(n = 0; n < NSTATES; ++n)
-    if(!strcmp(vec[0], statestrings[n].enable)) {
+    if(statestrings[n].enable && !strcmp(vec[0], statestrings[n].enable)) {
       c->statebits |= statestrings[n].bit;
       break;
-    } else if(!strcmp(vec[0], statestrings[n].disable)) {
+    } else if(statestrings[n].disable && !strcmp(vec[0], statestrings[n].disable)) {
       c->statebits &= ~statestrings[n].bit;
       break;
     }