Toggle Navigation
Hatchery
Eggs
Mod Music Player
__init__.py
Users
Badges
Login
Register
MCH2022 badge?
go to mch2022.badge.team
__init__.py
raw
Content
import sys print("Importing internal dependencies...") # The badge does support relative imports without a known parent package, but normal python doesn't (it probably does # but the context is not known to me, and therefore this dirty hack :) if hasattr(sys, "_called_from_test"): from player import ( next_track, get_random_track, previous_track, volume_raise, volume_lower, set_playing_track, set_current_volume, set_playlist, next_playlist, previous_playlist, get_current_volume, current_playlist_directory, ) from graphics import ( set_animation, animation_wifi_searching_progress, full_sceen_feedback, animation_wifi_searching, progress_animation, default_animation, get_previous_animation, get_next_animation, ) from settings import ( KEYS, TRACK_SERVER ) else: from .player import ( next_track, get_random_track, previous_track, volume_raise, volume_lower, set_playing_track, set_current_volume, set_playlist, next_playlist, previous_playlist, get_current_volume, current_playlist_directory ) from .graphics import ( set_animation, animation_wifi_searching_progress, full_sceen_feedback, animation_wifi_searching, progress_animation, default_animation, get_previous_animation, get_next_animation, ) from .settings import ( KEYS, TRACK_SERVER ) print("Importing external dependencies...") import wifi, audio, keypad, sndmixer, machine, touchpads # noqa (missing libs while developing) print("Imported internal dependencies.") MUSIC = True INTERACTION = True ANIMATIONS = True # Every time an audio channel is made, it's added to this list. Audio channels can't be just a single variable because # multiple audio channels might be claimed (and will be) for reasons. So using this trick, we're sure that hitting # the "next" button actually stops playing everything and moves to the next track. audio_channels = [] # thnx better radio app :) this is so friendly, would be a shame if something happened to it. def setvolume(volume): set_current_volume(volume) for index in audio.handles.keys(): sndmixer.volume(index, volume) def stop_all_audio(): global audio_channels # can be multiple channels, and a random new channel is created each time # you press next. This might cause two or more songs are playing at the same time. # because it's not smart to alter an array while iterating, a "remove list" is created # and then the audio channels are removed one by one. remove = [] for audio_channel in audio_channels: audio.stop_channel(audio_channel) remove.append(audio_channel) for item in remove: audio_channels.remove(item) def play_track(track_name): global audio_channels set_playing_track(track_name) stop_all_audio() # switching to an animating loading animation is impossible: the display locks while downloading a file. if not wifi.status(): connect_wifi() try: track_url = "" + TRACK_SERVER + current_playlist_directory() + "/" + track_name print("Attempting to retrieve track from: " + track_url) audio_channels.append( audio.play( track_url, volume=get_current_volume(), loop=False, on_finished=play_next, ), ) except ValueError as e: """ Exception in keypad event handler Traceback (most recent call last): File "keypad.py", line 41, in _keypad_interrupt_handler File "apps/mod_music_player/__init__.py", line 116, in on_key File "apps/mod_music_player/__init__.py", line 64, in play_next File "apps/mod_music_player/__init__.py", line 61, in play_track File "audio.py", line 73, in play File "audio.py", line 26, in _add_channel ... File "urequests.py", line 111, in get File "urequests.py", line 35, in request ValueError: WiFi not connected :return: """ if "WiFi not connected" in str(e): print("Wifi connection issues...") connect_wifi() play_track(track_name) except MemoryError: """ It looks like in some cases files are damaged or unreadable. In such cases try the next song. Shame though. :) Now playing: an-path.xm Exception in keypad event handler Traceback (most recent call last): File "keypad.py", line 41, in _keypad_interrupt_handler File "apps/mod_music_player/__init__.py", line 142, in on_key File "apps/mod_music_player/__init__.py", line 90, in play_next File "apps/mod_music_player/__init__.py", line 87, in play_track File "apps/mod_music_player/__init__.py", line 68, in play_track File "audio.py", line 73, in play File "audio.py", line 43, in _add_channel MemoryError: memory allocation failed, """ print("Probably a corrupt or unsupported song is being played.") play_next() except OSError: """ Traceback (most recent call last): File "boot.py", line 62, in <module> File "apps/mod_music_player/__init__.py", line 268, in <module> File "apps/mod_music_player/__init__.py", line 244, in initialize File "apps/mod_music_player/__init__.py", line 159, in play_track File "apps/mod_music_player/__init__.py", line 116, in play_track File "audio.py", line 73, in play File "audio.py", line 43, in _add_channel OSError: [Errno 110] ETIMEDOUT """ print("Could not register channels, trying next track...") play_next() def play_next(): play_track(next_track()) def play_previous(): play_track(previous_track()) def on_key(key_index, pressed): if pressed: print("Pressed key: " + str(key_index)) if key_index == KEYS["previous_track"]: full_sceen_feedback() play_previous() full_sceen_feedback() if key_index == KEYS["next_track"]: full_sceen_feedback() play_next() full_sceen_feedback() if key_index == KEYS["previous_animation"]: set_animation(get_previous_animation()) if key_index == KEYS["next_animation"]: set_animation(get_next_animation()) full_sceen_feedback() def vol_up(is_pressed): if is_pressed: full_sceen_feedback() setvolume(volume_raise()) def vol_down(is_pressed): if is_pressed: full_sceen_feedback() setvolume(volume_lower()) def switch_to_next_playlist(is_pressed): if is_pressed: full_sceen_feedback() set_playlist(next_playlist()) play_next() full_sceen_feedback() def switch_to_previous_playlist(is_pressed): if is_pressed: full_sceen_feedback() set_playlist(previous_playlist()) play_next() full_sceen_feedback() def connect_wifi(): print("Creating wifi connection") animation_wifi_searching() while not wifi.status(): # show that wifi is expected. The home button still works to exit. print("- Attempting to connect to wifi...") animation_wifi_searching_progress() wifi.connect() wifi.wait() print("Connected to wifi") def initialize(): print("Initializing app.") if MUSIC: print("Setting up audio.") retrieved_volume = machine.nvs_getint("system", "volume") if retrieved_volume: setvolume(retrieved_volume) # setting up a wifi connection is slow, which will be animated. connect_wifi() print("Playing the first track") play_track(get_random_track()) if ANIMATIONS: print("Setting up display effects") # Only base timers 0~3 and extended timers 4~11 can be used. timer = machine.Timer(3) # pretty smooth, 20 fps # # mytimer: Period: 100 ms; Repeat: True; Type: Periodic; Running: yes Events: 70; Callbacks: 13; Missed: 57 # https://techtutorialsx.com/2017/10/07/esp32-micropython-timer-interrupts/ timer.init(period=100, mode=machine.Timer.PERIODIC, callback=progress_animation) print("Showing the first visual") set_animation(default_animation) if INTERACTION: print("Setting up keypad") keypad.add_handler(on_key) print("Setting up touchpads") touchpads.on(touchpads.RIGHT, vol_up) touchpads.on(touchpads.LEFT, vol_down) touchpads.on(touchpads.CANCEL, switch_to_previous_playlist) touchpads.on(touchpads.OK, switch_to_next_playlist) if not hasattr(sys, "_called_from_test"): initialize()