-
Notifications
You must be signed in to change notification settings - Fork 1
/
music_player.py
181 lines (144 loc) · 5.3 KB
/
music_player.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
from circular_doubly_linked_list import CircularDoublyLinkedList
import pyglet
import os
class Song:
'''
Song Class
Represents a song in the playlist
Contains the song name, the artist, and the path to the song
'''
def __init__(self, name: str, artist: str, file: str) -> None:
self.name = name # song name
self.artist = artist # artist name
self.file = file # path to the file
def get_name(self) -> str:
return self.name
def get_artist(self) -> str:
return self.artist
def get_file(self) -> str:
return self.file
def __eq__(self, other):
'''
if two songs have the same file path then they are the same
'''
return self.get_file() == other.get_file()
class MusicPlayer(CircularDoublyLinkedList):
'''
Song Manager Class
Contains all the songs in the playlist
'''
def __init__(self, playlist_path: str) -> None:
super().__init__()
self.playlist_path = playlist_path # path to playlist folder
self.player = pyglet.media.Player() # the sound player
self.__clean_up(playlist_path)
self.__read_files(playlist_path)
self.now_playing = self.head # the song that is currently being played
self.playing = True # determine if music is being played or paused
self.current_song_duration = 0 # the duration of the currently playing song
self.__load_current_song()
def to_next_song(self) -> None:
'''
skip to the next song
'''
self.now_playing = self.now_playing.next
self.__load_current_song()
def to_previous_song(self) -> None:
'''
go back to the previous song
'''
self.now_playing = self.now_playing.prev
self.__load_current_song()
def replay(self) -> None:
'''
replay the current song
'''
self.__load_current_song()
def get_song_name(self) -> str:
'''
get the name of the currently playing song
'''
name = self.now_playing.value.get_name()
return name
def get_artist_name(self) -> str:
'''
get the artist's name of the currently playing song
'''
artist = self.now_playing.value.get_artist()
return artist
def get_song_duration(self) -> float:
'''
get the duration of the currently playing song
'''
return self.current_song_duration
def is_playing(self) -> bool:
'''
check if the player is playing song or paused
'''
return self.playing
def delete_song(self) -> bool:
'''
permanently remove the song from the playlist
@return: whether the song is successfully removed
'''
self.player.pause()
# remove the song from the folder
if not os.path.exists(self.now_playing.value.get_file()):
return False
os.remove(self.now_playing.value.get_file())
# remove the song from the linked list (media player)
if self.remove(self.now_playing.value) == -1:
return False
return True
def play_pause(self) -> None:
'''
play or pause the song
'''
# if song is playing -> pause it
if self.playing:
self.player.pause()
self.playing = False
# if is paused -> continue playing
else:
self.player.play()
self.playing = True
def destroy(self) -> None:
'''
destroy the music player and shut down the song
'''
self.player.delete()
def __load_current_song(self) -> None:
'''
add the current song to queue and then play it
when the song finishes, continue to the next song in the playlist
'''
self.player.next_source()
src = pyglet.media.load(self.now_playing.value.get_file())
self.current_song_duration = src.duration
self.player.queue(src)
self.player.play()
def __read_files(self, path) -> None:
'''
initialize the linked list with all the songs in the path given
'''
for file in os .listdir(path):
string = file.split('-')
artist = self.__make_readable(string[0])
name = self.__make_readable(string[1])
song = Song(name, artist, path + '/' + file)
self.append(song)
def __clean_up(self, path: str) -> None:
'''
delete all the files that are not m4a type in the playlist folder
'''
for file in os.listdir(path):
if not file.endswith('.m4a'):
os.remove(path + '/' + file)
def __make_readable(self, string: str) -> str:
'''
turn a snake case string into a normal string with spaces
also remove the file name at the end
'''
string = string.removesuffix('.m4a')
string = string.replace('_', ' ')
return ''.join((element + ' ') for element in string)