Skip to content

Instantly share code, notes, and snippets.

@huynhbaoan
Last active December 19, 2024 08:18
Show Gist options
  • Save huynhbaoan/2758671d55df827cfcfc7be1037126e8 to your computer and use it in GitHub Desktop.
Save huynhbaoan/2758671d55df827cfcfc7be1037126e8 to your computer and use it in GitHub Desktop.
import threading
class MusicPlayer:
def __init__(self, music_folder="~/home/audio-extracted/"):
pygame.mixer.init(44100, -16, 2, 2048)
self.music_folder = os.path.expanduser(music_folder)
self.current_track = None
self.playing = False
self.paused = False
self.playlist = []
self.volume = 0.5 # 50% volume
pygame.mixer.music.set_volume(self.volume)
self.load_music_files()
self.stop_event = threading.Event()
def play_next_track(self):
if not self.playlist:
self.playing = False
return "No tracks available"
try:
self.current_track = self.playlist.pop(0)
self.playlist.append(self.current_track)
pygame.mixer.music.load(self.current_track)
pygame.mixer.music.play()
self.stop_event.clear() # Reset the stop event for the new track
threading.Thread(target=self._monitor_track, daemon=True).start()
return f"Now playing: {os.path.basename(self.current_track)}"
except Exception as e:
return f"Error playing {os.path.basename(self.current_track)}: {str(e)}"
def _monitor_track(self):
"""Monitor the current track and play the next one when it ends."""
while not self.stop_event.is_set():
if not pygame.mixer.music.get_busy() and not self.paused:
self.play_next_track()
time.sleep(1) # Check every second
def stop(self):
self.playing = False
self.paused = False
self.stop_event.set() # Signal the monitoring thread to stop
pygame.mixer.music.stop()
return "Stopped"
def draw_interface(stdscr, player, status_message=""):
stdscr.clear()
height, width = stdscr.getmaxyx()
try:
# Title
title = "Python Music Player"
stdscr.addstr(1, 1, title[:width-2]) # Ensure content fits within the terminal width
# Current track
if player.current_track:
current = f"Now Playing: {os.path.basename(player.current_track)}"
stdscr.addstr(2, 1, current[:width-2]) # Truncate if too long
# Status
status = f"Status: {'Playing' if player.playing and not player.paused else 'Paused' if player.paused else 'Stopped'}"
stdscr.addstr(4, 1, status[:width-2])
# Volume
volume = f"Volume: {int(player.volume * 100)}%"
stdscr.addstr(5, 1, volume[:width-2])
# Controls
controls = [
"Controls:",
"SPACE - Play/Pause",
"N - Next Track",
"P - Previous Track",
"S - Stop",
"R - Shuffle Playlist",
"↑/↓ - Volume Up/Down",
"Q - Quit"
]
for i, control in enumerate(controls):
if 6 + i < height: # Ensure within terminal height
stdscr.addstr(6 + i, 1, control[:width-2])
# Status message
if status_message and height > 1:
stdscr.addstr(height-2, 1, f"Message: {status_message[:width-2]}")
except curses.error:
pass # Safely ignore curses errors if the terminal size is too small
# Update the screen
stdscr.refresh()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment