From ee8db58fb25a3deb20953cea0fd7f6fa5865ef81 Mon Sep 17 00:00:00 2001 From: Anna Schumaker Date: Tue, 19 Jul 2022 15:51:22 -0400 Subject: [PATCH] audio: Add an 'artwork' property And use it to track the existence of artwork for the current file. This could either be a cover.jpg file in the same directory as the currently playing track or embedded artwork found in the Gst.TagList. Signed-off-by: Anna Schumaker --- emmental/__init__.py | 2 +- emmental/audio/__init__.py | 20 +++++++++++++++++--- emmental/mpris2/player.py | 6 +++++- tests/audio/test_audio.py | 33 +++++++++++++++++++++++++++++++++ tests/mpris2/test_player.py | 5 +++++ tests/util/__init__.py | 3 +++ tests/util/cover.jpg | Bin 0 -> 29866 bytes 7 files changed, 64 insertions(+), 5 deletions(-) create mode 100644 tests/util/cover.jpg diff --git a/emmental/__init__.py b/emmental/__init__.py index d079e38..8204860 100644 --- a/emmental/__init__.py +++ b/emmental/__init__.py @@ -114,7 +114,7 @@ class Application(Adw.Application): self.mpris.app.connect("Quit", self.win.close) for tag in ["artist", "album", "album-artist", "album-disc-number", - "title", "track-number", "duration", "file"]: + "title", "track-number", "duration", "file", "artwork"]: self.player.bind_property(tag, self.mpris.player, tag) for (prop, mpris_prop) in [("have-track", "CanPlay"), ("have-track", "CanPause"), diff --git a/emmental/audio/__init__.py b/emmental/audio/__init__.py index 2cdfdab..92e9ceb 100644 --- a/emmental/audio/__init__.py +++ b/emmental/audio/__init__.py @@ -6,6 +6,7 @@ from gi.repository import GLib from gi.repository import Gst from . import replaygain from .. import path +from .. import tmpdir UPDATE_INTERVAL = 100 @@ -24,6 +25,7 @@ class Player(GObject.GObject): position = GObject.Property(type=float, default=0) duration = GObject.Property(type=float, default=0) volume = GObject.Property(type=float, default=1.0) + artwork = GObject.Property(type=GObject.TYPE_PYOBJECT) file = GObject.Property(type=GObject.TYPE_PYOBJECT) playing = GObject.Property(type=bool, default=False) @@ -92,8 +94,16 @@ class Player(GObject.GObject): def __msg_tags(self, bus: Gst.Bus, message: Gst.Message) -> None: taglist = message.parse_tag() for tag in ["artist", "album", "album-artist", "album-disc-number", - "title", "track-number"]: + "title", "track-number", "artwork"]: match tag: + case "artwork": + (res, sample) = taglist.get_sample("image") + if res: + buffer = sample.get_buffer() + (res, map) = buffer.map(Gst.MapFlags.READ) + if res: + value = tmpdir.cover_jpg(map.data) + buffer.unmap(map) case "track-number" | "album-disc-number": (res, value) = taglist.get_uint(tag) case _: @@ -107,11 +117,13 @@ class Player(GObject.GObject): print(f"audio: loading {uri}") self._playbin.set_property("uri", uri) - def __reset_properties(self, *, duration: float = 0.0) -> None: + def __reset_properties(self, *, duration: float = 0.0, + artwork: pathlib.Path | None = None) -> None: for tag in ["artist", "album-artist", "album", "title"]: self.set_property(tag, "") for tag in ["album-disc-number", "track-number", "position"]: self.set_property(tag, 0) + self.artwork = artwork self.duration = duration def __update_position(self) -> bool: @@ -176,7 +188,9 @@ class Player(GObject.GObject): """Signal that a new URI has started.""" print("audio: file loaded") (res, dur) = self._playbin.query_duration(Gst.Format.TIME) - self.__reset_properties(duration=(dur / Gst.USECOND if res else 0)) + cover = self.file.parent / "cover.jpg" + self.__reset_properties(duration=(dur / Gst.USECOND if res else 0), + artwork=(cover if cover.is_file() else None)) self.have_track = True @GObject.Signal diff --git a/emmental/mpris2/player.py b/emmental/mpris2/player.py index abe5308..e4d3889 100644 --- a/emmental/mpris2/player.py +++ b/emmental/mpris2/player.py @@ -38,6 +38,7 @@ class Player(dbus.Object): trackid = GObject.Property(type=int) file = GObject.Property(type=GObject.TYPE_PYOBJECT) + artwork = GObject.Property(type=GObject.TYPE_PYOBJECT) def __init__(self): """Initialize the mpris2 application object.""" @@ -47,7 +48,8 @@ class Player(dbus.Object): """Notify DBus when tags change.""" match property: case "artist" | "album" | "album-artist" | "album-disc-number" | \ - "title" | "track-number" | "duration" | "trackid" | "uri": + "title" | "track-number" | "duration" | "trackid" | \ + "uri" | "artwork": changed = GLib.Variant("a{sv}", self.Metadata) self.properties_changed({"Metadata": changed}) case "PlaybackStatus": @@ -73,6 +75,8 @@ class Player(dbus.Object): res["mpris:length"] = GLib.Variant("x", self.duration) res["xesam:url"] = GLib.Variant("s", self.file.as_uri()) + if self.artwork is not None: + res["mpris:artUrl"] = GLib.Variant("s", self.artwork.as_uri()) if len(self.artist) > 0: res["xesam:artist"] = GLib.Variant("as", [self.artist]) if len(self.album) > 0: diff --git a/tests/audio/test_audio.py b/tests/audio/test_audio.py index ab316a9..49db631 100644 --- a/tests/audio/test_audio.py +++ b/tests/audio/test_audio.py @@ -1,6 +1,7 @@ # Copyright 2022 (c) Anna Schumaker. """Tests our GObject audio player wrapping a GStreamer Playbin element.""" import io +import pathlib import unittest import unittest.mock import emmental.audio @@ -58,6 +59,7 @@ class TestAudio(unittest.TestCase): self.player.file = tests.util.TRACK_OGG self.player.duration = 10 self.player.position = 8 + self.player.artwork = pathlib.Path("/a/b/c.jpg") eos = Gst.Message.new_eos(self.player._playbin) self.player._playbin.get_bus().post(eos) @@ -70,6 +72,7 @@ class TestAudio(unittest.TestCase): for prop in ["album-disc-number", "track-number", "position", "duration"]: self.assertEqual(self.player.get_property(prop), 0) + self.assertIsNone(self.player.artwork) self.assertEqual(self.player.get_state(), Gst.State.READY) self.assertEqual(self.player.status, "Stopped") @@ -254,6 +257,36 @@ class TestAudio(unittest.TestCase): self.assertRegex(mock_stdout.getvalue(), r"audio: setting ReplayGain mode to 'disabled'") + @unittest.mock.patch("sys.stdout", new_callable=io.StringIO) + def test_artwork(self, mock_stdout: io.StringIO): + """Test that we handle album artwork.""" + self.assertIsNone(self.player.artwork) + + with unittest.mock.patch.object(pathlib.Path, "is_file", + return_value=False): + self.player.file = tests.util.TRACK_OGG + self.player.pause() + self.main_loop() + self.assertIsNone(self.player.artwork) + + self.player.stop() + self.player.pause() + self.main_loop() + self.assertEqual(self.player.artwork, tests.util.COVER_JPG) + + buffer = Gst.Buffer.new_wrapped_bytes(tests.util.COVER_JPG_BYTES) + taglist = Gst.TagList.new_empty() + taglist.add_value(Gst.TagMergeMode.APPEND, "image", + Gst.Sample.new(buffer)) + tag = Gst.Message.new_tag(self.player._playbin, taglist) + self.player._playbin.get_bus().post(tag) + self.main_loop() + + expected = emmental.tmpdir.cover_jpg() + self.assertEqual(self.player.artwork, + emmental.tmpdir.cover_jpg()) + self.assertTrue(expected.is_file()) + def test_shutdown(self): """Test that the shutdown function works as expected.""" self.player.shutdown() diff --git a/tests/mpris2/test_player.py b/tests/mpris2/test_player.py index e596326..192aaf5 100644 --- a/tests/mpris2/test_player.py +++ b/tests/mpris2/test_player.py @@ -4,6 +4,7 @@ import pathlib import unittest import unittest.mock import emmental.mpris2.player +import tests.util from gi.repository import GLib from gi.repository import Gio @@ -57,6 +58,7 @@ class TestPlayer(unittest.TestCase): self.assertEqual(self.player.duration, 0) self.assertEqual(self.player.trackid, 0) self.assertIsNone(self.player.file) + self.assertIsNone(self.player.artwork) self.assertDictEqual(self.player.Metadata, {}) @@ -66,11 +68,14 @@ class TestPlayer(unittest.TestCase): self.player.title = "Test Title" self.player.duration = 12345 self.player.file = pathlib.Path("/a/b/c.ogg") + self.player.artwork = tests.util.COVER_JPG + cover_uri = tests.util.COVER_JPG.as_uri() res = {"mpris:trackid": GLib.Variant("o", "/com/nowheycreamery/emmental/0"), "mpris:length": GLib.Variant("x", 12345), "xesam:url": GLib.Variant("s", "file:///a/b/c.ogg"), + "mpris:artUrl": GLib.Variant("s", cover_uri), "xesam:album": GLib.Variant("s", "Test Album"), "xesam:albumArtist": GLib.Variant("as", ["Test Album Artist"]), "xesam:artist": GLib.Variant("as", ["Test Artist"]), diff --git a/tests/util/__init__.py b/tests/util/__init__.py index b5061f2..347493c 100644 --- a/tests/util/__init__.py +++ b/tests/util/__init__.py @@ -4,9 +4,12 @@ import pathlib import unittest import emmental.db from gi.repository import GObject +from gi.repository import GLib TRACK_OGG = pathlib.Path(__file__).parent / "track.ogg" +COVER_JPG = pathlib.Path(__file__).parent / "cover.jpg" +COVER_JPG_BYTES = GLib.Bytes(COVER_JPG.open("rb").read()) class TestCase(unittest.TestCase): diff --git a/tests/util/cover.jpg b/tests/util/cover.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c6991634d36b4a93fe2e93bb210d1ac8e17c961c GIT binary patch literal 29866 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