From 62dc37489c39c8d20046b4d5e323707239491df6 Mon Sep 17 00:00:00 2001 Message-Id: <62dc37489c39c8d20046b4d5e323707239491df6.1713557906.git.mdw@distorted.org.uk> From: Mark Wooding Date: Sat, 3 Nov 2007 12:44:55 +0000 Subject: [PATCH] pattern based dispatch for tracklength plugins Organization: Straylight/Edgeware From: Richard Kettlewell --- debian/etc.disorder.config | 9 +++++++++ doc/disorder_config.5.in | 38 ++++++++++++++++++++++++-------------- examples/config.sample.in | 9 +++++++++ lib/configuration.c | 12 ++++++++++++ lib/configuration.h | 3 +++ lib/plugin.c | 18 ++++++++++++------ lib/plugin.h | 6 +----- plugins/Makefile.am | 8 ++++---- prepare | 2 +- server/rescan.c | 25 ++++++++++++++++--------- 10 files changed, 91 insertions(+), 39 deletions(-) diff --git a/debian/etc.disorder.config b/debian/etc.disorder.config index 7c89a8f..f5fd10c 100644 --- a/debian/etc.disorder.config +++ b/debian/etc.disorder.config @@ -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 diff --git a/doc/disorder_config.5.in b/doc/disorder_config.5.in index 9c8a493..743bb51 100644 --- a/doc/disorder_config.5.in +++ b/doc/disorder_config.5.in @@ -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 diff --git a/examples/config.sample.in b/examples/config.sample.in index 5648b43..1bf4088 100644 --- a/examples/config.sample.in +++ b/examples/config.sample.in @@ -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 diff --git a/lib/configuration.c b/lib/configuration.c index 34f8d53..3ca9a73 100644 --- a/lib/configuration.c +++ b/lib/configuration.c @@ -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 }, diff --git a/lib/configuration.h b/lib/configuration.h index c5cc2e1..4ef7862 100644 --- a/lib/configuration.h +++ b/lib/configuration.h @@ -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; diff --git a/lib/plugin.c b/lib/plugin.c index 57496e6..1c526de 100644 --- a/lib/plugin.c +++ b/lib/plugin.c @@ -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); } diff --git a/lib/plugin.h b/lib/plugin.h index d7e0afb..4134111 100644 --- a/lib/plugin.h +++ b/lib/plugin.h @@ -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 *******************************************************/ diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 1b7386c..fe51ade 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -18,16 +18,16 @@ # 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 a419ab0..48337ea 100755 --- 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 "$@" diff --git a/server/rescan.c b/server/rescan.c index 53c566c..aaa5f93 100644 --- a/server/rescan.c +++ b/server/rescan.c @@ -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; -- [mdw]