+/** @brief Track structure
+ *
+ * Known tracks are kept in a linked list. Usually there will be at most two
+ * of these but rearranging the queue can cause there to be more.
+ */
+struct track {
+ /** @brief Next track */
+ struct track *next;
+
+ /** @brief Input file descriptor */
+ int fd;
+
+ /** @brief Track ID */
+ char id[24];
+
+ /** @brief Start position of data in buffer */
+ size_t start;
+
+ /** @brief Number of bytes of data in buffer */
+ size_t used;
+
+ /** @brief Set @c fd is at EOF */
+ int eof;
+
+ /** @brief Total number of samples played */
+ unsigned long long played;
+
+ /** @brief Slot in @ref fds */
+ int slot;
+
+ /** @brief Set when playable
+ *
+ * A track becomes playable whenever it fills its buffer or reaches EOF; it
+ * stops being playable when it entirely empties its buffer. Tracks start
+ * out life not playable.
+ */
+ int playable;
+
+ /** @brief Set when finished
+ *
+ * This is set when we've notified the server that the track is finished.
+ * Once this has happened (typically very late in the track's lifetime) the
+ * track cannot be paused or cancelled.
+ */
+ int finished;
+
+ /** @brief Input buffer
+ *
+ * 1Mbyte is enough for nearly 6s of 44100Hz 16-bit stereo
+ */
+ char buffer[1048576];
+};
+
+/** @brief Lock protecting data structures
+ *
+ * This lock protects values shared between the main thread and the callback.
+ *
+ * It is held 'all' the time by the main thread, the exceptions being when
+ * called activate/deactivate callbacks and when calling (potentially) slow
+ * system calls (in particular poll(), where in fact the main thread will spend
+ * most of its time blocked).
+ *
+ * The callback holds it when it's running.
+ */
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+
+/** @brief Linked list of all prepared tracks
+ *
+ * This includes @ref playing and @ref pending_playing.
+ */
+static struct track *tracks;
+
+/** @brief Playing track, or NULL
+ *
+ * This means the track the speaker process intends to play. It does not
+ * reflect any other state (e.g. activation of uaudio backend).
+ *
+ * This track remains on @ref track.
+ */
+static struct track *playing;
+
+/** @brief Pending playing track, or NULL
+ *
+ * This means the track the server wants the speaker to play.
+ *
+ * This track remains on @p track.
+ */
+static struct track *pending_playing;