Added a "Playlist" class.
This commit is contained in:
parent
1190059218
commit
94269fdae4
7 changed files with 119 additions and 53 deletions
|
@ -13,7 +13,7 @@ class Settings:
|
||||||
self.settings.visibilityChanged.connect(self.update_all)
|
self.settings.visibilityChanged.connect(self.update_all)
|
||||||
self.settings.save_button.pressed.connect(self.write_settings)
|
self.settings.save_button.pressed.connect(self.write_settings)
|
||||||
|
|
||||||
def update_all(self, settings_visible: bool=True):
|
def update_all(self, _=True): # ignore visible parameter passed by visibilityChanged event
|
||||||
self.settings.file_settings.library_path_input.setText(self.app.settings.library_path)
|
self.settings.file_settings.library_path_input.setText(self.app.settings.library_path)
|
||||||
|
|
||||||
def update_settings(self, key, value):
|
def update_settings(self, key, value):
|
||||||
|
|
|
@ -37,24 +37,24 @@ class TrackControl:
|
||||||
self.track_control.track_progress_slider.sliderReleased.connect(self.on_slider_release)
|
self.track_control.track_progress_slider.sliderReleased.connect(self.on_slider_release)
|
||||||
|
|
||||||
def previous_track(self):
|
def previous_track(self):
|
||||||
if len(self.app.player.current_playlist) > 0:
|
if self.app.player.current_playlist.has_tracks():
|
||||||
self.app.player.previous_track()
|
self.app.player.previous_track()
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
if len(self.app.player.current_playlist) > 0:
|
if self.app.player.current_playlist.has_tracks():
|
||||||
self.app.player.stop()
|
self.app.player.stop()
|
||||||
|
|
||||||
def next_track(self):
|
def next_track(self):
|
||||||
if len(self.app.player.current_playlist) > 0:
|
if self.app.player.current_playlist.has_tracks():
|
||||||
self.app.player.next_track()
|
self.app.player.next_track()
|
||||||
|
|
||||||
def on_slider_release(self):
|
def on_slider_release(self):
|
||||||
if len(self.app.player.current_playlist) > 0:
|
if self.app.player.current_playlist.has_tracks():
|
||||||
self.app.player.seek(self.track_control.track_progress_slider.value())
|
self.app.player.seek(self.track_control.track_progress_slider.value())
|
||||||
|
|
||||||
def on_track_start(self):
|
def on_track_start(self):
|
||||||
if self.app.player.playing:
|
if self.app.player.playing:
|
||||||
duration = self.app.player.current_track.duration
|
duration = self.app.player.current_playlist.current_track.duration
|
||||||
|
|
||||||
self.track_control.track_progress_slider.setRange(
|
self.track_control.track_progress_slider.setRange(
|
||||||
0,
|
0,
|
||||||
|
@ -73,7 +73,7 @@ class TrackControl:
|
||||||
if remaining == -1:
|
if remaining == -1:
|
||||||
remaining = self.app.player.track_progress.remaining_time
|
remaining = self.app.player.track_progress.remaining_time
|
||||||
|
|
||||||
track_duration = self.app.player.current_track.duration
|
track_duration = self.app.player.current_playlist.current_track.duration
|
||||||
|
|
||||||
progress = track_duration - remaining
|
progress = track_duration - remaining
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ class TrackControl:
|
||||||
self.app.player.pause()
|
self.app.player.pause()
|
||||||
self.track_control.toggle_play_button.setIcon(self.play_icon)
|
self.track_control.toggle_play_button.setIcon(self.play_icon)
|
||||||
|
|
||||||
elif len(self.app.player.current_playlist) > 0: # stopped but tracks in the current playlist
|
elif self.app.player.current_playlist.has_tracks(): # stopped but tracks in the current playlist
|
||||||
self.app.player.start_playing()
|
self.app.player.start_playing()
|
||||||
self.track_control.toggle_play_button.setIcon(self.pause_icon)
|
self.track_control.toggle_play_button.setIcon(self.pause_icon)
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import os
|
||||||
import pygame.mixer
|
import pygame.mixer
|
||||||
import pygame.event
|
import pygame.event
|
||||||
from .track import Track
|
from .track import Track
|
||||||
|
from .playlist import Playlist
|
||||||
from .track_progress_timer import TrackProgress
|
from .track_progress_timer import TrackProgress
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,14 +19,11 @@ class Player:
|
||||||
|
|
||||||
self.track_progress = TrackProgress(self.app)
|
self.track_progress = TrackProgress(self.app)
|
||||||
|
|
||||||
|
self.current_playlist = Playlist(self.app)
|
||||||
|
|
||||||
self.playing = False
|
self.playing = False
|
||||||
self.paused = False
|
self.paused = False
|
||||||
|
|
||||||
self.current_playlist = []
|
|
||||||
self.current_playlist_index = 0
|
|
||||||
|
|
||||||
self.current_track = None
|
|
||||||
|
|
||||||
self.current_sound = None
|
self.current_sound = None
|
||||||
self.current_sound_duration = 0
|
self.current_sound_duration = 0
|
||||||
|
|
||||||
|
@ -34,19 +32,11 @@ class Player:
|
||||||
Load tracks from list of paths.
|
Load tracks from list of paths.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
tracks = []
|
self.current_playlist = Playlist(self.app)
|
||||||
|
self.current_playlist.load_from_paths(track_paths)
|
||||||
|
|
||||||
for track_path in track_paths:
|
self.current_sound = self.current_playlist.current_track.sound
|
||||||
if os.path.isfile(track_path):
|
self.current_sound_duration = self.current_playlist.current_track.duration
|
||||||
tracks.append(Track(track_path, True))
|
|
||||||
|
|
||||||
self.current_playlist = tracks
|
|
||||||
self.current_playlist_index = 0
|
|
||||||
|
|
||||||
self.current_track = self.current_playlist[0]
|
|
||||||
|
|
||||||
self.current_sound = self.current_track.sound
|
|
||||||
self.current_sound_duration = self.current_track.duration
|
|
||||||
|
|
||||||
def play(self):
|
def play(self):
|
||||||
self.music_channel.play(self.current_sound)
|
self.music_channel.play(self.current_sound)
|
||||||
|
@ -55,14 +45,8 @@ class Player:
|
||||||
self.paused = False
|
self.paused = False
|
||||||
|
|
||||||
def track_finished(self):
|
def track_finished(self):
|
||||||
|
if not self.current_playlist.on_last_track():
|
||||||
# if the last track wasn't the last in the playlist
|
self.current_sound, self.current_sound_duration = self.current_playlist.next_track()
|
||||||
if self.current_playlist_index < len(self.current_playlist) - 1:
|
|
||||||
self.current_playlist_index += 1
|
|
||||||
|
|
||||||
self.current_track = self.current_playlist[self.current_playlist_index]
|
|
||||||
self.current_sound = self.current_track.sound
|
|
||||||
self.current_sound_duration = self.current_track.duration
|
|
||||||
|
|
||||||
self.play()
|
self.play()
|
||||||
self.track_progress.start()
|
self.track_progress.start()
|
||||||
|
@ -72,8 +56,8 @@ class Player:
|
||||||
self.stop()
|
self.stop()
|
||||||
|
|
||||||
def start_playing(self):
|
def start_playing(self):
|
||||||
self.current_sound = self.current_track.sound
|
self.current_sound = self.current_playlist.current_track.sound
|
||||||
self.current_sound_duration = self.current_track.duration
|
self.current_sound_duration = self.current_playlist.current_track.duration
|
||||||
|
|
||||||
self.play()
|
self.play()
|
||||||
self.track_progress.start()
|
self.track_progress.start()
|
||||||
|
@ -91,23 +75,19 @@ class Player:
|
||||||
self.paused = False
|
self.paused = False
|
||||||
|
|
||||||
def next_track(self):
|
def next_track(self):
|
||||||
if self.current_playlist_index < len(self.current_playlist) - 1: # if the playing track isn't the last
|
if not self.current_playlist.on_last_track():
|
||||||
self.music_channel.stop()
|
self.music_channel.stop()
|
||||||
self.track_progress.stop()
|
self.track_progress.stop()
|
||||||
self.track_finished()
|
self.track_finished()
|
||||||
|
|
||||||
def previous_track(self):
|
def previous_track(self):
|
||||||
if self.current_playlist_index > 0: # if the current track isn't the first in the playlist
|
if not self.current_playlist.on_first_track():
|
||||||
self.music_channel.stop()
|
self.music_channel.stop()
|
||||||
|
|
||||||
self.current_playlist_index -= 1
|
self.current_sound, self.current_sound_duration = self.current_playlist.previous_track()
|
||||||
self.current_track = self.current_playlist[self.current_playlist_index]
|
|
||||||
|
|
||||||
self.track_progress.stop()
|
self.track_progress.stop()
|
||||||
|
|
||||||
self.current_sound = self.current_track.sound
|
|
||||||
self.current_sound_duration = self.current_track.duration
|
|
||||||
|
|
||||||
self.play()
|
self.play()
|
||||||
self.track_progress.start()
|
self.track_progress.start()
|
||||||
|
|
||||||
|
@ -116,7 +96,7 @@ class Player:
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self.music_channel.stop()
|
self.music_channel.stop()
|
||||||
self.track_progress.stop()
|
self.track_progress.stop()
|
||||||
self.current_sound_duration = self.current_track.duration
|
self.current_sound_duration = self.current_playlist.current_track.duration
|
||||||
|
|
||||||
self.playing = False
|
self.playing = False
|
||||||
self.paused = False
|
self.paused = False
|
||||||
|
@ -125,7 +105,7 @@ class Player:
|
||||||
self.music_channel.stop()
|
self.music_channel.stop()
|
||||||
self.track_progress.stop()
|
self.track_progress.stop()
|
||||||
|
|
||||||
(self.current_sound, self.current_sound_duration) = self.current_track.remaining(position)
|
(self.current_sound, self.current_sound_duration) = self.current_playlist.current_track.remaining(position)
|
||||||
|
|
||||||
self.play()
|
self.play()
|
||||||
self.track_progress.start()
|
self.track_progress.start()
|
||||||
|
|
80
wobuzz/player/playlist.py
Normal file
80
wobuzz/player/playlist.py
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
import os
|
||||||
|
from .track import Track
|
||||||
|
|
||||||
|
|
||||||
|
class Playlist:
|
||||||
|
def __init__(self, app):
|
||||||
|
self.app = app
|
||||||
|
self.tracks: list[Track] = []
|
||||||
|
self.current_track_index = 0
|
||||||
|
self.current_track: Track | None = None
|
||||||
|
|
||||||
|
def load_from_paths(self, paths):
|
||||||
|
i = 0
|
||||||
|
|
||||||
|
while i < len(paths):
|
||||||
|
path = paths[i]
|
||||||
|
|
||||||
|
if os.path.isfile(path):
|
||||||
|
self.tracks.append(Track(self.app, path, cache=i==0)) # first track is cached
|
||||||
|
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
self.current_track = self.tracks[0] # current track is the first track in the playlist
|
||||||
|
|
||||||
|
def load_from_m3u(self, path):
|
||||||
|
file = open(path, "r")
|
||||||
|
m3u = file.read()
|
||||||
|
file.close()
|
||||||
|
|
||||||
|
lines = m3u.split("\n") # m3u entries
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
|
||||||
|
while i < len(lines):
|
||||||
|
line = lines[i]
|
||||||
|
|
||||||
|
if line.startswith("#") or line.startswith("http"): # filter out comments, extended m3u and urls
|
||||||
|
continue
|
||||||
|
|
||||||
|
self.tracks.append(Track(self.app, line, cache=i==0)) # first track is cached
|
||||||
|
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
def load_from_wbz(self, path):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def has_tracks(self):
|
||||||
|
return len(self.tracks) > 0
|
||||||
|
|
||||||
|
def on_first_track(self):
|
||||||
|
return self.current_track_index == 0
|
||||||
|
|
||||||
|
def on_last_track(self): # if the current track is the last
|
||||||
|
return self.current_track_index == len(self.tracks) - 1
|
||||||
|
|
||||||
|
def next_track(self):
|
||||||
|
self.current_track_index += 1
|
||||||
|
self.current_track = self.tracks[self.current_track_index]
|
||||||
|
|
||||||
|
if not self.current_track.cached: # make sure the track is cached because else the player can't play it
|
||||||
|
self.current_track.cache()
|
||||||
|
self.current_track.cached = True
|
||||||
|
|
||||||
|
return self.current_track.sound, self.current_track.duration
|
||||||
|
|
||||||
|
def previous_track(self):
|
||||||
|
if self.on_first_track():
|
||||||
|
return self.current_track, self.current_track.duration
|
||||||
|
|
||||||
|
self.current_track_index -= 1
|
||||||
|
self.current_track = self.tracks[self.current_track_index]
|
||||||
|
|
||||||
|
if not self.current_track.cached: # make sure the track is cached because else the player can't play it
|
||||||
|
self.current_track.cache()
|
||||||
|
self.current_track.cached = True
|
||||||
|
|
||||||
|
return self.current_track.sound, self.current_track.duration
|
||||||
|
|
|
@ -10,22 +10,28 @@ class Track:
|
||||||
Class containing data for a track like file path, raw data...
|
Class containing data for a track like file path, raw data...
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, path: str, cache: bool=False):
|
def __init__(self, app, path: str, property_string: str=None, cache: bool=False):
|
||||||
|
self.app = app
|
||||||
self.path = path
|
self.path = path
|
||||||
|
self.property_string = property_string
|
||||||
self.cached = cache
|
self.cached = cache
|
||||||
|
|
||||||
(self.audio, self.sound, self.duration) = self.cache() if self.cached else (None, None, 0)
|
self.audio = None
|
||||||
|
self.sound = None
|
||||||
|
self.duration = 0
|
||||||
|
|
||||||
|
if self.cached:
|
||||||
|
self.cache()
|
||||||
|
|
||||||
def cache(self):
|
def cache(self):
|
||||||
audio = AudioSegment.from_mp3(self.path)
|
self.audio = AudioSegment.from_mp3(self.path)
|
||||||
# audio = normalize(audio)
|
# audio = normalize(audio)
|
||||||
|
|
||||||
wav = audio.export(format="wav")
|
wav = self.audio.export(format="wav")
|
||||||
|
|
||||||
sound = Sound(wav)
|
self.sound = Sound(wav)
|
||||||
|
|
||||||
# return pygame.mixer.Sound object and track duration in milliseconds
|
self.duration = len(self.audio) # track duration in milliseconds
|
||||||
return audio, sound, len(audio)
|
|
||||||
|
|
||||||
def remaining(self, position: int):
|
def remaining(self, position: int):
|
||||||
remaining_audio = self.audio[position:]
|
remaining_audio = self.audio[position:]
|
||||||
|
@ -34,4 +40,5 @@ class Track:
|
||||||
|
|
||||||
sound = Sound(wav)
|
sound = Sound(wav)
|
||||||
|
|
||||||
|
# return the remaining part of the track's audio and the duration of the remaining part
|
||||||
return sound, len(remaining_audio)
|
return sound, len(remaining_audio)
|
||||||
|
|
|
@ -28,4 +28,4 @@ class TrackProgress:
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self.timer.stop()
|
self.timer.stop()
|
||||||
self.remaining_time = self.app.player.current_track.duration
|
self.remaining_time = self.app.player.current_playlist.current_track.duration
|
||||||
|
|
|
@ -33,4 +33,3 @@ class MainWindow(QMainWindow):
|
||||||
self.library_dock = LibraryDock()
|
self.library_dock = LibraryDock()
|
||||||
self.addDockWidget(Qt.DockWidgetArea.RightDockWidgetArea, self.library_dock)
|
self.addDockWidget(Qt.DockWidgetArea.RightDockWidgetArea, self.library_dock)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue