Skip to content

Commit e943bef

Browse files
committed
WIP SDL tray
1 parent 9b397a8 commit e943bef

File tree

2 files changed

+147
-5
lines changed

2 files changed

+147
-5
lines changed

src/tauon/t_modules/t_dbus.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ def start_indicator(self) -> None:
107107
pctl = self.tauon.pctl
108108
tauon = self.tauon
109109

110+
# Create SDL tray
111+
tauon.requested_tray = True
112+
113+
110114
import gi
111115

112116
try:
@@ -210,19 +214,19 @@ def update() -> None:
210214

211215
if self.loaded_indicator == "AyatanaAppIndicatorGlib":
212216
pActions = Gio.SimpleActionGroup.new ()
213-
# self.menu.append(tauon.strings.menu_open_tauon, restore)
217+
#self.menu.append(tauon.strings.menu_open_tauon, restore)
214218
pSimpleAction = Gio.SimpleAction.new("restore", None)
215219
pActions.add_action (pSimpleAction)
216220
pSimpleAction.connect ("activate", restore, 6)
217221
pItem = Gio.MenuItem.new(tauon.strings.menu_open_tauon, "indicator.restore")
218222
self.menu.append_item (pItem)
219223
# TODO(Martin): Add rest of actions
220224
# TODO(Martin): Separator
221-
# self.menu.append(tauon.strings.menu_play_pause, play_pause)
222-
# self.menu.append(tauon.strings.menu_next, next)
223-
# self.menu.append(tauon.strings.menu_previous, back)
225+
#self.menu.append(tauon.strings.menu_play_pause, play_pause)
226+
#self.menu.append(tauon.strings.menu_next, next)
227+
#self.menu.append(tauon.strings.menu_previous, back)
224228
# TODO(Martin): Separator
225-
# self.menu.append(tauon.strings.menu_quit, menu_quit)
229+
#self.menu.append(tauon.strings.menu_quit, menu_quit)
226230
self.indicator.set_actions(pActions)
227231
else:
228232
item = Gtk.MenuItem(label=tauon.strings.menu_open_tauon)

src/tauon/t_modules/t_main.py

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6028,6 +6028,140 @@ def __init__(self, holder: Holder, bag: Bag, gui: GuiVar) -> None:
60286028
self.now_searching: Literal["off", "searching", "errored", "success"] = "off"
60296029

60306030
self.requested_raise = False
6031+
self.requested_tray = False
6032+
self.sdl_tray = None
6033+
self._tray_quit_cb = None
6034+
self._tray_open_cb = None
6035+
self._tray_playpause_cb = None
6036+
self._tray_next_cb = None
6037+
self._tray_prev_cb = None
6038+
6039+
def tray_quit_callback(self, userdata, entry):
6040+
"""Called when the 'Quit' tray entry is clicked."""
6041+
logging.info("Exit via tray")
6042+
self.exit("Exit received from app indicator")
6043+
6044+
def tray_open_callback(self, userdata, entry):
6045+
"""Open Tauon main UI."""
6046+
# Adjust to whatever your real function is
6047+
self.request_raise()
6048+
6049+
6050+
def tray_playpause_callback(self, userdata, entry):
6051+
"""Toggle play/pause."""
6052+
self.pctl.play_pause()
6053+
6054+
6055+
def tray_next_callback(self, userdata, entry):
6056+
"""Next track."""
6057+
self.pctl.advance()
6058+
6059+
6060+
def tray_prev_callback(self, userdata, entry):
6061+
"""Previous track."""
6062+
self.pctl.back()
6063+
6064+
def load_sdl_icon(self, path: Path):
6065+
"""Load an image file into an SDL_Surface suitable for a tray icon."""
6066+
# Load image as a surface (requires SDL3_image installed)
6067+
surf = sdl3.IMG_Load(str(path).encode("utf-8"))
6068+
if not surf:
6069+
raise RuntimeError(f"IMG_Load failed: {sdl3.SDL_GetError().decode()}")
6070+
return surf
6071+
6072+
def init_sdl_tray(self):
6073+
icon_surface = self.load_sdl_icon(Path(self.get_tray_icon("tray-indicator-default")))
6074+
# Create tray (no icon, just tooltip)
6075+
self.sdl_tray = sdl3.SDL_CreateTray(icon_surface, b"My tray")
6076+
if not self.sdl_tray:
6077+
raise RuntimeError(f"SDL_CreateTray failed: {sdl3.SDL_GetError().decode()}")
6078+
# Create menu
6079+
menu = sdl3.SDL_CreateTrayMenu(self.sdl_tray)
6080+
if not menu:
6081+
raise RuntimeError(f"SDL_CreateTrayMenu failed: {sdl3.SDL_GetError().decode()}")
6082+
6083+
# --- Open Tauon Music Box ---
6084+
open_entry = sdl3.SDL_InsertTrayEntryAt(
6085+
menu,
6086+
-1,
6087+
b"Open Tauon Music Box",
6088+
sdl3.SDL_TRAYENTRY_BUTTON,
6089+
)
6090+
if not open_entry:
6091+
raise RuntimeError(f"SDL_InsertTrayEntryAt(Open) failed: {sdl3.SDL_GetError().decode()}")
6092+
6093+
# --- Separator ---
6094+
sep1 = sdl3.SDL_InsertTrayEntryAt(
6095+
menu,
6096+
-1,
6097+
None, # NULL label => separator
6098+
0, # flags ignored for separators
6099+
)
6100+
if not sep1:
6101+
raise RuntimeError(f"SDL_InsertTrayEntryAt(sep1) failed: {sdl3.SDL_GetError().decode()}")
6102+
6103+
# --- Play/Pause ---
6104+
playpause_entry = sdl3.SDL_InsertTrayEntryAt(
6105+
menu,
6106+
-1,
6107+
b"Play/Pause",
6108+
sdl3.SDL_TRAYENTRY_BUTTON,
6109+
)
6110+
if not playpause_entry:
6111+
raise RuntimeError(f"SDL_InsertTrayEntryAt(Play/Pause) failed: {sdl3.SDL_GetError().decode()}")
6112+
6113+
# --- Next Track ---
6114+
next_entry = sdl3.SDL_InsertTrayEntryAt(
6115+
menu,
6116+
-1,
6117+
b"Next Track",
6118+
sdl3.SDL_TRAYENTRY_BUTTON,
6119+
)
6120+
if not next_entry:
6121+
raise RuntimeError(f"SDL_InsertTrayEntryAt(Next) failed: {sdl3.SDL_GetError().decode()}")
6122+
6123+
# --- Previous Track ---
6124+
prev_entry = sdl3.SDL_InsertTrayEntryAt(
6125+
menu,
6126+
-1,
6127+
b"Previous Track",
6128+
sdl3.SDL_TRAYENTRY_BUTTON,
6129+
)
6130+
if not prev_entry:
6131+
raise RuntimeError(f"SDL_InsertTrayEntryAt(Previous) failed: {sdl3.SDL_GetError().decode()}")
6132+
6133+
# --- Separator ---
6134+
sep2 = sdl3.SDL_InsertTrayEntryAt(
6135+
menu,
6136+
-1,
6137+
None, # separator
6138+
0,
6139+
)
6140+
if not sep2:
6141+
raise RuntimeError(f"SDL_InsertTrayEntryAt(sep2) failed: {sdl3.SDL_GetError().decode()}")
6142+
6143+
# --- Quit ---
6144+
quit_entry = sdl3.SDL_InsertTrayEntryAt(
6145+
menu,
6146+
-1,
6147+
b"Quit",
6148+
sdl3.SDL_TRAYENTRY_BUTTON,
6149+
)
6150+
if not quit_entry:
6151+
raise RuntimeError(f"SDL_InsertTrayEntryAt(Quit) failed: {sdl3.SDL_GetError().decode()}")
6152+
6153+
self._tray_open_cb = sdl3.SDL_TrayCallback(self.tray_open_callback)
6154+
self._tray_playpause_cb = sdl3.SDL_TrayCallback(self.tray_playpause_callback)
6155+
self._tray_next_cb = sdl3.SDL_TrayCallback(self.tray_next_callback)
6156+
self._tray_quit_cb = sdl3.SDL_TrayCallback(self.tray_quit_callback)
6157+
self._tray_prev_cb = sdl3.SDL_TrayCallback(self.tray_prev_callback)
6158+
6159+
sdl3.SDL_SetTrayEntryCallback(open_entry, self._tray_open_cb, None)
6160+
sdl3.SDL_SetTrayEntryCallback(playpause_entry, self._tray_playpause_cb, None)
6161+
sdl3.SDL_SetTrayEntryCallback(next_entry, self._tray_next_cb, None)
6162+
sdl3.SDL_SetTrayEntryCallback(quit_entry, self._tray_quit_cb, None)
6163+
sdl3.SDL_SetTrayEntryCallback(prev_entry, self._tray_prev_cb, None)
6164+
60316165

60326166
def coll(self, r: list[int]) -> bool:
60336167
return r[0] < self.inp.mouse_position[0] <= r[0] + r[2] and r[1] <= self.inp.mouse_position[1] <= r[1] + r[3]
@@ -44955,6 +45089,10 @@ def dev_mode_disable_save_state() -> None:
4495545089
tauon.raise_window()
4495645090
tauon.requested_raise = False
4495745091

45092+
if tauon.requested_tray:
45093+
tauon.init_sdl_tray()
45094+
tauon.requested_tray = False
45095+
4495845096
if pctl.playing_state != PlayingState.STOPPED:
4495945097
power += 400
4496045098

0 commit comments

Comments
 (0)