aboutsummaryrefslogtreecommitdiffstats
path: root/src/decoder_control.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/decoder_control.h')
-rw-r--r--src/decoder_control.h94
1 files changed, 78 insertions, 16 deletions
diff --git a/src/decoder_control.h b/src/decoder_control.h
index 566b153ee..9ecbde73e 100644
--- a/src/decoder_control.h
+++ b/src/decoder_control.h
@@ -67,6 +67,14 @@ struct decoder_control {
enum decoder_state state;
enum decoder_command command;
+ /**
+ * The error that occurred in the decoder thread. This
+ * attribute is only valid if #state is #DECODE_STATE_ERROR.
+ * The object must be freed when this object transitions to
+ * any other state (usually #DECODE_STATE_START).
+ */
+ GError *error;
+
bool quit;
bool seek_error;
bool seekable;
@@ -82,8 +90,11 @@ struct decoder_control {
* The song currently being decoded. This attribute is set by
* the player thread, when it sends the #DECODE_COMMAND_START
* command.
+ *
+ * This is a duplicate, and must be freed when this attribute
+ * is cleared.
*/
- const struct song *song;
+ struct song *song;
/**
* The initial seek position (in milliseconds), e.g. to the
@@ -188,6 +199,50 @@ decoder_has_failed(const struct decoder_control *dc)
return dc->state == DECODE_STATE_ERROR;
}
+/**
+ * Checks whether an error has occurred, and if so, returns a newly
+ * allocated copy of the #GError object.
+ *
+ * Caller must lock the object.
+ */
+static inline GError *
+dc_get_error(const struct decoder_control *dc)
+{
+ assert(dc != NULL);
+ assert(dc->command == DECODE_COMMAND_NONE);
+ assert(dc->state != DECODE_STATE_ERROR || dc->error != NULL);
+
+ return dc->state == DECODE_STATE_ERROR
+ ? g_error_copy(dc->error)
+ : NULL;
+}
+
+/**
+ * Like dc_get_error(), but locks and unlocks the object.
+ */
+static inline GError *
+dc_lock_get_error(struct decoder_control *dc)
+{
+ decoder_lock(dc);
+ GError *error = dc_get_error(dc);
+ decoder_unlock(dc);
+ return error;
+}
+
+/**
+ * Clear the error condition and free the #GError object (if any).
+ *
+ * Caller must lock the object.
+ */
+static inline void
+dc_clear_error(struct decoder_control *dc)
+{
+ if (dc->state == DECODE_STATE_ERROR) {
+ g_error_free(dc->error);
+ dc->state = DECODE_STATE_STOP;
+ }
+}
+
static inline bool
decoder_lock_is_idle(struct decoder_control *dc)
{
@@ -224,28 +279,35 @@ decoder_lock_has_failed(struct decoder_control *dc)
return ret;
}
-static inline const struct song *
-decoder_current_song(const struct decoder_control *dc)
-{
- switch (dc->state) {
- case DECODE_STATE_STOP:
- case DECODE_STATE_ERROR:
- return NULL;
-
- case DECODE_STATE_START:
- case DECODE_STATE_DECODE:
- return dc->song;
- }
+/**
+ * Check if the specified song is currently being decoded. If the
+ * decoder is not running currently (or being started), then this
+ * function returns false in any case.
+ *
+ * Caller must lock the object.
+ */
+gcc_pure
+bool
+decoder_is_current_song(const struct decoder_control *dc,
+ const struct song *song);
- assert(false);
- return NULL;
+gcc_pure
+static inline bool
+decoder_lock_is_current_song(struct decoder_control *dc,
+ const struct song *song)
+{
+ decoder_lock(dc);
+ const bool result = decoder_is_current_song(dc, song);
+ decoder_unlock(dc);
+ return result;
}
/**
* Start the decoder.
*
* @param the decoder
- * @param song the song to be decoded
+ * @param song the song to be decoded; the given instance will be
+ * owned and freed by the decoder
* @param start_ms see #decoder_control
* @param end_ms see #decoder_control
* @param pipe the pipe which receives the decoded chunks (owned by