generated from LouisMazin/PythonApplicationTemplate
nice
This commit is contained in:
parent
9cbe5d4de0
commit
7b29ea57b7
@ -141,33 +141,41 @@ class AudioDownloadWorker(QThread):
|
||||
if track_album:
|
||||
tags.add(TALB(encoding=3, text=track_album))
|
||||
|
||||
tags.delall("APIC")
|
||||
if track_cover:
|
||||
cover_file = Path(track_cover)
|
||||
if cover_file.exists() and cover_file.is_file():
|
||||
mime_type = "image/jpeg"
|
||||
cover_data = None
|
||||
if cover_file.suffix.lower() in (".png", ".webp"):
|
||||
try:
|
||||
from PIL import Image
|
||||
import io
|
||||
img = Image.open(cover_file)
|
||||
buf = io.BytesIO()
|
||||
img.convert("RGB").save(buf, format="JPEG")
|
||||
cover_data = buf.getvalue()
|
||||
mime_type = "image/jpeg"
|
||||
except Exception:
|
||||
with open(cover_file, "rb") as stream:
|
||||
cover_data = stream.read()
|
||||
mime_type = "image/png" if cover_file.suffix.lower() == ".png" else "image/webp"
|
||||
else:
|
||||
with open(cover_file, "rb") as stream:
|
||||
cover_data = stream.read()
|
||||
if cover_data:
|
||||
tags.add(APIC(encoding=3, mime=mime_type, type=3, desc="Cover", data=cover_data))
|
||||
|
||||
tags.save(str(file_path), v2_version=4)
|
||||
|
||||
# Use only eyeD3 for cover art (Windows Explorer compatibility)
|
||||
if track_cover:
|
||||
try:
|
||||
import eyed3
|
||||
from PIL import Image
|
||||
import io
|
||||
audiofile = eyed3.load(str(file_path))
|
||||
if audiofile is not None:
|
||||
if audiofile.tag is None:
|
||||
audiofile.initTag()
|
||||
cover_file = Path(track_cover)
|
||||
if cover_file.exists() and cover_file.is_file():
|
||||
# Always convert to JPEG and resize to 999x999
|
||||
try:
|
||||
img = Image.open(cover_file)
|
||||
img = img.convert("RGB")
|
||||
img = img.resize((999, 999), Image.LANCZOS)
|
||||
buf = io.BytesIO()
|
||||
img.save(buf, format="JPEG")
|
||||
image_data = buf.getvalue()
|
||||
mime_type = "image/jpeg"
|
||||
except Exception as e:
|
||||
print(f"[eyeD3] Failed to process image: {e}")
|
||||
image_data = cover_file.read_bytes()
|
||||
mime_type = "image/jpeg"
|
||||
audiofile.tag.images.set(3, image_data, mime_type, u"Cover")
|
||||
# Force ID3v2.3
|
||||
audiofile.tag.version = (2, 3, 0)
|
||||
audiofile.tag.save(version=(2, 3, 0))
|
||||
except Exception as e:
|
||||
print(f"[eyeD3] Failed to embed cover: {e}")
|
||||
|
||||
renamed_file = self._rename_output_file(file_path, track_title or fallback_title, track_artist)
|
||||
if renamed_file is not None:
|
||||
self.progress_text.emit(renamed_file.stem)
|
||||
@ -441,84 +449,10 @@ class DownloadManager(QObject):
|
||||
return False
|
||||
|
||||
track = self.track_list[index]
|
||||
clean_mp3_title = mp3_title.strip() or track.get("title", "")
|
||||
clean_artist = artist.strip()
|
||||
clean_album = album.strip()
|
||||
clean_cover = cover_path.strip()
|
||||
|
||||
# Update in-memory metadata
|
||||
track["mp3_title"] = clean_mp3_title
|
||||
track["artist"] = clean_artist
|
||||
track["album"] = clean_album
|
||||
track["cover_path"] = clean_cover
|
||||
|
||||
# Try to find the file path (assume output dir is known, search for file)
|
||||
# Use the current filename or try to reconstruct it
|
||||
output_dir = self.settings_manager.get_config("output_dir")
|
||||
if not output_dir:
|
||||
output_dir = "."
|
||||
output_dir = Path(output_dir)
|
||||
# Try to find the file by matching artist/title or fallback to most recent
|
||||
found_file = None
|
||||
for f in output_dir.glob("*.mp3"):
|
||||
# Try to match by old artist/title
|
||||
if f.stem == f"{track.get('artist', '')} - {track.get('mp3_title', '')}":
|
||||
found_file = f
|
||||
break
|
||||
if not found_file:
|
||||
# fallback: most recent
|
||||
mp3_files = sorted(output_dir.glob("*.mp3"), key=lambda file_path: file_path.stat().st_mtime, reverse=True)
|
||||
if mp3_files:
|
||||
found_file = mp3_files[0]
|
||||
|
||||
if found_file and found_file.exists():
|
||||
# Update ID3 tags
|
||||
try:
|
||||
id3_delete(str(found_file))
|
||||
except Exception:
|
||||
pass
|
||||
tags = ID3()
|
||||
tags.delall("TIT2")
|
||||
tags.add(TIT2(encoding=3, text=clean_mp3_title or track.get("title", "")))
|
||||
tags.delall("TPE1")
|
||||
if clean_artist:
|
||||
tags.add(TPE1(encoding=3, text=clean_artist))
|
||||
tags.delall("TALB")
|
||||
if clean_album:
|
||||
tags.add(TALB(encoding=3, text=clean_album))
|
||||
tags.delall("APIC")
|
||||
if clean_cover:
|
||||
cover_file = Path(clean_cover)
|
||||
if cover_file.exists() and cover_file.is_file():
|
||||
mime_type = "image/jpeg"
|
||||
if cover_file.suffix.lower() == ".png":
|
||||
mime_type = "image/png"
|
||||
elif cover_file.suffix.lower() == ".webp":
|
||||
mime_type = "image/webp"
|
||||
with open(cover_file, "rb") as stream:
|
||||
cover_data = stream.read()
|
||||
if cover_data:
|
||||
tags.add(APIC(encoding=3, mime=mime_type, type=3, desc="Cover", data=cover_data))
|
||||
tags.save(str(found_file), v2_version=4)
|
||||
|
||||
# Always rename file to 'artist - title.mp3'
|
||||
safe_title = self._sanitize_filename_part(clean_mp3_title)
|
||||
safe_artist = self._sanitize_filename_part(clean_artist)
|
||||
if safe_artist and safe_title:
|
||||
base_name = f"{safe_artist} - {safe_title}"
|
||||
else:
|
||||
base_name = safe_title or self._sanitize_filename_part(found_file.stem)
|
||||
target_path = found_file.with_name(f"{base_name}{found_file.suffix}")
|
||||
if target_path != found_file:
|
||||
counter = 2
|
||||
while target_path.exists():
|
||||
target_path = found_file.with_name(f"{base_name} ({counter}){found_file.suffix}")
|
||||
counter += 1
|
||||
try:
|
||||
found_file.rename(target_path)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
track["mp3_title"] = mp3_title.strip()
|
||||
track["artist"] = artist.strip()
|
||||
track["album"] = album.strip()
|
||||
track["cover_path"] = cover_path.strip()
|
||||
self.list_changed.emit(self.get_tracks())
|
||||
return True
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"app_name": "Application",
|
||||
"app_name": "Youtube MP3 Downloader",
|
||||
"app_os": "Windows",
|
||||
"app_version": "1.0.0",
|
||||
"architecture": "x64",
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 8.4 KiB |
75
main.py
75
main.py
@ -24,82 +24,95 @@ def preload_application(progress_callback, splash=None):
|
||||
|
||||
try:
|
||||
main_manager = MainManager.get_instance()
|
||||
|
||||
language_manager = main_manager.get_language_manager()
|
||||
update_manager = main_manager.get_update_manager()
|
||||
license_manager = main_manager.get_license_manager()
|
||||
settings_manager = main_manager.get_settings_manager()
|
||||
|
||||
# Vérifier la licence uniquement si le système est activé
|
||||
if settings_manager.get_config("enable_licensing"):
|
||||
progress_callback(language_manager.get_text("verifying_license"))
|
||||
license_manager.verify_license()
|
||||
|
||||
progress_callback(language_manager.get_text("checking_updates"))
|
||||
|
||||
if update_manager.check_for_update(splash, splash):
|
||||
return False
|
||||
|
||||
progress_callback(language_manager.get_text("initializing"))
|
||||
|
||||
preloaded_window = MainWindow()
|
||||
|
||||
progress_callback(language_manager.get_text("loading_complete"))
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error during preload: {e}")
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
def main() -> int:
|
||||
global preloaded_window
|
||||
try:
|
||||
QApplication.setAttribute(Qt.ApplicationAttribute.AA_ShareOpenGLContexts, True)
|
||||
except Exception:
|
||||
return 0
|
||||
|
||||
QApplication.setAttribute(Qt.ApplicationAttribute.AA_ShareOpenGLContexts, True)
|
||||
try:
|
||||
main_manager: MainManager = MainManager.get_instance()
|
||||
|
||||
main_manager: MainManager = MainManager.get_instance()
|
||||
theme_manager = main_manager.get_theme_manager()
|
||||
settings_manager = main_manager.get_settings_manager()
|
||||
theme_manager = main_manager.get_theme_manager()
|
||||
settings_manager = main_manager.get_settings_manager()
|
||||
except Exception:
|
||||
return 0
|
||||
|
||||
app: QApplication = QApplication(sys.argv)
|
||||
app.setStyleSheet(theme_manager.get_sheet())
|
||||
app.setApplicationName(settings_manager.get_config("app_name"))
|
||||
app.setWindowIcon(QIcon(paths.get_asset_path("icon")))
|
||||
try:
|
||||
app: QApplication = QApplication(sys.argv)
|
||||
except Exception:
|
||||
return 0
|
||||
|
||||
try:
|
||||
app.setStyleSheet(theme_manager.get_sheet())
|
||||
app.setApplicationName(settings_manager.get_config("app_name"))
|
||||
app.setWindowIcon(QIcon(paths.get_asset_path("icon")))
|
||||
except Exception:
|
||||
return 0
|
||||
|
||||
splash_image_path = paths.get_asset_path(settings_manager.get_config("splash_image"))
|
||||
use_splash = splash_image_path and paths.Path(splash_image_path).exists()
|
||||
|
||||
if use_splash:
|
||||
splash = SplashScreen(preload_function=lambda callback: preload_application(callback, splash))
|
||||
splash.show_splash()
|
||||
try:
|
||||
splash = SplashScreen(preload_function=lambda callback: preload_application(callback, splash))
|
||||
splash.show_splash()
|
||||
except Exception as e:
|
||||
return 0
|
||||
|
||||
def on_splash_finished(success):
|
||||
global preloaded_window
|
||||
if not success:
|
||||
app.quit()
|
||||
return
|
||||
|
||||
if preloaded_window:
|
||||
preloaded_window.show()
|
||||
else:
|
||||
window = MainWindow()
|
||||
window.show()
|
||||
try:
|
||||
if preloaded_window:
|
||||
preloaded_window.show()
|
||||
else:
|
||||
window = MainWindow()
|
||||
window.show()
|
||||
except Exception:
|
||||
app.quit()
|
||||
|
||||
splash.finished.connect(on_splash_finished)
|
||||
return app.exec()
|
||||
else:
|
||||
|
||||
def dummy_progress(text):
|
||||
pass
|
||||
|
||||
success = preload_application(dummy_progress)
|
||||
if not success:
|
||||
return 0
|
||||
|
||||
window = preloaded_window if preloaded_window else MainWindow()
|
||||
window.show()
|
||||
|
||||
try:
|
||||
window = preloaded_window if preloaded_window else MainWindow()
|
||||
window.show()
|
||||
except Exception:
|
||||
return 0
|
||||
return app.exec()
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
sys.exit(main())
|
||||
except KeyboardInterrupt:
|
||||
sys.exit(0)
|
||||
sys.exit(main())
|
||||
@ -5,3 +5,4 @@ python-dotenv
|
||||
requests
|
||||
yt-dlp
|
||||
mutagen
|
||||
pillow
|
||||
Loading…
x
Reference in New Issue
Block a user