diff --git a/README.md b/README.md
index f2c55564..5959892b 100644
--- a/README.md
+++ b/README.md
@@ -250,7 +250,7 @@ Parameters that are enabled by default have to be explicitly disabled. These (cu
| `vsync`
`gl_vsync` | Set vsync for OpenGL or Vulkan |
| `media_player` | Show media player metadata |
| `media_player_name` | Force media player DBus service name without the `org.mpris.MediaPlayer2` part, like `spotify`, `vlc`, `audacious` or `cantata`. If none is set, MangoHud tries to switch between currently playing players. |
-| `media_player_order` | Media player metadata field order. Defaults to `title,artist,album`. |
+| `media_player_format` | Format media player metadata. Add extra text etc. Semi-colon breaks to new line. Defaults to `{title};{artist};{album}`. |
| `font_scale_media_player` | Change size of media player text relative to font_size |
| `io_read`
`io_write` | Show non-cached IO read/write, in MiB/s |
| `pci_dev` | Select GPU device in multi-gpu setups |
diff --git a/bin/MangoHud.conf b/bin/MangoHud.conf
index c82ba310..b49b7870 100644
--- a/bin/MangoHud.conf
+++ b/bin/MangoHud.conf
@@ -117,7 +117,9 @@ frame_timing
### Display media player metadata
# media_player
# media_player_name=spotify
-# media_player_order=title,artist,album
+## Format metadata, lines are delimited by ; (wip)
+# media_player_format={title};{artist};{album}
+# media_player_format=Track:;{title};By:;{artist};From:;{album}
### Change the hud font size
# font_size=24
diff --git a/src/dbus_info.h b/src/dbus_info.h
index 762b8b31..6d0ddcd3 100644
--- a/src/dbus_info.h
+++ b/src/dbus_info.h
@@ -28,6 +28,12 @@ struct metadata {
bool got_playback_data = false;
};
+struct mp_fmt
+{
+ std::string text;
+ float width;
+};
+
struct mutexed_metadata {
std::mutex mtx;
metadata meta;
@@ -37,9 +43,7 @@ struct mutexed_metadata {
int dir = -1;
bool needs_recalc = true;
- float tw0;
- float tw1;
- float tw2;
+ std::vector formatted;
} ticker;
};
diff --git a/src/overlay.cpp b/src/overlay.cpp
index ead08efe..4d9a4d59 100644
--- a/src/overlay.cpp
+++ b/src/overlay.cpp
@@ -284,13 +284,26 @@ void render_mpris_metadata(struct overlay_params& params, mutexed_metadata& meta
//ImGui::PushFont(data.font1);
if (meta.ticker.needs_recalc) {
- meta.ticker.tw0 = ImGui::CalcTextSize(meta.meta.title.c_str()).x;
- meta.ticker.tw1 = ImGui::CalcTextSize(meta.meta.artists.c_str()).x;
- meta.ticker.tw2 = ImGui::CalcTextSize(meta.meta.album.c_str()).x;
- meta.ticker.longest = std::max(std::max(
- meta.ticker.tw0,
- meta.ticker.tw1),
- meta.ticker.tw2);
+ meta.ticker.formatted.clear();
+ meta.ticker.longest = 0;
+ for (const auto& f : params.media_player_format)
+ {
+ std::string str;
+ try
+ {
+ str = fmt::format(f,
+ fmt::arg("artist", meta.meta.artists),
+ fmt::arg("title", meta.meta.title),
+ fmt::arg("album", meta.meta.album));
+ }
+ catch (const fmt::v7::format_error& err)
+ {
+ SPDLOG_ERROR("formatting error in '{}': {}", f, err.what());
+ }
+ float w = ImGui::CalcTextSize(str.c_str()).x;
+ meta.ticker.longest = std::max(meta.ticker.longest, w);
+ meta.ticker.formatted.push_back({str, w});
+ }
meta.ticker.needs_recalc = false;
}
@@ -307,34 +320,12 @@ void render_mpris_metadata(struct overlay_params& params, mutexed_metadata& meta
meta.ticker.pos -= .5f * (frame_timing / 16666666.7f /* ns */) * meta.ticker.dir;
- for (auto order : params.media_player_order) {
- switch (order) {
- case MP_ORDER_TITLE:
- {
- new_pos = get_ticker_limited_pos(meta.ticker.pos, meta.ticker.tw0, left_limit, right_limit);
- ImGui::SetCursorPosX(new_pos);
- ImGui::TextColored(color, "%s", meta.meta.title.c_str());
- }
- break;
- case MP_ORDER_ARTIST:
- {
- new_pos = get_ticker_limited_pos(meta.ticker.pos, meta.ticker.tw1, left_limit, right_limit);
- ImGui::SetCursorPosX(new_pos);
- ImGui::TextColored(color, "%s", meta.meta.artists.c_str());
- }
- break;
- case MP_ORDER_ALBUM:
- {
- //ImGui::NewLine();
- if (!meta.meta.album.empty()) {
- new_pos = get_ticker_limited_pos(meta.ticker.pos, meta.ticker.tw2, left_limit, right_limit);
- ImGui::SetCursorPosX(new_pos);
- ImGui::TextColored(color, "%s", meta.meta.album.c_str());
- }
- }
- break;
- default: break;
- }
+ for (const auto& fmt : meta.ticker.formatted)
+ {
+ if (fmt.text.empty()) continue;
+ new_pos = get_ticker_limited_pos(meta.ticker.pos, fmt.width, left_limit, right_limit);
+ ImGui::SetCursorPosX(new_pos);
+ ImGui::TextColored(color, "%s", fmt.text.c_str());
}
if (!meta.meta.playing) {
diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp
index 227b9662..d47ec0f0 100644
--- a/src/overlay_params.cpp
+++ b/src/overlay_params.cpp
@@ -225,13 +225,14 @@ parse_load_value(const char *str)
static std::vector
-parse_str_tokenize(const char *str)
+parse_str_tokenize(const char *str, const std::string& delims = ",:+", bool btrim = true)
{
std::vector data;
- auto tokens = str_tokenize(str);
+ auto tokens = str_tokenize(str, delims);
std::string token;
for (auto& token : tokens) {
- trim(token);
+ if (btrim)
+ trim(token);
data.push_back(token);
}
return data;
@@ -283,25 +284,6 @@ parse_path(const char *str)
return str;
}
-static std::vector
-parse_media_player_order(const char *str)
-{
- std::vector order;
- auto tokens = str_tokenize(str);
- for (auto& token : tokens) {
- trim(token);
- std::transform(token.begin(), token.end(), token.begin(), ::tolower);
- if (token == "title")
- order.push_back(MP_ORDER_TITLE);
- else if (token == "artist")
- order.push_back(MP_ORDER_ARTIST);
- else if (token == "album")
- order.push_back(MP_ORDER_ALBUM);
- }
- return order;
-}
-
-
static std::vector
parse_benchmark_percentiles(const char *str)
{
@@ -440,7 +422,7 @@ parse_gl_size_query(const char *str)
#define parse_fps_value(s) parse_load_value(s)
#define parse_fps_color(s) parse_load_color(s)
#define parse_battery_color(s) parse_color(s)
-
+#define parse_media_player_format(s) parse_str_tokenize(s, ";", false)
static bool
parse_help(const char *str)
@@ -618,7 +600,7 @@ parse_overlay_config(struct overlay_params *params,
params->cpu_load_color = { 0x39f900, 0xfdfd09, 0xb22222 };
params->font_scale_media_player = 0.55f;
params->log_interval = 100;
- params->media_player_order = { MP_ORDER_TITLE, MP_ORDER_ARTIST, MP_ORDER_ALBUM };
+ params->media_player_format = { "{title}", "{artist}", "{album}" };
params->permit_upload = 0;
params->benchmark_percentiles = { "97", "AVG", "1", "0.1" };
params->gpu_load_value = { 60, 90 };
diff --git a/src/overlay_params.h b/src/overlay_params.h
index 4c0d391b..36aef580 100644
--- a/src/overlay_params.h
+++ b/src/overlay_params.h
@@ -124,7 +124,7 @@ typedef unsigned long KeySym;
OVERLAY_PARAM_CUSTOM(pci_dev) \
OVERLAY_PARAM_CUSTOM(media_player_name) \
OVERLAY_PARAM_CUSTOM(media_player_color) \
- OVERLAY_PARAM_CUSTOM(media_player_order) \
+ OVERLAY_PARAM_CUSTOM(media_player_format) \
OVERLAY_PARAM_CUSTOM(cpu_text) \
OVERLAY_PARAM_CUSTOM(gpu_text) \
OVERLAY_PARAM_CUSTOM(log_interval) \
@@ -159,12 +159,6 @@ enum overlay_plots {
OVERLAY_PLOTS_MAX,
};
-enum media_player_order {
- MP_ORDER_TITLE,
- MP_ORDER_ARTIST,
- MP_ORDER_ALBUM,
-};
-
enum font_glyph_ranges {
FG_KOREAN = (1u << 0),
FG_CHINESE_FULL = (1u << 1),
@@ -239,7 +233,7 @@ struct overlay_params {
std::string cpu_text, gpu_text;
std::vector blacklist;
unsigned log_interval, autostart_log;
- std::vector media_player_order;
+ std::vector media_player_format;
std::vector benchmark_percentiles;
std::string font_file, font_file_text;
uint32_t font_glyph_ranges;
diff --git a/src/string_utils.h b/src/string_utils.h
index e7062add..47a5acae 100644
--- a/src/string_utils.h
+++ b/src/string_utils.h
@@ -110,7 +110,7 @@ static float parse_float(const std::string& s, std::size_t* float_len = nullptr)
return ret;
}
-static std::vector str_tokenize(const std::string& s, const std::string&& delims = ",:+")
+static std::vector str_tokenize(const std::string& s, const std::string& delims = ",:+")
{
std::vector v;
size_t old_n = 0, new_n = 0;