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
This commit is contained in:
exislow
2024-03-22 15:50:23 +01:00
committed by GitHub
8 changed files with 103 additions and 58 deletions
+1 -1
View File
@@ -170,7 +170,7 @@ profile = "black"
multi_line_output = 3 multi_line_output = 3
indent = 4 indent = 4
color_output = true color_output = true
known_third_party = ["Crypto", "PySide6", "coloredlogs", "dataclasses_json", "ffmpeg", "m3u8", "mpegdash", "mutagen", "pathvalidate", "requests", "rich", "tidalapi", "typer"] known_third_party = ["Crypto", "PySide6", "coloredlogs", "dataclasses_json", "ffmpeg", "helper", "m3u8", "mpegdash", "mutagen", "pathvalidate", "requests", "rich", "tidalapi", "typer"]
[tool.mypy] [tool.mypy]
# https://mypy.readthedocs.io/en/latest/config_file.html#using-a-pyproject-toml-file # https://mypy.readthedocs.io/en/latest/config_file.html#using-a-pyproject-toml-file
+50 -22
View File
@@ -2,6 +2,7 @@ import os.path
from enum import Enum from enum import Enum
from pathlib import Path from pathlib import Path
from helper.path import is_installed_ffmpeg
from PySide6 import QtCore, QtGui, QtWidgets from PySide6 import QtCore, QtGui, QtWidgets
from tidalapi import Quality as QualityAudio from tidalapi import Quality as QualityAudio
@@ -86,19 +87,39 @@ class DialogPreferences(QtWidgets.QDialog):
pixmapi: QtWidgets.QStyle.StandardPixmap = QtWidgets.QStyle.SP_MessageBoxQuestion pixmapi: QtWidgets.QStyle.StandardPixmap = QtWidgets.QStyle.SP_MessageBoxQuestion
self.icon = self.style().standardIcon(pixmapi) self.icon = self.style().standardIcon(pixmapi)
self.parameters_checkboxes = [ self._init_checkboxes()
"lyrics_embed", self._init_comboboxes()
"lyrics_file", self._init_line_edit()
"video_download",
"download_delay", # Create an instance of the GUI
"video_convert_mp4", self.ui = Ui_DialogSettings()
]
self.parameters_combo = [ # Run the .setupUi() method to show the GUI
("skip_existing", SkipExisting), self.ui.setupUi(self)
("quality_audio", QualityAudio), # Set data.
("quality_video", QualityVideo), self.gui_populate()
("metadata_cover_dimension", CoverDimensions), self._init_signals()
]
self.exec()
def _init_signals(self):
self.ui.cb_video_convert_mp4.stateChanged.connect(self.on_cb_video_convert_mp4)
def on_cb_video_convert_mp4(self, int):
if self.ui.cb_video_convert_mp4.isChecked():
# Check if ffmpeg is in PATH otherwise show error message.
if not is_installed_ffmpeg():
self.ui.cb_video_convert_mp4.setChecked(False)
self.ui.cb_video_convert_mp4.setCheckState(QtCore.Qt.CheckState.Unchecked)
QtWidgets.QMessageBox.critical(
self,
"FFmpeg not found!",
"Either FFmpeg is not installed on your computer or not set within "
"your PATH variable. You cannot activate this option until FFmpeg "
"is correctly installed and set to your environmental PATH variable.",
)
def _init_line_edit(self):
self.parameters_line_edit = [ self.parameters_line_edit = [
"download_base_path", "download_base_path",
"format_album", "format_album",
@@ -108,15 +129,22 @@ class DialogPreferences(QtWidgets.QDialog):
"format_video", "format_video",
] ]
# Create an instance of the GUI def _init_comboboxes(self):
self.ui = Ui_DialogSettings() self.parameters_combo = [
("skip_existing", SkipExisting),
("quality_audio", QualityAudio),
("quality_video", QualityVideo),
("metadata_cover_dimension", CoverDimensions),
]
# Run the .setupUi() method to show the GUI def _init_checkboxes(self):
self.ui.setupUi(self) self.parameters_checkboxes = [
# Set data. "lyrics_embed",
self.gui_populate() "lyrics_file",
"video_download",
self.exec() "download_delay",
"video_convert_mp4",
]
def gui_populate(self): def gui_populate(self):
self.populate_checkboxes() self.populate_checkboxes()
@@ -190,7 +218,7 @@ class DialogPreferences(QtWidgets.QDialog):
checkbox.setChecked(getattr(self.data, pn)) checkbox.setChecked(getattr(self.data, pn))
def accept(self): def accept(self):
# Get settings. TODO # Get settings.
self.to_settings() self.to_settings()
self.done(1) self.done(1)
+11 -2
View File
@@ -29,7 +29,7 @@ from tidal_dl_ng.constants import (
) )
from tidal_dl_ng.helper.decryption import decrypt_file, decrypt_security_token from tidal_dl_ng.helper.decryption import decrypt_file, decrypt_security_token
from tidal_dl_ng.helper.exceptions import MediaMissing, UnknownManifestFormat from tidal_dl_ng.helper.exceptions import MediaMissing, UnknownManifestFormat
from tidal_dl_ng.helper.path import check_file_exists, format_path_media, path_file_sanitize from tidal_dl_ng.helper.path import check_file_exists, format_path_media, is_installed_ffmpeg, path_file_sanitize
from tidal_dl_ng.helper.tidal import ( from tidal_dl_ng.helper.tidal import (
instantiate_media, instantiate_media,
items_results_all, items_results_all,
@@ -82,6 +82,13 @@ class Download:
self.progress = progress self.progress = progress
self.path_base = path_base self.path_base = path_base
if not is_installed_ffmpeg() and self.settings.data.video_convert_mp4:
self.settings.data.video_convert_mp4 = False
self.fn_logger.error(
"Cannot find FFmpeg in PATH. Videos can be downloaded but will not be processed. "
"Make sure FFmpeg is installed correctly and present within your environmental PATH variable."
)
def _download( def _download(
self, self,
media: Track | Video, media: Track | Video,
@@ -284,7 +291,9 @@ class Download:
def metadata_write(self, track: Track, path_file: str): def metadata_write(self, track: Track, path_file: str):
result: bool = False result: bool = False
release_date: str = ( release_date: str = (
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 "" 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 ""
) )
copy_right: str = track.copyright if hasattr(track, "copyright") and track.copyright else "" copy_right: str = track.copyright if hasattr(track, "copyright") and track.copyright else ""
isrc: str = track.isrc if hasattr(track, "isrc") and track.isrc else "" isrc: str = track.isrc if hasattr(track, "isrc") and track.isrc else ""
+10 -10
View File
@@ -287,16 +287,16 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
self.thread_it(self.list_items_show_result, point=point) self.thread_it(self.list_items_show_result, point=point)
def on_download_list_media(self, point: QtCore.QPoint): def on_download_list_media(self, point: QtCore.QPoint):
self.b_download.setEnabled(False) self.pb_download.setEnabled(False)
self.b_download.setText("Downloading...") self.pb_download.setText("Downloading...")
item = self.tr_lists_user.itemAt(point) item = self.tr_lists_user.itemAt(point)
media = item.data(3, QtCore.Qt.ItemDataRole.UserRole) media = item.data(3, QtCore.Qt.ItemDataRole.UserRole)
self.download(media, self.dl) self.download(media, self.dl)
self.b_download.setText("Download") self.pb_download.setText("Download")
self.b_download.setEnabled(True) self.pb_download.setEnabled(True)
def search_populate_results(self, query: str, type_media: SearchTypes): def search_populate_results(self, query: str, type_media: SearchTypes):
self.tr_results.clear() self.tr_results.clear()
@@ -447,11 +447,11 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
return result return result
def _init_signals(self): def _init_signals(self):
self.b_download.clicked.connect(lambda: self.thread_it(self.on_download_results)) self.pb_download.clicked.connect(lambda: self.thread_it(self.on_download_results))
self.l_search.returnPressed.connect( self.l_search.returnPressed.connect(
lambda: self.search_populate_results(self.l_search.text(), self.cb_search_type.currentData()) lambda: self.search_populate_results(self.l_search.text(), self.cb_search_type.currentData())
) )
self.b_search.clicked.connect( self.pb_search.clicked.connect(
lambda: self.search_populate_results(self.l_search.text(), self.cb_search_type.currentData()) lambda: self.search_populate_results(self.l_search.text(), self.cb_search_type.currentData())
) )
self.cb_quality_audio.currentIndexChanged.connect(self.on_quality_set_audio) self.cb_quality_audio.currentIndexChanged.connect(self.on_quality_set_audio)
@@ -543,8 +543,8 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
self.threadpool.start(worker) self.threadpool.start(worker)
def on_download_results(self): def on_download_results(self):
self.b_download.setEnabled(False) self.pb_download.setEnabled(False)
self.b_download.setText("Downloading...") self.pb_download.setText("Downloading...")
items: [QtWidgets.QTreeWidgetItem] = self.tr_results.selectedItems() items: [QtWidgets.QTreeWidgetItem] = self.tr_results.selectedItems()
@@ -564,8 +564,8 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
self.download(media, self.dl, delay_track=download_delay) self.download(media, self.dl, delay_track=download_delay)
self.b_download.setText("Download") self.pb_download.setText("Download")
self.b_download.setEnabled(True) self.pb_download.setEnabled(True)
def download(self, media: Track | Album | Playlist | Video | Mix, dl: Download, delay_track: bool = False) -> None: def download(self, media: Track | Album | Playlist | Video | Mix, dl: Download, delay_track: bool = False) -> None:
self.s_pb_reset.emit() self.s_pb_reset.emit()
+9 -1
View File
@@ -2,6 +2,7 @@ import glob
import math import math
import os import os
import re import re
import shutil
from pathlib import Path, PosixPath from pathlib import Path, PosixPath
from pathvalidate import sanitize_filename, sanitize_filepath from pathvalidate import sanitize_filename, sanitize_filepath
@@ -10,7 +11,7 @@ from tidalapi import Album, Mix, Playlist, Track, UserPlaylist, Video
from tidal_dl_ng import __name_display__ from tidal_dl_ng import __name_display__
from tidal_dl_ng.constants import FILENAME_SANITIZE_PLACEHOLDER, UNIQUIFY_THRESHOLD, AudioExtensions, MediaType from tidal_dl_ng.constants import FILENAME_SANITIZE_PLACEHOLDER, UNIQUIFY_THRESHOLD, AudioExtensions, MediaType
from tidal_dl_ng.helper.tidal import name_builder_artist, name_builder_title, name_builder_album_artist from tidal_dl_ng.helper.tidal import name_builder_album_artist, name_builder_artist, name_builder_title
def path_home() -> str: def path_home() -> str:
@@ -261,3 +262,10 @@ def check_file_exists(path_file: str, extension_ignore: bool = False) -> bool:
result = bool(sum([glob.glob(_file) for _file in path_files], [])) result = bool(sum([glob.glob(_file) for _file in path_files], []))
return result return result
def is_installed_ffmpeg() -> bool:
# Checks if ffmpeg is found in PATH.
result: bool = bool(shutil.which("ffmpeg"))
return result
+1 -1
View File
@@ -1,5 +1,5 @@
from tidalapi import Album, Mix, Playlist, Session, Track, UserPlaylist, Video from tidalapi import Album, Mix, Playlist, Session, Track, UserPlaylist, Video
from tidalapi.artist import Role, Artist from tidalapi.artist import Artist, Role
from tidalapi.session import SearchTypes from tidalapi.session import SearchTypes
from tidal_dl_ng.constants import MediaType from tidal_dl_ng.constants import MediaType
+19 -19
View File
@@ -187,26 +187,26 @@ class Ui_MainWindow:
self.lh_search.addWidget(self.cb_search_type) self.lh_search.addWidget(self.cb_search_type)
self.b_search = QPushButton(self.w_central) self.pb_search = QPushButton(self.w_central)
self.b_search.setObjectName("b_search") self.pb_search.setObjectName("pb_search")
# if QT_CONFIG(statustip) # if QT_CONFIG(statustip)
self.b_search.setStatusTip("") self.pb_search.setStatusTip("")
# endif // QT_CONFIG(statustip) # endif // QT_CONFIG(statustip)
# if QT_CONFIG(whatsthis) # if QT_CONFIG(whatsthis)
self.b_search.setWhatsThis("") self.pb_search.setWhatsThis("")
# endif // QT_CONFIG(whatsthis) # endif // QT_CONFIG(whatsthis)
# if QT_CONFIG(accessibility) # if QT_CONFIG(accessibility)
self.b_search.setAccessibleName("") self.pb_search.setAccessibleName("")
# endif // QT_CONFIG(accessibility) # endif // QT_CONFIG(accessibility)
# if QT_CONFIG(accessibility) # if QT_CONFIG(accessibility)
self.b_search.setAccessibleDescription("") self.pb_search.setAccessibleDescription("")
# endif // QT_CONFIG(accessibility) # endif // QT_CONFIG(accessibility)
self.b_search.setText("Search") self.pb_search.setText("Search")
# if QT_CONFIG(shortcut) # if QT_CONFIG(shortcut)
self.b_search.setShortcut("") self.pb_search.setShortcut("")
# endif // QT_CONFIG(shortcut) # endif // QT_CONFIG(shortcut)
self.lh_search.addWidget(self.b_search) self.lh_search.addWidget(self.pb_search)
self.lv_search_result.addLayout(self.lh_search) self.lv_search_result.addLayout(self.lh_search)
@@ -315,29 +315,29 @@ class Ui_MainWindow:
self.lh_download.addWidget(self.cb_quality_video) self.lh_download.addWidget(self.cb_quality_video)
self.b_download = QPushButton(self.w_central) self.pb_download = QPushButton(self.w_central)
self.b_download.setObjectName("b_download") self.pb_download.setObjectName("pb_download")
# if QT_CONFIG(tooltip) # if QT_CONFIG(tooltip)
self.b_download.setToolTip("") self.pb_download.setToolTip("")
# endif // QT_CONFIG(tooltip) # endif // QT_CONFIG(tooltip)
# if QT_CONFIG(statustip) # if QT_CONFIG(statustip)
self.b_download.setStatusTip("") self.pb_download.setStatusTip("")
# endif // QT_CONFIG(statustip) # endif // QT_CONFIG(statustip)
# if QT_CONFIG(whatsthis) # if QT_CONFIG(whatsthis)
self.b_download.setWhatsThis("") self.pb_download.setWhatsThis("")
# endif // QT_CONFIG(whatsthis) # endif // QT_CONFIG(whatsthis)
# if QT_CONFIG(accessibility) # if QT_CONFIG(accessibility)
self.b_download.setAccessibleName("") self.pb_download.setAccessibleName("")
# endif // QT_CONFIG(accessibility) # endif // QT_CONFIG(accessibility)
# if QT_CONFIG(accessibility) # if QT_CONFIG(accessibility)
self.b_download.setAccessibleDescription("") self.pb_download.setAccessibleDescription("")
# endif // QT_CONFIG(accessibility) # endif // QT_CONFIG(accessibility)
self.b_download.setText("Download") self.pb_download.setText("Download")
# if QT_CONFIG(shortcut) # if QT_CONFIG(shortcut)
self.b_download.setShortcut("") self.pb_download.setShortcut("")
# endif // QT_CONFIG(shortcut) # endif // QT_CONFIG(shortcut)
self.lh_download.addWidget(self.b_download) self.lh_download.addWidget(self.pb_download)
self.lh_download.setStretch(0, 5) self.lh_download.setStretch(0, 5)
self.lh_download.setStretch(2, 5) self.lh_download.setStretch(2, 5)
+2 -2
View File
@@ -246,7 +246,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="b_search"> <widget class="QPushButton" name="pb_search">
<property name="statusTip"> <property name="statusTip">
<string notr="true"/> <string notr="true"/>
</property> </property>
@@ -436,7 +436,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="b_download"> <widget class="QPushButton" name="pb_download">
<property name="toolTip"> <property name="toolTip">
<string notr="true"/> <string notr="true"/>
</property> </property>