Repository: voicepaw/so-vits-svc-fork

Issue:
Changing Model and Config path in GUI does not update Speaker name.
In the GUI, changing the Model Path and Config Path does not change the Speaker name. The name remains as the initial loaded model's name.

Stack Trace:

```
C:\Users\LXC PC\Desktop\sovits\venv\Scripts>svcg
[13:35:50] INFO     [13:35:50] Loaded config from C:/Users/LXC                                                gui.py:404
                    PC/Desktop/sovits/venv/Scripts/configs/44k/config.json
[13:36:01] INFO     [13:36:01] Event model_path, values {'model_path': 'C:/Users/LXC                          gui.py:432
                    PC/Desktop/sovits/venv/Scripts/logs/21/G_13600.pth', 'model_path_browse': 'C:/Users/LXC
                    PC/Desktop/sovits/venv/Scripts/logs/21/G_13600.pth', 'config_path': 'C:/Users/LXC
                    PC/Desktop/sovits/venv/Scripts/configs/44k/config.json', 'config_path_browse': '',
                    'cluster_model_path': '', 'cluster_model_path_browse': '', 'speaker': 'hapiraw',
                    'silence_threshold': -35.0, 'transpose': 12.0, 'auto_predict_f0': False, 'f0_method':
                    'dio', 'cluster_infer_ratio': 0.0, 'noise_scale': 0.4, 'pad_seconds': 0.1,
                    'chunk_seconds': 0.5, 'absolute_thresh': True, 'input_path': '', 'input_path_browse': '',
                    'auto_play': False, 'crossfade_seconds': 0.05, 'block_seconds': 0.35,
                    'additional_infer_before_seconds': 0.15, 'additional_infer_after_seconds': 0.1,
                    'realtime_algorithm': '1 (Divide constantly)', 'input_device': 'Microsoft Sound Mapper -
                    Input', 'output_device': 'Microsoft Sound Mapper - Output', 'passthrough_original':
                    False, 'presets': 'Default VC (GPU, GTX 1060)', 'preset_name': '', 'use_gpu': True}
           INFO     [13:36:01] Updating browser <PySimpleGUI.PySimpleGUI.Button object at 0x0000028C5EF5EC40> gui.py:438
                    to C:\Users\LXC PC\Desktop\sovits\venv\Scripts\logs\21
           INFO     [13:36:01] Updating browser <PySimpleGUI.PySimpleGUI.Button object at 0x0000028C5EF5EDC0> gui.py:438
                    to C:\Users\LXC PC\Desktop\sovits\venv\Scripts\logs\21
           INFO     [13:36:01] Updating browser <PySimpleGUI.PySimpleGUI.Button object at 0x0000028C5EF5EF40> gui.py:438
                    to C:\Users\LXC PC\Desktop\sovits\venv\Scripts\logs\21
           INFO     [13:36:01] Updating browser <PySimpleGUI.PySimpleGUI.Button object at 0x0000028C5EF73A30> gui.py:438
                    to C:\Users\LXC PC\Desktop\sovits\venv\Scripts\logs\21
[13:36:09] INFO     [13:36:09] Event config_path, values {'model_path': 'C:/Users/LXC                         gui.py:432
                    PC/Desktop/sovits/venv/Scripts/logs/21/G_13600.pth', 'model_path_browse': 'C:/Users/LXC
                    PC/Desktop/sovits/venv/Scripts/logs/21/G_13600.pth', 'config_path': 'C:/Users/LXC
                    PC/Desktop/sovits/venv/Scripts/configs/21/config.json', 'config_path_browse':
                    'C:/Users/LXC PC/Desktop/sovits/venv/Scripts/configs/21/config.json',
                    'cluster_model_path': '', 'cluster_model_path_browse': '', 'speaker': 'hapiraw',
                    'silence_threshold': -35.0, 'transpose': 12.0, 'auto_predict_f0': False, 'f0_method':
                    'dio', 'cluster_infer_ratio': 0.0, 'noise_scale': 0.4, 'pad_seconds': 0.1,
                    'chunk_seconds': 0.5, 'absolute_thresh': True, 'input_path': '', 'input_path_browse': '',
                    'auto_play': False, 'crossfade_seconds': 0.05, 'block_seconds': 0.35,
                    'additional_infer_before_seconds': 0.15, 'additional_infer_after_seconds': 0.1,
                    'realtime_algorithm': '1 (Divide constantly)', 'input_device': 'Microsoft Sound Mapper -
                    Input', 'output_device': 'Microsoft Sound Mapper - Output', 'passthrough_original':
                    False, 'presets': 'Default VC (GPU, GTX 1060)', 'preset_name': '', 'use_gpu': True}
           INFO     [13:36:09] Updating browser <PySimpleGUI.PySimpleGUI.Button object at 0x0000028C5EF5EC40> gui.py:438
                    to C:\Users\LXC PC\Desktop\sovits\venv\Scripts\configs\21
           INFO     [13:36:09] Updating browser <PySimpleGUI.PySimpleGUI.Button object at 0x0000028C5EF5EDC0> gui.py:438
                    to C:\Users\LXC PC\Desktop\sovits\venv\Scripts\configs\21
           INFO     [13:36:09] Updating browser <PySimpleGUI.PySimpleGUI.Button object at 0x0000028C5EF5EF40> gui.py:438
                    to C:\Users\LXC PC\Desktop\sovits\venv\Scripts\configs\21
           INFO     [13:36:09] Updating browser <PySimpleGUI.PySimpleGUI.Button object at 0x0000028C5EF73A30> gui.py:438
                    to C:\Users\LXC PC\Desktop\sovits\venv\Scripts\configs\21
```


Discussion:

Resolving patch:
diff --git a/src/so_vits_svc_fork/__main__.py b/src/so_vits_svc_fork/__main__.py
--- a/src/so_vits_svc_fork/__main__.py
+++ b/src/so_vits_svc_fork/__main__.py
@@ -18,8 +18,16 @@
 import torch
 from rich.logging import RichHandler
 
+from so_vits_svc_fork import __version__
+
+LOG = getLogger(__name__)
+LOGGER_INIT = False
+
 
 def init_logger() -> None:
+    global LOGGER_INIT
+    if LOGGER_INIT:
+        return
     IN_COLAB = os.getenv("COLAB_RELEASE_TAG")
     IS_TEST = "test" in Path(__file__).parent.stem
 
@@ -36,10 +44,11 @@ def init_logger() -> None:
     if IS_TEST:
         LOG.debug("Test mode is on.")
 
+    LOG.info(f"Version: {__version__}")
+    LOGGER_INIT = True
 
-init_logger()
 
-LOG = getLogger(__name__)
+init_logger()
 
 
 class RichHelpFormatter(click.HelpFormatter):
diff --git a/src/so_vits_svc_fork/gui.py b/src/so_vits_svc_fork/gui.py
--- a/src/so_vits_svc_fork/gui.py
+++ b/src/so_vits_svc_fork/gui.py
@@ -54,13 +54,19 @@ def delete_preset(name: str) -> dict:
     return load_presets()
 
 
-def main():
-    sg.theme("Dark")
-    model_candidates = list(sorted(Path("./logs/44k/").glob("G_*.pth")))
-
+def get_devices(update: bool = True) -> tuple[list[str], list[str]]:
+    if update:
+        sd._terminate()
+        sd._initialize()
     devices = sd.query_devices()
     input_devices = [d["name"] for d in devices if d["max_input_channels"] > 0]
     output_devices = [d["name"] for d in devices if d["max_output_channels"] > 0]
+    return input_devices, output_devices
+
+
+def main():
+    sg.theme("Dark")
+    model_candidates = list(sorted(Path("./logs/44k/").glob("G_*.pth")))
 
     frame_contents = {
         "Paths": [
@@ -278,9 +284,8 @@ def main():
                 sg.Push(),
                 sg.Combo(
                     key="input_device",
-                    values=input_devices,
+                    values=[],
                     size=(20, 1),
-                    default_value=input_devices[0],
                 ),
             ],
             [
@@ -288,9 +293,8 @@ def main():
                 sg.Push(),
                 sg.Combo(
                     key="output_device",
-                    values=output_devices,
+                    values=[],
                     size=(20, 1),
-                    default_value=output_devices[0],
                 ),
             ],
             [
@@ -401,11 +405,31 @@ def update_speaker() -> None:
         config_path = Path(values["config_path"])
         if config_path.exists() and config_path.is_file():
             hp = utils.get_hparams_from_file(values["config_path"])
-            LOG.info(f"Loaded config from {values['config_path']}")
+            LOG.debug(f"Loaded config from {values['config_path']}")
             window["speaker"].update(
                 values=list(hp.__dict__["spk"].keys()), set_to_index=0
             )
 
+    def update_devices() -> None:
+        input_devices, output_devices = get_devices()
+        window["input_device"].update(
+            values=input_devices, value=values["input_device"]
+        )
+        window["output_device"].update(
+            values=output_devices, value=values["output_device"]
+        )
+        input_default, output_default = sd.default.device
+        if values["input_device"] not in input_devices:
+            window["input_device"].update(
+                values=input_devices,
+                set_to_index=0 if input_default is None else input_default - 1,
+            )
+        if values["output_device"] not in output_devices:
+            window["output_device"].update(
+                values=output_devices,
+                set_to_index=0 if output_default is None else output_default - 1,
+            )
+
     PRESET_KEYS = [
         key
         for key in values.keys()
@@ -416,8 +440,8 @@ def apply_preset(name: str) -> None:
         for key, value in load_presets()[name].items():
             if key in PRESET_KEYS:
                 window[key].update(value)
+                values[key] = value
 
-    update_speaker()
     default_name = list(load_presets().keys())[0]
     apply_preset(default_name)
     window["presets"].update(default_name)
@@ -425,11 +449,12 @@ def apply_preset(name: str) -> None:
     with ProcessPool(max_workers=1) as pool:
         future: None | ProcessFuture = None
         while True:
-            event, values = window.read(100)
+            event, values = window.read(500)
             if event == sg.WIN_CLOSED:
                 break
             if not event == sg.EVENT_TIMEOUT:
                 LOG.info(f"Event {event}, values {values}")
+            update_devices()
             if event.endswith("_path"):
                 for name in window.AllKeysDict:
                     if str(name).endswith("_browse"):
@@ -442,7 +467,7 @@ def apply_preset(name: str) -> None:
                             browser.update()
                         else:
                             LOG.warning(f"Browser {browser} is not a FileBrowse")
-            elif event == "add_preset":
+            if event == "add_preset":
                 presets = add_preset(
                     values["preset_name"], {key: values[key] for key in PRESET_KEYS}
                 )


Test patch: