✨ FLAC can be extracted from MP4 containers (see options). Downgrade on HI_RES download is possible (see options). Fixes #93 #86

This commit is contained in:
Robert Honz
2024-04-21 19:18:05 +02:00
parent 78670a38ba
commit b07c3374b2
7 changed files with 226 additions and 114 deletions
+2
View File
@@ -160,6 +160,8 @@ class DialogPreferences(QtWidgets.QDialog):
"video_download", "video_download",
"download_delay", "download_delay",
"video_convert_mp4", "video_convert_mp4",
"extract_flac",
"downgrade_on_hi_res",
] ]
def gui_populate(self): def gui_populate(self):
+71 -17
View File
@@ -12,7 +12,7 @@ import requests
from requests.exceptions import HTTPError from requests.exceptions import HTTPError
from rich.progress import Progress, TaskID from rich.progress import Progress, TaskID
from tidalapi import Album, Mix, Playlist, Session, Track, UserPlaylist, Video from tidalapi import Album, Mix, Playlist, Session, Track, UserPlaylist, Video
from tidalapi.media import AudioExtensions, Quality, StreamManifest, VideoExtensions from tidalapi.media import AudioExtensions, Codec, Quality, StreamManifest, VideoExtensions, VideoQuality
from tidal_dl_ng.config import Settings, Tidal from tidal_dl_ng.config import Settings, Tidal
from tidal_dl_ng.constants import EXTENSION_LYRICS, REQUESTS_TIMEOUT_SEC, MediaType, SkipExisting from tidal_dl_ng.constants import EXTENSION_LYRICS, REQUESTS_TIMEOUT_SEC, MediaType, SkipExisting
@@ -70,11 +70,15 @@ class Download:
self.progress = progress self.progress = progress
self.path_base = path_base self.path_base = path_base
if not self.settings.data.path_binary_ffmpeg and self.settings.data.video_convert_mp4: if not self.settings.data.path_binary_ffmpeg and (
self.settings.data.video_convert_mp4 or self.settings.data.extract_flac
):
self.settings.data.video_convert_mp4 = False self.settings.data.video_convert_mp4 = False
self.settings.data.extract_flac = False
self.fn_logger.error( self.fn_logger.error(
"FFmpeg in path is not set. Videos can be downloaded but will not be processed. " "FFmpeg is not set. Videos can be downloaded but will not be processed. FLAC cannot be extracted from MP4 containers. "
"Make sure FFmpeg is installed and the path to the binary is configured ('path_binary_ffmpeg')." "Make sure FFmpeg is installed and the path to the binary is configured (`path_binary_ffmpeg`)."
) )
def _download( def _download(
@@ -174,7 +178,8 @@ class Download:
media_type: MediaType = None, media_type: MediaType = None,
video_download: bool = True, video_download: bool = True,
download_delay: bool = False, download_delay: bool = False,
quality: Quality | None = None, quality_audio: Quality | None = None,
quality_video: VideoQuality | None = None,
) -> (bool, str): ) -> (bool, str):
try: try:
if media_id and media_type: if media_id and media_type:
@@ -203,17 +208,34 @@ class Download:
return False, "" return False, ""
# If a quality is explicitly set, change it.
if quality:
quality_old: Quality = self.quality_adjust(quality)
# Get extension. # Get extension.
file_extension: str file_extension: str
if isinstance(media, Track): if isinstance(media, Track):
# If hi_res is forbidden in settings and highest track quality is hi_res, downgrade to high_lossless.
if self.settings.data.downgrade_on_hires and media.get_stream().audio_quality == Quality.hi_res:
quality_audio = Quality.high_lossless
# If a quality is explicitly set, change it.
if quality_audio:
quality_audio_old: Quality = self.adjust_quality_audio(quality_audio)
file_extension = media.get_stream().get_stream_manifest().file_extension file_extension = media.get_stream().get_stream_manifest().file_extension
if self.settings.data.extract_flac:
do_flac_extract = False
if (
media.get_stream().get_stream_manifest().codecs.upper() == Codec.FLAC
and file_extension != AudioExtensions.FLAC
):
file_extension = AudioExtensions.FLAC
do_flac_extract = True
elif isinstance(media, Video): elif isinstance(media, Video):
file_extension = VideoExtensions.TS if quality_video:
quality_video_old = self.adjust_quality_video(quality_video)
file_extension = AudioExtensions.MP4 if self.settings.data.video_convert_mp4 else VideoExtensions.TS
# Create file name and path # Create file name and path
file_name_relative = format_path_media(file_template, media) file_name_relative = format_path_media(file_template, media)
@@ -235,14 +257,18 @@ class Download:
if not file_exists: if not file_exists:
# Create a temp directory and file. # Create a temp directory and file.
with tempfile.TemporaryDirectory(ignore_cleanup_errors=True) as tmp_path_dir: with tempfile.TemporaryDirectory(ignore_cleanup_errors=True) as tmp_path_dir:
tmp_path_file = os.path.join(tmp_path_dir, str(uuid4()) + file_extension) tmp_path_file = os.path.join(tmp_path_dir, str(uuid4()))
# Download media. # Download media.
tmp_path_file = self._download(media=media, path_file=tmp_path_file) tmp_path_file = self._download(media=media, path_file=tmp_path_file)
# Convert video from TS to MP4
if isinstance(media, Video) and self.settings.data.video_convert_mp4: if isinstance(media, Video) and self.settings.data.video_convert_mp4:
# Convert `*.ts` file to `*.mp4` using ffmpeg # Convert `*.ts` file to `*.mp4` using ffmpeg
tmp_path_file = self._video_convert(tmp_path_file) tmp_path_file = self._video_convert(tmp_path_file)
path_file = os.path.splitext(path_file)[0] + ".mp4"
# Extract FLAC from MP4 container using ffmpeg
if self.settings.data.extract_flac and do_flac_extract:
tmp_path_file = self._extract_flac(tmp_path_file, media.isrc)
# Move final file to the configured destination directory. # Move final file to the configured destination directory.
os.makedirs(os.path.dirname(path_file), exist_ok=True) os.makedirs(os.path.dirname(path_file), exist_ok=True)
@@ -256,9 +282,13 @@ class Download:
status_download: bool = not file_exists status_download: bool = not file_exists
if quality: if quality_audio:
# Set quality back to the global user value # Set quality back to the global user value
self.quality_adjust(quality_old) self.adjust_quality_audio(quality_audio_old)
if quality_video:
# Set quality back to the global user value
self.adjust_quality_video(quality_video_old)
# Whether a file was downloaded or skipped and the download delay is enabled, wait until the next download. # Whether a file was downloaded or skipped and the download delay is enabled, wait until the next download.
# Only use this, if you have a list of several Track items. # Only use this, if you have a list of several Track items.
@@ -270,7 +300,7 @@ class Download:
return status_download, path_file return status_download, path_file
def quality_adjust(self, quality) -> Quality: def adjust_quality_audio(self, quality) -> Quality:
# Save original quality settings # Save original quality settings
quality_old: Quality = self.session.audio_quality quality_old: Quality = self.session.audio_quality
self.session.audio_quality = quality self.session.audio_quality = quality
@@ -284,6 +314,13 @@ class Download:
return quality_old return quality_old
def adjust_quality_video(self, quality) -> VideoQuality:
quality_old: VideoQuality = self.session.video_quality
self.session.video_quality = quality
return quality_old
def _move_lyrics(self, file_media_dst: str, file_media_src: str): def _move_lyrics(self, file_media_dst: str, file_media_src: str):
# Build tmp lyrics filename # Build tmp lyrics filename
tmp_lyrics_file_path: str = file_media_src + EXTENSION_LYRICS tmp_lyrics_file_path: str = file_media_src + EXTENSION_LYRICS
@@ -405,7 +442,7 @@ class Download:
for media in items: for media in items:
# Download the item. # Download the item.
status_download, result_path_file = self.item( status_download, result_path_file = self.item(
media=media, file_template=file_name_relative, quality=quality media=media, file_template=file_name_relative, quality_audio=quality
) )
# Advance progress bar. # Advance progress bar.
@@ -422,11 +459,28 @@ class Download:
time.sleep(time_sleep) time.sleep(time_sleep)
def _video_convert(self, path_file: str) -> str: def _video_convert(self, path_file: str) -> str:
path_file_out = os.path.splitext(path_file)[0] + AudioExtensions.MP4 path_file_out = path_file + AudioExtensions.MP4
result, _ = ffmpeg.input(path_file).output(path_file_out, map=0, c="copy").run() result, _ = ffmpeg.input(path_file).output(path_file_out, map=0, c="copy").run()
return path_file_out return path_file_out
def _extract_flac(self, path_file: str, isrc: str) -> str:
path_file_out = path_file + AudioExtensions.FLAC
result, _ = (
ffmpeg.input(path_file)
.output(
path_file_out,
map=0,
movflags="use_metadata_tags",
acodec="copy",
map_metadata="0:g",
metadata=f"isrc={isrc}",
)
.run()
)
return path_file_out
def _extract_video_stream(self, m3u8_variant: m3u8.M3U8, quality: int) -> (m3u8.M3U8 | bool, str): def _extract_video_stream(self, m3u8_variant: m3u8.M3U8, quality: int) -> (m3u8.M3U8 | bool, str):
m3u8_playlist: m3u8.M3U8 | bool = False m3u8_playlist: m3u8.M3U8 | bool = False
resolution_best: int = 0 resolution_best: int = 0
+1 -1
View File
@@ -864,7 +864,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
if isinstance(media, Track | Video): if isinstance(media, Track | Video):
result_dl, path_file = dl.item( result_dl, path_file = dl.item(
media=media, file_template=file_template, download_delay=delay_track, quality=quality media=media, file_template=file_template, download_delay=delay_track, quality_audio=quality
) )
elif isinstance(media, Album | Playlist | Mix): elif isinstance(media, Album | Playlist | Mix):
dl.items( dl.items(
+1 -1
View File
@@ -141,7 +141,7 @@ class Metadata:
self.m.tags["\xa9day"] = self.date self.m.tags["\xa9day"] = self.date
self.m.tags["\xa9wrt"] = ", ".join(self.composer) if self.composer else "" self.m.tags["\xa9wrt"] = ", ".join(self.composer) if self.composer else ""
self.m.tags["\xa9lyr"] = self.lyrics self.m.tags["\xa9lyr"] = self.lyrics
self.m.tags["ISRC"] = self.isrc self.m.tags["isrc"] = self.isrc
@staticmethod @staticmethod
def cover_data(url: str = None, path_file: str = None) -> str | bytes: def cover_data(url: str = None, path_file: str = None) -> str | bytes:
+6
View File
@@ -35,6 +35,8 @@ class Settings:
video_convert_mp4: bool = True video_convert_mp4: bool = True
path_binary_ffmpeg: str = "" path_binary_ffmpeg: str = ""
metadata_cover_dimension: CoverDimensions = CoverDimensions.Px320 metadata_cover_dimension: CoverDimensions = CoverDimensions.Px320
extract_flac: bool = True
downgrade_on_hi_res: bool = False
@dataclass_json @dataclass_json
@@ -74,6 +76,10 @@ class HelpSettings:
metadata_cover_dimension: str = ( metadata_cover_dimension: str = (
"The dimensions of the cover image embedded into the track. Possible values: 320x320, 640x640x 1280x1280." "The dimensions of the cover image embedded into the track. Possible values: 320x320, 640x640x 1280x1280."
) )
extract_flac: str = "Extract FLAC audio tracks from MP4 containers and save them as `*.flac` (uses FFmpeg)."
downgrade_on_hi_res: bool = (
"Never download HI_RES (MQA) quality. Downgrade to the next best available quality instead."
)
@dataclass_json @dataclass_json
+58 -37
View File
@@ -1,7 +1,7 @@
################################################################################ ################################################################################
## Form generated from reading UI file 'dialog_settings.ui' ## Form generated from reading UI file 'dialog_settings.ui'
## ##
## Created by: Qt User Interface Compiler version 6.6.1 ## Created by: Qt User Interface Compiler version 6.7.0
## ##
## WARNING! All changes made in this file will be lost when recompiling UI file! ## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################ ################################################################################
@@ -27,7 +27,7 @@ class Ui_DialogSettings:
if not DialogSettings.objectName(): if not DialogSettings.objectName():
DialogSettings.setObjectName("DialogSettings") DialogSettings.setObjectName("DialogSettings")
DialogSettings.resize(640, 682) DialogSettings.resize(640, 682)
sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) sizePolicy = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
sizePolicy.setHorizontalStretch(100) sizePolicy.setHorizontalStretch(100)
sizePolicy.setVerticalStretch(100) sizePolicy.setVerticalStretch(100)
sizePolicy.setHeightForWidth(DialogSettings.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(DialogSettings.sizePolicy().hasHeightForWidth())
@@ -41,7 +41,7 @@ class Ui_DialogSettings:
self.lv_main.setContentsMargins(12, 12, 12, 12) self.lv_main.setContentsMargins(12, 12, 12, 12)
self.gb_flags = QGroupBox(DialogSettings) self.gb_flags = QGroupBox(DialogSettings)
self.gb_flags.setObjectName("gb_flags") self.gb_flags.setObjectName("gb_flags")
sizePolicy1 = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) sizePolicy1 = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
sizePolicy1.setHorizontalStretch(100) sizePolicy1.setHorizontalStretch(100)
sizePolicy1.setVerticalStretch(100) sizePolicy1.setVerticalStretch(100)
sizePolicy1.setHeightForWidth(self.gb_flags.sizePolicy().hasHeightForWidth()) sizePolicy1.setHeightForWidth(self.gb_flags.sizePolicy().hasHeightForWidth())
@@ -52,56 +52,56 @@ class Ui_DialogSettings:
self.lv_flags.setObjectName("lv_flags") self.lv_flags.setObjectName("lv_flags")
self.lh_flags_1 = QHBoxLayout() self.lh_flags_1 = QHBoxLayout()
self.lh_flags_1.setObjectName("lh_flags_1") self.lh_flags_1.setObjectName("lh_flags_1")
self.lv_flags_video_download = QVBoxLayout() self.lv_flag_video_download = QVBoxLayout()
self.lv_flags_video_download.setObjectName("lv_flags_video_download") self.lv_flag_video_download.setObjectName("lv_flag_video_download")
self.cb_video_download = QCheckBox(self.gb_flags) self.cb_video_download = QCheckBox(self.gb_flags)
self.cb_video_download.setObjectName("cb_video_download") self.cb_video_download.setObjectName("cb_video_download")
sizePolicy1.setHeightForWidth(self.cb_video_download.sizePolicy().hasHeightForWidth()) sizePolicy1.setHeightForWidth(self.cb_video_download.sizePolicy().hasHeightForWidth())
self.cb_video_download.setSizePolicy(sizePolicy1) self.cb_video_download.setSizePolicy(sizePolicy1)
self.lv_flags_video_download.addWidget(self.cb_video_download) self.lv_flag_video_download.addWidget(self.cb_video_download)
self.lh_flags_1.addLayout(self.lv_flags_video_download) self.lh_flags_1.addLayout(self.lv_flag_video_download)
self.lv_flags_video_convert = QVBoxLayout() self.lv_flag_video_convert = QVBoxLayout()
self.lv_flags_video_convert.setObjectName("lv_flags_video_convert") self.lv_flag_video_convert.setObjectName("lv_flag_video_convert")
self.cb_video_convert_mp4 = QCheckBox(self.gb_flags) self.cb_video_convert_mp4 = QCheckBox(self.gb_flags)
self.cb_video_convert_mp4.setObjectName("cb_video_convert_mp4") self.cb_video_convert_mp4.setObjectName("cb_video_convert_mp4")
sizePolicy1.setHeightForWidth(self.cb_video_convert_mp4.sizePolicy().hasHeightForWidth()) sizePolicy1.setHeightForWidth(self.cb_video_convert_mp4.sizePolicy().hasHeightForWidth())
self.cb_video_convert_mp4.setSizePolicy(sizePolicy1) self.cb_video_convert_mp4.setSizePolicy(sizePolicy1)
self.lv_flags_video_convert.addWidget(self.cb_video_convert_mp4) self.lv_flag_video_convert.addWidget(self.cb_video_convert_mp4)
self.lh_flags_1.addLayout(self.lv_flags_video_convert) self.lh_flags_1.addLayout(self.lv_flag_video_convert)
self.lv_flags.addLayout(self.lh_flags_1) self.lv_flags.addLayout(self.lh_flags_1)
self.lh_flags_2 = QHBoxLayout() self.lh_flags_2 = QHBoxLayout()
self.lh_flags_2.setObjectName("lh_flags_2") self.lh_flags_2.setObjectName("lh_flags_2")
self.lh_flags_lyrics_embed = QHBoxLayout() self.lh_flag_lyrics_embed = QHBoxLayout()
self.lh_flags_lyrics_embed.setObjectName("lh_flags_lyrics_embed") self.lh_flag_lyrics_embed.setObjectName("lh_flag_lyrics_embed")
self.cb_lyrics_embed = QCheckBox(self.gb_flags) self.cb_lyrics_embed = QCheckBox(self.gb_flags)
self.cb_lyrics_embed.setObjectName("cb_lyrics_embed") self.cb_lyrics_embed.setObjectName("cb_lyrics_embed")
sizePolicy2 = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) sizePolicy2 = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
sizePolicy2.setHorizontalStretch(0) sizePolicy2.setHorizontalStretch(0)
sizePolicy2.setVerticalStretch(0) sizePolicy2.setVerticalStretch(0)
sizePolicy2.setHeightForWidth(self.cb_lyrics_embed.sizePolicy().hasHeightForWidth()) sizePolicy2.setHeightForWidth(self.cb_lyrics_embed.sizePolicy().hasHeightForWidth())
self.cb_lyrics_embed.setSizePolicy(sizePolicy2) self.cb_lyrics_embed.setSizePolicy(sizePolicy2)
self.lh_flags_lyrics_embed.addWidget(self.cb_lyrics_embed) self.lh_flag_lyrics_embed.addWidget(self.cb_lyrics_embed)
self.lh_flags_2.addLayout(self.lh_flags_lyrics_embed) self.lh_flags_2.addLayout(self.lh_flag_lyrics_embed)
self.lh_flags_lyrics_file = QHBoxLayout() self.lh_flag_lyrics_file = QHBoxLayout()
self.lh_flags_lyrics_file.setObjectName("lh_flags_lyrics_file") self.lh_flag_lyrics_file.setObjectName("lh_flag_lyrics_file")
self.cb_lyrics_file = QCheckBox(self.gb_flags) self.cb_lyrics_file = QCheckBox(self.gb_flags)
self.cb_lyrics_file.setObjectName("cb_lyrics_file") self.cb_lyrics_file.setObjectName("cb_lyrics_file")
sizePolicy1.setHeightForWidth(self.cb_lyrics_file.sizePolicy().hasHeightForWidth()) sizePolicy1.setHeightForWidth(self.cb_lyrics_file.sizePolicy().hasHeightForWidth())
self.cb_lyrics_file.setSizePolicy(sizePolicy1) self.cb_lyrics_file.setSizePolicy(sizePolicy1)
self.lh_flags_lyrics_file.addWidget(self.cb_lyrics_file) self.lh_flag_lyrics_file.addWidget(self.cb_lyrics_file)
self.lh_flags_2.addLayout(self.lh_flags_lyrics_file) self.lh_flags_2.addLayout(self.lh_flag_lyrics_file)
self.lv_flags.addLayout(self.lh_flags_2) self.lv_flags.addLayout(self.lh_flags_2)
@@ -118,18 +118,37 @@ class Ui_DialogSettings:
self.lh_flag_3.addLayout(self.lv_flag_download_delay) self.lh_flag_3.addLayout(self.lv_flag_download_delay)
self.verticalLayout_4 = QVBoxLayout() self.lv_flag_extract_flac = QVBoxLayout()
self.verticalLayout_4.setObjectName("verticalLayout_4") self.lv_flag_extract_flac.setObjectName("lv_flag_extract_flac")
self.cb_extract_flac = QCheckBox(self.gb_flags)
self.cb_extract_flac.setObjectName("cb_extract_flac")
sizePolicy2.setHeightForWidth(self.cb_extract_flac.sizePolicy().hasHeightForWidth())
self.cb_extract_flac.setSizePolicy(sizePolicy2)
self.lh_flag_3.addLayout(self.verticalLayout_4) self.lv_flag_extract_flac.addWidget(self.cb_extract_flac)
self.lh_flag_3.addLayout(self.lv_flag_extract_flac)
self.lv_flags.addLayout(self.lh_flag_3) self.lv_flags.addLayout(self.lh_flag_3)
self.horizontalLayout = QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.lv_flag_downgrade_on_hi_res = QVBoxLayout()
self.lv_flag_downgrade_on_hi_res.setObjectName("lv_flag_downgrade_on_hi_res")
self.cb_downgrade_on_hi_res = QCheckBox(self.gb_flags)
self.cb_downgrade_on_hi_res.setObjectName("cb_downgrade_on_hi_res")
self.lv_flag_downgrade_on_hi_res.addWidget(self.cb_downgrade_on_hi_res)
self.horizontalLayout.addLayout(self.lv_flag_downgrade_on_hi_res)
self.lv_flags.addLayout(self.horizontalLayout)
self.lv_main.addWidget(self.gb_flags) self.lv_main.addWidget(self.gb_flags)
self.gb_choices = QGroupBox(DialogSettings) self.gb_choices = QGroupBox(DialogSettings)
self.gb_choices.setObjectName("gb_choices") self.gb_choices.setObjectName("gb_choices")
sizePolicy3 = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) sizePolicy3 = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Fixed)
sizePolicy3.setHorizontalStretch(0) sizePolicy3.setHorizontalStretch(0)
sizePolicy3.setVerticalStretch(0) sizePolicy3.setVerticalStretch(0)
sizePolicy3.setHeightForWidth(self.gb_choices.sizePolicy().hasHeightForWidth()) sizePolicy3.setHeightForWidth(self.gb_choices.sizePolicy().hasHeightForWidth())
@@ -140,7 +159,7 @@ class Ui_DialogSettings:
self.lh_choices_skip_existing.setObjectName("lh_choices_skip_existing") self.lh_choices_skip_existing.setObjectName("lh_choices_skip_existing")
self.l_icon_skip_existing = QLabel(self.gb_choices) self.l_icon_skip_existing = QLabel(self.gb_choices)
self.l_icon_skip_existing.setObjectName("l_icon_skip_existing") self.l_icon_skip_existing.setObjectName("l_icon_skip_existing")
sizePolicy4 = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy4 = QSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
sizePolicy4.setHorizontalStretch(0) sizePolicy4.setHorizontalStretch(0)
sizePolicy4.setVerticalStretch(0) sizePolicy4.setVerticalStretch(0)
sizePolicy4.setHeightForWidth(self.l_icon_skip_existing.sizePolicy().hasHeightForWidth()) sizePolicy4.setHeightForWidth(self.l_icon_skip_existing.sizePolicy().hasHeightForWidth())
@@ -233,7 +252,7 @@ class Ui_DialogSettings:
self.c_metadata_cover_dimension = QComboBox(self.gb_choices) self.c_metadata_cover_dimension = QComboBox(self.gb_choices)
self.c_metadata_cover_dimension.setObjectName("c_metadata_cover_dimension") self.c_metadata_cover_dimension.setObjectName("c_metadata_cover_dimension")
sizePolicy5 = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) sizePolicy5 = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Fixed)
sizePolicy5.setHorizontalStretch(10) sizePolicy5.setHorizontalStretch(10)
sizePolicy5.setVerticalStretch(0) sizePolicy5.setVerticalStretch(0)
sizePolicy5.setHeightForWidth(self.c_metadata_cover_dimension.sizePolicy().hasHeightForWidth()) sizePolicy5.setHeightForWidth(self.c_metadata_cover_dimension.sizePolicy().hasHeightForWidth())
@@ -311,7 +330,7 @@ class Ui_DialogSettings:
self.lh_path_fmt_album.setObjectName("lh_path_fmt_album") self.lh_path_fmt_album.setObjectName("lh_path_fmt_album")
self.l_icon_format_album = QLabel(self.gb_path) self.l_icon_format_album = QLabel(self.gb_path)
self.l_icon_format_album.setObjectName("l_icon_format_album") self.l_icon_format_album.setObjectName("l_icon_format_album")
sizePolicy6 = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred) sizePolicy6 = QSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Preferred)
sizePolicy6.setHorizontalStretch(0) sizePolicy6.setHorizontalStretch(0)
sizePolicy6.setVerticalStretch(0) sizePolicy6.setVerticalStretch(0)
sizePolicy6.setHeightForWidth(self.l_icon_format_album.sizePolicy().hasHeightForWidth()) sizePolicy6.setHeightForWidth(self.l_icon_format_album.sizePolicy().hasHeightForWidth())
@@ -386,22 +405,22 @@ class Ui_DialogSettings:
self.verticalLayout = QVBoxLayout() self.verticalLayout = QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout") self.verticalLayout.setObjectName("verticalLayout")
self.horizontalLayout_3 = QHBoxLayout() self.horizontalLayout_10 = QHBoxLayout()
self.horizontalLayout_3.setObjectName("horizontalLayout_3") self.horizontalLayout_10.setObjectName("horizontalLayout_10")
self.le_download_base_path = QLineEdit(self.gb_path) self.le_download_base_path = QLineEdit(self.gb_path)
self.le_download_base_path.setObjectName("le_download_base_path") self.le_download_base_path.setObjectName("le_download_base_path")
sizePolicy2.setHeightForWidth(self.le_download_base_path.sizePolicy().hasHeightForWidth()) sizePolicy2.setHeightForWidth(self.le_download_base_path.sizePolicy().hasHeightForWidth())
self.le_download_base_path.setSizePolicy(sizePolicy2) self.le_download_base_path.setSizePolicy(sizePolicy2)
self.le_download_base_path.setDragEnabled(True) self.le_download_base_path.setDragEnabled(True)
self.horizontalLayout_3.addWidget(self.le_download_base_path) self.horizontalLayout_10.addWidget(self.le_download_base_path)
self.pb_download_base_path = QPushButton(self.gb_path) self.pb_download_base_path = QPushButton(self.gb_path)
self.pb_download_base_path.setObjectName("pb_download_base_path") self.pb_download_base_path.setObjectName("pb_download_base_path")
self.horizontalLayout_3.addWidget(self.pb_download_base_path) self.horizontalLayout_10.addWidget(self.pb_download_base_path)
self.verticalLayout.addLayout(self.horizontalLayout_3) self.verticalLayout.addLayout(self.horizontalLayout_10)
self.horizontalLayout_7 = QHBoxLayout() self.horizontalLayout_7 = QHBoxLayout()
self.horizontalLayout_7.setObjectName("horizontalLayout_7") self.horizontalLayout_7.setObjectName("horizontalLayout_7")
@@ -450,22 +469,22 @@ class Ui_DialogSettings:
self.verticalLayout.addLayout(self.horizontalLayout_8) self.verticalLayout.addLayout(self.horizontalLayout_8)
self.horizontalLayout_31 = QHBoxLayout() self.horizontalLayout_3 = QHBoxLayout()
self.horizontalLayout_31.setObjectName("horizontalLayout_31") self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.le_path_binary_ffmpeg = QLineEdit(self.gb_path) self.le_path_binary_ffmpeg = QLineEdit(self.gb_path)
self.le_path_binary_ffmpeg.setObjectName("le_path_binary_ffmpeg") self.le_path_binary_ffmpeg.setObjectName("le_path_binary_ffmpeg")
sizePolicy2.setHeightForWidth(self.le_path_binary_ffmpeg.sizePolicy().hasHeightForWidth()) sizePolicy2.setHeightForWidth(self.le_path_binary_ffmpeg.sizePolicy().hasHeightForWidth())
self.le_path_binary_ffmpeg.setSizePolicy(sizePolicy2) self.le_path_binary_ffmpeg.setSizePolicy(sizePolicy2)
self.le_path_binary_ffmpeg.setDragEnabled(True) self.le_path_binary_ffmpeg.setDragEnabled(True)
self.horizontalLayout_31.addWidget(self.le_path_binary_ffmpeg) self.horizontalLayout_3.addWidget(self.le_path_binary_ffmpeg)
self.pb_path_binary_ffmpeg = QPushButton(self.gb_path) self.pb_path_binary_ffmpeg = QPushButton(self.gb_path)
self.pb_path_binary_ffmpeg.setObjectName("pb_path_binary_ffmpeg") self.pb_path_binary_ffmpeg.setObjectName("pb_path_binary_ffmpeg")
self.horizontalLayout_31.addWidget(self.pb_path_binary_ffmpeg) self.horizontalLayout_3.addWidget(self.pb_path_binary_ffmpeg)
self.verticalLayout.addLayout(self.horizontalLayout_31) self.verticalLayout.addLayout(self.horizontalLayout_3)
self.horizontalLayout_2.addLayout(self.verticalLayout) self.horizontalLayout_2.addLayout(self.verticalLayout)
@@ -501,6 +520,8 @@ class Ui_DialogSettings:
self.cb_lyrics_embed.setText(QCoreApplication.translate("DialogSettings", "CheckBox", None)) self.cb_lyrics_embed.setText(QCoreApplication.translate("DialogSettings", "CheckBox", None))
self.cb_lyrics_file.setText(QCoreApplication.translate("DialogSettings", "CheckBox", None)) self.cb_lyrics_file.setText(QCoreApplication.translate("DialogSettings", "CheckBox", None))
self.cb_download_delay.setText(QCoreApplication.translate("DialogSettings", "CheckBox", None)) self.cb_download_delay.setText(QCoreApplication.translate("DialogSettings", "CheckBox", None))
self.cb_extract_flac.setText(QCoreApplication.translate("DialogSettings", "CheckBox", None))
self.cb_downgrade_on_hi_res.setText(QCoreApplication.translate("DialogSettings", "CheckBox", None))
self.gb_choices.setTitle(QCoreApplication.translate("DialogSettings", "Choices", None)) self.gb_choices.setTitle(QCoreApplication.translate("DialogSettings", "Choices", None))
self.l_icon_skip_existing.setText(QCoreApplication.translate("DialogSettings", "TextLabel", None)) self.l_icon_skip_existing.setText(QCoreApplication.translate("DialogSettings", "TextLabel", None))
self.l_skip_existing.setText(QCoreApplication.translate("DialogSettings", "TextLabel", None)) self.l_skip_existing.setText(QCoreApplication.translate("DialogSettings", "TextLabel", None))
+87 -58
View File
@@ -70,7 +70,7 @@
<item> <item>
<layout class="QHBoxLayout" name="lh_flags_1"> <layout class="QHBoxLayout" name="lh_flags_1">
<item> <item>
<layout class="QVBoxLayout" name="lv_flags_video_download"> <layout class="QVBoxLayout" name="lv_flag_video_download">
<item> <item>
<widget class="QCheckBox" name="cb_video_download"> <widget class="QCheckBox" name="cb_video_download">
<property name="sizePolicy"> <property name="sizePolicy">
@@ -87,7 +87,7 @@
</layout> </layout>
</item> </item>
<item> <item>
<layout class="QVBoxLayout" name="lv_flags_video_convert"> <layout class="QVBoxLayout" name="lv_flag_video_convert">
<item> <item>
<widget class="QCheckBox" name="cb_video_convert_mp4"> <widget class="QCheckBox" name="cb_video_convert_mp4">
<property name="sizePolicy"> <property name="sizePolicy">
@@ -108,7 +108,7 @@
<item> <item>
<layout class="QHBoxLayout" name="lh_flags_2"> <layout class="QHBoxLayout" name="lh_flags_2">
<item> <item>
<layout class="QHBoxLayout" name="lh_flags_lyrics_embed"> <layout class="QHBoxLayout" name="lh_flag_lyrics_embed">
<item> <item>
<widget class="QCheckBox" name="cb_lyrics_embed"> <widget class="QCheckBox" name="cb_lyrics_embed">
<property name="sizePolicy"> <property name="sizePolicy">
@@ -128,7 +128,7 @@
</layout> </layout>
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="lh_flags_lyrics_file"> <layout class="QHBoxLayout" name="lh_flag_lyrics_file">
<item> <item>
<widget class="QCheckBox" name="cb_lyrics_file"> <widget class="QCheckBox" name="cb_lyrics_file">
<property name="sizePolicy"> <property name="sizePolicy">
@@ -166,7 +166,36 @@
</layout> </layout>
</item> </item>
<item> <item>
<layout class="QVBoxLayout" name="verticalLayout_4"/> <layout class="QVBoxLayout" name="lv_flag_extract_flac">
<item>
<widget class="QCheckBox" name="cb_extract_flac">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>CheckBox</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<layout class="QVBoxLayout" name="lv_flag_downgrade_on_hi_res">
<item>
<widget class="QCheckBox" name="cb_downgrade_on_hi_res">
<property name="text">
<string>CheckBox</string>
</property>
</widget>
</item>
</layout>
</item> </item>
</layout> </layout>
</item> </item>
@@ -519,41 +548,41 @@
</layout> </layout>
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="lh_path_binary_ffmpeg"> <layout class="QHBoxLayout" name="lh_path_binary_ffmpeg">
<item> <item>
<widget class="QLabel" name="l_icon_path_binary_ffmpeg"> <widget class="QLabel" name="l_icon_path_binary_ffmpeg">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed"> <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="text"> <property name="text">
<string>TextLabel</string> <string>TextLabel</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLabel" name="l_path_binary_ffmpeg"> <widget class="QLabel" name="l_path_binary_ffmpeg">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed"> <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="text"> <property name="text">
<string>TextLabel</string> <string>TextLabel</string>
</property> </property>
</widget> </widget>
</item> </item>
</layout> </layout>
</item> </item>
</layout> </layout>
</item> </item>
<item> <item>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_3"> <layout class="QHBoxLayout" name="horizontalLayout_10">
<item> <item>
<widget class="QLineEdit" name="le_download_base_path"> <widget class="QLineEdit" name="le_download_base_path">
<property name="sizePolicy"> <property name="sizePolicy">
@@ -619,29 +648,29 @@
</layout> </layout>
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_3"> <layout class="QHBoxLayout" name="horizontalLayout_3">
<item> <item>
<widget class="QLineEdit" name="le_path_binary_ffmpeg"> <widget class="QLineEdit" name="le_path_binary_ffmpeg">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed"> <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="dragEnabled"> <property name="dragEnabled">
<bool>true</bool> <bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="pb_path_binary_ffmpeg"> <widget class="QPushButton" name="pb_path_binary_ffmpeg">
<property name="text"> <property name="text">
<string>...</string> <string>...</string>
</property> </property>
</widget> </widget>
</item> </item>
</layout> </layout>
</item> </item>
</layout> </layout>
</item> </item>
</layout> </layout>