@@ -30,6 +30,8 @@ from gi.repository import GLib, Playerctl # noqa: E402
3030config = None
3131logger = logging .getLogger (__name__ )
3232artfp = Path ("/tmp/waybar-mediaplayer-art" )
33+ selected_player_fp = Path ("/tmp/waybar-mediaplayer-selected-player" )
34+ current_player_name = None
3335last_metadata = None
3436last_art_url = None
3537last_rot = 0
@@ -43,19 +45,58 @@ is_text_rotating = None
4345lyrics = dict ()
4446
4547
46- def on_player_appeared (manager , player , requested_player ):
48+ def on_player_appeared (manager , player , requested_players ):
4749 logger .debug ("I was called" )
48- if player and (player .name == requested_player ):
50+ if player and any (player .name . startswith ( rp ) for rp in requested_players ):
4951 init_player (manager , player )
5052 else :
5153 logger .debug (
5254 "New player appeared, but it's not the selected player, skipping"
5355 )
54-
5556 logger .debug ("Returning True" )
5657 return True
5758
5859
60+ def get_selected_player ():
61+ """Get the currently selected player from file."""
62+ if selected_player_fp .is_file ():
63+ with open (selected_player_fp , "r" ) as f :
64+ return f .read ().strip ()
65+ return None
66+
67+
68+ def set_selected_player (player_name ):
69+ """Save the selected player to file."""
70+ with open (selected_player_fp , "w" ) as f :
71+ f .write (player_name )
72+
73+
74+ def get_active_player (manager , requested_players ):
75+ """Get the active player, prioritizing the selected one."""
76+ selected = get_selected_player ()
77+ available_players = []
78+
79+ result = subprocess .run (
80+ ["playerctl" , "--list-all" ],
81+ capture_output = True ,
82+ text = True ,
83+ timeout = 1
84+ )
85+ if result .returncode == 0 :
86+ all_players = result .stdout .strip ().split ('\n ' )
87+ for player in all_players :
88+ if player and any (player .startswith (rp ) for rp in requested_players ):
89+ available_players .append (player )
90+
91+ if not available_players :
92+ return None
93+
94+ if selected and selected in available_players :
95+ return selected
96+
97+ return available_players [0 ]
98+
99+
59100def delete_album_art ():
60101 p = Path (__file__ )
61102 if config ["album_art_placeholder" ] == "dark" :
@@ -95,7 +136,6 @@ def on_metadata(player, metadata, manager):
95136def on_playback_status (player , status , manager ):
96137 logger .info ("I was called" )
97138 logger .debug (f"status={ status } " )
98- # Update the icon in the progressbar (play/pause)
99139 logger .debug ("Calling register_refresh_interval_callback" )
100140 register_refresh_interval_callback (player , manager )
101141 logger .debug ("Calling update_progressbar" )
@@ -107,19 +147,16 @@ def on_playback_status(player, status, manager):
107147def on_refresh_interval (manager ):
108148 global is_refint
109149 logger .debug ("I was called" )
110- # If there are no players, stop calling this handler
111150 if len (manager .props .players ) == 0 :
112151 logger .debug ("Returning False" )
113152 is_refint = False
114153 return False
115154 player = manager .props .players [0 ]
116- # If we are not playing, stop calling this handler
117155 is_playing = player .props .status == "Playing"
118156 if not is_playing :
119157 logger .debug ("Returning False" )
120158 is_refint = False
121159 return False
122- # Update progressbar and return
123160 update_progressbar (manager , player )
124161 logger .debug ("Returning True" )
125162 return True
@@ -525,8 +562,11 @@ def update_progressbar(manager, player):
525562
526563
527564def init_player (manager , name ):
565+ global current_player_name
528566 logger .debug ("I was called" )
529567 logger .debug (f"name.name={ name .name } " )
568+ # Track current player
569+ current_player_name = name .name
530570 # Register handlers
531571 player = Playerctl .Player .new_from_name (name )
532572 player .connect ("playback-status" , on_playback_status , manager )
@@ -604,33 +644,95 @@ def main():
604644
605645 manager = Playerctl .PlayerManager ()
606646
607- requested_player = config ["player_name" ].split ("." )[0 ]
647+ # Support both string and list for player_name
648+ player_names = config ["player_name" ]
649+ if isinstance (player_names , str ):
650+ player_names = [player_names ]
651+ # Split on "." to get base player names
652+ requested_players = [pn .split ("." )[0 ] for pn in player_names ]
608653 logger .debug (
609- f"Splitting player_name on `.`. requested_player= { requested_player } "
654+ f"Requested players: { requested_players } "
610655 )
611656
612- ini = False
613- for player in manager .props .player_names :
614- logger .debug (f"Found player '{ player .name } '" )
615- if not player .name .startswith (requested_player ):
616- logger .debug ("This is not the filtered player, skipping it" )
617- continue
618- if arguments .command == "play-pause" :
619- Playerctl .Player .new (player .name ).play_pause ()
620- sys .exit (0 )
621- elif arguments .command == "next" :
622- Playerctl .Player .new (player .name ).next ()
657+ # Handle select command
658+ if arguments .command == "select" :
659+ # Get available players
660+ available = []
661+ for player in manager .props .player_names :
662+ if any (player .name .startswith (rp ) for rp in requested_players ):
663+ available .append (player .name )
664+
665+ if not available :
666+ print ("No media players found" )
623667 sys .exit (0 )
624- elif arguments .command == "previous" :
625- Playerctl .Player .new (player .name ).previous ()
668+
669+ # Use rofi for player selection
670+ menu_cmd = ["rofi" , "-dmenu" , "-p" , "Select player:" ]
671+
672+ # Show menu
673+ try :
674+ result = subprocess .run (
675+ menu_cmd ,
676+ input = "\n " .join (available ),
677+ capture_output = True ,
678+ text = True
679+ )
680+ if result .returncode == 0 and result .stdout .strip ():
681+ selected = result .stdout .strip ()
682+ set_selected_player (selected )
683+ print (f"Selected player: { selected } " )
684+ except Exception as e :
685+ logger .error (f"Error running menu: { e } " )
686+ sys .exit (0 )
687+
688+ # Handle control commands using playerctl CLI (more reliable for quick actions)
689+ if arguments .command in ["play-pause" , "next" , "previous" ]:
690+ # Get active player
691+ active_player = get_active_player (manager , requested_players )
692+
693+ if not active_player :
694+ logger .debug ("No active player found" )
626695 sys .exit (0 )
627- elif arguments .command == "monitor" :
696+
697+ # Use playerctl CLI for the action
698+ cmd_map = {
699+ "play-pause" : "play-pause" ,
700+ "next" : "next" ,
701+ "previous" : "previous"
702+ }
703+
704+ cmd = ["playerctl" , "--player=" + active_player , cmd_map [arguments .command ]]
705+ logger .debug (f"Running command: { ' ' .join (cmd )} " )
706+ subprocess .run (cmd )
707+ sys .exit (0 )
708+
709+ # Handle monitor command
710+ ini = False
711+ if arguments .command == "monitor" :
712+ # Prioritize selected player
713+ selected = get_selected_player ()
714+ player_to_init = None
715+
716+ for player in manager .props .player_names :
717+ logger .debug (f"Found player '{ player .name } '" )
718+ if not any (player .name .startswith (rp ) for rp in requested_players ):
719+ logger .debug ("This is not the filtered player, skipping it" )
720+ continue
721+
722+ # Use selected player if available, otherwise first match
723+ if selected and player .name == selected :
724+ player_to_init = player
725+ break
726+ elif not player_to_init :
727+ player_to_init = player
728+
729+ if player_to_init :
628730 logger .debug ("Initializing player" )
629- init_player (manager , player )
731+ init_player (manager , player_to_init )
630732 ini = True
631- else :
632- logger .critical (f"Invalid argument { sys . argv [ 1 ] } " )
633- sys .exit (1 )
733+ elif arguments . command not in [ "play-pause" , "next" , "previous" , "select" ] :
734+ logger .critical (f"Invalid argument { arguments . command } " )
735+ sys .exit (1 )
634736
635737 if not ini :
636738 logger .debug ("No player found. Printing empty" )
@@ -639,7 +741,7 @@ def main():
639741 loop = GLib .MainLoop ()
640742
641743 on_player_appeared_inst = partial (
642- on_player_appeared , requested_player = requested_player
744+ on_player_appeared , requested_players = requested_players
643745 )
644746 # manager.connect("player-appeared", on_player_appeared)
645747 manager .connect ("name-appeared" , on_player_appeared_inst )
0 commit comments