- playing_failed, /* failed to play */
- playing_isscratch, /* this is a scratch track */
- playing_no_player, /* couldn't find a player */
- playing_ok, /* played OK */
- playing_paused, /* started but paused */
- playing_quitting, /* interrupt because server quit */
- playing_random, /* unplayed randomly chosen track */
- playing_scratched, /* was scratched */
- playing_started, /* started to play */
- playing_unplayed /* haven't played this track yet */
+ /** @brief Track failed to play */
+ playing_failed,
+
+ /** @brief OBSOLETE
+ *
+ * Formerly denoted an unplayed scratch. This is now indicated by @p
+ * playing_unplayed and @p origin_scratch.
+ */
+ playing_isscratch,
+
+ /** @brief OBSOLETE
+ *
+ * Formerly meant that no player could be found. Nothing sets this any more.
+ */
+ playing_no_player,
+
+ /** @brief Play completed successfully
+ *
+ * Currently this actually means it finished decoding - it might still be
+ * buffered in the speaker, RTP player, sound card, etc.
+ *
+ * It might also mean that it's a (short!) track that hasn't been played at
+ * all yet but has been fully decoded ahead of time! (This is very confusing
+ * so might change.)
+ */
+ playing_ok,
+
+ /** @brief Track is playing, but paused */
+ playing_paused,
+
+ /** @brief Track is playing but the server is quitting */
+ playing_quitting,
+
+ /** @brief OBSOLETE
+ *
+ * Formerly this meant a track that was picked at random and has not yet been
+ * played. This situation is now indicated by @p playing_unplayed and @p
+ * origin_random (or @p origin_adopted).
+ */
+ playing_random,
+
+ /** @brief Track was scratched */
+ playing_scratched,
+
+ /** @brief Track is now playing
+ *
+ * This refers to the actual playing track, not something being decoded ahead
+ * of time.
+ */
+ playing_started,
+
+ /** @brief Track has not been played yet */
+ playing_unplayed
+};
+
+extern const char *const playing_states[];
+
+/** @brief Possible track origins
+ *
+ * This is a newly introduced field. The aim is ultimately to separate the
+ * concepts of the track origin and its current state. NB that both are
+ * potentially mutable!
+ */
+enum track_origin {
+ /** @brief Track was picked at random and then adopted by a user
+ *
+ * @c submitter identifies who adopted it.
+ */
+ origin_adopted,
+
+ /** @brief Track was picked by a user
+ *
+ * @c submitter identifies who picked it
+ */
+ origin_picked,
+
+ /** @brief Track was picked at random
+ *
+ * @c submitter will be NULL
+ */
+ origin_random,
+
+ /** @brief Track was scheduled by a user
+ *
+ * @c submitter identifies who picked it
+ */
+ origin_scheduled,
+
+ /** @brief Track is a scratch
+ *
+ * @c submitter identifies who did the scratching
+ */
+ origin_scratch