Skip to content

Commit 0461c53

Browse files
authored
Merge pull request #66 from exislow/63-feature-provide-feedback-if-ffmpeg-not-found-on-path
63 feature provide feedback if ffmpeg not found on path
2 parents 134836d + d331f93 commit 0461c53

File tree

8 files changed

+103
-58
lines changed

8 files changed

+103
-58
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ profile = "black"
170170
multi_line_output = 3
171171
indent = 4
172172
color_output = true
173-
known_third_party = ["Crypto", "PySide6", "coloredlogs", "dataclasses_json", "ffmpeg", "m3u8", "mpegdash", "mutagen", "pathvalidate", "requests", "rich", "tidalapi", "typer"]
173+
known_third_party = ["Crypto", "PySide6", "coloredlogs", "dataclasses_json", "ffmpeg", "helper", "m3u8", "mpegdash", "mutagen", "pathvalidate", "requests", "rich", "tidalapi", "typer"]
174174

175175
[tool.mypy]
176176
# https://mypy.readthedocs.io/en/latest/config_file.html#using-a-pyproject-toml-file

tidal_dl_ng/dialog.py

Lines changed: 50 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from enum import Enum
33
from pathlib import Path
44

5+
from helper.path import is_installed_ffmpeg
56
from PySide6 import QtCore, QtGui, QtWidgets
67
from tidalapi import Quality as QualityAudio
78

