diff --git a/include/modules/mpd/mpd.hpp b/include/modules/mpd/mpd.hpp index 32d526e9..dd9c949c 100644 --- a/include/modules/mpd/mpd.hpp +++ b/include/modules/mpd/mpd.hpp @@ -41,6 +41,7 @@ class MPD : public ALabel { private: std::string getTag(mpd_tag_type type, unsigned idx = 0) const; + Glib::ustring getArtistTitleOrFilename() const; std::string getFilename() const; void setLabel(); std::string getStateIcon() const; diff --git a/src/modules/mpd/mpd.cpp b/src/modules/mpd/mpd.cpp index 192e6c1a..77b5398a 100644 --- a/src/modules/mpd/mpd.cpp +++ b/src/modules/mpd/mpd.cpp @@ -77,6 +77,49 @@ std::string waybar::modules::MPD::getTag(mpd_tag_type type, unsigned idx) const return result; } +Glib::ustring waybar::modules::MPD::getArtistTitleOrFilename() const { + const char* artist = mpd_song_get_tag(this->song_.get(), MPD_TAG_ARTIST, 0); + const char* title = mpd_song_get_tag(this->song_.get(), MPD_TAG_TITLE, 0); + // https://mpd.readthedocs.io/en/latest/protocol.html#tags + const char* name = mpd_song_get_tag(this->song_.get(), MPD_TAG_NAME, 0); + // it is important to use Glib::ustring here, as filenames may be utf8 encoded + // DECO*27 x ピノキオピー - デビルじゃないもん feat. 初音ミク-lMEt3RdqB9Y.m4a + Glib::ustring result; + + auto starts_with = [&](const Glib::ustring& str, const char* other) { + size_t other_len = strlen(other); + if (str.size() < other_len) { + return false; + } + + for (size_t i = 0; i < other_len; i++) { + if (str[i] != other[i]) { + return false; + } + } + return true; + }; + + if (title || name) { + result = title ? title : name; + bool prepend_artist = artist != nullptr && !starts_with(result, artist); + + if (config_["title-len"].isInt()) { + result = result.substr(0, config_["title-len"].asInt()); + } + if (prepend_artist) { + result = std::string(artist) + " - " + std::move(result); + } + return result; + } + + result = this->getFilename(); + if (config_["title-len"].isInt()) { + result = result.substr(0, config_["title-len"].asInt()); + } + return result; +} + std::string waybar::modules::MPD::getFilename() const { std::string path = mpd_song_get_uri(song_.get()); size_t position = path.find_last_of("/"); @@ -117,7 +160,7 @@ void waybar::modules::MPD::setLabel() { label_.get_style_context()->remove_class("disconnected"); auto format = format_; - Glib::ustring artist, album_artist, album, title; + Glib::ustring artist, album_artist, album, title, artist_title_or_filename; std::string date, filename; int song_pos = 0, queue_length = 0, volume = 0; std::chrono::seconds elapsedTime, totalTime; @@ -151,6 +194,7 @@ void waybar::modules::MPD::setLabel() { title = sanitize_string(getTag(MPD_TAG_TITLE)); date = sanitize_string(getTag(MPD_TAG_DATE)); filename = sanitize_string(getFilename()); + artist_title_or_filename = sanitize_string(this->getArtistTitleOrFilename()); song_pos = mpd_status_get_song_pos(status_.get()) + 1; volume = mpd_status_get_volume(status_.get()); if (volume < 0) { @@ -179,7 +223,8 @@ void waybar::modules::MPD::setLabel() { auto text = fmt::format( fmt::runtime(format), fmt::arg("artist", artist.raw()), fmt::arg("albumArtist", album_artist.raw()), fmt::arg("album", album.raw()), - fmt::arg("title", title.raw()), fmt::arg("date", date), fmt::arg("volume", volume), + fmt::arg("title", title.raw()), fmt::arg("artistTitleOrFilename", artist_title_or_filename.raw()), + fmt::arg("date", date), fmt::arg("volume", volume), fmt::arg("elapsedTime", elapsedTime), fmt::arg("totalTime", totalTime), fmt::arg("songPosition", song_pos), fmt::arg("queueLength", queue_length), fmt::arg("stateIcon", stateIcon), fmt::arg("consumeIcon", consumeIcon),