Fix Podcast and Audiobook support on SMB Filesystem provider (#1944)
authorMarcel van der Veldt <m.vanderveldt@outlook.com>
Thu, 6 Feb 2025 11:32:23 +0000 (12:32 +0100)
committerGitHub <noreply@github.com>
Thu, 6 Feb 2025 11:32:23 +0000 (12:32 +0100)
* Chore: Start full sync after reset of library db

* Fix Podcast and Audiobook support on SMB Filesystem provider

music_assistant/controllers/music.py
music_assistant/providers/filesystem_local/__init__.py
music_assistant/providers/filesystem_smb/__init__.py

index 321c8a8c32362c62caad15673c4fc2848207e2c7..ca4b851cc8f4c6e8396933a5e7d319a8479fb56d 100644 (file)
@@ -1261,6 +1261,8 @@ class MusicController(CoreController):
         db_path = os.path.join(self.mass.storage_path, "library.db")
         await asyncio.to_thread(os.remove, db_path)
         await self._setup_database()
+        # initiate full sync
+        self.start_sync()
 
     async def __create_database_tables(self) -> None:
         """Create database tables."""
index d61f28bba4ecd5d9b96809ad75bd3d0a9decd497..9fc581adc5106a43e9ce131a2ddd2f1677da7871 100644 (file)
@@ -106,15 +106,8 @@ async def setup(
     mass: MusicAssistant, manifest: ProviderManifest, config: ProviderConfig
 ) -> ProviderInstanceType:
     """Initialize provider(instance) with given configuration."""
-    conf_path = config.get_value(CONF_PATH)
-    if not await isdir(conf_path):
-        msg = f"Music Directory {conf_path} does not exist"
-        raise SetupFailedError(msg)
-    prov = LocalFileSystemProvider(mass, manifest, config)
-    prov.base_path = str(config.get_value(CONF_PATH))
-    await prov.check_write_access()
-    prov.media_content_type = cast(str, config.get_value(CONF_ENTRY_CONTENT_TYPE.key))
-    return prov
+    base_path = cast(str, config.get_value(CONF_PATH))
+    return LocalFileSystemProvider(mass, manifest, config, base_path)
 
 
 async def get_config_entries(
@@ -137,17 +130,7 @@ async def get_config_entries(
             CONF_ENTRY_PATH,
             CONF_ENTRY_MISSING_ALBUM_ARTIST,
         )
-    media_type = values.get(CONF_ENTRY_CONTENT_TYPE.key)
-    if media_type == "music":
-        return (
-            CONF_ENTRY_PATH,
-            CONF_ENTRY_CONTENT_TYPE_READ_ONLY,
-            CONF_ENTRY_MISSING_ALBUM_ARTIST,
-        )
-    return (
-        CONF_ENTRY_PATH,
-        CONF_ENTRY_CONTENT_TYPE_READ_ONLY,
-    )
+    return (CONF_ENTRY_PATH, CONF_ENTRY_CONTENT_TYPE_READ_ONLY, CONF_ENTRY_MISSING_ALBUM_ARTIST)
 
 
 class LocalFileSystemProvider(MusicProvider):
@@ -159,10 +142,19 @@ class LocalFileSystemProvider(MusicProvider):
     Supports m3u files for playlists.
     """
 
-    base_path: str
-    write_access: bool = False
-    sync_running: bool = False
-    media_content_type: str = "music"
+    def __init__(
+        self,
+        mass: MusicAssistant,
+        manifest: ProviderManifest,
+        config: ProviderConfig,
+        base_path: str,
+    ) -> None:
+        """Initialize MusicProvider."""
+        super().__init__(mass, manifest, config)
+        self.base_path: str = base_path
+        self.write_access: bool = False
+        self.sync_running: bool = False
+        self.media_content_type = cast(str, config.get_value(CONF_ENTRY_CONTENT_TYPE.key))
 
     @property
     def supported_features(self) -> set[ProviderFeature]:
@@ -200,6 +192,13 @@ class LocalFileSystemProvider(MusicProvider):
         postfix = self.base_path.split(os.sep)[-1]
         return f"{self.manifest.name} {postfix}"
 
+    async def handle_async_init(self) -> None:
+        """Handle async initialization of the provider."""
+        if not await isdir(self.base_path):
+            msg = f"Music Directory {self.base_path} does not exist"
+            raise SetupFailedError(msg)
+        await self.check_write_access()
+
     async def search(
         self,
         search_query: str,
index 8c18601869a3057ecdd07c5e954379c1f187750e..bc2c5b004708936618438e9e4c3f113fe2093f3c 100644 (file)
@@ -16,6 +16,7 @@ from music_assistant.helpers.util import get_ip_from_host
 from music_assistant.providers.filesystem_local import LocalFileSystemProvider, exists, makedirs
 from music_assistant.providers.filesystem_local.constants import (
     CONF_ENTRY_CONTENT_TYPE,
+    CONF_ENTRY_CONTENT_TYPE_READ_ONLY,
     CONF_ENTRY_MISSING_ALBUM_ARTIST,
 )
 
@@ -46,7 +47,9 @@ async def setup(
     if not share or "/" in share or "\\" in share:
         msg = "Invalid share name"
         raise LoginFailed(msg)
-    return SMBFileSystemProvider(mass, manifest, config)
+    # base_path will be the path where we're going to mount the remote share
+    base_path = f"/tmp/{config.instance_id}"  # noqa: S108
+    return SMBFileSystemProvider(mass, manifest, config, base_path)
 
 
 async def get_config_entries(
@@ -63,7 +66,7 @@ async def get_config_entries(
     values: the (intermediate) raw values for config entries sent with the action.
     """
     # ruff: noqa: ARG001
-    return (
+    base_entries = (
         ConfigEntry(
             key=CONF_HOST,
             type=ConfigEntryType.STRING,
@@ -107,7 +110,6 @@ async def get_config_entries(
             description="[optional] Use if your music is stored in a sublevel of the share. "
             "E.g. 'collections' or 'albums/A-K'.",
         ),
-        CONF_ENTRY_CONTENT_TYPE,
         ConfigEntry(
             key=CONF_MOUNT_OPTIONS,
             type=ConfigEntryType.STRING,
@@ -121,6 +123,16 @@ async def get_config_entries(
         CONF_ENTRY_MISSING_ALBUM_ARTIST,
     )
 
+    if instance_id is None or values is None:
+        return (
+            CONF_ENTRY_CONTENT_TYPE,
+            *base_entries,
+        )
+    return (
+        *base_entries,
+        CONF_ENTRY_CONTENT_TYPE_READ_ONLY,
+    )
+
 
 class SMBFileSystemProvider(LocalFileSystemProvider):
     """
@@ -149,11 +161,8 @@ class SMBFileSystemProvider(LocalFileSystemProvider):
 
     async def handle_async_init(self) -> None:
         """Handle async initialization of the provider."""
-        # base_path will be the path where we're going to mount the remote share
-        self.base_path = f"/tmp/{self.instance_id}"  # noqa: S108
         if not await exists(self.base_path):
             await makedirs(self.base_path)
-
         try:
             # do unmount first to cleanup any unexpected state
             await self.unmount(ignore_error=True)
@@ -161,7 +170,6 @@ class SMBFileSystemProvider(LocalFileSystemProvider):
         except Exception as err:
             msg = f"Connection failed for the given details: {err}"
             raise LoginFailed(msg) from err
-
         await self.check_write_access()
 
     async def unload(self, is_removed: bool = False) -> None: