4
4
"""
5
5
PyPortal winamp displayio widget classes.
6
6
"""
7
+ import os
7
8
import time
8
9
import json
9
10
import board
@@ -28,7 +29,7 @@ class WinampApplication(displayio.Group):
28
29
29
30
STATE_PLAYING = 0
30
31
STATE_PAUSED = 1
31
- # pylint: disable=too-many-statements
32
+ # pylint: disable=too-many-statements,too-many-branches
32
33
def __init__ (
33
34
self ,
34
35
playlist_file = "playlist.json" ,
@@ -45,10 +46,29 @@ def __init__(
45
46
self .CONFIG_DATA = json .loads (f .read ())
46
47
f .close ()
47
48
48
- # read the playlist data into variable
49
- f = open (self .PLAYLIST_FILE , "r" )
50
- self .PLAYLIST = json .loads (f .read ())
51
- f .close ()
49
+ if self .PLAYLIST_FILE :
50
+ try :
51
+ # read the playlist data into variable
52
+ f = open (self .PLAYLIST_FILE , "r" )
53
+ self .PLAYLIST = json .loads (f .read ())
54
+ f .close ()
55
+ except OSError :
56
+ # file not found
57
+ self .auto_find_tracks ()
58
+ except ValueError :
59
+ # json parse error
60
+ self .auto_find_tracks ()
61
+ else :
62
+ # playlist file argument was None
63
+ self .auto_find_tracks ()
64
+
65
+ if self .PLAYLIST :
66
+ try :
67
+ if len (self .PLAYLIST ["playlist" ]["files" ]) == 0 :
68
+ # valid playlist json data, but no tracks
69
+ self .auto_find_tracks ()
70
+ except KeyError :
71
+ self .auto_find_tracks ()
52
72
53
73
# initialize clock display
54
74
self .clock_display = ClockDisplay (text_color = self .CONFIG_DATA ["time_color" ])
@@ -148,6 +168,80 @@ def __init__(
148
168
self ._seconds_elapsed = 0
149
169
self ._last_increment_time = 0
150
170
171
+ def auto_find_tracks (self ):
172
+ """
173
+ Initialize the song_list by searching for all MP3's within
174
+ two layers of directories on the SDCard.
175
+
176
+ e.g. It will find all of:
177
+ /sd/Amazing Song.mp3
178
+ /sd/[artist_name]/Amazing Song.mp3
179
+ /sd/[artist_name]/[album_name]/Amazing Song.mp3
180
+
181
+ but won't find:
182
+ /sd/my_music/[artist_name]/[album_name]/Amazing Song.mp3
183
+
184
+ :return: None
185
+ """
186
+ # list that holds all files in the root of SDCard
187
+ _root_sd_all_files = os .listdir ("/sd/" )
188
+
189
+ # list that will hold all directories in the root of the SDCard.
190
+ _root_sd_dirs = []
191
+
192
+ # list that will hold all subdirectories inside of root level directories
193
+ _second_level_dirs = []
194
+
195
+ # list that will hold all MP3 file songs that we find
196
+ _song_list = []
197
+
198
+ # loop over all files found on SDCard
199
+ for _file in _root_sd_all_files :
200
+ try :
201
+ # Check if the current file is a directory
202
+ os .listdir ("/sd/{}" .format (_file ))
203
+
204
+ # add it to a list to look at later
205
+ _root_sd_dirs .append (_file )
206
+ except OSError :
207
+ # current file was not a directory, nothing to do.
208
+ pass
209
+
210
+ # if current file is an MP3 file
211
+ if _file .endswith (".mp3" ):
212
+ # we found an MP3 file, add it to the list that will become our playlist
213
+ _song_list .append ("/sd/{}" .format (_file ))
214
+
215
+ # loop over root level directories
216
+ for _dir in _root_sd_dirs :
217
+ # loop over all files inside of root level directory
218
+ for _file in os .listdir ("/sd/{}" .format (_dir )):
219
+
220
+ # check if current file is a directory
221
+ try :
222
+ # if it is a directory, loop over all files inside of it
223
+ for _inner_file in os .listdir ("/sd/{}/{}" .format (_dir , _file )):
224
+ # check if inner file is an MP3
225
+ if _inner_file .endswith (".mp3" ):
226
+ # we found an MP3 file, add it to the list that will become our playlist
227
+ _song_list .append (
228
+ "/sd/{}/{}/{}" .format (_dir , _file , _inner_file )
229
+ )
230
+ except OSError :
231
+ # current file is not a directory
232
+ pass
233
+ # if the current file is an MP3 file
234
+ if _file .endswith (".mp3" ):
235
+ # we found an MP3 file, add it to the list that will become our playlist
236
+ _song_list .append ("/sd/{}/{}" .format (_dir , _file ))
237
+
238
+ # format the songs we found into the PLAYLIST data structure
239
+ self .PLAYLIST = {"playlist" : {"files" : _song_list }}
240
+
241
+ # print message to user letting them know we auto-generated the playlist
242
+ print ("Auto Generated Playlist from MP3's found on SDCard:" )
243
+ print (json .dumps (self .PLAYLIST ))
244
+
151
245
def update (self ):
152
246
"""
153
247
Must be called each iteration from the main loop.
@@ -359,7 +453,7 @@ def song_list(self, new_song_list):
359
453
def from_files_list (self , files_list ):
360
454
"""
361
455
Initialize the song_list from a list of filenames.
362
- Directories and mp3 file extension will be removed.
456
+ Directories and MP3 file extension will be removed.
363
457
364
458
:param files_list: list of strings containing filenames
365
459
:return: None
0 commit comments