diff --git a/.gitignore b/.gitignore index 640dcc2..3a60f5d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ __pycache__ -art/* +.cache/ *.log auth diff --git a/textual1/app.py b/textual1/app.py index c8e5ed3..5757a21 100644 --- a/textual1/app.py +++ b/textual1/app.py @@ -10,6 +10,11 @@ LOG_FORMAT = '[%(asctime)s] %(levelname)s in %(module)s: %(message)s' if os.path.exists(LOG_FILE): os.remove(LOG_FILE) +CACHE = True + +os.makedirs(".cache/art/", exist_ok=True) +os.makedirs(".cache/audio/", exist_ok=True) + logging.basicConfig(filename=LOG_FILE, level=LOGGING_LEVEL, format=LOG_FORMAT) import SubSonic @@ -316,13 +321,30 @@ class CoverArtPixels(Container): @work(exclusive=True, thread=True) def get_cover_art(self, cover_art_id: str) -> None: - try: - cover_art_data = conn.getCoverArtRaw(cover_art_id) - image = Image.open(io.BytesIO(cover_art_data)) - self.cover = image - except Exception as e: - logging.error(f"Failed to get cover art: {e}") - self.cover = None + image = None + cache_path = f".cache/art/{cover_art_id}.png" + + if CACHE and os.path.exists(cache_path): + try: + image = Image.open(cache_path) + self.cover = image + except Exception as e: + logging.error(f"Failed to load cached cover art {cache_path}: {e}") + + if image is None: + try: + cover_art_data = conn.getCoverArtRaw(cover_art_id) + image = Image.open(io.BytesIO(cover_art_data)) + if CACHE: + try: + image.save(cache_path, "PNG") + except Exception as e: + logging.error(f"Failed to save cover art to cache {cache_path}: {e}") + self.cover = image + except Exception as e: + logging.error(f"Failed to get cover art: {e}") + self.cover = None + return class QueueTable(Widget): @@ -473,8 +495,21 @@ class TextualSubpyPlayer(App): self.notify(f"Playing \"{song.title}\" by {song.artist}.") - r = conn.stream(song.id) - audio_data = io.BytesIO(r.content) + audio_data = None + audio_cache_path = f'.cache/audio/{song.id}.ogg' + + if CACHE: + if os.path.exists(audio_cache_path): + with open(audio_cache_path, 'rb') as file: + audio_data = io.BytesIO(file.read()) + + if not audio_data: + r = conn.stream(song.id) + if CACHE: + with open(audio_cache_path, "wb") as file: + file.write(r.content) + + audio_data = io.BytesIO(r.content) pygame.mixer.music.load(audio_data) pygame.mixer.music.play()