/*
- * Copyright (C) 2005-2013 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2005-2014 Andre Noll <maan@systemlinux.org>
*
* Licensed under the GPL v2. For licencing details see COPYING.
*/
/** \file audiod.c The paraslash's audio daemon. */
+
+#include <netinet/in.h>
+#include <sys/socket.h>
#include <regex.h>
#include <sys/types.h>
+#include <arpa/inet.h>
+#include <sys/un.h>
+#include <netdb.h>
#include <signal.h>
#include "para.h"
* from the status items received from para_server and the start time of the
* (first) writer of the given slot.
*
- * It has to to take into account that probably the stream was not started at
+ * It has to take into account that the stream was probably not started at
* the beginning of the file, that the clock between the server and the client
* host may differ and that playback of the stream was delayed, e.g. because
* the prebuffer filter is used in the filter configuration of the given slot.
return true;
}
-static unsigned compute_time_diff(const struct timeval *status_time)
+static void compute_time_diff(const struct timeval *status_time)
{
struct timeval tmp, diff;
static unsigned count;
const struct timeval max_deviation = {0, 500 * 1000};
const int time_smooth = 5;
- if (!status_time)
- return count;
sign = tv_diff(status_time, now, &diff);
// PARA_NOTICE_LOG("%s: sign = %i, sa_time_diff_sign = %i\n", __func__,
// sign, sa_time_diff_sign);
);
out:
stat_task->sa_time_diff_sign = sa_time_diff_sign;
- return count;
}
static int update_item(int itemnum, char *buf)
case SIGINT:
case SIGTERM:
case SIGHUP:
- PARA_EMERG_LOG("terminating on signal %d\n", signum);
+ PARA_NOTICE_LOG("received signal %d\n", signum);
clean_exit(EXIT_FAILURE, "caught deadly signal");
}
return 0;
int ret;
struct command_task *ct = container_of(t, struct command_task, task);
static struct timeval last_status_dump;
- struct timeval tmp, delay = {0, 500 * 1000};
-
- tv_add(&last_status_dump, &delay, &tmp);
- if (tv_diff(&tmp, now, NULL) < 0) {
- audiod_status_dump();
- last_status_dump = *now;
- }
+ struct timeval tmp, delay;
+ bool force = true;
ret = handle_connect(ct->fd, &s->rfds);
if (ret < 0)
PARA_ERROR_LOG("%s\n", para_strerror(-ret));
- audiod_status_dump();
- return 0;
+ else if (ret > 0)
+ goto dump;
+
+ /* if last status dump was less than 500ms ago, do nothing */
+ delay.tv_sec = 0;
+ delay.tv_usec = 500 * 1000;
+ tv_add(&last_status_dump, &delay, &tmp);
+ if (tv_diff(now, &tmp, NULL) < 0)
+ return 0;
+
+ /*
+ * If last status dump was more than 5s ago, force update. Otherwise,
+ * update only those items that have changed.
+ */
+ delay.tv_sec = 5;
+ delay.tv_usec = 0;
+ tv_add(&last_status_dump, &delay, &tmp);
+ if (tv_diff(now, &tmp, NULL) < 0)
+ force = false;
+dump:
+ audiod_status_dump(force);
+ last_status_dump = *now;
+ return 1;
}
static void init_command_task(struct command_task *ct)
stat_task->offset_seconds = 0;
stat_task->vss_status = 0;
stat_task->current_audio_format_num = -1;
- audiod_status_dump();
+ audiod_status_dump(true);
}
/* avoid busy loop if server is down */
*/
void __noreturn clean_exit(int status, const char *msg)
{
- int i;
-
- PARA_EMERG_LOG("%s\n", msg);
if (socket_name)
unlink(socket_name);
close_stat_pipe();
- FOR_EACH_SLOT(i)
- close_slot(i);
+ close_unused_slots();
audiod_cmdline_parser_free(&conf);
+ close_stat_clients();
+ PARA_EMERG_LOG("%s\n", msg);
exit(status);
}
char *buf;
size_t sz;
int ret;
- if (st->ct->task.error < 0) {
+
+ ret = btr_node_status(st->btrn, st->min_iqs, BTR_NT_LEAF);
+ if (ret < 0) {
close_stat_pipe();
goto out;
}
if (st->ct->status != CL_EXECUTING)
goto out;
- ret = btr_node_status(st->btrn, st->min_iqs, BTR_NT_LEAF);
- if (ret <= 0) {
+ if (ret == 0) {
struct timeval diff;
tv_diff(now, &st->last_status_read, &diff);
if (diff.tv_sec > 61)