chiark / gitweb /
pattern based dispatch for tracklength plugins
authorRichard Kettlewell <rjk@greenend.org.uk>
Sat, 3 Nov 2007 12:44:55 +0000 (12:44 +0000)
committerRichard Kettlewell <rjk@greenend.org.uk>
Sat, 3 Nov 2007 12:44:55 +0000 (12:44 +0000)
debian/etc.disorder.config
doc/disorder_config.5.in
examples/config.sample.in
lib/configuration.c
lib/configuration.h
lib/plugin.c
lib/plugin.h
plugins/Makefile.am
prepare
server/rescan.c

index 7c89a8f5bfa785dfedb7db6b31e5615d4b1f25e7..f5fd10c9037673ac0836e0fc111854bc8829907e 100644 (file)
@@ -19,6 +19,15 @@ player *.ogg execraw disorder-decode
 player *.wav execraw disorder-decode
 player *.flac execraw disorder-decode
 
+# Track length calculators
+#
+# If you add new formats then can add a plugin module to calculate the
+# length of a track.  See disorder(3) for the interface.
+tracklength *.mp3 disorder-tracklength
+tracklength *.ogg disorder-tracklength
+tracklength *.wav disorder-tracklength
+tracklength *.flac disorder-tracklength
+
 # Don't leave a gap between tracks.
 gap 0
 
index 9c8a493317cd3f48ff8aa53970889948048f8387..743bb51b2b4f1ea7ef36ed835a6b06435bfa7fd8 100644 (file)
@@ -320,6 +320,12 @@ the shell quoting rules.
 .RE
 .IP
 If multiple player commands match a track then the first match is used.
+.IP
+For the server to be able to calculate track lengths, there should be a
+.B tracklength
+command corresponding to each
+.B player
+command.
 .TP
 .B prefsync \fISECONDS\fR
 The interval at which the preferences log file will be synchronised.  Defaults
@@ -329,6 +335,20 @@ to 3600, i.e. one hour.
 The target size of the queue.  If random play is enabled then randomly picked
 tracks will be added until the queue is at least this big.
 .TP
+.B restrict \fR[\fBscratch\fR] [\fBremove\fR] [\fBmove\fR]
+Determine which operations are restricted to the submitter of a
+track.  By default, no operations are restricted, i.e. anyone can
+scratch or remove anything.
+.IP
+If \fBrestrict scratch\fR or \fBrestrict remove\fR are set then only the user
+that submitted a track can scratch or remove it, respectively.
+.IP
+If \fBrestrict move\fR is set then only trusted users can move tracks around in
+the queue.
+.IP
+If \fBrestrict\fR is used more than once then only the final use has any
+effect.
+.TP
 .B sample_format \fIBITS\fB/\fIRATE\fB/\fICHANNELS
 Describes the sample format expected by the \fBspeaker_command\fR (below).  The
 components of the format specification are as follows:
@@ -413,20 +433,6 @@ is invoked to translate it.  If
 .B sox
 is not installed then this will not work.
 .TP
-.B restrict \fR[\fBscratch\fR] [\fBremove\fR] [\fBmove\fR]
-Determine which operations are restricted to the submitter of a
-track.  By default, no operations are restricted, i.e. anyone can
-scratch or remove anything.
-.IP
-If \fBrestrict scratch\fR or \fBrestrict remove\fR are set then only the user
-that submitted a track can scratch or remove it, respectively.
-.IP
-If \fBrestrict move\fR is set then only trusted users can move tracks around in
-the queue.
-.IP
-If \fBrestrict\fR is used more than once then only the final use has any
-effect.
-.TP
 .B scratch \fIPATH\fR
 Specifies a scratch.  When a track is scratched, a scratch track is
 played at random.
@@ -438,6 +444,10 @@ UTF-8 (which means that ASCII will do).
 .B stopword \fIWORD\fR ...
 Specifies one or more stopwords that should not take part in searches
 over track names.
+.TP
+.B tracklength \fIPATTERN\fR \fIMODULE\fR
+Specifies the module used to calculate the length of files matching
+\fIPATTERN\fR.  \fIMODULE\fR specifies which plugin module to use.
 .SS "Client Configuration"
 .TP
 .B connect \fIHOST SERVICE\fR
