From b4480bafa621ce87634b03552cb14f94e87a744d Mon Sep 17 00:00:00 2001
From: Aproxia-dev <apro@r4ilax.eu>
Date: Mon, 17 Apr 2023 15:05:44 +0200
Subject: [PATCH 1/2] Added metadata_v2

---
 signal/playerctl/playerctl_lib.lua | 145 ++++++++++++++++++++++-------
 1 file changed, 109 insertions(+), 36 deletions(-)

diff --git a/signal/playerctl/playerctl_lib.lua b/signal/playerctl/playerctl_lib.lua
index ca196333..4e19d9e4 100644
--- a/signal/playerctl/playerctl_lib.lua
+++ b/signal/playerctl/playerctl_lib.lua
@@ -66,9 +66,27 @@ function playerctl:disable()
     self._private.last_position = -1
     self._private.last_length = -1
     self._private.last_player = nil
-    self._private.last_title = ""
-    self._private.last_artist = ""
-    self._private.last_artUrl = ""
+    self._private.last_metadata_table = {
+        album          = "",
+        albumArtist    = "",
+        artist         = "",
+        asText         = "",
+        audioBPM       = "",
+        autoRating     = "",
+        comment        = "",
+        composer       = "",
+        contentCreated = "",
+        discNumber     = "",
+        firstUsed      = "",
+        genre          = "",
+        lastUsed       = "",
+        lyricist       = "",
+        title          = "",
+        trackNumber    = "",
+        url            = "",
+        useCount       = "",
+        userRating     = "",
+    }
 end
 
 function playerctl:pause(player)
@@ -179,25 +197,46 @@ function playerctl:get_player_of_name(name)
     return nil
 end
 
-local function emit_metadata_signal(self, title, artist, artUrl, album, new, player_name)
-    title = gstring.xml_escape(title)
-    artist = gstring.xml_escape(artist)
-    album = gstring.xml_escape(album)
+local function join_table_of_strings(t)
+    if type(t) ~= "table" then return "" end
+    local out = t[1]
+    for i = 2, #t do
+        out = out .. ", " .. t[i]
+    end
+	return out
+end
+
+local function emit_metadata_signal(self, metadata, new, player_name)
+    for i, v in pairs(metadata) do
+        if i ~= "artUrl" and type(v) ~= "number" then
+            metadata[i] = gstring.xml_escape(v)
+        end
+    end
 
     -- Spotify client doesn't report its art URL's correctly...
     if player_name == "spotify" then
-        artUrl = artUrl:gsub("open.spotify.com", "i.scdn.co")
+        metadata.artUrl = metadata.artUrl:gsub("open.spotify.com", "i.scdn.co")
     end
 
-    if artUrl ~= "" then
+    if metadata.artUrl ~= "" then
         local art_path = os.tmpname()
-        helpers.filesystem.save_image_async_curl(artUrl, art_path, function()
-            self:emit_signal("metadata", title, artist, art_path, album, new, player_name)
-            capi.awesome.emit_signal("bling::playerctl::title_artist_album", title, artist, art_path, player_name)
+        helpers.filesystem.save_image_async_curl(metadata.artUrl, art_path, function()
+            if self.metadata_v2 then
+                self:emit_signal("metadata", metadata, art_path, new, player_name)
+                capi.awesome.emit_signal("bling::playerctl::title_artist_album", metadata, art_path, player_name)
+            elseif not self.metadata_v2 then
+                self:emit_signal("metadata", metadata.title, metadata.artist, art_path, metadata.album, new, player_name)
+                capi.awesome.emit_signal("bling::playerctl::title_artist_album", metadata.title, metadata.artist, art_path, player_name)
+            end
         end)
     else
-        capi.awesome.emit_signal("bling::playerctl::title_artist_album", title, artist, "", player_name)
-        self:emit_signal("metadata", title, artist, "", album, new, player_name)
+        if self.metadata_v2 then
+            self:emit_signal("metadata", metadata, "", new, player_name)
+            capi.awesome.emit_signal("bling::playerctl::title_artist_album", metadata, "", player_name)
+        elseif not self.metadata_v2 then
+            self:emit_signal("metadata", metadata.title, metadata.artist, "", metadata.album, new, player_name)
+            capi.awesome.emit_signal("bling::playerctl::title_artist_album", metadata.title, metadata.artist, "", player_name)
+        end
     end
 end
 
@@ -208,13 +247,30 @@ local function metadata_cb(self, player, metadata)
 
     local data = metadata.value
 
-    local title = data["xesam:title"] or ""
-    local artist = data["xesam:artist"][1] or ""
-    for i = 2, #data["xesam:artist"] do
-        artist = artist .. ", " .. data["xesam:artist"][i]
-    end
-    local artUrl = data["mpris:artUrl"] or ""
-    local album = data["xesam:album"] or ""
+    local metadata_table = {
+        album          = data["xesam:album"]          or "",
+        artUrl         = data["mpris:artUrl"]         or "",
+        asText         = data["xesam:asText"]         or "",
+        audioBPM       = data["xesam:audioBPM"]       or "",
+        autoRating     = data["xesam:autoRating"]     or "",
+        contentCreated = data["xesam:contentCreated"] or "",
+        discNumber     = data["xesam:discNumber"]     or "",
+        firstUsed      = data["xesam:firstUsed"]      or "",
+        lastUsed       = data["xesam:lastUsed"]       or "",
+        title          = data["xesam:title"]          or "",
+        trackNumber    = data["xesam:trackNumber"]    or "",
+        url            = data["xesam:url"]            or "",
+        useCount       = data["xesam:useCount"]       or "",
+        userRating     = data["xesam:userRating"]     or "",
+    }
+
+    metadata_table.albumArtist = join_table_of_strings(data["xesam:albumArtist"])
+    metadata_table.artist      = join_table_of_strings(data["xesam:artist"])
+    metadata_table.comment     = join_table_of_strings(data["xesam:comment"])
+    metadata_table.composer    = join_table_of_strings(data["xesam:composer"])
+    metadata_table.genre       = join_table_of_strings(data["xesam:genre"])
+    metadata_table.lyricist    = join_table_of_strings(data["xesam:lyricist"])
+
 
     if player == self._private.manager.players[1] then
         self._private.active_player = player
@@ -223,11 +279,9 @@ local function metadata_cb(self, player, metadata)
         -- changed, so check to see if they have
         if
             player ~= self._private.last_player
-            or title ~= self._private.last_title
-            or artist ~= self._private.last_artist
-            or artUrl ~= self._private.last_artUrl
+            or metadata_table ~= self._private.last_metadata_table
         then
-            if (title == "" and artist == "" and artUrl == "") then return end
+            if (metadata_table.title == "" and metadata_table.artist == "" and metadata_table.artUrl == "") then return end
 
             if self._private.metadata_timer ~= nil and self._private.metadata_timer.started then
                 self._private.metadata_timer:stop()
@@ -238,16 +292,14 @@ local function metadata_cb(self, player, metadata)
                 autostart = true,
                 single_shot = true,
                 callback = function()
-                    emit_metadata_signal(self, title, artist, artUrl, album, true, player.player_name)
+                    emit_metadata_signal(self, metadata_table, true, player.player_name)
                 end
             }
 
             -- Re-sync with position timer when track changes
             self._private.position_timer:again()
             self._private.last_player = player
