diff --git a/tidal_dl_ng/dialog.py b/tidal_dl_ng/dialog.py
index 073e016..4e36d8a 100644
--- a/tidal_dl_ng/dialog.py
+++ b/tidal_dl_ng/dialog.py
@@ -162,7 +162,7 @@ class DialogPreferences(QtWidgets.QDialog):
]
def _init_spin_box(self):
- self.parameters_spin_box = ["album_track_num_pad_min"]
+ self.parameters_spin_box = ["album_track_num_pad_min", "downloads_concurrent_max"]
def _init_comboboxes(self):
self.parameters_combo = [
diff --git a/tidal_dl_ng/download.py b/tidal_dl_ng/download.py
index 83d8743..af00497 100644
--- a/tidal_dl_ng/download.py
+++ b/tidal_dl_ng/download.py
@@ -621,22 +621,30 @@ class Download:
# Iterate through list items
while not self.progress.finished:
- for item_media in items:
- # Download the item.
- status, result_path_file = self.item(
- media=item_media,
- file_template=file_name_relative,
- quality_audio=quality_audio,
- quality_video=quality_video,
- download_delay=download_delay,
- is_parent_album=is_album,
- )
+ with futures.ThreadPoolExecutor(max_workers=self.settings.data.downloads_concurrent_max) as executor:
+ # Dispatch all download tasks to worker threads
+ l_futures: [any] = [
+ executor.submit(
+ self.item,
+ media=item_media,
+ file_template=file_name_relative,
+ quality_audio=quality_audio,
+ quality_video=quality_video,
+ download_delay=download_delay,
+ is_parent_album=is_album,
+ )
+ for item_media in items
+ ]
+ # Report results as they become available
+ for future in futures.as_completed(l_futures):
+ # Retrieve result
+ status, result_path_file = future.result()
- # Advance progress bar.
- self.progress.advance(p_task1)
+ # Advance progress bar.
+ self.progress.advance(p_task1)
- if not progress_stdout:
- self.progress_gui.list_item.emit(self.progress.tasks[p_task1].percentage)
+ if not progress_stdout:
+ self.progress_gui.list_item.emit(self.progress.tasks[p_task1].percentage)
self.fn_logger.info(f"Finished list '{list_media_name}'.")
diff --git a/tidal_dl_ng/model/cfg.py b/tidal_dl_ng/model/cfg.py
index bf01814..88636f1 100644
--- a/tidal_dl_ng/model/cfg.py
+++ b/tidal_dl_ng/model/cfg.py
@@ -40,7 +40,8 @@ class Settings:
downloads_simultaneous_per_track_max: int = 20
download_delay_sec_min: float = 3.0
download_delay_sec_max: float = 5.0
- album_track_num_pad_min: int = 0
+ album_track_num_pad_min: int = 1
+ downloads_concurrent_max: int = 3
@dataclass_json
@@ -86,8 +87,9 @@ class HelpSettings:
download_delay_sec_min: str = "Lower boundary for the calculation of the download delay in seconds."
download_delay_sec_max: str = "Upper boundary for the calculation of the download delay in seconds."
album_track_num_pad_min: str = (
- "Minimum length of the album track count, will be padded with zeroes (0). To disable " "padding set this to 0."
+ "Minimum length of the album track count, will be padded with zeroes (0). To disable padding set this to 1."
)
+ downloads_concurrent_max: str = "Maximum concurrent number of downloads (threads)."
@dataclass_json
diff --git a/tidal_dl_ng/ui/dialog_settings.py b/tidal_dl_ng/ui/dialog_settings.py
index d3d2401..945af92 100644
--- a/tidal_dl_ng/ui/dialog_settings.py
+++ b/tidal_dl_ng/ui/dialog_settings.py
@@ -27,7 +27,7 @@ class Ui_DialogSettings:
def setupUi(self, DialogSettings):
if not DialogSettings.objectName():
DialogSettings.setObjectName("DialogSettings")
- DialogSettings.resize(640, 705)
+ DialogSettings.resize(640, 767)
sizePolicy = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
sizePolicy.setHorizontalStretch(100)
sizePolicy.setVerticalStretch(100)
@@ -293,6 +293,27 @@ class Ui_DialogSettings:
self.verticalLayout_8.addLayout(self.horizontalLayout_9)
+ self.horizontalLayout_11 = QHBoxLayout()
+ self.horizontalLayout_11.setObjectName("horizontalLayout_11")
+ self.l_downloads_concurrent_max = QLabel(self.gb_numbers)
+ self.l_downloads_concurrent_max.setObjectName("l_downloads_concurrent_max")
+
+ self.horizontalLayout_11.addWidget(self.l_downloads_concurrent_max)
+
+ self.l_icon_downloads_concurrent_max = QLabel(self.gb_numbers)
+ self.l_icon_downloads_concurrent_max.setObjectName("l_icon_downloads_concurrent_max")
+
+ self.horizontalLayout_11.addWidget(self.l_icon_downloads_concurrent_max)
+
+ self.sb_downloads_concurrent_max = QSpinBox(self.gb_numbers)
+ self.sb_downloads_concurrent_max.setObjectName("sb_downloads_concurrent_max")
+ self.sb_downloads_concurrent_max.setMinimum(1)
+ self.sb_downloads_concurrent_max.setMaximum(5)
+
+ self.horizontalLayout_11.addWidget(self.sb_downloads_concurrent_max)
+
+ self.verticalLayout_8.addLayout(self.horizontalLayout_11)
+
self.lv_main.addWidget(self.gb_numbers)
self.gb_path = QGroupBox(DialogSettings)
@@ -563,6 +584,8 @@ class Ui_DialogSettings:
self.gb_numbers.setTitle(QCoreApplication.translate("DialogSettings", "Numbers", None))
self.l_album_track_num_pad_min.setText(QCoreApplication.translate("DialogSettings", "TextLabel", None))
self.l_icon_album_track_num_pad_min.setText(QCoreApplication.translate("DialogSettings", "TextLabel", None))
+ self.l_downloads_concurrent_max.setText(QCoreApplication.translate("DialogSettings", "TextLabel", None))
+ self.l_icon_downloads_concurrent_max.setText(QCoreApplication.translate("DialogSettings", "TextLabel", None))
self.gb_path.setTitle(QCoreApplication.translate("DialogSettings", "Path", None))
self.l_icon_download_base_path.setText(QCoreApplication.translate("DialogSettings", "TextLabel", None))
self.l_download_base_path.setText(QCoreApplication.translate("DialogSettings", "TextLabel", None))
diff --git a/tidal_dl_ng/ui/dialog_settings.ui b/tidal_dl_ng/ui/dialog_settings.ui
index bff04c7..d81701a 100644
--- a/tidal_dl_ng/ui/dialog_settings.ui
+++ b/tidal_dl_ng/ui/dialog_settings.ui
@@ -7,7 +7,7 @@
0
0
640
- 705
+ 767
@@ -386,6 +386,34 @@
+ -
+
+
-
+
+
+ TextLabel
+
+
+
+ -
+
+
+ TextLabel
+
+
+
+ -
+
+
+ 1
+
+
+ 5
+
+
+
+
+