@@ -86,27 +87,9 @@ def __init__(self, settings: Settings, settings_save: QtCore.Signal, parent=None
8687
pixmapi: QtWidgets.QStyle.StandardPixmap = QtWidgets.QStyle.SP_MessageBoxQuestion
8788
self.icon = self.style().standardIcon(pixmapi)
8889

89-
self.parameters_checkboxes = [
90-
"lyrics_embed",
91-
"lyrics_file",
92-
"video_download",
93-
"download_delay",
94-
"video_convert_mp4",
95-
]
96-
self.parameters_combo = [
97-
("skip_existing", SkipExisting),
98-
("quality_audio", QualityAudio),
99-
("quality_video", QualityVideo),
100-
("metadata_cover_dimension", CoverDimensions),
101-
]
102-
self.parameters_line_edit = [
103-
"download_base_path",
104-
"format_album",
105-
"format_playlist",
106-
"format_mix",
107-
"format_track",
108-
"format_video",
109-
]
90+
self._init_checkboxes()
91+
self._init_comboboxes()
92+
self._init_line_edit()
11093

11194
# Create an instance of the GUI
11295
self.ui = Ui_DialogSettings()
@@ -115,9 +98,54 @@ def __init__(self, settings: Settings, settings_save: QtCore.Signal, parent=None
11598
self.ui.setupUi(self)
11699
# Set data.
117100
self.gui_populate()
101+
self._init_signals()
118102

119103
self.exec()
120104

105+
def _init_signals(self):
106+
self.ui.cb_video_convert_mp4.stateChanged.connect(self.on_cb_video_convert_mp4)
107+
108+
def on_cb_video_convert_mp4(self, int):
109+
if self.ui.cb_video_convert_mp4.isChecked():
110+
# Check if ffmpeg is in PATH otherwise show error message.
111+
if not is_installed_ffmpeg():
112+
self.ui.cb_video_convert_mp4.setChecked(False)
113+
self.ui.cb_video_convert_mp4.setCheckState(QtCore.Qt.CheckState.Unchecked)
114+
QtWidgets.QMessageBox.critical(
115+
self,
116+
"FFmpeg not found!",
117+
"Either FFmpeg is not installed on your computer or not set within "
118+
"your PATH variable. You cannot activate this option until FFmpeg "
119+
"is correctly installed and set to your environmental PATH variable.",
120+
)
121+
122+
def _init_line_edit(self):
123+
self.parameters_line_edit = [
124+
"download_base_path",
125+
"format_album",
126+
"format_playlist",
127+
"format_mix",
128+
"format_track",
129+
"format_video",
130+
]
131+
132+
def _init_comboboxes(self):
133+
self.parameters_combo = [
134+
("skip_existing", SkipExisting),
135+
("quality_audio", QualityAudio),
136+
("quality_video", QualityVideo),
137+
("metadata_cover_dimension", CoverDimensions),
138+
]
139+
140+
def _init_checkboxes(self):
141+
self.parameters_checkboxes = [
142+
"lyrics_embed",
143+
"lyrics_file",
144+
"video_download",
145+
"download_delay",
146+
"video_convert_mp4",
147+
]
148+
121149
def gui_populate(self):
122150
self.populate_checkboxes()
123151
self.populate_combo()
@@ -190,7 +218,7 @@ def populate_checkboxes(self):
190218
checkbox.setChecked(getattr(self.data, pn))
191219

192220
def accept(self):
193-
# Get settings. TODO
221+
# Get settings.
194222
self.to_settings()
195223
self.done(1)
196224

tidal_dl_ng/download.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
)
3030
from tidal_dl_ng.helper.decryption import decrypt_file, decrypt_security_token
3131
from tidal_dl_ng.helper.exceptions import MediaMissing, UnknownManifestFormat
32-
from tidal_dl_ng.helper.path import check_file_exists, format_path_media, path_file_sanitize
32+
from tidal_dl_ng.helper.path import check_file_exists, format_path_media, is_installed_ffmpeg, path_file_sanitize
3333
from tidal_dl_ng.helper.tidal import (
3434
instantiate_media,
3535
items_results_all,
@@ -82,6 +82,13 @@ def __init__(
8282
self.progress = progress
8383
self.path_base = path_base
8484

85+
if not is_installed_ffmpeg() and self.settings.data.video_convert_mp4:
86+
self.settings.data.video_convert_mp4 = False
87+
self.fn_logger.error(
88+
"Cannot find FFmpeg in PATH. Videos can be downloaded but will not be processed. "
89+
"Make sure FFmpeg is installed correctly and present within your environmental PATH variable."
90+
)
91+
8592
def _download(
8693
self,
8794
media: Track | Video,
@@ -284,7 +291,9 @@ def lyrics_write_file(self, file_path: str, lyrics: str) -> str:
284291
def metadata_write(self, track: Track, path_file: str):
285292
result: bool = False
286293
release_date: str = (
287-
track.album.available_release_date.strftime("%Y-%m-%d") if track.album.available_release_date else track.album.release_date.strftime("%Y-%m-%d") if track.album.release_date else ""
294+
track.album.available_release_date.strftime("%Y-%m-%d")
295+
if track.album.available_release_date
296+
else track.album.release_date.strftime("%Y-%m-%d") if track.album.release_date else ""
288297
)
289298
copy_right: str = track.copyright if hasattr(track, "copyright") and track.copyright else ""
290299
isrc: str = track.isrc if hasattr(track, "isrc") and track.isrc else ""

tidal_dl_ng/gui.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -287,16 +287,16 @@ def thread_download_list_media(self, point):
287287
self.thread_it(self.list_items_show_result, point=point)
288288

289289
def on_download_list_media(self, point: QtCore.QPoint):
290-
self.b_download.setEnabled(False)
291-
self.b_download.setText("Downloading...")
290+
self.pb_download.setEnabled(False)
291+
self.pb_download.setText("Downloading...")
292292

293293
item = self.tr_lists_user.itemAt(point)
294294
media = item.data(3, QtCore.Qt.ItemDataRole.UserRole)
295295

296296
self.download(media, self.dl)
297297

298-
self.b_download.setText("Download")
299-
self.b_download.setEnabled(True)
298+
self.pb_download.setText("Download")
299+
self.pb_download.setEnabled(True)
300300

301301
def search_populate_results(self, query: str, type_media: SearchTypes):
302302
self.tr_results.clear()
@@ -447,11 +447,11 @@ def search_result_to_model(self, items: [*SearchTypes]) -> [ResultItem]:
447447
return result
448448

449449
def _init_signals(self):
450-
self.b_download.clicked.connect(lambda: self.thread_it(self.on_download_results))
450+
self.pb_download.clicked.connect(lambda: self.thread_it(self.on_download_results))
451451
self.l_search.returnPressed.connect(
452452
lambda: self.search_populate_results(self.l_search.text(), self.cb_search_type.currentData())
453453
)
454-
self.b_search.clicked.connect(
454+
self.pb_search.clicked.connect(
455455
lambda: self.search_populate_results(self.l_search.text(), self.cb_search_type.currentData())
456456
)
457457
self.cb_quality_audio.currentIndexChanged.connect(self.on_quality_set_audio)
@@ -543,8 +543,8 @@ def thread_it(self, fn: Callable, *args, **kwargs):
543543
self.threadpool.start(worker)
544544

545545
def on_download_results(self):
546-
self.b_download.setEnabled(False)
547-
self.b_download.setText("Downloading...")
546+
self.pb_download.setEnabled(False)
547+
self.pb_download.setText("Downloading...")
548548

549549
items: [QtWidgets.QTreeWidgetItem] = self.tr_results.selectedItems()
550550

@@ -564,8 +564,8 @@ def on_download_results(self):
564564

565565
self.download(media, self.dl, delay_track=download_delay)
566566

567-
self.b_download.setText("Download")
568-
self.b_download.setEnabled(True)
567+
self.pb_download.setText("Download")
568+
self.pb_download.setEnabled(True)
569569

570570
def download(self, media: Track | Album | Playlist | Video | Mix, dl: Download, delay_track: bool = False) -> None:
571571
self.s_pb_reset.emit()

tidal_dl_ng/helper/path.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import math
33
import os
44
import re
5+
import shutil
56
from pathlib import Path, PosixPath
67

78
from pathvalidate import sanitize_filename, sanitize_filepath
@@ -10,7 +11,7 @@
1011

1112
from tidal_dl_ng import __name_display__
1213
from tidal_dl_ng.constants import FILENAME_SANITIZE_PLACEHOLDER, UNIQUIFY_THRESHOLD, AudioExtensions, MediaType
13-
from tidal_dl_ng.helper.tidal import name_builder_artist, name_builder_title, name_builder_album_artist
14+
from tidal_dl_ng.helper.tidal import name_builder_album_artist, name_builder_artist, name_builder_title
1415

1516

1617
def path_home() -> str:
@@ -261,3 +262,10 @@ def check_file_exists(path_file: str, extension_ignore: bool = False) -> bool:
261262
result = bool(sum([glob.glob(_file) for _file in path_files], []))
262263

263264
return result
265+
266+
267+
def is_installed_ffmpeg() -> bool:
268+
# Checks if ffmpeg is found in PATH.
269+
result: bool = bool(shutil.which("ffmpeg"))
270+
271+
return result

tidal_dl_ng/helper/tidal.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from tidalapi import Album, Mix, Playlist, Session, Track, UserPlaylist, Video
2-
from tidalapi.artist import Role, Artist
2+
from tidalapi.artist import Artist, Role
33
from tidalapi.session import SearchTypes
44

55
from tidal_dl_ng.constants import MediaType

tidal_dl_ng/ui/main.py

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -187,26 +187,26 @@ def setupUi(self, MainWindow):
187187

188188
self.lh_search.addWidget(self.cb_search_type)
189189

190-
self.b_search = QPushButton(self.w_central)
191-
self.b_search.setObjectName("b_search")
190+
self.pb_search = QPushButton(self.w_central)
191+
self.pb_search.setObjectName("pb_search")
192192
# if QT_CONFIG(statustip)
193-
self.b_search.setStatusTip("")
193+
self.pb_search.setStatusTip("")
194194
# endif // QT_CONFIG(statustip)
195195
# if QT_CONFIG(whatsthis)
196-
self.b_search.setWhatsThis("")
196+
self.pb_search.setWhatsThis("")
197197
# endif // QT_CONFIG(whatsthis)
198198
# if QT_CONFIG(accessibility)
199-
self.b_search.setAccessibleName("")
199+
self.pb_search.setAccessibleName("")
200200
# endif // QT_CONFIG(accessibility)
201201
# if QT_CONFIG(accessibility)
202-
self.b_search.setAccessibleDescription("")
202+
self.pb_search.setAccessibleDescription("")
203203
# endif // QT_CONFIG(accessibility)
204-
self.b_search.setText("Search")
204+
self.pb_search.setText("Search")
205205
# if QT_CONFIG(shortcut)
206-
self.b_search.setShortcut("")
206+
self.pb_search.setShortcut("")
207207
# endif // QT_CONFIG(shortcut)
208208

209-
self.lh_search.addWidget(self.b_search)
209+
self.lh_search.addWidget(self.pb_search)
210210

211211
self.lv_search_result.addLayout(self.lh_search)
212212

@@ -315,29 +315,29 @@ def setupUi(self, MainWindow):
315315

316316
self.lh_download.addWidget(self.cb_quality_video)
317317

318-
self.b_download = QPushButton(self.w_central)
319-
self.b_download.setObjectName("b_download")
318+
self.pb_download = QPushButton(self.w_central)
319+
self.pb_download.setObjectName("pb_download")
320320
# if QT_CONFIG(tooltip)
321-
self.b_download.setToolTip("")
321+
self.pb_download.setToolTip("")
322322
# endif // QT_CONFIG(tooltip)
323323
# if QT_CONFIG(statustip)
324-
self.b_download.setStatusTip("")
324+
self.pb_download.setStatusTip("")
325325
# endif // QT_CONFIG(statustip)
326326
# if QT_CONFIG(whatsthis)
327-
self.b_download.setWhatsThis("")
327+
self.pb_download.setWhatsThis("")
328328
# endif // QT_CONFIG(whatsthis)
329329
# if QT_CONFIG(accessibility)
330-
self.b_download.setAccessibleName("")
330+
self.pb_download.setAccessibleName("")
331331
# endif // QT_CONFIG(accessibility)
332332
# if QT_CONFIG(accessibility)
333-
self.b_download.setAccessibleDescription("")
333+
self.pb_download.setAccessibleDescription("")
334334
# endif // QT_CONFIG(accessibility)
335-
self.b_download.setText("Download")
335+
self.pb_download.setText("Download")
336336
# if QT_CONFIG(shortcut)
337-
self.b_download.setShortcut("")
337+
self.pb_download.setShortcut("")
338338
# endif // QT_CONFIG(shortcut)
339339

340-
self.lh_download.addWidget(self.b_download)
340+
self.lh_download.addWidget(self.pb_download)
341341

342342
self.lh_download.setStretch(0, 5)
343343
self.lh_download.setStretch(2, 5)

tidal_dl_ng/ui/main.ui

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@
246246
</widget>
247247
</item>
248248
<item>
249-
<widget class="QPushButton" name="b_search">
249+
<widget class="QPushButton" name="pb_search">
250250
<property name="statusTip">
251251
<string notr="true"/>
252252
</property>
@@ -436,7 +436,7 @@
436436
</widget>
437437
</item>
438438
<item>
439-
<widget class="QPushButton" name="b_download">
439+
<widget class="QPushButton" name="pb_download">
440440
<property name="toolTip">
441441
<string notr="true"/>
442442
</property>

0 commit comments

Comments
 (0)