diff --git a/include/modules/mpris/mpris.hpp b/include/modules/mpris/mpris.hpp index ea5f7de6..aff2673c 100644 --- a/include/modules/mpris/mpris.hpp +++ b/include/modules/mpris/mpris.hpp @@ -66,6 +66,8 @@ class Mpris : public ALabel { int album_len_; int title_len_; int dynamic_len_; + std::string dynamic_separator_; + std::vector dynamic_order_; std::vector dynamic_prio_; bool truncate_hours_; bool tooltip_len_limits_; diff --git a/man/waybar-mpris.5.scd b/man/waybar-mpris.5.scd index 145e6da4..eaa1ec96 100644 --- a/man/waybar-mpris.5.scd +++ b/man/waybar-mpris.5.scd @@ -71,12 +71,27 @@ The *mpris* module displays currently playing media via libplayerctl. something less than or equal to this value, so the title will always be ++ displayed. +*dynamic-order*: ++ + typeof: []string ++ + default: ["title", "artist", "album", "position", "length"] ++ + Order of the tags shown by Dynamic tag. The position and length tags ++ + will always be combined in the format [{position}/{length}]. The order ++ + of these tags in relation to other tags will be determined based on the ++ + declaration of the first among the two tags. Absence in this list means ++ + force exclusion. + *dynamic-priority*: ++ typeof: []string ++ default: ["title", "length", "position", "artist", "album"] ++ Priority of the tags when truncating the Dynamic tag (absence in this list means force inclusion). +*dynamic-separator*: ++ + typeof: string ++ + default: " - " ++ + These characters will be used to separate two different tags, except ++ + when one of these tags is position and length. + *truncate-hours*: ++ typeof: bool ++ default: true ++ diff --git a/src/modules/mpris/mpris.cpp b/src/modules/mpris/mpris.cpp index e4346941..0f83f87b 100644 --- a/src/modules/mpris/mpris.cpp +++ b/src/modules/mpris/mpris.cpp @@ -24,7 +24,9 @@ Mpris::Mpris(const std::string& id, const Json::Value& config) album_len_(-1), title_len_(-1), dynamic_len_(-1), - dynamic_prio_({"title", "length", "position", "artist", "album"}), + dynamic_prio_({"title", "artist", "album", "position", "length"}), + dynamic_order_({"title", "artist", "album", "position", "length"}), + dynamic_separator_(" - "), truncate_hours_(true), tooltip_len_limits_(false), // this character is used in Gnome so it's fine to use it here @@ -44,6 +46,9 @@ Mpris::Mpris(const std::string& id, const Json::Value& config) if (config_["ellipsis"].isString()) { ellipsis_ = config_["ellipsis"].asString(); } + if (config_["dynamic-separator"].isString()) { + dynamic_separator_ = config_["dynamic-separator"].asString(); + } if (tooltipEnabled()) { if (config_["tooltip-format"].isString()) { tooltip_ = config_["tooltip-format"].asString(); @@ -83,6 +88,14 @@ Mpris::Mpris(const std::string& id, const Json::Value& config) } } } + if (config_["dynamic-order"].isArray()) { + dynamic_order_.clear(); + for (auto it = config_["dynamic-order"].begin(); it != config_["dynamic-order"].end(); ++it) { + if (it->isString()) { + dynamic_order_.push_back(it->asString()); + } + } + } if (config_["truncate-hours"].isBool()) { truncate_hours_ = config["truncate-hours"].asBool(); @@ -272,18 +285,28 @@ auto Mpris::getDynamicStr(const PlayerInfo& info, bool truncated, bool html) -> size_t lengthLen = length.length(); size_t posLen = position.length(); - bool showArtist = artistLen != 0; - bool showAlbum = albumLen != 0; - bool showTitle = titleLen != 0; - bool showLength = lengthLen != 0; - bool showPos = posLen != 0; + bool showArtist = (artistLen != 0) && (std::find(dynamic_order_.begin(), dynamic_order_.end(), + "artist") != dynamic_order_.end()); + bool showAlbum = (albumLen != 0) && (std::find(dynamic_order_.begin(), dynamic_order_.end(), + "album") != dynamic_order_.end()); + bool showTitle = (titleLen != 0) && (std::find(dynamic_order_.begin(), dynamic_order_.end(), + "title") != dynamic_order_.end()); + bool showLength = (lengthLen != 0) && (std::find(dynamic_order_.begin(), dynamic_order_.end(), + "length") != dynamic_order_.end()); + bool showPos = (posLen != 0) && (std::find(dynamic_order_.begin(), dynamic_order_.end(), + "position") != dynamic_order_.end()); if (truncated && dynamic_len_ >= 0) { - size_t dynamicLen = dynamic_len_; - if (showArtist) artistLen += 3; - if (showAlbum) albumLen += 3; - if (showLength) lengthLen += 3; - if (showPos) posLen += 3; + //Since the first element doesn't present a separator and we don't know a priori which one + //it will be, we add a "virtual separatorLen" to the dynamicLen, since we are adding the + //separatorLen to all the other lengths. + size_t separatorLen = utf8_width(dynamic_separator_); + size_t dynamicLen = dynamic_len_ + separatorLen; + if (showArtist) artistLen += separatorLen; + if (showAlbum) albumLen += separatorLen; + if (showTitle) albumLen += separatorLen; + if (showLength) lengthLen += separatorLen; + if (showPos) posLen += separatorLen; size_t totalLen = 0; @@ -330,20 +353,47 @@ auto Mpris::getDynamicStr(const PlayerInfo& info, bool truncated, bool html) -> album = Glib::Markup::escape_text(album); title = Glib::Markup::escape_text(title); } - if (showArtist) dynamic << artist << " - "; - if (showAlbum) dynamic << album << " - "; - if (showTitle) dynamic << title; - if (showLength || showPos) { - dynamic << ' '; - if (html) dynamic << ""; - dynamic << '['; - if (showPos) { - dynamic << position; - if (showLength) dynamic << '/'; + + bool lengthOrPositionShown = false; + bool previousShown = false; + std::string previousOrder = ""; + + for (const std::string& order : dynamic_order_) { + if ((order == "artist" && showArtist) || + (order == "album" && showAlbum) || + (order == "title" && showTitle)) { + if (previousShown && + previousOrder != "length" && + previousOrder != "position") { + dynamic << dynamic_separator_; + } + + if (order == "artist") { + dynamic << artist; + } else if (order == "album") { + dynamic << album; + } else if (order == "title") { + dynamic << title; + } + + previousShown = true; + } else if (order == "length" || order == "position") { + if (!lengthOrPositionShown && (showLength || showPos)) { + if (html) dynamic << ""; + if (previousShown) dynamic << ' '; + dynamic << '['; + if (showPos) { + dynamic << position; + if (showLength) dynamic << '/'; + } + if (showLength) dynamic << length; + dynamic << ']'; + if (!dynamic.str().empty()) dynamic << ' '; + if (html) dynamic << ""; + lengthOrPositionShown = true; + } } - if (showLength) dynamic << length; - dynamic << ']'; - if (html) dynamic << ""; + previousOrder = order; } return dynamic.str(); }