From 2055606d0b66f303c98468849eeee80e4969e44c Mon Sep 17 00:00:00 2001 From: Robert Honz Date: Sun, 12 Jan 2025 17:42:09 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=91=B7=20File=20extension=20guesser=20imp?= =?UTF-8?q?roved.=20Fixes=20#322?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyproject.toml | 2 +- tidal_dl_ng/download.py | 15 +++++++-- tidal_dl_ng/gui.py | 59 +++++++++++++++-------------------- tidal_dl_ng/helper/gui.py | 22 ++++++++++++- tidal_dl_ng/model/gui_data.py | 5 ++- tidal_dl_ng/ui/main.py | 39 +++++++++++++---------- tidal_dl_ng/ui/main.ui | 37 ++++++++++++---------- 7 files changed, 106 insertions(+), 73 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index d1e7c9a..c00fe57 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -171,7 +171,7 @@ profile = "black" multi_line_output = 3 indent = 4 color_output = true -known_third_party = ["Crypto", "PySide6", "coloredlogs", "dataclasses_json", "ffmpeg", "m3u8", "mutagen", "pathvalidate", "requests", "rich", "tidalapi", "toml", "typer"] +known_third_party = ["Crypto", "PySide6", "coloredlogs", "dataclasses_json", "ffmpeg", "helper", "m3u8", "mutagen", "pathvalidate", "requests", "rich", "tidalapi", "toml", "typer"] [tool.mypy] # https://mypy.readthedocs.io/en/latest/config_file.html#using-a-pyproject-toml-file diff --git a/tidal_dl_ng/download.py b/tidal_dl_ng/download.py index a91aae0..e676933 100644 --- a/tidal_dl_ng/download.py +++ b/tidal_dl_ng/download.py @@ -260,7 +260,9 @@ class Download: result=result, url=url, path_segment=path_segment, id_segment=id_segment, error=error ) - def extension_guess(self, quality_audio: Quality, is_video: bool) -> AudioExtensions | VideoExtensions: + def extension_guess( + self, quality_audio: Quality, metadata_tags: [str], is_video: bool + ) -> AudioExtensions | VideoExtensions: result: AudioExtensions | VideoExtensions if is_video: @@ -268,7 +270,12 @@ class Download: else: result = ( AudioExtensions.FLAC - if self.settings.data.extract_flac and quality_audio in (Quality.hi_res_lossless, Quality.high_lossless) + if ( + self.settings.data.extract_flac + and quality_audio in (Quality.hi_res_lossless, Quality.high_lossless) + ) + or ("HIRES_LOSSLESS" not in metadata_tags and quality_audio not in (Quality.low_96k, Quality.low_320k)) + or quality_audio == Quality.high_lossless else AudioExtensions.M4A ) @@ -314,7 +321,9 @@ class Download: return False, "" # Create file name and path - file_extension_dummy: str = self.extension_guess(quality_audio, isinstance(media, Video)) + file_extension_dummy: str = self.extension_guess( + quality_audio, metadata_tags=media.media_metadata_tags, is_video=isinstance(media, Video) + ) file_name_relative: str = format_path_media(file_template, media, self.settings.data.album_track_num_pad_min) path_media_dst: pathlib.Path = ( pathlib.Path(self.path_base).expanduser() / (file_name_relative + file_extension_dummy) diff --git a/tidal_dl_ng/gui.py b/tidal_dl_ng/gui.py index 0d20758..08abd29 100644 --- a/tidal_dl_ng/gui.py +++ b/tidal_dl_ng/gui.py @@ -49,6 +49,7 @@ import sys import time from collections.abc import Callable, Sequence +from helper.gui import get_queue_download_quality_audio, get_queue_download_quality_video from requests.exceptions import HTTPError from tidalapi.session import LinkLogin @@ -58,7 +59,6 @@ from tidal_dl_ng.helper.gui import ( FilterHeader, HumanProxyModel, get_queue_download_media, - get_queue_download_quality, get_results_media_item, get_user_list_media_item, set_queue_download_media, @@ -697,7 +697,8 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): ) -> QueueDownloadItem | bool: result: QueueDownloadItem | False name: str = "" - quality: Quality | QualityVideo | str = "" + quality_audio: Quality = self.settings.data.quality_audio + quality_video: QualityVideo = self.settings.data.quality_video explicit: str = "" # Check if item is available on TIDAL. @@ -713,31 +714,26 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): name = f"{name_builder_artist(media)} - {name_builder_title(media)}{explicit}" elif isinstance(media, Playlist | Artist): name = media.name - quality = self.settings.data.quality_audio elif isinstance(media, Album): name = f"{name_builder_artist(media)} - {media.name}{explicit}" elif isinstance(media, Mix): name = media.title - quality = self.settings.data.quality_audio # Determine actual quality. if isinstance(media, Track | Album): - quality_highest: str = quality_audio_highest(media) + quality_highest: Quality = quality_audio_highest(media) if ( self.settings.data.quality_audio == quality_highest or self.settings.data.quality_audio == Quality.hi_res_lossless ): - quality = quality_highest - else: - quality = self.settings.data.quality_audio - elif isinstance(media, Video): - quality = self.settings.data.quality_video + quality_audio = quality_highest if name: result = QueueDownloadItem( name=name, - quality=quality, + quality_audio=quality_audio, + quality_video=quality_video, type_media=type(media).__name__, status=QueueDownloadStatus.Waiting, obj=media, @@ -956,7 +952,8 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): set_queue_download_media(child, queue_dl_item.obj) child.setText(2, queue_dl_item.name) child.setText(3, queue_dl_item.type_media) - child.setText(4, queue_dl_item.quality) + child.setText(4, queue_dl_item.quality_audio) + child.setText(5, queue_dl_item.quality_video) self.tr_queue_download.addTopLevelItem(child) def watcher_queue_download(self) -> None: @@ -969,12 +966,12 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): result: QueueDownloadStatus item: QtWidgets.QTreeWidgetItem = items[0] media: Track | Album | Playlist | Video | Mix | Artist = get_queue_download_media(item) - tmp_quality: str = get_queue_download_quality(item) - quality: Quality | QualityVideo | None = tmp_quality if tmp_quality else None + quality_audio: Quality = get_queue_download_quality_audio(item) + quality_video: QualityVideo = get_queue_download_quality_video(item) try: self.s_queue_download_item_downloading.emit(item) - result = self.on_queue_download(media, quality=quality) + result = self.on_queue_download(media, quality_audio=quality_audio, quality_video=quality_video) if result == QueueDownloadStatus.Finished: self.s_queue_download_item_finished.emit(item) @@ -1002,7 +999,10 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): item.setText(0, status) def on_queue_download( - self, media: Track | Album | Playlist | Video | Mix | Artist, quality: Quality | QualityVideo | None = None + self, + media: Track | Album | Playlist | Video | Mix | Artist, + quality_audio: Quality | None = None, + quality_video: QualityVideo | None = None, ) -> QueueDownloadStatus: result: QueueDownloadStatus items_media: [Track | Album | Playlist | Video | Mix | Artist] @@ -1015,7 +1015,13 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): download_delay: bool = bool(isinstance(media, Track | Video) and self.settings.data.download_delay) for item_media in items_media: - result = self.download(item_media, self.dl, delay_track=download_delay, quality=quality) + result = self.download( + item_media, + self.dl, + delay_track=download_delay, + quality_audio=quality_audio, + quality_video=quality_video, + ) return result @@ -1024,26 +1030,18 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): media: Track | Album | Playlist | Video | Mix | Artist, dl: Download, delay_track: bool = False, - quality: Quality | QualityVideo | None = None, + quality_audio: Quality | None = None, + quality_video: QualityVideo | None = None, ) -> QueueDownloadStatus: result_dl: bool path_file: str result: QueueDownloadStatus - quality_audio: Quality | None - quality_video: QualityVideo | None self.s_pb_reset.emit() self.s_statusbar_message.emit(StatusbarMessage(message="Download started...")) file_template = get_format_template(media, self.settings) if isinstance(media, Track | Video): - if isinstance(media, Track): - quality_audio = quality - quality_video = None - else: - quality_audio = None - quality_video = quality - result_dl, path_file = dl.item( media=media, file_template=file_template, @@ -1052,13 +1050,6 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): quality_video=quality_video, ) elif isinstance(media, Album | Playlist | Mix): - if isinstance(media, Album): - quality_audio = quality - quality_video = None - else: - quality_audio = None - quality_video = None - dl.items( media=media, file_template=file_template, diff --git a/tidal_dl_ng/helper/gui.py b/tidal_dl_ng/helper/gui.py index 187f6a8..d680b19 100644 --- a/tidal_dl_ng/helper/gui.py +++ b/tidal_dl_ng/helper/gui.py @@ -1,10 +1,13 @@ import re +from typing import cast from PySide6 import QtCore, QtGui, QtWidgets from tidalapi import Album, Mix, Playlist, Track, UserPlaylist, Video from tidalapi.artist import Artist from tidalapi.media import Quality +from tidal_dl_ng.constants import QualityVideo + def get_table_data( item: QtWidgets.QTreeWidgetItem, column: int @@ -46,8 +49,25 @@ def get_queue_download_media( def get_queue_download_quality( item: QtWidgets.QTreeWidgetItem, + column: int, +) -> str: + result: str = get_table_text(item, column) + + return result + + +def get_queue_download_quality_audio( + item: QtWidgets.QTreeWidgetItem, ) -> Quality: - result: Quality = get_table_text(item, 4) + result: Quality = cast(Quality, get_queue_download_quality(item, 4)) + + return result + + +def get_queue_download_quality_video( + item: QtWidgets.QTreeWidgetItem, +) -> QualityVideo: + result: QualityVideo = cast(QualityVideo, get_queue_download_quality(item, 5)) return result diff --git a/tidal_dl_ng/model/gui_data.py b/tidal_dl_ng/model/gui_data.py index 186ed98..69cc266 100644 --- a/tidal_dl_ng/model/gui_data.py +++ b/tidal_dl_ng/model/gui_data.py @@ -2,6 +2,8 @@ from dataclasses import dataclass from tidalapi.media import Quality +from tidal_dl_ng.constants import QualityVideo + try: from PySide6 import QtCore @@ -42,5 +44,6 @@ class QueueDownloadItem: status: str name: str type_media: str - quality: Quality + quality_audio: Quality + quality_video: QualityVideo obj: object diff --git a/tidal_dl_ng/ui/main.py b/tidal_dl_ng/ui/main.py index 9c1525d..4c68126 100644 --- a/tidal_dl_ng/ui/main.py +++ b/tidal_dl_ng/ui/main.py @@ -1,7 +1,7 @@ ################################################################################ ## Form generated from reading UI file 'main.ui' ## -## Created by: Qt User Interface Compiler version 6.7.0 +## Created by: Qt User Interface Compiler version 6.8.0 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ @@ -110,9 +110,9 @@ class Ui_MainWindow: # if QT_CONFIG(accessibility) self.tr_lists_user.setAccessibleDescription("") # endif // QT_CONFIG(accessibility) - self.tr_lists_user.setEditTriggers(QAbstractItemView.NoEditTriggers) + self.tr_lists_user.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers) self.tr_lists_user.setProperty("showDropIndicator", False) - self.tr_lists_user.setSelectionMode(QAbstractItemView.ExtendedSelection) + self.tr_lists_user.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection) self.tr_lists_user.setIndentation(10) self.tr_lists_user.setUniformRowHeights(True) self.tr_lists_user.setSortingEnabled(True) @@ -196,7 +196,7 @@ class Ui_MainWindow: self.cb_search_type.setAccessibleDescription("") # endif // QT_CONFIG(accessibility) self.cb_search_type.setCurrentText("") - self.cb_search_type.setSizeAdjustPolicy(QComboBox.AdjustToContentsOnFirstShow) + self.cb_search_type.setSizeAdjustPolicy(QComboBox.SizeAdjustPolicy.AdjustToContentsOnFirstShow) self.cb_search_type.setPlaceholderText("") self.lh_search.addWidget(self.cb_search_type) @@ -226,11 +226,11 @@ class Ui_MainWindow: self.tr_results = QTreeView(self.w_central) self.tr_results.setObjectName("tr_results") - self.tr_results.setEditTriggers(QAbstractItemView.NoEditTriggers) + self.tr_results.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers) self.tr_results.setProperty("showDropIndicator", False) self.tr_results.setDragDropOverwriteMode(False) self.tr_results.setAlternatingRowColors(False) - self.tr_results.setSelectionMode(QAbstractItemView.ExtendedSelection) + self.tr_results.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection) self.tr_results.setIndentation(10) self.tr_results.setSortingEnabled(True) @@ -256,7 +256,9 @@ class Ui_MainWindow: self.l_quality_audio.setAccessibleDescription("") # endif // QT_CONFIG(accessibility) self.l_quality_audio.setText("Audio") - self.l_quality_audio.setAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) + self.l_quality_audio.setAlignment( + Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignTrailing | Qt.AlignmentFlag.AlignVCenter + ) self.lh_download.addWidget(self.l_quality_audio) @@ -279,7 +281,7 @@ class Ui_MainWindow: self.cb_quality_audio.setAccessibleDescription("") # endif // QT_CONFIG(accessibility) self.cb_quality_audio.setCurrentText("") - self.cb_quality_audio.setSizeAdjustPolicy(QComboBox.AdjustToContentsOnFirstShow) + self.cb_quality_audio.setSizeAdjustPolicy(QComboBox.SizeAdjustPolicy.AdjustToContentsOnFirstShow) self.cb_quality_audio.setPlaceholderText("") self.cb_quality_audio.setFrame(True) @@ -303,7 +305,9 @@ class Ui_MainWindow: self.l_quality_video.setAccessibleDescription("") # endif // QT_CONFIG(accessibility) self.l_quality_video.setText("Video") - self.l_quality_video.setAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) + self.l_quality_video.setAlignment( + Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignTrailing | Qt.AlignmentFlag.AlignVCenter + ) self.lh_download.addWidget(self.l_quality_video) @@ -326,7 +330,7 @@ class Ui_MainWindow: self.cb_quality_video.setAccessibleDescription("") # endif // QT_CONFIG(accessibility) self.cb_quality_video.setCurrentText("") - self.cb_quality_video.setSizeAdjustPolicy(QComboBox.AdjustToContentsOnFirstShow) + self.cb_quality_video.setSizeAdjustPolicy(QComboBox.SizeAdjustPolicy.AdjustToContentsOnFirstShow) self.cb_quality_video.setPlaceholderText("") self.lh_download.addWidget(self.cb_quality_video) @@ -408,10 +412,10 @@ class Ui_MainWindow: self.l_pm_cover.setSizePolicy(sizePolicy3) self.l_pm_cover.setMaximumSize(QSize(280, 280)) self.l_pm_cover.setBaseSize(QSize(0, 0)) - self.l_pm_cover.setFrameShape(QFrame.NoFrame) + self.l_pm_cover.setFrameShape(QFrame.Shape.NoFrame) self.l_pm_cover.setPixmap(QPixmap("default_album_image.png")) self.l_pm_cover.setScaledContents(True) - self.l_pm_cover.setAlignment(Qt.AlignHCenter | Qt.AlignTop) + self.l_pm_cover.setAlignment(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignTop) self.horizontalLayout_2.addWidget(self.l_pm_cover) @@ -436,12 +440,12 @@ class Ui_MainWindow: __qtreewidgetitem4.setText(0, "\ud83e\uddd1\u200d\ud83d\udcbb\ufe0f") self.tr_queue_download.setHeaderItem(__qtreewidgetitem4) self.tr_queue_download.setObjectName("tr_queue_download") - self.tr_queue_download.setEditTriggers(QAbstractItemView.NoEditTriggers) + self.tr_queue_download.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers) self.tr_queue_download.setTabKeyNavigation(False) self.tr_queue_download.setProperty("showDropIndicator", False) self.tr_queue_download.setDragDropOverwriteMode(False) - self.tr_queue_download.setSelectionMode(QAbstractItemView.ExtendedSelection) - self.tr_queue_download.setSelectionBehavior(QAbstractItemView.SelectRows) + self.tr_queue_download.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection) + self.tr_queue_download.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows) self.tr_queue_download.setRootIsDecorated(False) self.tr_queue_download.setItemsExpandable(False) self.tr_queue_download.setSortingEnabled(False) @@ -533,7 +537,7 @@ class Ui_MainWindow: # if QT_CONFIG(accessibility) self.statusbar.setAccessibleDescription("") # endif // QT_CONFIG(accessibility) - self.statusbar.setLayoutDirection(Qt.LeftToRight) + self.statusbar.setLayoutDirection(Qt.LayoutDirection.LeftToRight) MainWindow.setStatusBar(self.statusbar) self.menubar.addAction(self.m_file.menuAction()) @@ -575,7 +579,8 @@ class Ui_MainWindow: self.l_pm_cover.setText("") self.l_h_queue_download.setText(QCoreApplication.translate("MainWindow", "Download Queue", None)) ___qtreewidgetitem4 = self.tr_queue_download.headerItem() - ___qtreewidgetitem4.setText(4, QCoreApplication.translate("MainWindow", "Quality", None)) + ___qtreewidgetitem4.setText(5, QCoreApplication.translate("MainWindow", "Quality Video", None)) + ___qtreewidgetitem4.setText(4, QCoreApplication.translate("MainWindow", "Quality Audio", None)) ___qtreewidgetitem4.setText(3, QCoreApplication.translate("MainWindow", "Type", None)) ___qtreewidgetitem4.setText(2, QCoreApplication.translate("MainWindow", "Name", None)) ___qtreewidgetitem4.setText(1, QCoreApplication.translate("MainWindow", "obj", None)) diff --git a/tidal_dl_ng/ui/main.ui b/tidal_dl_ng/ui/main.ui index 0ad3693..47f17a4 100644 --- a/tidal_dl_ng/ui/main.ui +++ b/tidal_dl_ng/ui/main.ui @@ -59,13 +59,13 @@ - QAbstractItemView::NoEditTriggers + QAbstractItemView::EditTrigger::NoEditTriggers false - QAbstractItemView::ExtendedSelection + QAbstractItemView::SelectionMode::ExtendedSelection 10 @@ -262,7 +262,7 @@ - QComboBox::AdjustToContentsOnFirstShow + QComboBox::SizeAdjustPolicy::AdjustToContentsOnFirstShow @@ -296,7 +296,7 @@ - QAbstractItemView::NoEditTriggers + QAbstractItemView::EditTrigger::NoEditTriggers false @@ -308,7 +308,7 @@ false - QAbstractItemView::ExtendedSelection + QAbstractItemView::SelectionMode::ExtendedSelection 10 @@ -341,7 +341,7 @@ Audio - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter @@ -372,7 +372,7 @@ - QComboBox::AdjustToContentsOnFirstShow + QComboBox::SizeAdjustPolicy::AdjustToContentsOnFirstShow @@ -403,7 +403,7 @@ Video - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter @@ -434,7 +434,7 @@ - QComboBox::AdjustToContentsOnFirstShow + QComboBox::SizeAdjustPolicy::AdjustToContentsOnFirstShow @@ -543,7 +543,7 @@ - QFrame::NoFrame + QFrame::Shape::NoFrame @@ -555,7 +555,7 @@ true - Qt::AlignHCenter|Qt::AlignTop + Qt::AlignmentFlag::AlignHCenter|Qt::AlignmentFlag::AlignTop @@ -582,7 +582,7 @@ - QAbstractItemView::NoEditTriggers + QAbstractItemView::EditTrigger::NoEditTriggers false @@ -594,10 +594,10 @@ false - QAbstractItemView::ExtendedSelection + QAbstractItemView::SelectionMode::ExtendedSelection - QAbstractItemView::SelectRows + QAbstractItemView::SelectionBehavior::SelectRows false @@ -639,7 +639,12 @@ - Quality + Quality Audio + + + + + Quality Video @@ -752,7 +757,7 @@ - Qt::LeftToRight + Qt::LayoutDirection::LeftToRight