Provide a decent interface for finding out about the audio cache and
[jog] / au.c
diff --git a/au.c b/au.c
index 80382b8..5c90186 100644 (file)
--- a/au.c
+++ b/au.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: au.c,v 1.1 2002/02/02 19:16:28 mdw Exp $
+ * $Id: au.c,v 1.2 2002/02/02 22:43:50 mdw Exp $
  *
  * High-level audio subsystem
  *
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: au.c,v $
+ * Revision 1.2  2002/02/02 22:43:50  mdw
+ * Provide a decent interface for finding out about the audio cache and
+ * configuring its capacity.
+ *
  * Revision 1.1  2002/02/02 19:16:28  mdw
  * New audio subsystem.
  *
@@ -68,7 +72,7 @@ static unsigned au_flags = 0;
 static sym_table au_tab;               /* Sample cache, by name */
 static const char *au_dir = AUDIODIR;  /* Directory containing samples */
 static struct { au_data *next, *prev; } au_spare; /* Lists for sample data */
-static size_t au_sz, au_max;           /* Size of cached samples */
+static au_cacheinfo cache;             /* Cache usage information */
 
 #define AU_SPARE ((au_data*)&au_spare)
 #define f_init 1u
@@ -106,18 +110,21 @@ static const char *filename(const char *tag)
 static void prune(void)
 {
   T( trace(T_AU, "au: pruning cache (%lu/%lu)",
-          (unsigned long)au_sz, (unsigned long)au_max); )
-  while (au_sz > au_max && AU_SPARE->next != AU_SPARE) {
+          (unsigned long)cache.sz_total, (unsigned long)cache.sz_max); )
+  while (cache.sz_total > cache.sz_max && AU_SPARE->next != AU_SPARE) {
     au_data *a = AU_SPARE->next;
     au_sample *s = a->s;
     assert(!a->ref);
     AU_SPARE->next = a->next;
     a->next->prev = AU_SPARE;
     s->a = 0;
-    au_sz -= a->sz;
+    cache.sz_spare -= a->sz;
+    cache.sz_total -= a->sz;
+    cache.n_spare--;
+    cache.n_total--;
     ausys_free(a);
     T( trace(T_AU, "au: ... discarded `%s' (%lu/%lu)", SYM_NAME(s),
-            (unsigned long)au_sz, (unsigned long)au_max); )
+            (unsigned long)cache.sz_total, (unsigned long)cache.sz_max); )
   }
 }
 
@@ -149,7 +156,7 @@ void au_init(const char *dir, size_t max)
 
   sym_create(&au_tab);
   AU_SPARE->next = AU_SPARE->prev = AU_SPARE;
-  au_max = max;
+  cache.sz_max = max;
 
   /* --- Initialize the system-specific subsystem --- */
 
@@ -178,6 +185,42 @@ void au_shutdown(void)
   T( trace(T_AU, "au: shutdown ok"); )
 }
 
+/* --- @au_getcacheinfo@ --- *
+ *
+ * Arguments:  @au_cacheinfo *c@ = where to put the information
+ *
+ * Returns:    ---
+ *
+ * Use:                Extracts audio cache information.
+ */
+
+void au_getcacheinfo(au_cacheinfo *c)
+{
+  ausys_lock();
+  *c = cache;
+  ausys_unlock();
+  assert(c->sz_spare + c->sz_queue == c->sz_total);
+  assert(c->n_spare + c->n_queue == c->n_total);
+}
+
+/* --- @au_setcachelimit@ --- *
+ *
+ * Arguments:  @size_t max@ = new cache limit
+ *
+ * Returns:    ---
+ *
+ * Use:                Reconfigures the maximum cache size.  This probably isn't
+ *             very useful, but it was easy...
+ */
+
+void au_setcachelimit(size_t max)
+{
+  ausys_lock();
+  cache.sz_max = max;
+  prune();
+  ausys_unlock();
+}
+
 /* --- @au_find@ --- *
  *
  * Arguments:  @const char *tag@ = sample tag string
@@ -251,6 +294,11 @@ au_data *au_fetch(au_sample *s)
       a->prev->next = a->next;
       a->next->prev = a->prev;
       a->next = a->prev = 0;
+      cache.sz_spare -= a->sz;
+      cache.sz_queue += a->sz;
+      cache.n_spare--;
+      cache.n_queue++;
+      cache.hits++;
     }
     a->ref++;
     T( trace(T_AU, "au: reusing sample `%s'", SYM_NAME(s)); )
@@ -302,7 +350,6 @@ au_data *au_fetch(au_sample *s)
 
   if ((a = ausys_decode(s, d.buf, d.len)) == 0)
     goto fail_0;
-  au_sz += a->sz;
   a->ref = 1;
   a->next = a->prev = 0;
   a->s = s;
@@ -311,6 +358,11 @@ au_data *au_fetch(au_sample *s)
   /* --- Done --- */
 
   ausys_lock();
+  cache.sz_queue += a->sz;
+  cache.sz_total += a->sz;
+  cache.n_queue++;
+  cache.n_total++;
+  cache.misses++;
   prune();
   ausys_unlock();
   goto done;
@@ -385,6 +437,10 @@ void au_free_unlocked(au_data *a)
     a->prev = AU_SPARE->prev;
     AU_SPARE->prev->next = a;
     AU_SPARE->prev = a;
+    cache.sz_queue -= a->sz;
+    cache.sz_spare += a->sz;
+    cache.n_queue--;
+    cache.n_spare++;
     T( trace(T_AU, "au: drop last ref to `%s'", SYM_NAME(a->s)); )
     prune();
   }