audio: Rework the Artwork widget
It now sets artwork based on the signals sent by the player, allowing us to move it out of the Player class and create instances based on the global Player instead. Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
parent
f55377cc69
commit
3a50235c38
|
@ -15,6 +15,9 @@ tagdb.Stack.Counter = Player.Autopause
|
||||||
def AudioControls():
|
def AudioControls():
|
||||||
return controls.AudioControls(Player, Player.Autopause)
|
return controls.AudioControls(Player, Player.Autopause)
|
||||||
|
|
||||||
|
def Artwork():
|
||||||
|
return artwork.Artwork(Player)
|
||||||
|
|
||||||
def NowPlaying():
|
def NowPlaying():
|
||||||
return nowplaying.NowPlaying(Player)
|
return nowplaying.NowPlaying(Player)
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,9 @@
|
||||||
from gi.repository import Gtk, GdkPixbuf, Gst
|
from gi.repository import Gtk, GdkPixbuf, Gst
|
||||||
|
|
||||||
class Artwork(Gtk.AspectFrame):
|
class Artwork(Gtk.AspectFrame):
|
||||||
def __init__(self):
|
def __init__(self, player):
|
||||||
Gtk.AspectFrame.__init__(self)
|
Gtk.AspectFrame.__init__(self)
|
||||||
self.picture = Gtk.Picture()
|
self.picture = Gtk.Picture()
|
||||||
|
|
||||||
self.frame = Gtk.Frame()
|
self.frame = Gtk.Frame()
|
||||||
self.frame.set_child(self.picture)
|
self.frame.set_child(self.picture)
|
||||||
|
|
||||||
|
@ -16,31 +15,32 @@ class Artwork(Gtk.AspectFrame):
|
||||||
self.set_margin_top(5)
|
self.set_margin_top(5)
|
||||||
self.set_margin_bottom(5)
|
self.set_margin_bottom(5)
|
||||||
self.set_ratio(1.0)
|
self.set_ratio(1.0)
|
||||||
self.reset()
|
|
||||||
|
|
||||||
def get_default_path(self):
|
self.player = player
|
||||||
display = self.picture.get_display()
|
self.player.connect("artwork", self.on_artwork)
|
||||||
theme = Gtk.IconTheme.get_for_display(display)
|
self.player.connect("track-changed", self.on_track_changed)
|
||||||
icon = theme.lookup_icon("emmental", [ ], 1024, 1, 0, 0)
|
self.on_track_changed(player, None, player.track)
|
||||||
return icon.get_file().get_path()
|
|
||||||
|
|
||||||
def set_from_data(self, data):
|
def __set_from_cover_jpg__(self, track):
|
||||||
loader = GdkPixbuf.PixbufLoader()
|
cover = track.filepath().parent / "cover.jpg"
|
||||||
loader.write(data)
|
if cover.exists():
|
||||||
|
self.picture.set_filename(str(cover))
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
pixbuf = loader.get_pixbuf()
|
def on_artwork(self, player, sample):
|
||||||
self.picture.set_pixbuf(pixbuf)
|
|
||||||
loader.close()
|
|
||||||
|
|
||||||
def set_from_sample(self, sample):
|
|
||||||
buffer = sample.get_buffer()
|
buffer = sample.get_buffer()
|
||||||
|
|
||||||
(res, map) = buffer.map(Gst.MapFlags.READ)
|
(res, map) = buffer.map(Gst.MapFlags.READ)
|
||||||
if res == True:
|
if res:
|
||||||
self.set_from_data(map.data)
|
loader = GdkPixbuf.PixbufLoader()
|
||||||
buffer.unmap(map)
|
loader.write(map.data)
|
||||||
else:
|
self.picture.set_pixbuf(loader.get_pixbuf())
|
||||||
self.reset()
|
loader.close()
|
||||||
|
buffer.unmap(map)
|
||||||
|
|
||||||
def reset(self):
|
def on_track_changed(self, player, prev, new):
|
||||||
self.picture.set_filename(self.get_default_path())
|
if not (new and self.__set_from_cover_jpg__(new)):
|
||||||
|
display = self.picture.get_display()
|
||||||
|
theme = Gtk.IconTheme.get_for_display(display)
|
||||||
|
icon = theme.lookup_icon("emmental", [ ], 1024, 1, 0, 0)
|
||||||
|
self.picture.set_file(icon.get_file())
|
||||||
|
|
|
@ -17,9 +17,6 @@ class Player(bass.BassPlayer):
|
||||||
self.track = None
|
self.track = None
|
||||||
|
|
||||||
self.bus.connect("message::eos", self.next)
|
self.bus.connect("message::eos", self.next)
|
||||||
self.bus.connect("message::tag", self.on_tag)
|
|
||||||
|
|
||||||
self.Artwork = artwork.Artwork()
|
|
||||||
|
|
||||||
self.load_track(tagdb.Tracks[settings.get_int("audio.trackid")])
|
self.load_track(tagdb.Tracks[settings.get_int("audio.trackid")])
|
||||||
if self.track:
|
if self.track:
|
||||||
|
@ -34,14 +31,6 @@ class Player(bass.BassPlayer):
|
||||||
self.load_track(track)
|
self.load_track(track)
|
||||||
self.playing = cont
|
self.playing = cont
|
||||||
|
|
||||||
def on_tag(self, bus, message):
|
|
||||||
taglist = message.parse_tag()
|
|
||||||
(res, sample) = taglist.get_sample("image")
|
|
||||||
if res == True:
|
|
||||||
self.Artwork.set_from_sample(sample)
|
|
||||||
else:
|
|
||||||
self.Artwork.reset()
|
|
||||||
|
|
||||||
def play(self): self.playing = True
|
def play(self): self.playing = True
|
||||||
def pause(self): self.playing = False
|
def pause(self): self.playing = False
|
||||||
def playpause(self, *args): self.playing = not self.playing
|
def playpause(self, *args): self.playing = not self.playing
|
||||||
|
|
|
@ -1,19 +1,23 @@
|
||||||
# Copyright 2021 (c) Anna Schumaker.
|
# Copyright 2021 (c) Anna Schumaker.
|
||||||
from . import artwork
|
|
||||||
from gi.repository import Gtk
|
|
||||||
import pathlib
|
|
||||||
import unittest
|
import unittest
|
||||||
|
from gi.repository import Gtk
|
||||||
|
from . import artwork
|
||||||
|
|
||||||
Path = pathlib.Path("./data/hicolor/scalable/apps/emmental.svg")
|
class FakePlayer:
|
||||||
|
def __init__(self):
|
||||||
|
self.track = None
|
||||||
|
def connect(self, name, cb): pass
|
||||||
|
|
||||||
class TestAudioArtwork(unittest.TestCase):
|
class TestAudioArtwork(unittest.TestCase):
|
||||||
def test_audio_artwork_init(self):
|
def test_audio_artwork_init(self):
|
||||||
art = artwork.Artwork()
|
fake = FakePlayer()
|
||||||
|
art = artwork.Artwork(fake)
|
||||||
|
|
||||||
self.assertIsInstance(art, Gtk.AspectFrame)
|
self.assertIsInstance(art, Gtk.AspectFrame)
|
||||||
self.assertIsInstance(art.frame, Gtk.Frame)
|
self.assertIsInstance(art.frame, Gtk.Frame)
|
||||||
self.assertIsInstance(art.picture, Gtk.Picture)
|
self.assertIsInstance(art.picture, Gtk.Picture)
|
||||||
|
|
||||||
|
self.assertEqual(art.player, fake)
|
||||||
self.assertEqual(art.get_child(), art.frame)
|
self.assertEqual(art.get_child(), art.frame)
|
||||||
self.assertEqual(art.frame.get_child(), art.picture)
|
self.assertEqual(art.frame.get_child(), art.picture)
|
||||||
self.assertEqual(art.get_obey_child(), False)
|
self.assertEqual(art.get_obey_child(), False)
|
||||||
|
@ -23,5 +27,3 @@ class TestAudioArtwork(unittest.TestCase):
|
||||||
self.assertEqual(art.get_margin_end(), 5)
|
self.assertEqual(art.get_margin_end(), 5)
|
||||||
self.assertEqual(art.get_margin_top(), 5)
|
self.assertEqual(art.get_margin_top(), 5)
|
||||||
self.assertEqual(art.get_margin_bottom(), 5)
|
self.assertEqual(art.get_margin_bottom(), 5)
|
||||||
|
|
||||||
self.assertIsNotNone(art.get_default_path())
|
|
||||||
|
|
|
@ -23,6 +23,10 @@ class TestAudio(unittest.TestCase):
|
||||||
def test_audio_widgets(self):
|
def test_audio_widgets(self):
|
||||||
seeker = audio.SeekControl()
|
seeker = audio.SeekControl()
|
||||||
|
|
||||||
|
self.assertIsInstance(audio.AudioControls(),
|
||||||
|
audio.controls.AudioControls)
|
||||||
|
self.assertIsInstance(audio.Artwork(),
|
||||||
|
audio.artwork.Artwork)
|
||||||
self.assertIsInstance(audio.NowPlaying(),
|
self.assertIsInstance(audio.NowPlaying(),
|
||||||
audio.nowplaying.NowPlaying)
|
audio.nowplaying.NowPlaying)
|
||||||
self.assertIsInstance(seeker, audio.scale.ScaleButtonBox)
|
self.assertIsInstance(seeker, audio.scale.ScaleButtonBox)
|
||||||
|
|
|
@ -43,7 +43,6 @@ class TestPlayer(unittest.TestCase):
|
||||||
play = player.Player()
|
play = player.Player()
|
||||||
self.assertIsInstance(play, bass.BassPlayer)
|
self.assertIsInstance(play, bass.BassPlayer)
|
||||||
self.assertIsInstance(play.bus, Gst.Bus)
|
self.assertIsInstance(play.bus, Gst.Bus)
|
||||||
self.assertIsInstance(play.Artwork, artwork.Artwork)
|
|
||||||
self.assertIsInstance(play.Autopause, scale.AutoPauseScale)
|
self.assertIsInstance(play.Autopause, scale.AutoPauseScale)
|
||||||
self.assertIsNone(play.track)
|
self.assertIsNone(play.track)
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ add_stack_page("Decades", tagbox.ParentTagBox(tagdb.tags.Decade, "x-office-cal
|
||||||
add_stack_page("Libraries", library.Box)
|
add_stack_page("Libraries", library.Box)
|
||||||
|
|
||||||
|
|
||||||
Box.append(audio.Player.Artwork)
|
Box.append(audio.Artwork())
|
||||||
Box.append(Gtk.Separator.new(Gtk.Orientation.HORIZONTAL))
|
Box.append(Gtk.Separator.new(Gtk.Orientation.HORIZONTAL))
|
||||||
Box.append(Stack)
|
Box.append(Stack)
|
||||||
Box.append(Gtk.Separator.new(Gtk.Orientation.HORIZONTAL))
|
Box.append(Gtk.Separator.new(Gtk.Orientation.HORIZONTAL))
|
||||||
|
|
|
@ -14,7 +14,7 @@ class TestSidebar(unittest.TestCase):
|
||||||
self.assertIsInstance(sidebar.Stack, Gtk.Stack)
|
self.assertIsInstance(sidebar.Stack, Gtk.Stack)
|
||||||
self.assertIsInstance(sidebar.Box, Gtk.Box)
|
self.assertIsInstance(sidebar.Box, Gtk.Box)
|
||||||
|
|
||||||
self.assertIn(audio.Player.Artwork, sidebar.Box)
|
#self.assertIn(audio.Player.Artwork, sidebar.Box)
|
||||||
self.assertIn(sidebar.Stack, sidebar.Box)
|
self.assertIn(sidebar.Stack, sidebar.Box)
|
||||||
self.assertIn(sidebar.pulser.Box, sidebar.Box)
|
self.assertIn(sidebar.pulser.Box, sidebar.Box)
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,5 @@ class EmmentalApplication(Gtk.Application):
|
||||||
def do_startup(self):
|
def do_startup(self):
|
||||||
Gtk.Application.do_startup(self)
|
Gtk.Application.do_startup(self)
|
||||||
self.add_window(window.Window)
|
self.add_window(window.Window)
|
||||||
audio.Player.Artwork.reset()
|
|
||||||
|
|
||||||
Application = EmmentalApplication()
|
Application = EmmentalApplication()
|
||||||
|
|
Loading…
Reference in New Issue