- struct timeval diff, adj_stream_start, tmp;
- int total = 0, use_server_time = 1,
- length_seconds = stat_task->length_seconds;
-
- if (!stat_task->playing) {
- if (length_seconds)
- return NULL;
- return make_message("%s:\n", status_item_list[SI_PLAY_TIME]);
+ PARA_INFO_LOG("closing client fd %d\n", sc->fd);
+ close(sc->fd);
+ list_del(&sc->node);
+ free(sc);
+ num_clients--;
+}
+
+/**
+ * Empty the status clients list.
+ *
+ * This iterates over the list of connected status clients, closes each client
+ * file descriptor and frees the resources.
+ */
+void close_stat_clients(void)
+{
+ struct stat_client *sc, *tmp;
+
+ list_for_each_entry_safe(sc, tmp, &client_list, node)
+ close_stat_client(sc);
+ assert(num_clients == 0);
+}
+
+/**
+ * Write a message to all connected status clients.
+ *
+ * \param item_num The number of the status item of \a msg.
+ *
+ * On write errors, remove the status client from the client list and close its
+ * file descriptor.
+ */
+void stat_client_write_item(int item_num)
+{
+ struct stat_client *sc, *tmp;
+ struct para_buffer pb = {.flags = 0};
+ struct para_buffer pfpb = {.flags = PBF_SIZE_PREFIX};
+ const uint64_t one = 1;
+ char *msg = stat_item_values[item_num];
+ struct para_buffer *b;
+
+ list_for_each_entry_safe(sc, tmp, &client_list, node) {
+ int ret;
+
+ if (!((one << item_num) & sc->item_mask))
+ continue;
+ b = (sc->flags & SCF_PARSER_FRIENDLY)? &pfpb : &pb;
+ if (!b->buf)
+ (void)WRITE_STATUS_ITEM(b, item_num, "%s\n",
+ msg? msg : "");
+ ret = write(sc->fd, b->buf, b->offset);
+ if (ret == b->offset)
+ continue;
+ /* write error or short write */
+ close_stat_client(sc);
+ dump_stat_client_list();