aboutsummaryrefslogtreecommitdiff
path: root/mpc/song_format.c
diff options
context:
space:
mode:
Diffstat (limited to 'mpc/song_format.c')
-rw-r--r--mpc/song_format.c109
1 files changed, 109 insertions, 0 deletions
diff --git a/mpc/song_format.c b/mpc/song_format.c
new file mode 100644
index 0000000..d628459
--- /dev/null
+++ b/mpc/song_format.c
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// Copyright The Music Player Daemon Project
+
+#include "song_format.h"
+#include "audio_format.h"
+#include "format.h"
+#include "charset.h"
+
+#include <mpd/client.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+static const char *
+format_mtime(char *buffer, size_t buffer_size,
+ const struct mpd_song *song, const char *format)
+{
+ time_t t = mpd_song_get_last_modified(song);
+ if (t == 0)
+ return NULL;
+
+ struct tm tm;
+#ifdef _WIN32
+ tm = *localtime(&t);
+#else
+ localtime_r(&t, &tm);
+#endif
+
+ strftime(buffer, buffer_size, format, &tm);
+ return buffer;
+}
+
+/**
+ * Extract an attribute from a song object.
+ *
+ * @param song the song object
+ * @param name the attribute name
+ * @return the attribute value; NULL if the attribute name is invalid;
+ * an empty string if the attribute name is valid, but not present in
+ * the song
+ */
+gcc_pure
+static const char *
+song_value(const struct mpd_song *song, const char *name)
+{
+ static char buffer[40];
+ const char *value;
+
+ if (strcmp(name, "file") == 0)
+ value = mpd_song_get_uri(song);
+ else if (strcmp(name, "time") == 0) {
+ unsigned duration = mpd_song_get_duration(song);
+
+ if (duration > 0) {
+ snprintf(buffer, sizeof(buffer), "%u:%02u",
+ duration / 60, duration % 60);
+ value = buffer;
+ } else
+ value = NULL;
+ } else if (strcmp(name, "position") == 0) {
+ unsigned pos = mpd_song_get_pos(song);
+ snprintf(buffer, sizeof(buffer), "%u", pos+1);
+ value = buffer;
+ } else if (strcmp(name, "id") == 0) {
+ snprintf(buffer, sizeof(buffer), "%u", mpd_song_get_id(song));
+ value = buffer;
+ } else if (strcmp(name, "prio") == 0) {
+ snprintf(buffer, sizeof(buffer), "%u",
+ mpd_song_get_prio(song));
+ value = buffer;
+ } else if (strcmp(name, "mtime") == 0) {
+ value = format_mtime(buffer, sizeof(buffer), song, "%c");
+ } else if (strcmp(name, "mdate") == 0) {
+ value = format_mtime(buffer, sizeof(buffer), song, "%x");
+ } else if (strcmp(name, "audioformat") == 0) {
+ const struct mpd_audio_format *audio_format = mpd_song_get_audio_format(song);
+ if (audio_format == NULL)
+ return NULL;
+
+ format_audio_format(buffer, sizeof(buffer), audio_format);
+ value = buffer;
+ } else {
+ enum mpd_tag_type tag_type = mpd_tag_name_iparse(name);
+ if (tag_type == MPD_TAG_UNKNOWN)
+ return NULL;
+
+ value = mpd_song_get_tag(song, tag_type, 0);
+ }
+
+ if (value != NULL)
+ value = charset_from_utf8(value);
+ else
+ value = "";
+
+ return value;
+}
+
+static const char *
+song_getter(const void *object, const char *name)
+{
+ return song_value((const struct mpd_song *)object, name);
+}
+
+char *
+format_song(const struct mpd_song *song, const char *format)
+{
+ return format_object(format, song, song_getter);
+}