import os import random import gi gi.require_version('Gst','1.0') from gi.repository import Gst, GObject, GLib import time class Playlist: def __init__(self, name, folder_path, shuffle=True): self.name = name self.folder_path = folder_path self.shuffle = shuffle self.tracks = self.load_tracks() self.current_index = 0 def load_tracks(self): files = [ os.path.join(self.folder_path, f) for f in os.listdir(self.folder_path) if f.lower().endswith(".mp3") ] if self.shuffle: random.shuffle(files) return files def next_track(self): if not self.tracks: return None self.current_index = (self.current_index + 1) % len(self.tracks) return self.tracks[self.current_index] def current_track(self): if not self.tracks: return None return self.tracks[self.current_index] Gst.init(None) class Player: def __init__(self, playlist: Playlist): self.playlist = playlist self.pipeline = None def play_current(self): track = self.playlist.current_track() if not track: print(f"No track found in playlist: {self.playlist.name}") return if self.pipeline: self.pipeline.set_state(Gst.State.NULL) self.pipeline = None print(f"[{self.playlist.name}] Playing: {os.path.basename(track)}") if not self.create_pipeline(track): print(f"[{self.playlist.name}] Failed to create pipeline.") return def create_pipeline(self, track_path): pipeline_str = ( f'filesrc location="{track_path}" ! \ decodebin ! \ audioconvert ! audioresample ! \ audio/x-raw,channels=2 ! \ jackaudiosink client-name={self.playlist.name} connect=1' ) try: self.pipeline = Gst.parse_launch(pipeline_str) except Exception as e: print(f"[{self.playlist.name}] Failed to create pipeline: {e}") return False #listen for end of track bus = self.pipeline.get_bus() bus.add_signal_watch() bus.connect("message", self.on_message) ret = self.pipeline.set_state(Gst.State.PLAYING) if ret == Gst.StateChangeReturn.FAILURE: print(f"[{self.playlist.name}] Failed to set pipeline to PLAYING") return False print(f"[{self.playlist.name}] Pipeline is playing") return True def on_message(self, bus, message): if message.type == Gst.MessageType.EOS: self.on_end_of_stream(bus, message) def on_end_of_stream(self, bus, msg): print(f"[{self.playlist.name}] Track finished") self.pipeline.set_state(Gst.State.NULL) self.playlist.next_track() self.play_current() if __name__ == "__main__": praise = Playlist("praise", "/home/media/Music/Praise") worship = Playlist("worship", "/home/media/Music/Worship") instrumental = Playlist("instrumental", "/home/media/Music/Instrumental") praise_player = Player(praise) worship_player = Player(worship) instrumental_player = Player(instrumental) praise_player.play_current() worship_player.play_current() instrumental_player.play_current() loop = GLib.MainLoop() try: loop.run() except KeyboardInterrupt: print("Stopping playback") for player in [praise_player, worship_player, instrumental_player]: if player.pipeline: player.pipeline.set_state(Gst.State.NULL) loop.quit() #print("Praise:",praise.current_track()) #print("Worship:", worship.current_track()) #print("Instrumenal:", instrumental.current_track())