int attribute((unused)) status,
const struct rusage attribute((unused)) *rusage,
void attribute((unused)) *u) {
- fatal(0, "speaker subprocess %s",
- wstat(status));
+ disorder_fatal(0, "speaker subprocess %s", wstat(status));
}
/** @brief Called when we get a message from the speaker process */
playing->sofar = sm.data;
break;
default:
- error(0, "unknown speaker message type %d", sm.type);
+ disorder_error(0, "unknown speaker message type %d", sm.type);
}
return 0;
}
struct speaker_message sm;
if(socketpair(PF_UNIX, SOCK_DGRAM, 0, sp) < 0)
- fatal(errno, "error calling socketpair");
+ disorder_fatal(errno, "error calling socketpair");
if(!(pid = xfork())) {
exitfn = _exit;
ev_signal_atfork(ev);
log_default == &log_syslog ? "--syslog" : "--no-syslog",
(char *)0);
#endif
- fatal(errno, "error invoking %s", SPEAKER);
+ disorder_fatal(errno, "error invoking %s", SPEAKER);
}
ev_child(ev, pid, 0, speaker_terminated, 0);
speaker_fd = sp[1];
speaker_recv(speaker_fd, &sm);
nonblock(speaker_fd);
if(ev_fd(ev, ev_read, speaker_fd, speaker_readable, 0, "speaker read") < 0)
- fatal(0, "error registering speaker socket fd");
+ disorder_fatal(0, "error registering speaker socket fd");
}
/** @brief Tell the speaker to reload its configuration */
/* Regardless we always report and record the status and do cleanup for
* prefork calls. */
if(status)
- error(0, "player for %s %s", q->track, wstat(status));
+ disorder_error(0, "player for %s %s", q->track, wstat(status));
if(q->type & DISORDER_PLAYER_PREFORK)
play_cleanup(q->pl, q->data);
q->wstat = status;
* @return @ref START_OK, @ref START_HARDFAIL or @ref START_SOFTFAIL
*
* This makes @p actually start playing. It calls prepare() if necessary and
- * either sends an @ref SM_START command or invokes the player itself in a
+ * either sends an @ref SM_PLAY command or invokes the player itself in a
* subprocess.
*
* It's up to the caller to set @ref playing and @c playing->state (this might
}
}
-/** @brief Child-process half of start() */
+/** @brief Child-process half of start()
+ * @return Process exit code
+ *
+ * Called in subprocess to execute non-raw-format players (via plugin).
+ */
static int start_child(struct queue_entry *q,
const struct pbgc_params *params,
void attribute((unused)) *bgdata) {
if(*params->waitdevice) {
n = ao_driver_id(params->waitdevice);
if(n == -1)
- fatal(0, "invalid libao driver: %s", params->waitdevice);
+ disorder_fatal(0, "invalid libao driver: %s", params->waitdevice);
} else
n = ao_default_driver_id();
/* Make up a format. */
/** @brief Prepare a track for later play
* @return @ref START_OK, @ref START_HARDFAIL or @ref START_SOFTFAIL
*
+ * This can be called either when we want to play the track or slightly before
+ * so that some samples are decoded and available in a buffer.
+ *
* Only applies to raw-format (i.e. speaker-using) players; everything else
* gets @c START_OK.
*/
return rc;
}
-/** @brief Child-process half of prepare() */
+/** @brief Child-process half of prepare()
+ * @return Process exit code
+ *
+ * Called in subprocess to execute the decoder for a raw-format player.
+ *
+ * @todo We currently run the normalizer from here in a double-fork. This is
+ * unsatisfactory for many reasons: we can't prevent it outliving the main
+ * server and we don't adequately report its exit status.
+ */
static int prepare_child(struct queue_entry *q,
const struct pbgc_params *params,
void attribute((unused)) *bgdata) {
/* np will be the pipe to disorder-normalize */
int np[2];
if(socketpair(PF_UNIX, SOCK_STREAM, 0, np) < 0)
- fatal(errno, "error calling socketpair");
+ disorder_fatal(errno, "error calling socketpair");
/* 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
"%s/speaker/socket", config->home);
int 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);
+ disorder_fatal(errno, "connecting to %s", addr.sun_path);
/* Send the ID, with a NATIVE-ENDIAN 32 bit length */
uint32_t 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);
+ disorder_fatal(errno, "writing to %s", addr.sun_path);
/* Await the ack */
if (read(sfd, &l, 1) < 0)
- fatal(errno, "reading ack from %s", addr.sun_path);
+ disorder_fatal(errno, "reading ack from %s", addr.sun_path);
/* Plumbing */
xdup2(np[0], 0);
xdup2(sfd, 1);
log_default == &log_syslog ? "--syslog" : "--no-syslog",
"--config", configfile,
(char *)0);
- fatal(errno, "executing disorder-normalize");
+ disorder_fatal(errno, "executing disorder-normalize");
/* End of the great-grandchild of disorderd */
}
/* Back in the grandchild of disorderd */
char buffer[64];
snprintf(buffer, sizeof buffer, "DISORDER_RAW_FD=%d", np[1]);
if(putenv(buffer) < 0)
- fatal(errno, "error calling putenv");
+ disorder_fatal(errno, "error calling putenv");
/* Close all the FDs we don't need */
xclose(np[0]);
/* Start the decoder itself */
if(!track)
return;
/* Add the track to the queue */
- q = queue_add(track, 0, WHERE_END, origin_random);
+ q = queue_add(track, 0, WHERE_END, NULL, origin_random);
D(("picked %p (%s) at random", (void *)q, q->track));
queue_write();
/* Maybe a track can now be played */
}
/* It's become the playing track */
playing = q;
- time(&playing->played);
+ xtime(&playing->played);
playing->state = playing_started;
notify_play(playing->track, playing->submitter);
eventlog("playing", playing->track,
/* Scratching --------------------------------------------------------------- */
/** @brief Scratch a track
- * @param User responsible (or NULL)
- * @param Track ID (or NULL for current)
+ * @param who User responsible (or NULL)
+ * @param id Track ID (or NULL for current)
*/
void scratch(const char *who, const char *id) {
struct queue_entry *q;
* bother if playing is disabled) */
if(playing_is_enabled() && config->scratch.n) {
int r = rand() * (double)config->scratch.n / (RAND_MAX + 1.0);
- q = queue_add(config->scratch.s[r], who, WHERE_START, origin_scratch);
+ q = queue_add(config->scratch.s[r], who, WHERE_START, NULL,
+ origin_scratch);
}
notify_scratch(playing->track, playing->submitter, who,
- time(0) - playing->played);
+ xtime(0) - playing->played);
}
}
case DISORDER_PLAYER_STANDALONE:
if(!(playing->type & DISORDER_PLAYER_PAUSES)) {
default:
- error(0, "cannot pause because player is not powerful enough");
+ disorder_error(0, "cannot pause because player is not powerful enough");
return -1;
}
if(play_pause(playing->pl, &played, playing->data)) {
- error(0, "player indicates it cannot pause");
+ disorder_error(0, "player indicates it cannot pause");
return -1;
}
- time(&playing->lastpaused);
+ xtime(&playing->lastpaused);
playing->uptopause = played;
playing->lastresumed = 0;
break;
speaker_send(speaker_fd, &sm);
break;
}
- if(who) info("paused by %s", who);
+ if(who)
+ disorder_info("paused by %s", who);
notify_pause(playing->track, who);
paused = 1;
if(playing->state == playing_started)
return;
}
play_resume(playing->pl, playing->data);
- time(&playing->lastresumed);
+ xtime(&playing->lastresumed);
break;
case DISORDER_PLAYER_RAW:
memset(&sm, 0, sizeof sm);
speaker_send(speaker_fd, &sm);
break;
}
- if(who) info("resumed by %s", who);
+ if(who) disorder_info("resumed by %s", who);
notify_resume(playing->track, who);
if(playing->state == playing_paused)
playing->state = playing_started;