-            self._private.last_title = title
-            self._private.last_artist = artist
-            self._private.last_artUrl = artUrl
+            self._private.last_metadata_table = metadata_table
         end
     end
 end
@@ -430,12 +482,10 @@ local function player_compare(self, a, b)
 end
 
 local function get_current_player_info(self, player)
-    local title = player:get_title() or ""
-    local artist = player:get_artist() or ""
+    local metadata = player.metadata
     local artUrl = player:print_metadata_prop("mpris:artUrl") or ""
-    local album = player:get_album() or ""
 
-    emit_metadata_signal(self, title, artist, artUrl, album, false, player.player_name)
+    metadata_cb(self, metadata, artUrl, false, player.player_name)
     playback_status_cb(self, player, player.playback_status)
     volume_cb(self, player, player.volume)
     loop_status_cb(self, player, player.loop_status)
@@ -526,6 +576,11 @@ local function new(args)
     else
         ret.update_on_activity = beautiful.playerctl_update_on_activity ~= false
     end
+    if args.metadata_v2 ~= nil then
+        ret.metadata_v2 = args.metadata_v2
+    else
+        ret.metadata_v2 = false -- Default to the old way of passing metadata for backwards compatibility
+    end
     ret.interval = args.interval or beautiful.playerctl_position_update_interval or 1
     ret.debounce_delay = args.debounce_delay or beautiful.playerctl_debounce_delay or 0.35
     parse_args(ret, args)
@@ -534,9 +589,27 @@ local function new(args)
 
     -- Metadata callback for title, artist, and album art
     ret._private.last_player = nil
-    ret._private.last_title = ""
-    ret._private.last_artist = ""
-    ret._private.last_artUrl = ""
+    ret._private.last_metadata_table = {
+        album          = "",
+        albumArtist    = "",
+        artist         = "",
+        asText         = "",
+        audioBPM       = "",
+        autoRating     = "",
+        comment        = "",
+        composer       = "",
+        contentCreated = "",
+        discNumber     = "",
+        firstUsed      = "",
+        genre          = "",
+        lastUsed       = "",
+        lyricist       = "",
+        title          = "",
+        trackNumber    = "",
+        url            = "",
+        useCount       = "",
+        userRating     = "",
+    }
 
     -- Track position callback
     ret._private.last_position = -1

From 9c9c24b39b268133e2073bdd70154ff44844528e Mon Sep 17 00:00:00 2001
From: Aproxia-dev <apro@r4ilax.eu>
Date: Mon, 17 Apr 2023 15:22:18 +0200
Subject: [PATCH 2/2] fix(playerctl): metadata didn't show the artist(s)

---
 signal/playerctl/playerctl_lib.lua | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/signal/playerctl/playerctl_lib.lua b/signal/playerctl/playerctl_lib.lua
index 4e19d9e4..23d8c53c 100644
--- a/signal/playerctl/playerctl_lib.lua
+++ b/signal/playerctl/playerctl_lib.lua
@@ -198,7 +198,7 @@ function playerctl:get_player_of_name(name)
 end
 
 local function join_table_of_strings(t)
-    if type(t) ~= "table" then return "" end
+    if type(t) == "nil" then return "" end
     local out = t[1]
     for i = 2, #t do
         out = out .. ", " .. t[i]