125 lines
3.8 KiB
Python
125 lines
3.8 KiB
Python
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()) |