44"""
55PyPortal winamp displayio widget classes.
66"""
7+ import os
78import time
89import json
910import board
@@ -28,7 +29,7 @@ class WinampApplication(displayio.Group):
2829
2930 STATE_PLAYING = 0
3031 STATE_PAUSED = 1
31- # pylint: disable=too-many-statements
32+ # pylint: disable=too-many-statements,too-many-branches
3233 def __init__ (
3334 self ,
3435 playlist_file = "playlist.json" ,
@@ -45,10 +46,29 @@ def __init__(
4546 self .CONFIG_DATA = json .loads (f .read ())
4647 f .close ()
4748
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 ()
5272
5373 # initialize clock display
5474 self .clock_display = ClockDisplay (text_color = self .CONFIG_DATA ["time_color" ])
@@ -148,6 +168,80 @@ def __init__(
148168 self ._seconds_elapsed = 0
149169 self ._last_increment_time = 0
150170
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+
151245 def update (self ):
152246 """
153247 Must be called each iteration from the main loop.
@@ -359,7 +453,7 @@ def song_list(self, new_song_list):
359453 def from_files_list (self , files_list ):
360454 """
361455 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.
363457
364458 :param files_list: list of strings containing filenames
365459 :return: None
0 commit comments