diff --git a/config/assets/icons/player/Pause.svg b/config/assets/icons/player/Pause.svg
new file mode 100644
index 0000000..e5a5c9a
--- /dev/null
+++ b/config/assets/icons/player/Pause.svg
@@ -0,0 +1,3 @@
+
diff --git a/config/assets/icons/player/Rewind.svg b/config/assets/icons/player/Rewind.svg
new file mode 100644
index 0000000..e52bc1d
--- /dev/null
+++ b/config/assets/icons/player/Rewind.svg
@@ -0,0 +1,3 @@
+
diff --git a/config/assets/icons/player/audio-switcher.svg b/config/assets/icons/player/audio-switcher.svg
new file mode 100644
index 0000000..d50264f
--- /dev/null
+++ b/config/assets/icons/player/audio-switcher.svg
@@ -0,0 +1,6 @@
+
diff --git a/config/assets/icons/player/fwd.svg b/config/assets/icons/player/fwd.svg
new file mode 100644
index 0000000..57f16c3
--- /dev/null
+++ b/config/assets/icons/player/fwd.svg
@@ -0,0 +1,3 @@
+
diff --git a/config/assets/icons/player/play.svg b/config/assets/icons/player/play.svg
new file mode 100644
index 0000000..d3356bf
--- /dev/null
+++ b/config/assets/icons/player/play.svg
@@ -0,0 +1,7 @@
+
diff --git a/modules/controlcenter/expanded_player.py b/modules/controlcenter/expanded_player.py
index f000a3f..52f48d4 100644
--- a/modules/controlcenter/expanded_player.py
+++ b/modules/controlcenter/expanded_player.py
@@ -14,6 +14,7 @@ from typing import List
import threading
from fabric.utils import bulk_connect, invoke_repeater, cooldown
+from fabric.utils.helpers import get_relative_path
from fabric.widgets.image import Image
from fabric.widgets.overlay import Overlay
from fabric.widgets.stack import Stack
@@ -207,27 +208,11 @@ class PlayerBoxStack(Box):
fallback_cover_path = f"{data.HOME_DIR}/.current.wall"
# Album cover with fallback image using Image widget
- album_cover_image = Image(
- name="macos-album-cover-image",
- pixbuf=None,
- )
-
- try:
- from gi.repository import GdkPixbuf
-
- pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
- fallback_cover_path, 70, 70, True
- )
- album_cover_image.set_from_pixbuf(pixbuf)
- album_cover_image.set_size_request(70, 70)
- except Exception as e:
- logger.warning(f"Failed to load fallback image in no-media box: {e}")
album_cover = Box(
name="macos-album-image",
- children=[album_cover_image],
)
- album_cover.set_size_request(70, 70)
+ album_cover.set_style(f"background-image:url('{fallback_cover_path}')")
image_stack = Box(h_align="start", v_align="center", name="player-image-stack")
image_stack.children = [album_cover]
@@ -501,7 +486,6 @@ class PlayerBox(Box):
self.player_stack = player_stack
self.fallback_cover_path = f"{data.HOME_DIR}/.current.wall"
- self.image_size = 70 # Medium album art size for expanded player
self.icon_size = 15
# State
@@ -515,10 +499,14 @@ class PlayerBox(Box):
self._download_cancelled = False # Flag to cancel downloads
self._signal_connections = [] # Track signal connections
- self.album_cover = Box(style_classes="macos-album-image")
+ # Use same CSS background approach as small player for consistency
+ self.album_cover = Box(
+ name="macos-album-image",
+ )
self.album_cover.set_style(
f"background-image:url('{self.fallback_cover_path}')"
)
+ self.album_cover.set_size_request(70, 70)
self.image_stack = Box(
h_align="start", v_align="center", name="player-image-stack"
@@ -556,39 +544,6 @@ class PlayerBox(Box):
visible=True, # Hide artist and album when no media
)
- # Use Image widget instead of CSS background for more reliable image display
- self.album_cover_image = Image(
- name="macos-album-cover-image",
- pixbuf=None,
- )
-
- # Set fallback image immediately with proper scaling
- try:
- from gi.repository import GdkPixbuf
-
- pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
- self.fallback_cover_path, 70, 70, True
- )
- self.album_cover_image.set_from_pixbuf(pixbuf)
- self.album_cover_image.set_size_request(70, 70)
- except Exception as e:
- logger.warning(f"Failed to load fallback image: {e}")
-
- # Container box for styling with fixed size
- self.album_cover = Box(
- name="macos-album-image",
- children=[self.album_cover_image],
- )
- self.album_cover.set_size_request(70, 70)
-
- self.image_stack = Box(
- h_align="start",
- v_align="start",
- h_expand=False, # Fixed width for album art
- name="macos-player-image-stack",
- )
- self.image_stack.children = [*self.image_stack.children, self.album_cover]
-
self.app_icon = Box(
children=Image(
icon_name=self.player.player_name, name="player-app-icon", icon_size=20
@@ -732,10 +687,20 @@ class PlayerBox(Box):
)
self.stack_buttons_box.hide() # Initially hidden
- self.skip_next_icon = Image(icon_name="player_fwd")
- self.skip_prev_icon = Image(icon_name="player_rew")
- self.shuffle_icon = Image(icon_name="shuffle")
- self.play_pause_icon = Image(icon_name="player_pause")
+ # Create SVG icons from player directory
+ self.skip_next_icon = Image(
+ image_file=get_relative_path("../../config/assets/icons/player/fwd.svg"),
+ icon_size=16,
+ )
+ self.skip_prev_icon = Image(
+ image_file=get_relative_path("../../config/assets/icons/player/Rewind.svg"),
+ icon_size=16,
+ )
+ self.shuffle_icon = Image(icon_name="shuffle") # Keep existing shuffle icon
+ self.play_pause_icon = Image(
+ image_file=get_relative_path("../../config/assets/icons/player/Pause.svg"),
+ icon_size=20,
+ )
self.play_pause_button = Button(
name="macos-play-button",
@@ -959,39 +924,22 @@ class PlayerBox(Box):
status = player.get_property("playback-status")
if status == "paused":
- self.play_pause_icon.set_from_icon_name("player_start")
+ self.play_pause_icon.set_from_file(
+ get_relative_path("../../config/assets/icons/player/play.svg")
+ )
if status == "playing":
- self.play_pause_icon.set_from_icon_name("player_pause")
+ self.play_pause_icon.set_from_file(
+ get_relative_path("../../config/assets/icons/player/Pause.svg")
+ )
def _update_image(self, image_path):
- try:
- from gi.repository import GdkPixbuf
-
- if image_path and os.path.isfile(image_path):
- # Create scaled pixbuf to ensure proper size
- pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
- image_path, 70, 70, True
- )
- self.album_cover_image.set_from_pixbuf(pixbuf)
- # Explicitly clear pixbuf reference to help GC
- del pixbuf
- else:
- # Use fallback image with scaling
- pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
- self.fallback_cover_path, 70, 70, True
- )
- self.album_cover_image.set_from_pixbuf(pixbuf)
- # Explicitly clear pixbuf reference to help GC
- del pixbuf
- except Exception as e:
- logger.warning(f"Failed to update album cover image: {e}")
- # Try simple file setting as last resort
- try:
- self.album_cover_image.set_from_file(self.fallback_cover_path)
- self.album_cover_image.set_size_request(70, 70)
- except Exception as e2:
- logger.error(f"Failed to set fallback image: {e2}")
+ if image_path and os.path.isfile(image_path):
+ self.album_cover.set_style(f"background-image:url('{image_path}')")
+ else:
+ self.album_cover.set_style(
+ f"background-image:url('{self.fallback_cover_path}')"
+ )
def _set_image(self, *_):
art_url = self.player.arturl
@@ -1022,6 +970,7 @@ class PlayerBox(Box):
)
self.current_download_thread.start()
else:
+ print(art_url)
self._update_image(art_url)
def _download_and_set_artwork(self, arturl):
diff --git a/modules/controlcenter/player.py b/modules/controlcenter/player.py
index 21f1bc4..0ee0b86 100644
--- a/modules/controlcenter/player.py
+++ b/modules/controlcenter/player.py
@@ -9,6 +9,7 @@ import threading
from fabric.utils import (
bulk_connect,
)
+from fabric.utils.helpers import get_relative_path
from fabric.widgets.box import Box
from fabric.widgets.button import Button
from fabric.widgets.image import Image
@@ -558,25 +559,36 @@ class PlayerBox(Box):
],
)
- # Buttons
+ # Buttons with fixed sizing for layout stability
self.button_box = Box(
name="button-box-c",
- # h_align="end",
- # visible=False,
h_expand=False,
spacing=2,
)
- self.skip_next_icon = Image(icon_name="player_fwd")
- self.skip_prev_icon = Image(icon_name="media-skip-backward")
- self.shuffle_icon = Image(icon_name="shuffle")
- self.play_pause_icon = Image(icon_name="player_pause")
+ # Create SVG icons with consistent sizing
+ self.skip_next_icon = Image(
+ image_file=get_relative_path("../../config/assets/icons/player/fwd.svg"),
+ icon_size=16
+ )
+ self.skip_prev_icon = Image(
+ image_file=get_relative_path("../../config/assets/icons/player/Rewind.svg"),
+ icon_size=16
+ )
+ self.shuffle_icon = Image(icon_name="shuffle", icon_size=16)
+ self.play_pause_icon = Image(
+ image_file=get_relative_path("../../config/assets/icons/player/Pause.svg"),
+ icon_size=18
+ )
+ # Fixed size buttons to prevent layout shifts
self.play_pause_button = Button(
name="player-button",
child=self.play_pause_icon,
on_clicked=self.player.play_pause,
)
+ # Set consistent button size
+ self.play_pause_button.set_size_request(32, 32)
self.player.bind_property("can_pause", self.play_pause_button, "sensitive")
@@ -585,6 +597,8 @@ class PlayerBox(Box):
child=self.skip_next_icon,
on_clicked=self._on_player_next,
)
+ # Set consistent button size
+ self.next_button.set_size_request(32, 32)
self.player.bind_property("can_go_next", self.next_button, "sensitive")
self.prev_button = Button(
@@ -592,11 +606,16 @@ class PlayerBox(Box):
child=self.skip_prev_icon,
on_clicked=self._on_prev_button_click,
)
+ # Set consistent button size
+ self.prev_button.set_size_request(32, 32)
+
self.shuffle_button = Button(
style_classes=["player-button"],
child=self.shuffle_icon,
on_clicked=self.player.toggle_shuffle,
)
+ # Set consistent button size
+ self.shuffle_button.set_size_request(32, 32)
self.player.bind_property("can_shuffle", self.shuffle_button, "sensitive")
self.button_box.children = (
@@ -767,10 +786,14 @@ class PlayerBox(Box):
status = player.get_property("playback-status")
if status == "paused":
- self.play_pause_icon.set_from_icon_name("player_play")
+ self.play_pause_icon.set_from_file(
+ get_relative_path("../../config/assets/icons/player/play.svg")
+ )
if status == "playing":
- self.play_pause_icon.set_from_icon_name("player_pause")
+ self.play_pause_icon.set_from_file(
+ get_relative_path("../../config/assets/icons/player/Pause.svg")
+ )
# Notify the player stack that this player started playing
if self.player_stack and hasattr(
self.player_stack, "on_player_playback_changed"
@@ -781,10 +804,14 @@ class PlayerBox(Box):
status = player.get_property("playback-status")
if status == "paused":
- self.play_pause_icon.set_from_icon_name("player_play")
+ self.play_pause_icon.set_from_file(
+ get_relative_path("../../config/assets/icons/player/play.svg")
+ )
if status == "playing":
- self.play_pause_icon.set_from_icon_name("player_pause")
+ self.play_pause_icon.set_from_file(
+ get_relative_path("../../config/assets/icons/player/Pause.svg")
+ )
# Notify the player stack that this player started playing
if self.player_stack and hasattr(
self.player_stack, "on_player_playback_changed"
diff --git a/styles/controlcenter.css b/styles/controlcenter.css
index a7714bb..465f584 100644
--- a/styles/controlcenter.css
+++ b/styles/controlcenter.css
@@ -557,11 +557,11 @@
/* macOS-style expanded player - more compact */
#macos-outer-player-box {
- min-height: 110px; /* Reduced height */
- min-width: 420px; /* Slightly wider to accommodate expanded track info */
+ min-height: 80px; /* Reduced height */
+ min-width: 380px; /* Slightly wider to accommodate expanded track info */
border-radius: 12px;
/* margin: 10px; */
- padding: 15px; /* Reduced padding */
+ padding: 15px;
background-color: alpha(#000, 0.4);
box-shadow:
0 4px 16px alpha(#000, 0.25),
@@ -572,17 +572,25 @@
margin-left: 5px;
}
+#macos-album-cover-image image {
+ min-width: 70px;
+ min-height: 70px;
+ border-radius: 9px;
+}
#macos-album-image {
min-width: 70px;
min-height: 70px;
border-radius: 9px;
+ background-position: center;
+ background-size: cover;
box-shadow: 0 2px 8px alpha(#000, 0.3);
}
-#macos-album-cover-image {
+#macos-album-image image {
min-width: 70px;
min-height: 70px;
border-radius: 9px;
+ box-shadow: 0 2px 8px alpha(#000, 0.3);
}
/* Track info container that expands to fill available space */