mirror of
https://github.com/csd4ni3l/music-player.git
synced 2025-11-05 04:58:17 +01:00
Total UI Refresh to card-based, merge playlists and tabs, fix album caching not working, add lyrics caching, add lyrics viewer, fix settings
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 541 B |
|
Before Width: | Height: | Size: 468 B After Width: | Height: | Size: 468 B |
Binary file not shown.
|
Before Width: | Height: | Size: 400 B |
Binary file not shown.
|
Before Width: | Height: | Size: 256 B |
264
menus/main.py
264
menus/main.py
@@ -2,18 +2,18 @@ import random, asyncio, pypresence, time, copy, json, os, logging
|
||||
import arcade, pyglet
|
||||
|
||||
from utils.preload import *
|
||||
from utils.constants import button_style, slider_style, audio_extensions, discord_presence_id, view_modes
|
||||
from utils.utils import FakePyPresence, UIFocusTextureButton, MusicItem
|
||||
from utils.constants import button_style, slider_style, audio_extensions, discord_presence_id
|
||||
from utils.utils import FakePyPresence, UIFocusTextureButton, MusicItem, MouseAwareScrollArea
|
||||
from utils.music_handling import update_last_play_statistics, extract_metadata_and_thumbnail, adjust_volume, truncate_end
|
||||
from utils.file_watching import watch_directories, watch_files
|
||||
|
||||
from thefuzz import process, fuzz
|
||||
|
||||
from arcade.gui.experimental.scroll_area import UIScrollArea, UIScrollBar
|
||||
from arcade.gui.experimental.scroll_area import UIScrollBar
|
||||
from arcade.gui.experimental.focus import UIFocusGroup
|
||||
|
||||
class Main(arcade.gui.UIView):
|
||||
def __init__(self, pypresence_client: None | FakePyPresence | pypresence.Presence=None, current_mode: str | None=None, current_music_artist: str | None=None,
|
||||
def __init__(self, pypresence_client: None | FakePyPresence | pypresence.Presence=None, current_tab: str | None=None, current_mode: str | None=None, current_music_artist: str | None=None,
|
||||
current_music_title: str | None=None, current_music_path: str | None=None, current_length: int | None=None,
|
||||
current_music_player: pyglet.media.Player | None=None, queue: list | None=None, loaded_sounds: dict | None=None, shuffle: bool=False):
|
||||
|
||||
@@ -71,9 +71,8 @@ class Main(arcade.gui.UIView):
|
||||
self.shuffle = shuffle
|
||||
self.volume = self.settings_dict.get("default_volume", 100)
|
||||
|
||||
self.current_mode = current_mode or "files"
|
||||
self.current_playlist = None
|
||||
self.current_tab = self.tab_options[0]
|
||||
self.current_mode = current_mode if current_mode else "files"
|
||||
self.current_tab = current_tab if current_tab else self.tab_options[0]
|
||||
self.search_term = ""
|
||||
self.highest_score_file = ""
|
||||
|
||||
@@ -95,19 +94,28 @@ class Main(arcade.gui.UIView):
|
||||
def create_ui(self):
|
||||
self.anchor = self.add_widget(UIFocusGroup(size_hint=(1, 1)))
|
||||
|
||||
self.ui_box = self.anchor.add(arcade.gui.UIBoxLayout(size_hint=(1, 1), space_between=10))
|
||||
self.ui_box = self.anchor.add(arcade.gui.UIBoxLayout(size_hint=(1, 0.97), space_between=5, vertical=False))
|
||||
|
||||
self.ui_box.add(arcade.gui.UISpace(width=5))
|
||||
|
||||
# Tabs
|
||||
self.tab_box = self.ui_box.add(arcade.gui.UIBoxLayout(size_hint=(0.95, 0.1), space_between=10, vertical=False))
|
||||
self.tab_box = self.ui_box.add(arcade.gui.UIBoxLayout(size_hint=(0.05, 1), space_between=10, align="center"))
|
||||
self.load_tabs()
|
||||
|
||||
if self.current_mode == "playlist" and not self.current_playlist:
|
||||
self.current_playlist = list(self.playlist_content.keys())[0] if self.playlist_content else None
|
||||
self.ui_box.add(arcade.gui.UISpace(width=5))
|
||||
|
||||
self.content_box = self.ui_box.add(arcade.gui.UIBoxLayout(size_hint=(0.915, 1), space_between=10))
|
||||
|
||||
self.search_bar = self.content_box.add(arcade.gui.UIInputText(size_hint=(0.5, 0.04), font_size=14))
|
||||
self.search_bar.on_change = lambda e: self.search()
|
||||
|
||||
if self.current_mode == "playlist" and not self.current_tab:
|
||||
self.current_tab = list(self.playlist_content.keys())[0] if self.playlist_content else None
|
||||
|
||||
# Scrollable Sounds
|
||||
self.scroll_box = self.ui_box.add(arcade.gui.UIBoxLayout(size_hint=(0.95, 0.85), space_between=15, vertical=False))
|
||||
self.scroll_box = self.content_box.add(arcade.gui.UIBoxLayout(size_hint=(1, 0.90), space_between=15, vertical=False))
|
||||
|
||||
self.scroll_area = UIScrollArea(size_hint=(0.95, 1)) # center on screen
|
||||
self.scroll_area = MouseAwareScrollArea(size_hint=(1, 1)) # center on screen
|
||||
self.scroll_area.scroll_speed = -50
|
||||
self.scroll_box.add(self.scroll_area)
|
||||
|
||||
@@ -115,33 +123,12 @@ class Main(arcade.gui.UIView):
|
||||
self.scrollbar.size_hint = (0.02, 1)
|
||||
self.scroll_box.add(self.scrollbar)
|
||||
|
||||
self.music_box = arcade.gui.UIBoxLayout(space_between=5)
|
||||
self.scroll_area.add(self.music_box)
|
||||
|
||||
# Utility
|
||||
|
||||
self.settings_box = self.anchor.add(arcade.gui.UIBoxLayout(space_between=10), anchor_x="right", anchor_y="center", align_x=-10)
|
||||
|
||||
self.new_tab_button = self.settings_box.add(UIFocusTextureButton(texture=plus_icon, texture_hovered=plus_icon, texture_pressed=plus_icon, style=button_style))
|
||||
self.new_tab_button.on_click = lambda event: self.new_tab()
|
||||
|
||||
self.downloader_button = self.settings_box.add(UIFocusTextureButton(texture=download_icon, texture_hovered=download_icon, texture_pressed=download_icon, style=button_style))
|
||||
self.downloader_button.on_click = lambda event: self.downloader()
|
||||
|
||||
if self.current_mode == "files":
|
||||
mode_icon = files_icon
|
||||
elif self.current_mode == "playlist":
|
||||
mode_icon = playlist_icon
|
||||
|
||||
self.mode_button = self.settings_box.add(UIFocusTextureButton(texture=mode_icon, texture_hovered=mode_icon, texture_pressed=mode_icon, style=button_style))
|
||||
self.mode_button.on_click = lambda event: self.change_mode()
|
||||
|
||||
self.settings_button = self.settings_box.add(UIFocusTextureButton(texture=settings_icon, style=button_style))
|
||||
self.settings_button.on_click = lambda event: self.settings()
|
||||
self.music_grid = arcade.gui.UIGridLayout(horizontal_spacing=10, vertical_spacing=10, row_count=99, column_count=7)
|
||||
self.scroll_area.add(self.music_grid)
|
||||
|
||||
# Controls
|
||||
|
||||
self.now_playing_box = self.ui_box.add(arcade.gui.UIBoxLayout(size_hint=(0.99, 0.075), space_between=10, vertical=False))
|
||||
self.now_playing_box = self.content_box.add(arcade.gui.UIBoxLayout(size_hint=(0.99, 0.075), space_between=10, vertical=False))
|
||||
|
||||
self.current_music_thumbnail_image = self.now_playing_box.add(arcade.gui.UIImage(texture=music_icon, width=self.window.width / 25, height=self.window.height / 15))
|
||||
|
||||
@@ -152,8 +139,6 @@ class Main(arcade.gui.UIView):
|
||||
self.current_music_title_label = self.current_music_box.add(arcade.gui.UILabel(text=truncate_end(self.current_music_title, int(self.window.width / 50)) if self.current_music_title else "No songs playing", font_name="Roboto", font_size=12))
|
||||
self.current_music_artist_label = self.current_music_box.add(arcade.gui.UILabel(text=truncate_end(self.current_music_artist, int(self.window.width / 50)) if self.current_music_artist else "No songs playing", font_name="Roboto", font_size=10, text_color=arcade.color.GRAY))
|
||||
|
||||
self.now_playing_box.add(arcade.gui.UISpace(width=self.window.width / 16))
|
||||
|
||||
# Time box with controls, progressbar and time
|
||||
self.current_time_box = self.now_playing_box.add(arcade.gui.UIBoxLayout(space_between=10))
|
||||
|
||||
@@ -180,7 +165,7 @@ class Main(arcade.gui.UIView):
|
||||
|
||||
self.time_label = self.progressbar_box.add(arcade.gui.UILabel(text="00:00", font_name="Roboto", font_size=13))
|
||||
|
||||
self.progressbar = self.progressbar_box.add(arcade.gui.UISlider(style=slider_style, width=self.window.width / 3, height=self.window.height / 45))
|
||||
self.progressbar = self.progressbar_box.add(arcade.gui.UISlider(style=slider_style, width=self.window.width / 4, height=self.window.height / 45))
|
||||
self.progressbar.on_change = self.on_progress_change
|
||||
|
||||
self.full_length_label = self.progressbar_box.add(arcade.gui.UILabel(text="00:00", font_name="Roboto", font_size=13))
|
||||
@@ -189,37 +174,34 @@ class Main(arcade.gui.UIView):
|
||||
self.progressbar.max_value = self.current_length
|
||||
self.volume = int(self.current_music_player.volume * 100)
|
||||
|
||||
self.now_playing_box.add(arcade.gui.UISpace(width=self.window.width / 16))
|
||||
|
||||
self.volume_icon_label = self.now_playing_box.add(arcade.gui.UIImage(texture=volume_icon))
|
||||
self.volume_slider = self.now_playing_box.add(arcade.gui.UISlider(style=slider_style, width=self.window.width / 10, height=35, value=self.volume, max_value=100))
|
||||
self.volume_slider.on_change = self.on_volume_slider_change
|
||||
|
||||
self.tools_box = self.anchor.add(arcade.gui.UIBoxLayout(space_between=15, vertical=False), anchor_x="right", anchor_y="bottom", align_x=-15, align_y=15)
|
||||
|
||||
self.metadata_button = self.tools_box.add(UIFocusTextureButton(texture=metadata_icon, style=button_style))
|
||||
self.metadata_button.on_click = lambda event: self.view_metadata(self.current_music_path) if self.current_music_path else None
|
||||
|
||||
self.downloader_button = self.tools_box.add(UIFocusTextureButton(texture=download_icon, style=button_style))
|
||||
self.downloader_button.on_click = lambda event: self.downloader()
|
||||
|
||||
self.settings_button = self.tools_box.add(UIFocusTextureButton(texture=settings_icon, style=button_style), anchor_x="right", anchor_y="bottom", align_x=-15, align_y=15)
|
||||
self.settings_button.on_click = lambda event: self.settings()
|
||||
|
||||
self.no_music_label = self.anchor.add(arcade.gui.UILabel(text="No music files were found in this directory or playlist.", font_name="Roboto", font_size=24), anchor_x="center", anchor_y="center")
|
||||
self.no_music_label.visible = False
|
||||
|
||||
self.no_playlists_label = self.anchor.add(arcade.gui.UILabel(text="You have no playlists.", font_name="Roboto", font_size=24))
|
||||
self.no_playlists_label.visible = False
|
||||
|
||||
if self.current_mode == "files":
|
||||
self.show_content(os.path.expanduser(self.current_tab))
|
||||
self.show_content(os.path.expanduser(self.current_tab), "files")
|
||||
elif self.current_mode == "playlist":
|
||||
self.show_content(self.current_playlist)
|
||||
self.show_content(self.current_tab, "playlist")
|
||||
|
||||
arcade.schedule(self.update_presence, 3)
|
||||
|
||||
self.update_presence(None)
|
||||
|
||||
def update_buttons(self):
|
||||
if self.current_mode == "files":
|
||||
mode_icon = files_icon
|
||||
elif self.current_mode == "playlist":
|
||||
mode_icon = playlist_icon
|
||||
|
||||
self.mode_button.texture = mode_icon
|
||||
self.mode_button.texture_hovered = mode_icon
|
||||
self.mode_button.texture_pressed = mode_icon
|
||||
|
||||
self.shuffle_button.texture = no_shuffle_icon if self.shuffle else shuffle_icon
|
||||
self.shuffle_button.texture_hovered = no_shuffle_icon if self.shuffle else shuffle_icon
|
||||
self.shuffle_button.texture_pressed = no_shuffle_icon if self.shuffle else shuffle_icon
|
||||
@@ -243,21 +225,6 @@ class Main(arcade.gui.UIView):
|
||||
|
||||
self.anchor.detect_focusable_widgets()
|
||||
|
||||
def change_mode(self):
|
||||
if view_modes.index(self.current_mode) == len(view_modes) - 1:
|
||||
self.current_mode = view_modes[0]
|
||||
else:
|
||||
self.current_mode = view_modes[view_modes.index(self.current_mode) + 1]
|
||||
|
||||
self.current_playlist = list(self.playlist_content.keys())[0] if self.playlist_content else None
|
||||
|
||||
self.highest_score_file = ""
|
||||
self.search_term = ""
|
||||
|
||||
self.reload()
|
||||
self.load_tabs()
|
||||
self.update_buttons()
|
||||
|
||||
def previous_track(self):
|
||||
if not self.current_music_player is None:
|
||||
if self.current_mode == "files":
|
||||
@@ -265,9 +232,9 @@ class Main(arcade.gui.UIView):
|
||||
current_idx = self.tab_content[self.current_tab].index(os.path.basename(self.current_music_path))
|
||||
self.queue.append(f"{self.current_tab}/{self.tab_content[self.current_tab][current_idx - 1]}")
|
||||
elif self.current_mode == "playlist":
|
||||
if os.path.basename(self.current_music_path) in self.playlist_content[self.current_playlist]:
|
||||
current_idx = self.playlist_content[self.current_playlist].index(os.path.basename(self.current_music_path))
|
||||
self.queue.append(f"{self.current_playlist}/{self.playlist_content[self.current_playlist][current_idx - 1]}")
|
||||
if os.path.basename(self.current_music_path) in self.playlist_content[self.current_tab]:
|
||||
current_idx = self.playlist_content[self.current_tab].index(os.path.basename(self.current_music_path))
|
||||
self.queue.append(f"{self.current_tab}/{self.playlist_content[self.current_tab][current_idx - 1]}")
|
||||
|
||||
self.skip_sound()
|
||||
|
||||
@@ -278,9 +245,9 @@ class Main(arcade.gui.UIView):
|
||||
current_idx = self.tab_content[self.current_tab].index(os.path.basename(self.current_music_path))
|
||||
self.queue.append(f"{self.current_tab}/{self.tab_content[self.current_tab][current_idx + 1]}")
|
||||
elif self.current_mode == "playlist":
|
||||
if os.path.basename(self.current_music_path) in self.playlist_content[self.current_playlist]:
|
||||
current_idx = self.playlist_content[self.current_playlist].index(os.path.basename(self.current_music_path))
|
||||
self.queue.append(f"{self.current_playlist}/{self.playlist_content[self.current_playlist][current_idx + 1]}")
|
||||
if os.path.basename(self.current_music_path) in self.playlist_content[self.current_tab]:
|
||||
current_idx = self.playlist_content[self.current_tab].index(os.path.basename(self.current_music_path))
|
||||
self.queue.append(f"{self.current_tab}/{self.playlist_content[self.current_tab][current_idx + 1]}")
|
||||
|
||||
self.skip_sound()
|
||||
|
||||
@@ -292,7 +259,7 @@ class Main(arcade.gui.UIView):
|
||||
|
||||
if self.settings_dict.get("music_mode", "Streaming") == "Streaming":
|
||||
del self.loaded_sounds[self.current_music_path]
|
||||
|
||||
|
||||
self.current_length = 0
|
||||
self.current_music_artist = None
|
||||
self.current_music_title = None
|
||||
@@ -324,58 +291,58 @@ class Main(arcade.gui.UIView):
|
||||
|
||||
def view_metadata(self, file_path):
|
||||
from menus.metadata_viewer import MetadataViewer
|
||||
self.window.show_view(MetadataViewer(self.pypresence_client, "music", self.file_metadata[file_path], file_path, self.current_mode, self.current_music_artist, self.current_music_title, self.current_music_path, self.current_length, self.current_music_player, self.queue, self.loaded_sounds, self.shuffle))
|
||||
self.window.show_view(MetadataViewer(self.pypresence_client, "music", self.file_metadata[file_path], file_path, self.current_tab, self.current_mode, self.current_music_artist, self.current_music_title, self.current_music_path, self.current_length, self.current_music_player, self.queue, self.loaded_sounds, self.shuffle))
|
||||
|
||||
def show_content(self, tab):
|
||||
def show_content(self, tab, content_type):
|
||||
for music_button in self.music_buttons.values():
|
||||
music_button.clear()
|
||||
self.music_box.remove(music_button)
|
||||
self.music_grid.remove(music_button)
|
||||
del music_button
|
||||
|
||||
self.music_box.clear()
|
||||
self.music_grid.clear()
|
||||
self.music_buttons.clear()
|
||||
|
||||
if self.current_mode == "files":
|
||||
self.current_tab = tab
|
||||
if not self.search_term == "":
|
||||
matches = process.extract(self.search_term, self.tab_content[self.current_tab], limit=5, processor=lambda text: text.lower(), scorer=fuzz.partial_token_sort_ratio)
|
||||
self.highest_score_file = f"{self.current_tab}/{matches[0][0]}"
|
||||
content_to_show = [match[0] for match in matches]
|
||||
self.current_tab = tab
|
||||
self.current_mode = content_type
|
||||
|
||||
original_content = self.tab_content[tab] if self.current_mode == "files" else self.playlist_content[tab]
|
||||
|
||||
if not self.search_term == "":
|
||||
matches = process.extract(self.search_term, original_content, limit=5, processor=lambda text: text.lower(), scorer=fuzz.partial_token_sort_ratio)
|
||||
self.highest_score_file = f"{self.current_tab}/{matches[0][0]}"
|
||||
content_to_show = [match[0] for match in matches]
|
||||
|
||||
else:
|
||||
self.highest_score_file = ""
|
||||
self.no_music_label.visible = not original_content
|
||||
content_to_show = original_content
|
||||
|
||||
n = 0
|
||||
row, col = 0, 0
|
||||
|
||||
for n, music_filename in enumerate(content_to_show):
|
||||
row = n // 7
|
||||
col = n % 7
|
||||
|
||||
if self.current_mode == "files":
|
||||
music_path = f"{tab}/{music_filename}"
|
||||
else:
|
||||
self.highest_score_file = ""
|
||||
self.no_music_label.visible = not self.tab_content[tab]
|
||||
content_to_show = self.tab_content[tab]
|
||||
music_path = music_filename
|
||||
|
||||
for music_filename in content_to_show:
|
||||
metadata = self.file_metadata[f"{tab}/{music_filename}"]
|
||||
|
||||
self.music_buttons[f"{tab}/{music_filename}"] = self.music_box.add(MusicItem(metadata=metadata, width=self.window.width / 1.2, height=self.window.height / 22))
|
||||
self.music_buttons[f"{tab}/{music_filename}"].button.on_click = lambda event, music_path=f"{tab}/{music_filename}": self.music_button_click(event, music_path)
|
||||
self.music_buttons[f"{tab}/{music_filename}"].view_metadata_button.on_click = lambda event, music_path=f"{tab}/{music_filename}": self.view_metadata(music_path)
|
||||
metadata = self.file_metadata[music_path]
|
||||
|
||||
self.music_buttons[music_path] = self.music_grid.add(MusicItem(metadata=metadata, width=self.window.width / 8, height=self.window.height / 5), row=row, column=col)
|
||||
self.music_buttons[music_path].button.on_click = lambda event, music_path=music_path: self.music_button_click(event, music_path)
|
||||
|
||||
elif self.current_mode == "playlist":
|
||||
self.current_playlist = tab
|
||||
row = (n + 1) // 7
|
||||
col = (n + 1) % 7
|
||||
|
||||
if self.current_playlist:
|
||||
if not self.search_term == "":
|
||||
matches = process.extract(self.search_term, self.playlist_content[tab], limit=5, processor=lambda text: text.lower(), scorer=fuzz.partial_token_sort_ratio)
|
||||
self.highest_score_file = matches[0][0]
|
||||
content_to_show = [match[0] for match in matches]
|
||||
self.music_grid.row_count = row + 1
|
||||
self.music_grid._update_size_hints()
|
||||
|
||||
else:
|
||||
self.highest_score_file = ""
|
||||
self.no_music_label.visible = not self.playlist_content[tab]
|
||||
content_to_show = self.playlist_content[tab]
|
||||
|
||||
for music_path in content_to_show:
|
||||
metadata = self.file_metadata[music_path]
|
||||
self.music_buttons[music_path] = self.music_box.add(MusicItem(metadata=metadata, width=self.window.width / 1.2, height=self.window.height / 22))
|
||||
self.music_buttons[music_path].button.on_click = lambda event, music_path=music_path: self.music_button_click(event, music_path)
|
||||
self.music_buttons[music_path].view_metadata_button.on_click = lambda event, music_path=music_path: self.view_metadata(music_path)
|
||||
|
||||
self.music_buttons["add_music"] = self.music_box.add(MusicItem(metadata=None, width=self.window.width / 1.2, height=self.window.height / 22))
|
||||
self.music_buttons["add_music"].button.on_click = lambda event: self.add_music()
|
||||
if self.current_mode == "playlist":
|
||||
self.music_buttons["add_music"] = self.music_grid.add(MusicItem(metadata=None, width=self.window.width / 8, height=self.window.height / 5), row=row, column=col)
|
||||
self.music_buttons["add_music"].button.on_click = lambda event: self.add_music()
|
||||
|
||||
self.anchor.detect_focusable_widgets()
|
||||
|
||||
@@ -386,7 +353,7 @@ class Main(arcade.gui.UIView):
|
||||
if self.current_mode == "files":
|
||||
os.remove(music_path)
|
||||
elif self.current_mode == "playlist":
|
||||
self.settings_dict["playlists"][self.current_playlist].remove(music_path)
|
||||
self.settings_dict["playlists"][self.current_tab].remove(music_path)
|
||||
|
||||
with open("settings.json", "w") as file:
|
||||
file.write(json.dumps(self.settings_dict, indent=4))
|
||||
@@ -439,18 +406,16 @@ class Main(arcade.gui.UIView):
|
||||
self.should_reload = True # needed because the observer runs in another thread and OpenGL is single-threaded.
|
||||
|
||||
def load_tabs(self):
|
||||
for button in self.tab_buttons.values():
|
||||
self.tab_box.remove(button)
|
||||
self.tab_buttons.clear()
|
||||
for tab in self.tab_options:
|
||||
self.tab_buttons[os.path.expanduser(tab)] = self.tab_box.add(arcade.gui.UITextureButton(texture=button_texture, texture_hovered=button_hovered_texture, text=os.path.basename(os.path.normpath(os.path.expanduser(tab))), style=button_style, width=self.window.width / 15, height=self.window.height / 15))
|
||||
self.tab_buttons[os.path.expanduser(tab)].on_click = lambda event, tab=os.path.expanduser(tab): self.show_content(os.path.expanduser(tab), "files")
|
||||
|
||||
for playlist in self.playlist_content:
|
||||
self.tab_buttons[playlist] = self.tab_box.add(arcade.gui.UITextureButton(texture=button_texture, texture_hovered=button_hovered_texture, text=playlist, style=button_style, width=self.window.width / 15, height=self.window.height / 15))
|
||||
self.tab_buttons[playlist].on_click = lambda event, playlist=playlist: self.show_content(playlist, "playlist")
|
||||
|
||||
if self.current_mode == "files":
|
||||
for tab in self.tab_options:
|
||||
self.tab_buttons[os.path.expanduser(tab)] = self.tab_box.add(arcade.gui.UITextureButton(texture=button_texture, texture_hovered=button_hovered_texture, text=os.path.basename(os.path.normpath(os.path.expanduser(tab))), style=button_style, width=self.window.width / 10, height=self.window.height / 15))
|
||||
self.tab_buttons[os.path.expanduser(tab)].on_click = lambda event, tab=os.path.expanduser(tab): self.show_content(os.path.expanduser(tab))
|
||||
elif self.current_mode == "playlist":
|
||||
for playlist in self.playlist_content:
|
||||
self.tab_buttons[playlist] = self.tab_box.add(arcade.gui.UITextureButton(texture=button_texture, texture_hovered=button_hovered_texture, text=playlist, style=button_style, width=self.window.width / 10, height=self.window.height / 15))
|
||||
self.tab_buttons[playlist].on_click = lambda event, playlist=playlist: self.show_content(playlist)
|
||||
self.new_tab_button = self.tab_box.add(arcade.gui.UITextureButton(texture=button_texture, texture_hovered=button_hovered_texture, style=button_style, text="Add Tab", width=self.window.width / 15, height=self.window.height / 15))
|
||||
self.new_tab_button.on_click = lambda event: self.new_tab()
|
||||
|
||||
def on_progress_change(self, event):
|
||||
if not self.current_music_player is None:
|
||||
@@ -534,27 +499,23 @@ class Main(arcade.gui.UIView):
|
||||
self.current_music_player.seek(self.current_music_player.time + 5)
|
||||
elif symbol == arcade.key.LEFT and self.current_music_player:
|
||||
self.current_music_player.seek(self.current_music_player.time - 5)
|
||||
elif symbol == arcade.key.BACKSPACE:
|
||||
self.search_term = self.search_term[:-1]
|
||||
if self.current_mode == "files":
|
||||
self.show_content(os.path.expanduser(self.current_tab))
|
||||
elif self.current_mode == "playlist":
|
||||
self.show_content(self.current_playlist)
|
||||
elif symbol == arcade.key.ENTER and self.highest_score_file:
|
||||
self.queue.append(self.highest_score_file)
|
||||
self.highest_score_file = ""
|
||||
self.search_term = ""
|
||||
self.search_bar.text = ""
|
||||
if self.current_mode == "files":
|
||||
self.show_content(os.path.expanduser(self.current_tab))
|
||||
self.show_content(os.path.expanduser(self.current_tab), "files")
|
||||
elif self.current_mode == "playlist":
|
||||
self.show_content(self.current_playlist)
|
||||
self.show_content(self.current_tab, "playlist")
|
||||
elif symbol == arcade.key.ESCAPE:
|
||||
self.highest_score_file = ""
|
||||
self.search_term = ""
|
||||
self.search_bar.text = ""
|
||||
if self.current_mode == "files":
|
||||
self.show_content(os.path.expanduser(self.current_tab))
|
||||
self.show_content(os.path.expanduser(self.current_tab), "files")
|
||||
elif self.current_mode == "playlist":
|
||||
self.show_content(self.current_playlist)
|
||||
self.show_content(self.current_tab, "playlist")
|
||||
|
||||
def on_button_press(self, controller, name):
|
||||
if name == "start":
|
||||
@@ -562,50 +523,45 @@ class Main(arcade.gui.UIView):
|
||||
elif name == "b":
|
||||
self.skip_sound()
|
||||
|
||||
def on_text(self, text):
|
||||
if not text.isprintable() or text == " ":
|
||||
return
|
||||
|
||||
self.search_term += text
|
||||
def search(self):
|
||||
self.search_term = self.search_bar.text
|
||||
|
||||
if self.current_mode == "files":
|
||||
self.show_content(os.path.expanduser(self.current_tab))
|
||||
self.show_content(os.path.expanduser(self.current_tab), "files")
|
||||
elif self.current_mode == "playlist":
|
||||
self.show_content(self.current_playlist)
|
||||
self.show_content(self.current_tab, "playlist")
|
||||
|
||||
def settings(self):
|
||||
from menus.settings import Settings
|
||||
arcade.unschedule(self.update_presence)
|
||||
self.ui.clear()
|
||||
self.window.show_view(Settings(self.pypresence_client, self.current_mode, self.current_music_artist, self.current_music_title, self.current_music_path, self.current_length, self.current_music_player, self.queue, self.loaded_sounds, self.shuffle))
|
||||
self.window.show_view(Settings(self.pypresence_client, self.current_tab, self.current_mode, self.current_music_artist, self.current_music_title, self.current_music_path, self.current_length, self.current_music_player, self.queue, self.loaded_sounds, self.shuffle))
|
||||
|
||||
def new_tab(self):
|
||||
from menus.new_tab import NewTab
|
||||
arcade.unschedule(self.update_presence)
|
||||
self.ui.clear()
|
||||
self.window.show_view(NewTab(self.pypresence_client, self.current_mode, self.current_music_artist, self.current_music_title, self.current_music_path, self.current_length, self.current_music_player, self.queue, self.loaded_sounds, self.shuffle))
|
||||
self.window.show_view(NewTab(self.pypresence_client, self.current_tab, self.current_mode, self.current_music_artist, self.current_music_title, self.current_music_path, self.current_length, self.current_music_player, self.queue, self.loaded_sounds, self.shuffle))
|
||||
|
||||
def add_music(self):
|
||||
from menus.add_music import AddMusic
|
||||
arcade.unschedule(self.update_presence)
|
||||
self.ui.clear()
|
||||
self.window.show_view(AddMusic(self.pypresence_client, self.current_mode, self.current_music_artist, self.current_music_title, self.current_music_path, self.current_length, self.current_music_player, self.queue, self.loaded_sounds, self.shuffle))
|
||||
self.window.show_view(AddMusic(self.pypresence_client, self.current_tab, self.current_mode, self.current_music_artist, self.current_music_title, self.current_music_path, self.current_length, self.current_music_player, self.queue, self.loaded_sounds, self.shuffle))
|
||||
|
||||
def downloader(self):
|
||||
from menus.downloader import Downloader
|
||||
arcade.unschedule(self.update_presence)
|
||||
self.ui.clear()
|
||||
self.window.show_view(Downloader(self.pypresence_client, self.current_mode, self.current_music_artist, self.current_music_title, self.current_music_path, self.current_length, self.current_music_player, self.queue, self.loaded_sounds, self.shuffle))
|
||||
self.window.show_view(Downloader(self.pypresence_client, self.current_tab, self.current_mode, self.current_music_artist, self.current_music_title, self.current_music_path, self.current_length, self.current_music_player, self.queue, self.loaded_sounds, self.shuffle))
|
||||
|
||||
def reload(self):
|
||||
self.load_content()
|
||||
|
||||
self.no_playlists_label.visible = not self.playlist_content
|
||||
|
||||
if self.current_mode == "files":
|
||||
self.show_content(os.path.expanduser(self.current_tab))
|
||||
self.show_content(os.path.expanduser(self.current_tab), "files")
|
||||
elif self.current_mode == "playlist":
|
||||
self.show_content(self.current_playlist)
|
||||
self.show_content(self.current_tab, "playlist")
|
||||
|
||||
self.anchor.detect_focusable_widgets()
|
||||
|
||||
|
||||
@@ -10,11 +10,11 @@ from utils.utils import convert_seconds_to_date
|
||||
from utils.music_handling import convert_timestamp_to_time_ago
|
||||
|
||||
class MetadataViewer(arcade.gui.UIView):
|
||||
def __init__(self, pypresence_client, metadata_type="music", metadata_dict=None, file_path=None, *args):
|
||||
def __init__(self, pypresence_client, metadata_type="music", metadata=None, file_path=None, *args):
|
||||
super().__init__()
|
||||
self.metadata_type = metadata_type
|
||||
if metadata_type == "music":
|
||||
self.file_metadata = metadata_dict
|
||||
self.file_metadata = metadata
|
||||
self.artist = self.file_metadata["artist"]
|
||||
self.file_path = file_path
|
||||
if self.artist == "Unknown":
|
||||
@@ -24,9 +24,13 @@ class MetadataViewer(arcade.gui.UIView):
|
||||
self.online_metadata = get_music_metadata(self.artist, self.title)
|
||||
|
||||
elif metadata_type == "artist":
|
||||
self.artist_metadata = metadata_dict
|
||||
self.artist_metadata = metadata
|
||||
elif metadata_type == "album":
|
||||
self.album_metadata = metadata_dict
|
||||
self.album_metadata = metadata
|
||||
elif metadata_type:
|
||||
self.artist = metadata["artist"]
|
||||
self.title = metadata["title"]
|
||||
self.music_lyrics = metadata["lyrics"]
|
||||
|
||||
self.pypresence_client = pypresence_client
|
||||
self.args = args
|
||||
@@ -75,19 +79,21 @@ Sound length: {convert_seconds_to_date(int(self.file_metadata['sound_length']))}
|
||||
Bitrate: {self.file_metadata['bitrate']}Kbps
|
||||
Sample rate: {self.file_metadata['sample_rate']}KHz
|
||||
'''
|
||||
self.more_metadata_buttons.append(self.more_metadata_box.add(arcade.gui.UITextureButton(text=f"Artist Metadata", style=button_style, texture=button_texture, texture_hovered=button_hovered_texture, width=self.window.width / 4.25, height=self.window.height / 15)))
|
||||
self.more_metadata_buttons.append(self.more_metadata_box.add(arcade.gui.UITextureButton(text="Artist Metadata", style=button_style, texture=button_texture, texture_hovered=button_hovered_texture, width=self.window.width / 5.5, height=self.window.height / 15)))
|
||||
self.more_metadata_buttons[-1].on_click = lambda event: self.window.show_view(MetadataViewer(self.pypresence_client, "artist", self.online_metadata[1], None, *self.args))
|
||||
|
||||
self.more_metadata_buttons.append(self.more_metadata_box.add(arcade.gui.UITextureButton(text=f"Album Metadata", style=button_style, texture=button_texture, texture_hovered=button_hovered_texture, width=self.window.width / 4.25, height=self.window.height / 15)))
|
||||
self.more_metadata_buttons.append(self.more_metadata_box.add(arcade.gui.UITextureButton(text="Album Metadata", style=button_style, texture=button_texture, texture_hovered=button_hovered_texture, width=self.window.width / 5.5, height=self.window.height / 15)))
|
||||
self.more_metadata_buttons[-1].on_click = lambda event: self.window.show_view(MetadataViewer(self.pypresence_client, "album", self.online_metadata[2], None, *self.args))
|
||||
|
||||
self.more_metadata_buttons.append(self.more_metadata_box.add(arcade.gui.UITextureButton(text=f"Open Uploader URL", style=button_style, texture=button_texture, texture_hovered=button_hovered_texture, width=self.window.width / 4.25, height=self.window.height / 15)))
|
||||
self.more_metadata_buttons.append(self.more_metadata_box.add(arcade.gui.UITextureButton(text="Lyrics", style=button_style, texture=button_texture, texture_hovered=button_hovered_texture, width=self.window.width / 5.5, height=self.window.height / 15)))
|
||||
self.more_metadata_buttons[-1].on_click = lambda event: self.window.show_view(MetadataViewer(self.pypresence_client, "lyrics", {"artist": self.artist, "title": self.title, "lyrics": self.online_metadata[3]}, None, *self.args))
|
||||
|
||||
self.more_metadata_buttons.append(self.more_metadata_box.add(arcade.gui.UITextureButton(text="Open Uploader URL", style=button_style, texture=button_texture, texture_hovered=button_hovered_texture, width=self.window.width / 5.5, height=self.window.height / 15)))
|
||||
self.more_metadata_buttons[-1].on_click = lambda event: webbrowser.open(self.file_metadata["uploader_url"]) if not self.file_metadata.get("uploader_url", "Unknown") == "Unknown" else None
|
||||
|
||||
self.more_metadata_buttons.append(self.more_metadata_box.add(arcade.gui.UITextureButton(text=f"Open Source URL", style=button_style, texture=button_texture, texture_hovered=button_hovered_texture, width=self.window.width / 4.25, height=self.window.height / 15)))
|
||||
self.more_metadata_buttons.append(self.more_metadata_box.add(arcade.gui.UITextureButton(text="Open Source URL", style=button_style, texture=button_texture, texture_hovered=button_hovered_texture, width=self.window.width / 5.5, height=self.window.height / 15)))
|
||||
self.more_metadata_buttons[-1].on_click = lambda event: webbrowser.open(self.file_metadata["source_url"]) if not self.file_metadata.get("source_url", "Unknown") == "Unknown" else None
|
||||
|
||||
|
||||
metadata_box = self.box.add(arcade.gui.UIBoxLayout(space_between=10, align='left'))
|
||||
|
||||
self.metadata_labels.append(metadata_box.add(arcade.gui.UILabel(text=name, font_size=20, font_name="Roboto", multiline=True)))
|
||||
@@ -140,6 +146,12 @@ Album Country: {album_dict['album_country']}
|
||||
else:
|
||||
full_box.add(arcade.gui.UILabel(text="No cover found.", font_size=18, font_name="Roboto"))
|
||||
|
||||
elif self.metadata_type == "lyrics":
|
||||
name = f"{self.artist} - {self.title} Lyrics"
|
||||
metadata_box = self.box.add(arcade.gui.UIBoxLayout(space_between=10, align='left'))
|
||||
self.metadata_labels.append(metadata_box.add(arcade.gui.UILabel(text=name, font_size=20, font_name="Roboto", multiline=True)))
|
||||
self.metadata_labels.append(metadata_box.add(arcade.gui.UILabel(text=self.music_lyrics, font_size=18, font_name="Roboto", multiline=True)))
|
||||
|
||||
def main_exit(self):
|
||||
from menus.main import Main
|
||||
self.window.show_view(Main(self.pypresence_client, *self.args))
|
||||
|
||||
@@ -20,7 +20,7 @@ class NewTab(arcade.gui.UIView):
|
||||
self.tab_options = self.settings_dict.get("tab_options", [os.path.join("~", "Music"), os.path.join("~", "Downloads")])
|
||||
self.playlists = self.settings_dict.get("playlists", {})
|
||||
|
||||
self.current_mode = self.args[0]
|
||||
self.tab_type = "Directory"
|
||||
|
||||
self.pypresence_client = pypresence_client
|
||||
self.pypresence_client.update(state="Adding new tab", start=self.pypresence_client.start_time)
|
||||
@@ -28,25 +28,32 @@ class NewTab(arcade.gui.UIView):
|
||||
def on_show_view(self):
|
||||
super().on_show_view()
|
||||
|
||||
self.create_ui()
|
||||
|
||||
def change_tab_type(self, tab_type):
|
||||
self.tab_type = tab_type
|
||||
|
||||
self.ui.clear()
|
||||
self.create_ui()
|
||||
|
||||
def create_ui(self):
|
||||
self.anchor = self.add_widget(UIFocusGroup(size_hint=(1, 1)))
|
||||
self.box = self.anchor.add(arcade.gui.UIBoxLayout(space_between=10), anchor_x="center", anchor_y="center")
|
||||
|
||||
if self.current_mode == "files":
|
||||
self.new_tab_label = self.box.add(arcade.gui.UILabel(text="New Tab Path:", font_name="Roboto", font_size=32))
|
||||
|
||||
self.add_music_input = self.box.add(arcade.gui.UITextureButton(texture=button_texture, texture_hovered=button_hovered_texture, text=f'Select Directory ({self.directory_selected})', style=button_style, font_name="Roboto", font_size=32, width=self.window.width / 2, height=self.window.height / 10))
|
||||
self.add_music_input.on_click = lambda event: self.select_directory()
|
||||
|
||||
self.new_tab_button = self.box.add(arcade.gui.UITextureButton(texture=button_texture, texture_hovered=button_hovered_texture, text='Add new tab', style=button_style, width=self.window.width / 2, height=self.window.height / 10))
|
||||
self.new_tab_button.on_click = lambda event: self.add_tab()
|
||||
self.new_tab_type_label = self.box.add(arcade.gui.UILabel(text="Tab Type:", font_name="Roboto", font_size=32))
|
||||
self.tab_type_dropdown = self.box.add(arcade.gui.UIDropdown(options=["Directory", "Playlist"], default=self.tab_type, primary_style=button_style, dropdown_style=button_style, active_style=button_style, width=self.window.width / 3, height=self.window.height / 15))
|
||||
self.tab_type_dropdown.on_change = lambda e: self.change_tab_type(e.new_value)
|
||||
|
||||
elif self.current_mode == "playlist":
|
||||
self.new_tab_label = self.box.add(arcade.gui.UILabel(text="New Playlist Name:", font_name="Roboto", font_size=32))
|
||||
|
||||
self.new_tab_input = self.box.add(arcade.gui.UIInputText(font_name="Roboto", font_size=32, width=self.window.width / 2, height=self.window.height / 10))
|
||||
|
||||
self.new_tab_button = self.box.add(arcade.gui.UITextureButton(texture=button_texture, texture_hovered=button_hovered_texture, text='Add new Playlist', style=button_style, width=self.window.width / 2, height=self.window.height / 10))
|
||||
self.new_tab_button.on_click = lambda event: self.add_tab()
|
||||
if self.tab_type == "Playlist":
|
||||
self.new_tab_label = self.box.add(arcade.gui.UILabel(text="New Tab Name:", font_name="Roboto", font_size=32))
|
||||
self.new_tab_input = self.box.add(arcade.gui.UIInputText(font_name="Roboto", font_size=32, width=self.window.width / 3, height=self.window.height / 15))
|
||||
else:
|
||||
self.new_tab_label = self.box.add(arcade.gui.UILabel(text="New Tab Path:", font_name="Roboto", font_size=32))
|
||||
self.add_music_input = self.box.add(arcade.gui.UITextureButton(texture=button_texture, texture_hovered=button_hovered_texture, text=f'Select Directory ({self.directory_selected})', style=button_style, font_name="Roboto", font_size=32, width=self.window.width / 3, height=self.window.height / 15))
|
||||
self.add_music_input.on_click = lambda event: self.select_directory()
|
||||
|
||||
self.new_tab_button = self.box.add(arcade.gui.UITextureButton(texture=button_texture, texture_hovered=button_hovered_texture, text='Add new Tab', style=button_style, width=self.window.width / 3, height=self.window.height / 15))
|
||||
self.new_tab_button.on_click = lambda event: self.add_tab()
|
||||
|
||||
self.back_button = self.anchor.add(arcade.gui.UITextureButton(texture=button_texture, texture_hovered=button_hovered_texture, text='<--', style=button_style, width=100, height=50), anchor_x="left", anchor_y="top", align_x=5, align_y=-5)
|
||||
self.back_button.on_click = lambda event: self.main_exit()
|
||||
@@ -57,7 +64,7 @@ class NewTab(arcade.gui.UIView):
|
||||
self.window.show_view(FileManager(os.path.expanduser("~"), [], "directory", self.pypresence_client, *self.args))
|
||||
|
||||
def add_tab(self):
|
||||
if self.current_mode == "files":
|
||||
if self.tab_type == "Directory":
|
||||
tab_path = self.directory_selected
|
||||
|
||||
if not tab_path:
|
||||
@@ -72,7 +79,7 @@ class NewTab(arcade.gui.UIView):
|
||||
self.tab_options.append(tab_path)
|
||||
self.settings_dict["tab_options"] = self.tab_options
|
||||
|
||||
elif self.current_mode == "playlist":
|
||||
elif self.tab_type == "Playlist":
|
||||
self.playlists[self.new_tab_input.text] = []
|
||||
self.settings_dict["playlists"] = self.playlists
|
||||
|
||||
|
||||
@@ -9,16 +9,10 @@ from utils.preload import button_texture, button_hovered_texture
|
||||
from arcade.gui.experimental.focus import UIFocusGroup
|
||||
|
||||
class Settings(arcade.gui.UIView):
|
||||
def __init__(self, pypresence_client, current_mode, current_music_name, current_length, current_music_player, queue, loaded_sounds, shuffle):
|
||||
def __init__(self, pypresence_client, *args):
|
||||
super().__init__()
|
||||
|
||||
self.current_mode = current_mode
|
||||
self.current_music_name = current_music_name
|
||||
self.current_length = current_length
|
||||
self.current_music_player = current_music_player
|
||||
self.queue = queue
|
||||
self.loaded_sounds = loaded_sounds
|
||||
self.shuffle = shuffle
|
||||
self.args = args
|
||||
|
||||
with open("settings.json", "r", encoding="utf-8") as file:
|
||||
self.settings_dict = json.load(file)
|
||||
@@ -293,7 +287,7 @@ class Settings(arcade.gui.UIView):
|
||||
|
||||
def main_exit(self):
|
||||
from menus.main import Main
|
||||
self.window.show_view(Main(self.pypresence_client, self.current_mode, self.current_music_name, self.current_length, self.current_music_player, self.queue, self.loaded_sounds, self.shuffle))
|
||||
self.window.show_view(Main(self.pypresence_client, *self.args))
|
||||
|
||||
def ui_cleanup(self):
|
||||
self.ui.clear()
|
||||
|
||||
@@ -86,17 +86,23 @@ def get_albums_metadata(release_list):
|
||||
|
||||
if release.get("status") == "Official":
|
||||
release_id = release["id"]
|
||||
if (release_id in metadata_cache["is_release_album_by_id"] and metadata_cache["is_release_album_by_id"][release_id]) or is_release_valid(release_id): # Only do it if the album is official, skipping many API calls
|
||||
metadata_cache["is_release_album_by_id"][release_id] = True
|
||||
album_metadata[release.get("title", "")] = {
|
||||
"musicbrainz_id": release.get("id") if release else "Unknown",
|
||||
"album_name": release.get("title") if release else "Unknown",
|
||||
"album_date": release.get("date") if release else "Unknown",
|
||||
"album_country": (get_country(release.get("country", "WZ")) or "Worldwide") if release else "Unknown",
|
||||
}
|
||||
if release_id in metadata_cache["is_release_album_by_id"]:
|
||||
if not metadata_cache["is_release_album_by_id"][release_id]:
|
||||
continue
|
||||
else:
|
||||
metadata_cache["is_release_album_by_id"][release_id] = False
|
||||
|
||||
if not is_release_valid(release_id):
|
||||
metadata_cache["is_release_album_by_id"][release_id] = False
|
||||
continue
|
||||
|
||||
metadata_cache["is_release_album_by_id"][release_id] = True
|
||||
|
||||
album_metadata[release.get("title", "")] = {
|
||||
"musicbrainz_id": release.get("id") if release else "Unknown",
|
||||
"album_name": release.get("title") if release else "Unknown",
|
||||
"album_date": release.get("date") if release else "Unknown",
|
||||
"album_country": (get_country(release.get("country", "WZ")) or "Worldwide") if release else "Unknown",
|
||||
}
|
||||
|
||||
with open("metadata_cache.json", "w") as file:
|
||||
file.write(json.dumps(metadata_cache))
|
||||
|
||||
@@ -111,7 +117,8 @@ def get_music_metadata(artist, title):
|
||||
"query_results": {},
|
||||
"recording_by_id": {},
|
||||
"artist_by_id": {},
|
||||
"is_release_album_by_id": {}
|
||||
"is_release_album_by_id": {},
|
||||
"lyrics_by_id": {}
|
||||
}
|
||||
|
||||
music_api.set_useragent(MUSICBRAINZ_PROJECT_NAME, MUSCIBRAINZ_VERSION, MUSICBRAINZ_CONTACT)
|
||||
@@ -155,6 +162,14 @@ def get_music_metadata(artist, title):
|
||||
"release-list": [{"id": release["id"], "title": release["title"], "status": release.get("status"), "date": release.get("date"), "country": release.get("country", "WZ")} for release in detailed["release-list"]] if "release-list" in detailed else []
|
||||
}
|
||||
|
||||
metadata_cache["lyrics_by_id"] = metadata_cache.get("lyrics_by_id", {})
|
||||
|
||||
if recording_id in metadata_cache["lyrics_by_id"]:
|
||||
lyrics = metadata_cache["lyrics_by_id"][recording_id]
|
||||
else:
|
||||
lyrics = get_lyrics(artist, title)
|
||||
metadata_cache["lyrics_by_id"][recording_id] = lyrics
|
||||
|
||||
with open("metadata_cache.json", "w") as file:
|
||||
file.write(json.dumps(metadata_cache))
|
||||
|
||||
@@ -169,8 +184,7 @@ def get_music_metadata(artist, title):
|
||||
"tags": [tag["name"] for tag in detailed.get("tag-list", [])]
|
||||
}
|
||||
|
||||
return music_metadata, artist_metadata, album_metadata
|
||||
|
||||
return music_metadata, artist_metadata, album_metadata, lyrics
|
||||
|
||||
def get_lyrics(artist, title):
|
||||
if artist:
|
||||
@@ -188,11 +202,12 @@ def get_lyrics(artist, title):
|
||||
if result.get("plainLyrics"):
|
||||
return result["plainLyrics"]
|
||||
|
||||
return "Unknown"
|
||||
if artist: # if there was an artist, it might have been misleading. For example, on Youtube, the uploader might not be the artist. We retry with only title.
|
||||
return get_lyrics(None, title)
|
||||
|
||||
def get_album_cover_art(musicbrainz_album_id):
|
||||
try:
|
||||
cover_art_bytes = music_api.get_image_front(musicbrainz_album_id)
|
||||
cover_art_bytes = music_api.get_image_front(musicbrainz_album_id, 250)
|
||||
except music_api.ResponseError:
|
||||
return None
|
||||
|
||||
|
||||
@@ -3,23 +3,19 @@ import arcade.gui, arcade
|
||||
button_texture = arcade.gui.NinePatchTexture(64 // 4, 64 // 4, 64 // 4, 64 // 4, arcade.load_texture("assets/graphics/button.png"))
|
||||
button_hovered_texture = arcade.gui.NinePatchTexture(64 // 4, 64 // 4, 64 // 4, 64 // 4, arcade.load_texture("assets/graphics/button_hovered.png"))
|
||||
|
||||
pause_icon = arcade.load_texture("assets/graphics/pause.png")
|
||||
resume_icon = arcade.load_texture("assets/graphics/resume.png")
|
||||
|
||||
stop_icon = arcade.load_texture("assets/graphics/stop.png")
|
||||
loop_icon = arcade.load_texture("assets/graphics/loop.png")
|
||||
no_loop_icon = arcade.load_texture("assets/graphics/no_loop.png")
|
||||
|
||||
shuffle_icon = arcade.load_texture("assets/graphics/shuffle.png")
|
||||
no_shuffle_icon = arcade.load_texture("assets/graphics/no_shuffle.png")
|
||||
|
||||
pause_icon = arcade.load_texture("assets/graphics/pause.png")
|
||||
resume_icon = arcade.load_texture("assets/graphics/resume.png")
|
||||
forward_icon = arcade.load_texture("assets/graphics/forward.png")
|
||||
backwards_icon = arcade.load_texture("assets/graphics/backwards.png")
|
||||
volume_icon = arcade.load_texture("assets/graphics/volume.png")
|
||||
|
||||
settings_icon = arcade.load_texture("assets/graphics/settings.png")
|
||||
download_icon = arcade.load_texture("assets/graphics/download.png")
|
||||
plus_icon = arcade.load_texture("assets/graphics/plus.png")
|
||||
|
||||
playlist_icon = arcade.load_texture("assets/graphics/playlist.png")
|
||||
files_icon = arcade.load_texture("assets/graphics/files.png")
|
||||
|
||||
music_icon = arcade.load_texture("assets/graphics/music.png")
|
||||
volume_icon = arcade.load_texture("assets/graphics/volume.png")
|
||||
metadata_icon = arcade.load_texture("assets/graphics/metadata.png")
|
||||
music_icon = arcade.load_texture("assets/graphics/music.png")
|
||||
128
utils/utils.py
128
utils/utils.py
@@ -1,10 +1,12 @@
|
||||
import logging, sys, traceback
|
||||
|
||||
from utils.constants import menu_background_color, button_style
|
||||
from utils.preload import button_texture, button_hovered_texture
|
||||
from utils.constants import menu_background_color
|
||||
from utils.preload import resume_icon, music_icon
|
||||
|
||||
import pyglet, arcade, arcade.gui
|
||||
|
||||
from arcade.gui.experimental.scroll_area import UIScrollArea
|
||||
|
||||
def dump_platform():
|
||||
import platform
|
||||
logging.debug(f'Platform: {platform.platform()}')
|
||||
@@ -59,7 +61,6 @@ class ErrorView(arcade.gui.UIView):
|
||||
msgbox.on_action = lambda event: self.exit()
|
||||
self.add_widget(msgbox)
|
||||
|
||||
|
||||
class FakePyPresence():
|
||||
def __init__(self):
|
||||
...
|
||||
@@ -79,41 +80,110 @@ class UIFocusTextureButton(arcade.gui.UITextureButton):
|
||||
else:
|
||||
self.resize(width=self.width / 1.1, height=self.height / 1.1)
|
||||
|
||||
# Thanks to Eruvanos for the MouseAwareScrollArea and the UIMouseOutOfAreaEvent
|
||||
class UIMouseOutOfAreaEvent(arcade.gui.UIEvent):
|
||||
"""Indicates that the mouse is outside a specific area."""
|
||||
pass
|
||||
|
||||
class MouseAwareScrollArea(UIScrollArea):
|
||||
"""Keep track of mouse position, None if outside of area."""
|
||||
mouse_inside = False
|
||||
def on_event(self, event: arcade.gui.UIEvent):
|
||||
if isinstance(event, arcade.gui.UIMouseMovementEvent):
|
||||
if self.rect.point_in_rect(event.pos):
|
||||
if not self.mouse_inside:
|
||||
self.mouse_inside = True
|
||||
else:
|
||||
if self.mouse_inside:
|
||||
self.mouse_inside = False
|
||||
self.dispatch_ui_event(UIMouseOutOfAreaEvent(self))
|
||||
|
||||
return super().on_event(event)
|
||||
|
||||
class MusicItem(arcade.gui.UIBoxLayout):
|
||||
def __init__(self, metadata: dict, width: int, height: int, padding=10):
|
||||
super().__init__(width=width, height=height, space_between=padding, align="top", vertical=False)
|
||||
super().__init__(width=width, height=height, space_between=padding, align="top")
|
||||
|
||||
self.metadata = metadata
|
||||
if metadata:
|
||||
self.image = self.add(arcade.gui.UIImage(
|
||||
self.button = self.add(arcade.gui.UITextureButton(
|
||||
texture=metadata["thumbnail"],
|
||||
width=height * 1.5,
|
||||
height=height,
|
||||
texture_hovered=metadata["thumbnail"],
|
||||
width=width / 1.25,
|
||||
height=height * 0.5,
|
||||
interaction_buttons=[arcade.MOUSE_BUTTON_LEFT, arcade.MOUSE_BUTTON_RIGHT]
|
||||
))
|
||||
|
||||
self.button = self.add(arcade.gui.UITextureButton(
|
||||
text=f"{metadata['artist']} - {metadata['title']}" if metadata else "Add Music",
|
||||
texture=button_texture,
|
||||
texture_hovered=button_hovered_texture,
|
||||
texture_pressed=button_texture,
|
||||
texture_disabled=button_texture,
|
||||
style=button_style,
|
||||
width=width * 0.85,
|
||||
height=height,
|
||||
interaction_buttons=[arcade.MOUSE_BUTTON_LEFT, arcade.MOUSE_BUTTON_RIGHT]
|
||||
))
|
||||
|
||||
if metadata:
|
||||
self.view_metadata_button = self.add(arcade.gui.UITextureButton(
|
||||
text="View Metadata",
|
||||
texture=button_texture,
|
||||
texture_hovered=button_hovered_texture,
|
||||
texture_pressed=button_texture,
|
||||
texture_disabled=button_texture,
|
||||
style=button_style,
|
||||
width=width * 0.1,
|
||||
height=height,
|
||||
self.title_label = self.add(arcade.gui.UILabel(
|
||||
text=metadata["title"],
|
||||
font_name="Roboto",
|
||||
font_size=14,
|
||||
width=width,
|
||||
height=height * 0.5,
|
||||
multiline=True
|
||||
))
|
||||
|
||||
self.artist_label = self.add(arcade.gui.UILabel(
|
||||
text=metadata["artist"],
|
||||
font_name="Roboto",
|
||||
font_size=12,
|
||||
width=width,
|
||||
height=height * 0.5,
|
||||
multiline=True,
|
||||
text_color=arcade.color.GRAY
|
||||
))
|
||||
|
||||
self.play_button = self.add(arcade.gui.UITextureButton(
|
||||
texture=resume_icon,
|
||||
texture_hovered=resume_icon,
|
||||
width=width / 10,
|
||||
height=height / 5,
|
||||
interaction_buttons=[arcade.MOUSE_BUTTON_LEFT, arcade.MOUSE_BUTTON_RIGHT]
|
||||
))
|
||||
self.play_button.visible = False
|
||||
|
||||
else:
|
||||
self.button = self.add(arcade.gui.UITextureButton(
|
||||
texture=music_icon,
|
||||
texture_hovered=music_icon,
|
||||
width=width / 1.25,
|
||||
height=height * 0.5,
|
||||
))
|
||||
|
||||
self.add_music_label = self.add(arcade.gui.UILabel(
|
||||
text="Add Music",
|
||||
font_name="Roboto",
|
||||
font_size=14,
|
||||
width=width,
|
||||
height=height * 0.5,
|
||||
multiline=True
|
||||
))
|
||||
|
||||
def on_event(self, event: arcade.gui.UIEvent):
|
||||
if self.metadata:
|
||||
if isinstance(event, UIMouseOutOfAreaEvent):
|
||||
# not hovering
|
||||
self.with_background(color=arcade.color.TRANSPARENT_BLACK)
|
||||
self.play_button.visible = False
|
||||
self.trigger_full_render()
|
||||
|
||||
elif isinstance(event, arcade.gui.UIMouseMovementEvent):
|
||||
if self.rect.point_in_rect(event.pos):
|
||||
# hovering
|
||||
self.with_background(color=arcade.color.DARK_GRAY)
|
||||
self.play_button.visible = True
|
||||
self.trigger_full_render()
|
||||
else:
|
||||
# not hovering
|
||||
self.with_background(color=arcade.color.TRANSPARENT_BLACK)
|
||||
self.play_button.visible = False
|
||||
self.trigger_full_render()
|
||||
|
||||
elif isinstance(event, arcade.gui.UIMousePressEvent) and self.rect.point_in_rect(event.pos):
|
||||
self.button.on_click(event)
|
||||
|
||||
return super().on_event(event)
|
||||
|
||||
def on_exception(*exc_info):
|
||||
logging.error(f"Unhandled exception:\n{''.join(traceback.format_exception(exc_info[1], limit=None))}")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user