index 5648b43a427bdeeac87acf7f9841a7bcc6de9aa0..1bf4088c59db2a7f4155b05e9da13288e93e75b9 100644 (file)
@@ -12,6 +12,15 @@ player *.ogg execraw disorder-decode
 player *.wav execraw disorder-decode
 player *.flac execraw disorder-decode
 
+# Track length calculators
+#
+# If you add new formats then can add a plugin module to calculate the
+# length of a track.  See disorder(3) for the interface.
+tracklength *.mp3 disorder-tracklength
+tracklength *.ogg disorder-tracklength
+tracklength *.wav disorder-tracklength
+tracklength *.flac disorder-tracklength
+
 # Use the fs module to list files under /export/mp3.  The encoding
 # is ISO-8859-1.
 collection fs ISO-8859-1 /export/mp3
index 34f8d53842473a5785ca7f8b7e203bc6515db2f8..3ca9a737775cd7973f95a66e91866e132db4f378 100644 (file)
@@ -635,6 +635,17 @@ static int validate_player(const struct config_state *cs,
   return 0;
 }
 
+static int validate_tracklength(const struct config_state *cs,
+                               int nvec,
+                               char attribute((unused)) **vec) {
+  if(nvec < 2) {
+    error(0, "%s:%d: should be at least 'tracklength PATTERN MODULE'",
+         cs->path, cs->line);
+    return -1;
+  }
+  return 0;
+}
+
 static int validate_allow(const struct config_state *cs,
                          int nvec,
                          char attribute((unused)) **vec) {
@@ -903,6 +914,7 @@ static const struct conf conf[] = {
   { C(speaker_command),  &type_string,           validate_any },
   { C(stopword),         &type_string_accum,     validate_any },
   { C(templates),        &type_string_accum,     validate_isdir },
+  { C(tracklength),      &type_stringlist_accum, validate_tracklength },
   { C(transform),        &type_transform,        validate_any },
   { C(trust),            &type_string_accum,     validate_any },
   { C(url),              &type_string,           validate_url },
index c5cc2e125fe0a51ef54f4cdfd3455910c0b14e42..4ef7862071aa0479222899ab2be7313bc5ce6fd9 100644 (file)
@@ -102,6 +102,9 @@ struct config {
   /** @brief All players */
   struct stringlistlist player;
 
+  /** @brief All tracklength plugins */
+  struct stringlistlist tracklength;
+
   /** @brief Allowed users */
   struct stringlistlist allow;
 
index 57496e64a9f0a10bdbbbdb5da85f5e17537c5623..1c526de937d1a8ed55f2be4b17ad540ec053ebd7 100644 (file)
@@ -58,6 +58,7 @@ const struct plugin *open_plugin(const char *name,
   for(pl = plugins; pl && strcmp(pl->name, name); pl = pl->next)
     ;
   if(pl) return pl;
+  /* Search the plugin path */
   for(n = 0; n <= config->plugins.n; ++n) {
     byte_xasprintf(&p, "%s/%s" SOSUFFIX,
                   n == config->plugins.n ? pkglibdir : config->plugins.s[n],
@@ -106,13 +107,18 @@ const void *get_plugin_object(const struct plugin *pl,
 
 typedef long tracklength_fn(const char *track, const char *path);
 
-long tracklength(const char *track, const char *path) {
-  static tracklength_fn *f = 0;
+/** Compute the length of a track
+ * @param plugin plugin to use, as configured
+ * @param track UTF-8 name of track
+ * @param path file system path or 0
+ * @return length of track in seconds, 0 for unknown, -1 for error
+ */
+long tracklength(const char *plugin, const char *track, const char *path) {
+  tracklength_fn *f = 0;
 
-  if(!f)
-    f = (tracklength_fn *)get_plugin_function(open_plugin("tracklength",
-                                                         PLUGIN_FATAL),
-                                             "disorder_tracklength");
+  f = (tracklength_fn *)get_plugin_function(open_plugin(plugin,
+                                                       PLUGIN_FATAL),
+                                           "disorder_tracklength");
   return (*f)(track, path);
 }
 
index d7e0afbbb43d672fe85da5d30b05e10e2d922a09..4134111f4140b7579ce08c8821ffd0d7c9261fe7 100644 (file)
@@ -42,11 +42,7 @@ const void *get_plugin_object(const struct plugin *handle,
 
 /* track length computation ***************************************************/
 
-long tracklength(const char *track, const char *path);
-/* compute the length of the track.  @track@ is the UTF-8 name of the
- * track, @path@ is the file system name (or 0 for tracks that don't
- * exist in the filesystem).  The return value should be a positive
- * number of seconds, 0 for unknown or -1 if an error occurred. */
+long tracklength(const char *plugin, const char *track, const char *path);
 
 /* collection interface *******************************************************/
 
index 1b7386c20c9402afe33cf1059e968d7d2aec688f..fe51ade0677c7c07f9e0bc4b834787b7f269df82 100644 (file)
 # USA
 #
 
-pkglib_LTLIBRARIES=tracklength.la fs.la notify.la exec.la shell.la \
+pkglib_LTLIBRARIES=disorder-tracklength.la fs.la notify.la exec.la shell.la \
                   execraw.la
 AM_CPPFLAGS=-I${top_srcdir}/lib
 
 notify_la_SOURCES=notify.c
 notify_la_LDFLAGS=-module
 
-tracklength_la_SOURCES=tracklength.c mad.c madshim.h ../lib/wav.h ../lib/wav.c
-tracklength_la_LDFLAGS=-module
-tracklength_la_LIBADD=$(LIBVORBISFILE) $(LIBMAD) $(LIBFLAC)
+disorder_tracklength_la_SOURCES=tracklength.c mad.c madshim.h ../lib/wav.h ../lib/wav.c
+disorder_tracklength_la_LDFLAGS=-module
+disorder_tracklength_la_LIBADD=$(LIBVORBISFILE) $(LIBMAD) $(LIBFLAC)
 
 fs_la_SOURCES=fs.c
 fs_la_LDFLAGS=-module
diff --git a/prepare b/prepare
index a419ab02c1e5731015ec96c738ea62856789aeca..48337ea5d5082dc9ce3f59ac1e1ba76086ef9420 100755 (executable)
--- a/prepare
+++ b/prepare
@@ -42,4 +42,4 @@ autoheader
 automake -a || true            # for INSTALL
 automake --foreign -a
 cd "$here"
-$srcdir/configure "$@" --sysconfdir=/etc --localstatedir=/var
+$srcdir/configure --sysconfdir=/etc --localstatedir=/var "$@"
index 53c566c1b977509959c1427597b257b65a9c2021..aaa5f93604bedb26fc35f5f0358d6833c9c4f45b 100644 (file)
@@ -198,8 +198,8 @@ static int recheck_callback(const char *track,
   const struct collection *c = cs->c;
   const char *path = kvp_get(data, "_path");
   char buffer[20];
-  int err;
-  long n;
+  int err, n;
+  long length;
 
   if(aborted()) return EINTR;
   D(("rechecking %s", track));
@@ -222,13 +222,20 @@ static int recheck_callback(const char *track,
   /* make sure we know the length */
   if(!kvp_get(data, "_length")) {
     D(("recalculating length of %s", track));
-    n = tracklength(track, path);
-    if(n > 0) {
-      byte_snprintf(buffer, sizeof buffer, "%ld", n);
-      kvp_set(&data, "_length", buffer);
-      if((err = trackdb_putdata(trackdb_tracksdb, track, data, tid, 0)))
-        return err;
-      ++cs->nlength;
+    for(n = 0; n < config->tracklength.n; ++n)
+      if(fnmatch(config->tracklength.s[n].s[0], track, 0) == 0)
+        break;
+    if(n >= config->tracklength.n)
+      error(0, "no tracklength plugin found for %s", track);
+    else {
+      length = tracklength(config->tracklength.s[n].s[1], track, path);
+      if(length > 0) {
+        byte_snprintf(buffer, sizeof buffer, "%ld", length);
+        kvp_set(&data, "_length", buffer);
+        if((err = trackdb_putdata(trackdb_tracksdb, track, data, tid, 0)))
+          return err;
+        ++cs->nlength;
+      }
     }
   }
   return 0;