chiark / gitweb /
speaker: protocol structure now has a union for different arg types
[disorder] / server / speaker.c
index 1db365830fa70bdf0895683a06c26c1d8c10b7fd..e4707596b2921996c6390ee53dda2a98132af66c 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * This file is part of DisOrder
- * Copyright (C) 2005-2010 Richard Kettlewell
+ * Copyright (C) 2005-2013 Richard Kettlewell
  * Portions (C) 2007 Mark Wooding
  *
  * This program is free software: you can redistribute it and/or modify
@@ -386,7 +386,7 @@ static void report(void) {
       return;
     memset(&sm, 0, sizeof sm);
     sm.type = paused ? SM_PAUSED : SM_PLAYING;
-    strcpy(sm.id, playing->id);
+    strcpy(sm.u.id, playing->id);
     sm.data = playing->played / (uaudio_rate * uaudio_channels);
     speaker_send(1, &sm);
     xtime(&last_report);
@@ -418,9 +418,13 @@ static int addfd(int fd, int events) {
 static size_t speaker_callback(void *buffer,
                                size_t max_samples,
                                void attribute((unused)) *userdata) {
-  const size_t max_bytes = max_samples * uaudio_sample_size;
+  size_t max_bytes = max_samples * uaudio_sample_size;
   size_t provided_samples = 0;
 
+  /* Be sure to keep the amount of data in a buffer a whole number of frames:
+   * otherwise the playing threads can become stuck. */
+  max_bytes -= max_bytes % (uaudio_sample_size * uaudio_channels);
+
   pthread_mutex_lock(&lock);
   /* TODO perhaps we should immediately go silent if we've been asked to pause
    * or cancel the playing track (maybe block in the cancel case and see what
@@ -437,6 +441,8 @@ static size_t speaker_callback(void *buffer,
       /* Limit to what we were asked for */
       if(bytes > max_bytes)
         bytes = max_bytes;
+      /* And truncate to a whole number of frames. */
+      bytes -= bytes % (uaudio_sample_size * uaudio_channels);
       /* Provide it */
       memcpy(buffer, playing->buffer + playing->start, bytes);
       playing->start += bytes;
@@ -557,7 +563,7 @@ static void mainloop(void) {
           }
           /* Notify the server that the connection arrived */
           sm.type = SM_ARRIVED;
-          strcpy(sm.id, id);
+          strcpy(sm.u.id, id);
           speaker_send(1, &sm);
         }
       } else
@@ -587,7 +593,7 @@ static void mainloop(void) {
             if(pending_playing)
               disorder_fatal(0, "got SM_PLAY but have a pending playing track");
           }
-         t = findtrack(sm.id, 1);
+         t = findtrack(sm.u.id, 1);
           D(("SM_PLAY %s fd %d", t->id, t->fd));
           if(t->fd == -1)
             disorder_error(0,
@@ -616,8 +622,8 @@ static void mainloop(void) {
           force_report = 1;
          break;
        case SM_CANCEL:
-          D(("SM_CANCEL %s", sm.id));
-         t = removetrack(sm.id);
+          D(("SM_CANCEL %s", sm.u.id));
+         t = removetrack(sm.u.id);
          if(t) {
            if(t == playing || t == pending_playing) {
               /* Scratching the track that the server believes is playing,
@@ -634,16 +640,16 @@ static void mainloop(void) {
                * 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. */
-              disorder_info("SM_CANCEL for nonplaying track %s", sm.id);
+              disorder_info("SM_CANCEL for nonplaying track %s", sm.u.id);
               sm.type = SM_STILLBORN;
             }
-            strcpy(sm.id, t->id);
+            strcpy(sm.u.id, t->id);
            destroy(t);
          } 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;
-           disorder_error(0, "SM_CANCEL for unknown track %s", sm.id);
+           disorder_error(0, "SM_CANCEL for unknown track %s", sm.u.id);
           }
           speaker_send(1, &sm);
           force_report = 1;
@@ -683,7 +689,7 @@ static void mainloop(void) {
        && playing->used <= early_finish) {
       memset(&sm, 0, sizeof sm);
       sm.type = SM_FINISHED;
-      strcpy(sm.id, playing->id);
+      strcpy(sm.u.id, playing->id);
       speaker_send(1, &sm);
       playing->finished = 1;
     }
@@ -795,6 +801,7 @@ int main(int argc, char **argv) {
   /* backend-specific initialization */
   if(backend->configure)
     backend->configure();
+  uaudio_set("application", "disorder-speaker");
   backend->start(speaker_callback, NULL);
   /* create the private socket directory */
   byte_xasprintf(&dir, "%s/private", config->home);
@@ -814,6 +821,8 @@ int main(int argc, char **argv) {
     disorder_fatal(errno, "error binding socket to %s", addr.sun_path);
   xlisten(listenfd, 128);
   nonblock(listenfd);
+  disorder_info("version "VERSION" process ID %lu",
+                (unsigned long)getpid());
   disorder_info("listening on %s", addr.sun_path);
   memset(&sm, 0, sizeof sm);
   sm.type = SM_READY;