+ /* Beware of the Leopard! On OS X 10.5.x, the order of the shutdown
+ * calls here DOES MATTER. If you do the SHUT_WR first then the SHUT_RD
+ * fails with "Socket is not connected". I think this is a bug but
+ * provided implementors either don't care about the order or all agree
+ * about the order, choosing the reliable order is an adequate
+ * workaround. */
+ xshutdown(np[1], SHUT_RD); /* decoder writes to np[1] */
+ xshutdown(np[0], SHUT_WR); /* normalize reads from np[0] */
+ blocking(np[0]);
+ blocking(np[1]);
+ /* Start disorder-normalize */
+ if(!(npid = xfork())) {
+ if(!xfork()) {
+ /* Connect to the speaker process */
+ memset(&addr, 0, sizeof addr);
+ addr.sun_family = AF_UNIX;
+ snprintf(addr.sun_path, sizeof addr.sun_path,
+ "%s/speaker/socket", config->home);
+ sfd = xsocket(PF_UNIX, SOCK_STREAM, 0);
+ if(connect(sfd, (const struct sockaddr *)&addr, sizeof addr) < 0)
+ fatal(errno, "connecting to %s", addr.sun_path);
+ l = strlen(q->id);
+ if(write(sfd, &l, sizeof l) < 0
+ || write(sfd, q->id, l) < 0)
+ fatal(errno, "writing to %s", addr.sun_path);
+ /* Await the ack */
+ read(sfd, &l, 1);
+ /* Plumbing */
+ xdup2(np[0], 0);
+ xdup2(sfd, 1);
+ xclose(np[0]);
+ xclose(np[1]);
+ xclose(sfd);
+ /* Ask the speaker to actually start playing the track; we do it here
+ * so it's definitely after ack. */
+ if(!prepare_only) {
+ strcpy(sm.id, q->id);
+ sm.type = SM_PLAY;
+ speaker_send(speaker_fd, &sm);
+ D(("sent SM_PLAY for %s", sm.id));
+ }
+ /* TODO stderr shouldn't be redirected for disorder-normalize
+ * (but it should be for play_track() */
+ execlp("disorder-normalize", "disorder-normalize",
+ log_default == &log_syslog ? "--syslog" : "--no-syslog",
+ "--config", configfile,
+ (char *)0);
+ fatal(errno, "executing disorder-normalize");
+ /* end of the innermost fork */
+ }
+ _exit(0);
+ /* end of the middle fork */
+ }
+ /* Wait for the middle fork to finish */
+ while(waitpid(npid, &n, 0) < 0 && errno == EINTR)
+ ;