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
.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
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:
.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.
.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
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
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) {
{ 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 },
/** @brief All players */
struct stringlistlist player;
+ /** @brief All tracklength plugins */
+ struct stringlistlist tracklength;
+
/** @brief Allowed users */
struct stringlistlist allow;
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],
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);
}
/* 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 *******************************************************/
# 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
automake -a || true # for INSTALL
automake --foreign -a
cd "$here"
-$srcdir/configure "$@" --sysconfdir=/etc --localstatedir=/var
+$srcdir/configure --sysconfdir=/etc --localstatedir=/var "$@"
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));
/* 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;