2024-12-24 17:22:30 +01:00
|
|
|
#!/usr/bin/python3
|
|
|
|
|
|
|
|
import os
|
2024-12-29 15:10:51 +01:00
|
|
|
from PyQt6.QtCore import Qt
|
2024-12-24 17:22:30 +01:00
|
|
|
from .track import Track
|
|
|
|
|
|
|
|
|
|
|
|
class Playlist:
|
2024-12-28 20:41:18 +01:00
|
|
|
def __init__(self, app, title: str):
|
2024-12-24 17:22:30 +01:00
|
|
|
self.app = app
|
2024-12-28 20:41:18 +01:00
|
|
|
self.title = title # playlist title
|
2024-12-29 15:10:51 +01:00
|
|
|
self.sorting: list[Qt.SortOrder] | None = None # Custom sort order if None
|
2024-12-24 17:22:30 +01:00
|
|
|
self.tracks: list[Track] = []
|
|
|
|
self.current_track_index = 0
|
|
|
|
self.current_track: Track | None = None
|
2025-01-25 17:21:43 +01:00
|
|
|
self.view = None
|
2024-12-24 17:22:30 +01:00
|
|
|
|
2025-01-26 12:07:18 +01:00
|
|
|
def clear(self):
|
|
|
|
self.sorting: list[Qt.SortOrder] | None = None
|
|
|
|
self.tracks = []
|
|
|
|
self.current_track_index = 0
|
|
|
|
self.current_track = None
|
|
|
|
|
2024-12-24 17:22:30 +01:00
|
|
|
def load_from_paths(self, paths):
|
|
|
|
i = 0
|
|
|
|
|
|
|
|
while i < len(paths):
|
|
|
|
path = paths[i]
|
|
|
|
|
|
|
|
if os.path.isfile(path):
|
2025-01-25 18:04:46 +01:00
|
|
|
self.tracks.append(Track(self.app, path, cache=i==0)) # first track is cached
|
2024-12-24 17:22:30 +01:00
|
|
|
|
|
|
|
i += 1
|
|
|
|
|
2025-01-25 21:46:48 +01:00
|
|
|
# set current track to the first track if there is no currently playing track
|
|
|
|
if self.current_track is None and self.has_tracks():
|
2024-12-28 20:41:18 +01:00
|
|
|
self.current_track = self.tracks[0]
|
2024-12-24 17:22:30 +01:00
|
|
|
|
|
|
|
def load_from_m3u(self, path):
|
|
|
|
file = open(path, "r")
|
|
|
|
m3u = file.read()
|
|
|
|
file.close()
|
|
|
|
|
2024-12-29 20:10:06 +01:00
|
|
|
lines = m3u.split("\n") # m3u entries are separated by newlines
|
|
|
|
lines = lines[:-1] # remove last entry because it is just an empty string
|
2024-12-24 17:22:30 +01:00
|
|
|
|
|
|
|
i = 0
|
2024-12-29 14:31:21 +01:00
|
|
|
num_lines = len(lines)
|
2024-12-24 17:22:30 +01:00
|
|
|
|
2024-12-29 14:31:21 +01:00
|
|
|
while i < num_lines:
|
2024-12-24 17:22:30 +01:00
|
|
|
line = lines[i]
|
|
|
|
|
|
|
|
if line.startswith("#") or line.startswith("http"): # filter out comments, extended m3u and urls
|
2024-12-29 14:31:21 +01:00
|
|
|
i += 1
|
|
|
|
|
2024-12-24 17:22:30 +01:00
|
|
|
continue
|
|
|
|
|
2025-01-25 18:04:46 +01:00
|
|
|
self.tracks.append(Track(self.app, line, cache=i==0)) # first track is cached
|
2024-12-24 17:22:30 +01:00
|
|
|
|
|
|
|
i += 1
|
|
|
|
|
2025-01-25 21:46:48 +01:00
|
|
|
# set current track to the first track if there is no currently playing track
|
|
|
|
if self.current_track is None and self.has_tracks():
|
2024-12-28 20:41:18 +01:00
|
|
|
self.current_track = self.tracks[0]
|
2024-12-28 18:12:59 +01:00
|
|
|
|
2025-01-26 16:49:09 +01:00
|
|
|
#self.app.player.history.append_track(self.current_track)
|
|
|
|
|
2024-12-24 17:22:30 +01:00
|
|
|
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()
|
|
|
|
|
|
|
|
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()
|
2024-12-29 14:31:21 +01:00
|
|
|
|
|
|
|
return self.current_track.sound, self.current_track.duration
|
|
|
|
|
|
|
|
def set_track(self, track_index):
|
|
|
|
self.current_track_index = track_index
|
|
|
|
|
|
|
|
self.current_track = self.tracks[self.current_track_index]
|
|
|
|
|
|
|
|
if not self.current_track.cached:
|
|
|
|
self.current_track.cache()
|
2024-12-24 17:22:30 +01:00
|
|
|
|
|
|
|
return self.current_track.sound, self.current_track.duration
|
|
|
|
|
2025-01-25 20:45:43 +01:00
|
|
|
def save(self):
|
|
|
|
wbz_data = ""
|
|
|
|
|
|
|
|
for track in self.tracks:
|
|
|
|
wbz_data += f"{track.path}\n"
|
|
|
|
|
2025-01-27 18:18:41 +01:00
|
|
|
wbz = open(
|
|
|
|
os.path.expanduser(
|
|
|
|
f"{self.app.settings.library_path}/playlists/{self.title.replace(" ", "_")}.wbz.m3u"
|
|
|
|
),
|
|
|
|
"w"
|
|
|
|
)
|
2025-01-25 20:45:43 +01:00
|
|
|
wbz.write(wbz_data)
|
|
|
|
wbz.close()
|
|
|
|
|
2025-01-27 18:18:41 +01:00
|
|
|
def delete(self):
|
2025-01-27 18:21:41 +01:00
|
|
|
path = f"{self.app.settings.library_path}/playlists/{self.title.replace(" ", "_")}.wbz.m3u"
|
|
|
|
|
|
|
|
if os.path.exists(path):
|
|
|
|
os.remove(os.path.expanduser(path))
|
2025-01-27 18:18:41 +01:00
|
|
|
|
2025-01-26 13:51:31 +01:00
|
|
|
def append_track(self, track):
|
|
|
|
self.tracks.append(track)
|
|
|
|
|
|
|
|
if self.view:
|
|
|
|
self.view.append_track(track)
|
|
|
|
|
|
|
|
def h_last_track(self):
|
|
|
|
# get last track in history (only gets used in player.history)
|
|
|
|
|
|
|
|
if len(self.tracks) > 1:
|
|
|
|
return self.tracks[-2]
|
|
|
|
|