diff --git a/.gitignore b/.gitignore index 9105cca..14af255 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ __pycache__ UIFileConverter.ps1 developer_notes.txt languages +settings.ini # Do not include model files and logs src/resources/user/models/**/*.pth src/resources/models/**/*.pth diff --git a/src/app.py b/src/app.py index 8f3b91f..7804887 100644 --- a/src/app.py +++ b/src/app.py @@ -55,8 +55,8 @@ class CustomApplication(QtWidgets.QApplication): # -Create Managers- self.logger = Logger() - self.settings = QtCore.QSettings(const.APPLICATION_SHORTNAME, const.APPLICATION_NAME) - #self.settings.clear() + self.settings = QtCore.QSettings(ResourcePaths.settingsIniFile, QtCore.QSettings.Format.IniFormat) + # self.settings.clear() self.resources = ResourcePaths() self.translator = Translator(self) self.themeManager = ThemeManager(self) @@ -105,7 +105,6 @@ class CustomApplication(QtWidgets.QApplication): for combobox in window.findChildren(QtWidgets.QComboBox): # Monkeypatch showPopup function combobox.showPopup = lambda wig=combobox, func=combobox.showPopup: self.improved_combobox_showPopup(wig, func) # nopep8 - if combobox.isEditable(): # Align editable comboboxes to center combobox.lineEdit().setAlignment(Qt.AlignCenter) @@ -184,7 +183,7 @@ class CustomApplication(QtWidgets.QApplication): seperation_data['save_instrumentals'] = self.windows['settings'].ui.checkBox_autoSaveInstrumentals.isChecked() seperation_data['save_vocals'] = self.windows['settings'].ui.checkBox_autoSaveVocals.isChecked() # Combobox - seperation_data['model'] = self.windows['settings'].ui.comboBox_instrumental.currentData() + seperation_data['model'] = self.windows['settings'].ui.comboBox_instrumental.currentData()['path'] seperation_data['modelDataPath'] = r"D:\Dilan\GitHub\ultimatevocalremovergui\src\inference\modelparams\2band_48000.json" seperation_data['isVocal'] = False # Lineedit (Constants) diff --git a/src/constants.py b/src/constants.py index cca8663..e9e354c 100644 --- a/src/constants.py +++ b/src/constants.py @@ -7,6 +7,7 @@ from PySide2 import QtCore # -Root imports- from .inference import converter from collections import OrderedDict +import torch __is_light_theme = bool(QtCore.QSettings("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", QtCore.QSettings.NativeFormat).value("AppsUseLightTheme")) @@ -20,7 +21,6 @@ APPLICATION_NAME = 'Ultimate Vocal Remover' JSON_TO_NAME = OrderedDict(**{ # -Conversion- # Boolean - 'gpuConversion': 'checkBox_gpuConversion', 'postProcess': 'checkBox_postProcess', 'tta': 'checkBox_tta', 'outputImage': 'checkBox_outputImage', @@ -34,6 +34,7 @@ JSON_TO_NAME = OrderedDict(**{ 'vocalModelName': 'comboBox_vocal', 'windowSize': 'comboBox_winSize', }) +CUDA_AVAILABLE = torch.cuda.is_available() DEFAULT_SETTINGS = { # --Independent Data (Data not directly connected with widgets)-- 'inputPaths': [], @@ -48,7 +49,6 @@ DEFAULT_SETTINGS = { ['ALL', { # -Conversion- # Boolean - 'gpuConversion': True, 'postProcess': True, 'tta': True, 'outputImage': True, @@ -58,14 +58,11 @@ DEFAULT_SETTINGS = { 'aggressiveness': 0.1, 'highEndProcess': 'Bypass', # -Models- - # 'instrumentalModelName': 'comboBox_instrumental', - # 'vocalModelName': 'comboBox_vocal', 'windowSize': 1024, }], ['NONE', { # -Conversion- # Boolean - 'gpuConversion': False, 'postProcess': False, 'tta': False, 'outputImage': False, @@ -75,8 +72,6 @@ DEFAULT_SETTINGS = { 'aggressiveness': -0.1, 'highEndProcess': 'Mirroring', # -Models- - # 'instrumentalModelName': 'comboBox_instrumental', - # 'vocalModelName': 'comboBox_vocal', 'windowSize': 352, }] ], @@ -87,7 +82,7 @@ DEFAULT_SETTINGS = { # --Settings window -> Seperation Settings-- # -Conversion- # Boolean - 'checkBox_gpuConversion': converter.default_data['gpuConversion'], + 'checkBox_gpuConversion': CUDA_AVAILABLE, 'checkBox_postProcess': converter.default_data['postProcess'], 'checkBox_tta': converter.default_data['tta'], 'checkBox_outputImage': converter.default_data['outputImage'], diff --git a/src/resources/resources_manager.py b/src/resources/resources_manager.py index 7ea1f1f..27666c8 100644 --- a/src/resources/resources_manager.py +++ b/src/resources/resources_manager.py @@ -78,6 +78,7 @@ class ResourcePaths: customInstrumentalModelsDir = os.path.join(abs_path, USER_FOLDER, MODELS_FOLDER, INSTRUMENTAL_FOLDER_NAME) customVocalModelsDir = os.path.join(abs_path, USER_FOLDER, MODELS_FOLDER, VOCAL_FOLDER_NAME) tempDir = os.path.join(abs_path, USER_FOLDER, TEMP_MUSIC_FILES_FOLDER) + settingsIniFile = os.path.join(abs_path, USER_FOLDER, 'settings.ini') class Logger(logging.Logger): diff --git a/src/resources/user/settings.ini b/src/resources/user/settings.ini new file mode 100644 index 0000000..52d703a --- /dev/null +++ b/src/resources/user/settings.ini @@ -0,0 +1,39 @@ +[settingswindow] +size=@Size(940 600) +pos=@Point(1960 229) +checkBox_gpuConversion=false +checkBox_tta=true +checkBox_modelFolder=true +checkBox_outputImage=true +checkBox_postProcess=true +checkBox_deepExtraction=true +comboBox_instrumental=MGM-v5-2Band-32000-BETA1 +comboBox_vocal= +comboBox_winSize=1024 +doubleSpinBox_aggressiveness=0.1 +comboBox_highEndProcess=Bypass +comboBox_presets=ALL +checkBox_notifiyOnFinish=false +checkBox_notifyUpdates=true +checkBox_settingsStartup=false +checkBox_disableAnimations=false +checkBox_disableShortcuts=false +checkBox_multithreading=false +comboBox_command=Aus +checkBox_autoSaveInstrumentals=true +checkBox_autoSaveVocals=true + +[mainwindow] +size=@Size(947 559) +pos=@Point(185 175) +isMaximized=false + +[user] +exportDirectory=C:/Users/boska/Desktop +language=de_DE +inputPaths=@Invalid() +inputsDirectory=C:/Users/boska/Desktop +presets=@Variant(\0\0\0\x7f\0\0\0\x18PySide::PyObjectWrapper\0\0\0\0\xc3\x80\x3X\x3\0\0\0\x41LLq\0}q\x1(X\xe\0\0\0\x61ggressivenessq\x2G?\xb9\x99\x99\x99\x99\x99\x9aX\xe\0\0\0\x64\x65\x65pExtractionq\x3\x88X\xe\0\0\0highEndProcessq\x4X\x6\0\0\0\x42ypassq\x5X\v\0\0\0modelFolderq\x6\x88X\v\0\0\0outputImageq\a\x88X\v\0\0\0postProcessq\b\x88X\x3\0\0\0ttaq\t\x88X\n\0\0\0windowSizeq\nM\0\x4u\x86q\v.), @Variant(\0\0\0\x7f\0\0\0\x18PySide::PyObjectWrapper\0\0\0\0\xc7\x80\x3X\x4\0\0\0NONEq\0}q\x1(X\xe\0\0\0\x61ggressivenessq\x2G\xbf\xb9\x99\x99\x99\x99\x99\x9aX\xe\0\0\0\x64\x65\x65pExtractionq\x3\x89X\xe\0\0\0highEndProcessq\x4X\t\0\0\0Mirroringq\x5X\v\0\0\0modelFolderq\x6\x89X\v\0\0\0outputImageq\a\x89X\v\0\0\0postProcessq\b\x89X\x3\0\0\0ttaq\t\x89X\n\0\0\0windowSizeq\nM`\x1u\x86q\v.) +presets_loadDir=C:/Users/boska/Desktop +presets_saveDir=C:/Users/boska/Desktop +theme=dark diff --git a/src/windows/design/mainwindow_ui.py b/src/windows/design/mainwindow_ui.py index 2e98ce9..38f3e82 100644 --- a/src/windows/design/mainwindow_ui.py +++ b/src/windows/design/mainwindow_ui.py @@ -174,6 +174,12 @@ class Ui_MainWindow(object): self.comboBox_presets.setObjectName(u"comboBox_presets") self.comboBox_presets.setMinimumSize(QSize(135, 25)) self.comboBox_presets.setMaximumSize(QSize(135, 16777215)) + self.comboBox_presets.setStyleSheet(u"QComboBox::down-arrow {\n" + " image: none;\n" + "}\n" + "QComboBox::drop-down {\n" + " border-width: 0px;\n" + "}") self.verticalLayout_10.addWidget(self.comboBox_presets) diff --git a/src/windows/mainwindow.py b/src/windows/mainwindow.py index 2049504..9a4c2b8 100644 --- a/src/windows/mainwindow.py +++ b/src/windows/mainwindow.py @@ -60,13 +60,14 @@ class MainWindow(QtWidgets.QWidget): self.ui.setupUi(self) self.app = app self.logger = app.logger - self.settings = QtCore.QSettings(const.APPLICATION_SHORTNAME, const.APPLICATION_NAME) + self.settings = self.app.settings self.setWindowIcon(QtGui.QIcon(ResourcePaths.images.icon)) # -Other Variables- # Independent data self.inputPaths: list = self.settings.value('user/inputPaths', - const.DEFAULT_SETTINGS['inputPaths']) + const.DEFAULT_SETTINGS['inputPaths'], + type=list) self.inputsDirectory: str = self.settings.value('user/inputsDirectory', const.DEFAULT_SETTINGS['inputsDirectory'], type=str) diff --git a/src/windows/presetseditorwindow.py b/src/windows/presetseditorwindow.py index 82fd6b4..a5f8620 100644 --- a/src/windows/presetseditorwindow.py +++ b/src/windows/presetseditorwindow.py @@ -33,7 +33,7 @@ class PresetsEditorWindow(QtWidgets.QWidget): self.ui.setupUi(self) self.app = app self.logger = app.logger - self.settings = QtCore.QSettings(const.APPLICATION_SHORTNAME, const.APPLICATION_NAME) + self.settings = self.app.settings self.setWindowModality(Qt.WindowModality.ApplicationModal) # -Other Variables- @@ -139,6 +139,7 @@ class PresetsEditorWindow(QtWidgets.QWidget): # Get current settings settingsManager = self.app.settingsWindow.settingsManager widget_settings = settingsManager.get_settings(page_idx=0) + del widget_settings['checkBox_gpuConversion'] del widget_settings['comboBox_presets'] name_to_json = {v: k for k, v in const.JSON_TO_NAME.items()} # Invert dict diff --git a/src/windows/settingswindow.py b/src/windows/settingswindow.py index a919e11..62b7a55 100644 --- a/src/windows/settingswindow.py +++ b/src/windows/settingswindow.py @@ -15,6 +15,7 @@ import datetime as dt from collections import OrderedDict import torch # System +import hashlib import os # Code annotation from typing import (Dict, Union, Optional) @@ -37,7 +38,7 @@ class SettingsWindow(QtWidgets.QWidget): self.ui.setupUi(self) self.app = app self.logger = app.logger - self.settings = QtCore.QSettings(const.APPLICATION_SHORTNAME, const.APPLICATION_NAME) + self.settings = self.app.settings self.settingsManager = SettingsManager(win=self) self.setWindowIcon(QtGui.QIcon(ResourcePaths.images.settings)) @@ -53,7 +54,6 @@ class SettingsWindow(QtWidgets.QWidget): const.DEFAULT_SETTINGS['exportDirectory'], type=str) self.search_for_preset = True - self.CUDA_AVAILABLE = torch.cuda.is_available() # -Widget Binds- def pushButton_clearCommand_clicked(self): @@ -207,10 +207,6 @@ class SettingsWindow(QtWidgets.QWidget): for json_key, value in settings.items(): widget_object_name = const.JSON_TO_NAME[json_key] - if not self.CUDA_AVAILABLE and widget_object_name == "checkBox_gpuConversion": - # CUDA not available, should not change the preset though - continue - if (str(current_settings[widget_object_name]) != str(value)): break else: @@ -219,9 +215,6 @@ class SettingsWindow(QtWidgets.QWidget): else: self.ui.comboBox_presets.setCurrentIndex(0) - if not self.CUDA_AVAILABLE: - self.ui.checkBox_gpuConversion.setChecked(False) - # -Window Setup Methods- def setup_window(self): @@ -377,7 +370,7 @@ class SettingsWindow(QtWidgets.QWidget): open_settings = self.settings.value('settingswindow/checkBox_settingsStartup', const.DEFAULT_SETTINGS['checkBox_settingsStartup'], bool) - if not self.CUDA_AVAILABLE: + if not const.CUDA_AVAILABLE: self.ui.checkBox_gpuConversion.setEnabled(False) self.ui.checkBox_gpuConversion.setToolTip("CUDA is not available on your system") @@ -445,7 +438,7 @@ class SettingsWindow(QtWidgets.QWidget): mainWindowPresetWidget.clear() self.ui.comboBox_presets.addItem('Custom') mainWindowPresetWidget.addItem('Custom') - for preset_name in self.app.windows['presetsEditor'].get_presets().keys(): + for i, preset_name in enumerate(self.app.windows['presetsEditor'].get_presets().keys()): # Add text to combobox self.ui.comboBox_presets.addItem(preset_name) mainWindowPresetWidget.addItem(preset_name) @@ -463,6 +456,19 @@ class SettingsWindow(QtWidgets.QWidget): Update the list of models to select from in the seperation settings page based on the selected AI Engine """ + def get_model_id(path: str) -> str: + buffer_size = 65536 + sha1 = hashlib.sha1() + + with open(path, 'rb') as f: + while True: + data = f.read(buffer_size) + if not data: + break + sha1.update(data) + + return sha1.hexdigest() + def fill_model_comboBox(widget: QtWidgets.QComboBox, folder: str): """ Fill the combobox for the model @@ -475,10 +481,15 @@ class SettingsWindow(QtWidgets.QWidget): continue # Get data full_path = os.path.join(folder, f) + model_id = get_model_id(full_path) + print(model_id) model_name = os.path.splitext(os.path.basename(f))[0] # Add item to combobox widget.addItem(model_name, - full_path) + { + 'path': full_path, + 'id': model_id + }) if model_name == currently_selected_model_name: # This model was selected before clearing the # QComboBox, so reselect diff --git a/ui_files/mainwindow.ui b/ui_files/mainwindow.ui index 8180c04..2ece212 100644 --- a/ui_files/mainwindow.ui +++ b/ui_files/mainwindow.ui @@ -393,6 +393,14 @@ 16777215 + + QComboBox::down-arrow { + image: none; +} +QComboBox::drop-down { + border-width: 0px; +} +