X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/blobdiff_plain/71b70599a2cd81c13cc4326499a5d0c45358cd7d..74b1f70dbce97198dc741ddd61214e55138f826f:/server/speaker.c diff --git a/server/speaker.c b/server/speaker.c index d21ad7c..bcc44cc 100644 --- a/server/speaker.c +++ b/server/speaker.c @@ -1,6 +1,6 @@ /* * This file is part of DisOrder - * Copyright (C) 2005, 2006, 2007 Richard Kettlewell + * Copyright (C) 2005-2008 Richard Kettlewell * Portions (C) 2007 Mark Wooding * * This program is free software; you can redistribute it and/or modify @@ -35,7 +35,7 @@ * this is arranged by the @c disorder-normalize program (see @ref * server/normalize.c). * - * @b Garbage @b Collection. This program deliberately does not use the +7 * @b Garbage @b Collection. This program deliberately does not use the * garbage collector even though it might be convenient to do so. This is for * two reasons. Firstly some sound APIs use thread threads and we do not want * to have to deal with potential interactions between threading and garbage @@ -69,6 +69,7 @@ #include #include #include +#include #include "configuration.h" #include "syscalls.h" @@ -78,6 +79,8 @@ #include "speaker-protocol.h" #include "user.h" #include "speaker.h" +#include "printf.h" +#include "version.h" /** @brief Linked list of all prepared tracks */ struct track *tracks; @@ -140,13 +143,6 @@ static void help(void) { exit(0); } -/* Display version number and terminate. */ -static void version(void) { - xprintf("%s", disorder_version_string); - xfclose(stdout); - exit(0); -} - /** @brief Return the number of bytes per frame in @p format */ static size_t bytes_per_frame(const struct stream_header *format) { return format->channels * format->bits / 8; @@ -551,18 +547,31 @@ static void mainloop(void) { report(); break; case SM_CANCEL: - D(("SM_CANCEL %s", sm.id)); + D(("SM_CANCEL %s", sm.id)); t = removetrack(sm.id); if(t) { if(t == playing) { + /* scratching the playing track */ sm.type = SM_FINISHED; - strcpy(sm.id, playing->id); - speaker_send(1, &sm); playing = 0; + } else { + /* Could be scratching the playing track before it's quite got + * going, or could be just removing a track from the queue. We + * log more because there's been a bug here recently than because + * it's particularly interesting; the log message will be removed + * if no further problems show up. */ + info("SM_CANCEL for nonplaying track %s", sm.id); + sm.type = SM_STILLBORN; } + strcpy(sm.id, t->id); destroy(t); - } else + } else { + /* Probably scratching the playing track well before it's got + * going, but could indicate a bug, so we log this as an error. */ + sm.type = SM_UNKNOWN; error(0, "SM_CANCEL for unknown track %s", sm.id); + } + speaker_send(1, &sm); report(); break; case SM_RELOAD: @@ -598,13 +607,14 @@ int main(int argc, char **argv) { static const int one = 1; struct speaker_message sm; const char *d; + char *dir; set_progname(argv); if(!setlocale(LC_CTYPE, "")) fatal(errno, "error calling setlocale"); while((n = getopt_long(argc, argv, "hVc:dDSs", options, 0)) >= 0) { switch(n) { case 'h': help(); - case 'V': version(); + case 'V': version("disorder-speaker"); case 'c': configfile = optarg; break; case 'd': debugging = 1; break; case 'D': debugging = 0; break; @@ -632,18 +642,23 @@ int main(int argc, char **argv) { if(getuid() == 0 || geteuid() == 0) fatal(0, "do not run as root"); /* identify the backend used to play */ for(n = 0; backends[n]; ++n) - if(backends[n]->backend == config->speaker_backend) + if(backends[n]->backend == config->api) break; if(!backends[n]) - fatal(0, "unsupported backend %d", config->speaker_backend); + fatal(0, "unsupported api %d", config->api); backend = backends[n]; /* backend-specific initialization */ backend->init(); + /* create the socket directory */ + byte_xasprintf(&dir, "%s/speaker", config->home); + unlink(dir); /* might be a leftover socket */ + if(mkdir(dir, 0700) < 0 && errno != EEXIST) + fatal(errno, "error creating %s", dir); /* set up the listen socket */ listenfd = xsocket(PF_UNIX, SOCK_STREAM, 0); memset(&addr, 0, sizeof addr); addr.sun_family = AF_UNIX; - snprintf(addr.sun_path, sizeof addr.sun_path, "%s/speaker", + snprintf(addr.sun_path, sizeof addr.sun_path, "%s/speaker/socket", config->home); if(unlink(addr.sun_path) < 0 && errno != ENOENT) error(errno, "removing %s", addr.sun_path);