chiark / gitweb /
Empty back= should be treated as if absent
[disorder] / server / lookup.c
index 4005238323f27d01ddb93afc9bffb274620ba8ec..6dc254cdee33c30d96f4c16b8a27409e18f9c737 100644 (file)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  * USA
  */
-/** @file server/macros-disorder.c
- * @brief DisOrder-specific expansions
- */
-
-#include <config.h>
-#include "types.h"
-
-#include <stdio.h>
-#include <string.h>
-
-#include "queue.h"
-#include "sink.h"
-#include "client.h"
-#include "rights.h"
-#include "lookup.h"
-#include "cgi.h"
-
-/** @brief Client used by CGI
+/** @file server/lookup.c
+ * @brief Server lookups
  *
- * The caller should arrange for this to be created before any of
- * these expansions are used (if it cannot connect then it's safe to
- * leave it as NULL).
+ * To improve performance many server lookups are cached.
  */
-disorder_client *client;
+
+#include "disorder-cgi.h"
 
 /** @brief Cached data */
 static unsigned flags;
 
-struct queue_entry *queue;
-struct queue_entry *playing;
-struct queue_entry *recent;
+/** @brief Map of hashes to queud data */
+static hash *queuemap;
 
-int volume_left;
-int volume_right;
+struct queue_entry *dcgi_queue;
+struct queue_entry *dcgi_playing;
+struct queue_entry *dcgi_recent;
 
-char **files;
-int nfiles;
+int dcgi_volume_left;
+int dcgi_volume_right;
 
-char **dirs;
-int ndirs;
+char **dcgi_new;
+int dcgi_nnew;
 
-char **new;
-int nnew;
+rights_type dcgi_rights;
 
-rights_type rights;
+int dcgi_enabled;
+int dcgi_random_enabled;
 
-int enabled;
-int random_enabled;
+static void queuemap_add(struct queue_entry *q) {
+  if(!queuemap)
+    queuemap = hash_new(sizeof (struct queue_entry *));
+  for(; q; q = q->next)
+    hash_add(queuemap, q->id, &q, HASH_INSERT_OR_REPLACE);
+}
 
 /** @brief Fetch cachable data */
-void lookup(unsigned want) {
+void dcgi_lookup(unsigned want) {
   unsigned need = want ^ (flags & want);
   struct queue_entry *r, *rnext;
-  const char *dir, *re;
-  char *rights_string;
+  char *rs;
 
-  if(!client || !need)
+  if(!dcgi_client || !need)
     return;
-  if(need & DC_QUEUE)
-    disorder_queue(client, &queue);
-  if(need & DC_PLAYING)
-    disorder_playing(client, &playing);
-  if(need & DC_NEW)
-    disorder_new_tracks(client, &new, &nnew, 0);
-  if(need & DC_RECENT) {
+  if(need & DCGI_QUEUE) {
+    disorder_queue(dcgi_client, &dcgi_queue);
+    queuemap_add(dcgi_queue);
+  }
+  if(need & DCGI_PLAYING) {
+    disorder_playing(dcgi_client, &dcgi_playing);
+    queuemap_add(dcgi_playing);
+  }
+  if(need & DCGI_NEW)
+    disorder_new_tracks(dcgi_client, &dcgi_new, &dcgi_nnew, 0);
+  if(need & DCGI_RECENT) {
     /* we need to reverse the order of the list */
-    disorder_recent(client, &r);
+    disorder_recent(dcgi_client, &r);
     while(r) {
       rnext = r->next;
-      r->next = recent;
-      recent = r;
+      r->next = dcgi_recent;
+      dcgi_recent = r;
       r = rnext;
     }
+    queuemap_add(dcgi_recent);
   }
-  if(need & DC_VOLUME)
-    disorder_get_volume(client,
-                        &volume_left, &volume_right);
-  /* DC_FILES and DC_DIRS are looking obsolete now */
-  if(need & (DC_FILES|DC_DIRS)) {
-    if(!(dir = cgi_get("directory")))
-      dir = "";
-    re = cgi_get("regexp");
-    if(need & DC_DIRS)
-      if(disorder_directories(client, dir, re,
-                              &dirs, &ndirs))
-        ndirs = 0;
-    if(need & DC_FILES)
-      if(disorder_files(client, dir, re,
-                        &files, &nfiles))
-        nfiles = 0;
+  if(need & DCGI_VOLUME)
+    disorder_get_volume(dcgi_client,
+                        &dcgi_volume_left, &dcgi_volume_right);
+  if(need & DCGI_RIGHTS) {
+    dcgi_rights = RIGHT_READ;  /* fail-safe */
+    if(!disorder_userinfo(dcgi_client, disorder_user(dcgi_client),
+                          "rights", &rs))
+      parse_rights(rs, &dcgi_rights, 1);
   }
-  if(need & DC_RIGHTS) {
-    rights = RIGHT_READ;       /* fail-safe */
-    if(!disorder_userinfo(client, disorder_user(client),
-                          "rights", &rights_string))
-      parse_rights(rights_string, &rights, 1);
-  }
-  if(need & DC_ENABLED)
-    disorder_enabled(client, &enabled);
-  if(need & DC_RANDOM_ENABLED)
-    disorder_random_enabled(client, &random_enabled);
-  if(need & DC_RANDOM_ENABLED)
+  if(need & DCGI_ENABLED)
+    disorder_enabled(dcgi_client, &dcgi_enabled);
+  if(need & DCGI_RANDOM_ENABLED)
+    disorder_random_enabled(dcgi_client, &dcgi_random_enabled);
   flags |= need;
 }
 
-void lookup_reset(void) {
-  /* Junk the old connection if there is one */
-  if(client)
-    disorder_close(client);
-  /* Create a new connection */
-  client = disorder_new(0);
+/** @brief Locate a track by ID */
+struct queue_entry *dcgi_findtrack(const char *id) {
+  struct queue_entry **qq;
+
+  if(queuemap && (qq = hash_find(queuemap, id)))
+    return *qq;
+  dcgi_lookup(DCGI_PLAYING);
+  if(queuemap && (qq = hash_find(queuemap, id)))
+    return *qq;
+  dcgi_lookup(DCGI_QUEUE);
+  if(queuemap && (qq = hash_find(queuemap, id)))
+    return *qq;
+  dcgi_lookup(DCGI_RECENT);
+  if(queuemap && (qq = hash_find(queuemap, id)))
+    return *qq;
+  return NULL;
+}
+
+void dcgi_lookup_reset(void) {
   /* Forget everything we knew */
   flags = 0;
+  queuemap = 0;
+  dcgi_recent = 0;
+  dcgi_queue = 0;
+  dcgi_playing = 0;
+  dcgi_rights = 0;
+  dcgi_new = 0;
+  dcgi_nnew = 0;
+  dcgi_enabled = 0;
+  dcgi_random_enabled = 0;
+  dcgi_volume_left = dcgi_volume_right = 0;
 }