Fix tunein radio playback (#270)
authorMarcel van der Veldt <m.vanderveldt@outlook.com>
Tue, 26 Apr 2022 11:23:06 +0000 (13:23 +0200)
committerGitHub <noreply@github.com>
Tue, 26 Apr 2022 11:23:06 +0000 (13:23 +0200)
* Fix playback of Tunein radio streams

* adjust db schema

music_assistant/helpers/database.py
music_assistant/providers/tunein.py

index 8399661442aec3f322b93a52f853888a5405d28f..0ec68f0b1c9793f6ce36ac8cb6b18758d915b802 100755 (executable)
@@ -11,7 +11,7 @@ from music_assistant.helpers.typing import MusicAssistant
 
 # pylint: disable=invalid-name
 
-SCHEMA_VERSION = 1
+SCHEMA_VERSION = 2
 
 
 class Database:
@@ -127,6 +127,17 @@ class Database:
             sql_query += " WHERE " + " AND ".join((f"{x} = :{x}" for x in match))
             await _db.execute(sql_query, match)
 
+    async def exists(self, table: str, db: Optional[Db] = None) -> bool:
+        """Return bool if table exists."""
+        async with self.get_db(db) as _db:
+            try:
+                await _db.execute(f"SELECT COUNT(*) FROM '{table}'")
+                return True
+            except Exception as exc:  # pylint: disable=broad-except
+                if table in str(exc):
+                    return False
+                raise exc
+
     async def _migrate(self):
         """Perform database migration actions if needed."""
         prev_version = await self.get_row("settings", {"key": "version"})
@@ -141,19 +152,29 @@ class Database:
                 SCHEMA_VERSION,
             )
 
-            # schema version 1: too many breaking changes, simply drop the media tables for now
-            async with self.get_db() as _db:
-                await _db.execute("DROP TABLE IF EXISTS artists")
-                await _db.execute("DROP TABLE IF EXISTS albums")
-                await _db.execute("DROP TABLE IF EXISTS tracks")
-                await _db.execute("DROP TABLE IF EXISTS playlists")
-                await _db.execute("DROP TABLE IF EXISTS radios")
-                await _db.execute("DROP TABLE IF EXISTS playlist_tracks")
-                await _db.execute("DROP TABLE IF EXISTS album_tracks")
-                await _db.execute("DROP TABLE IF EXISTS provider_mappings")
-                await _db.execute("DROP TABLE IF EXISTS cache")
-
-            # store current schema version
-            await self.insert_or_replace(
-                "settings", {"key": "version", "value": str(SCHEMA_VERSION)}
-            )
+            if prev_version < 1:
+                # schema version 1: too many breaking changes, simply drop the media tables for now
+                async with self.get_db() as _db:
+                    await _db.execute("DROP TABLE IF EXISTS artists")
+                    await _db.execute("DROP TABLE IF EXISTS albums")
+                    await _db.execute("DROP TABLE IF EXISTS tracks")
+                    await _db.execute("DROP TABLE IF EXISTS playlists")
+                    await _db.execute("DROP TABLE IF EXISTS radios")
+                    await _db.execute("DROP TABLE IF EXISTS playlist_tracks")
+                    await _db.execute("DROP TABLE IF EXISTS album_tracks")
+                    await _db.execute("DROP TABLE IF EXISTS provider_mappings")
+                    await _db.execute("DROP TABLE IF EXISTS cache")
+
+            if prev_version < 2:
+                # schema version 2: repair invalid data for radio items
+                async with self.get_db() as _db:
+                    await _db.execute("DROP TABLE IF EXISTS radios")
+                    if await self.exists("provider_mappings", _db):
+                        await self.delete(
+                            "provider_mappings", {"media_type": "radio"}, _db
+                        )
+
+        # store current schema version
+        await self.insert_or_replace(
+            "settings", {"key": "version", "value": str(SCHEMA_VERSION)}
+        )
index d436a00a1a4a15d36f91f547fdf8bcbdf885e609..62ff0dad36e88a20f2fdb7527c65114c8af255d0 100644 (file)
@@ -65,8 +65,7 @@ class TuneInProvider(MusicProvider):
 
     async def get_radio(self, prov_radio_id: str) -> Radio:
         """Get radio station details."""
-        prov_radio_id = prov_radio_id.split("--")[0]
-        media_type = prov_radio_id.split("--")[1]
+        prov_radio_id, media_type = prov_radio_id.split("--", 1)
         params = {"c": "composite", "detail": "listing", "id": prov_radio_id}
         result = await self._get_data("Describe.ashx", params)
         if result and result.get("body") and result["body"][0].get("children"):
@@ -113,9 +112,8 @@ class TuneInProvider(MusicProvider):
 
     async def get_stream_details(self, item_id: str) -> StreamDetails:
         """Get streamdetails for a radio station."""
-        prov_radio_id = item_id.split("--")[0]
-        media_type = prov_radio_id.split("--")[1]
-        stream_info = await self._get_data("Tune.ashx", {"id": prov_radio_id})
+        item_id, media_type = item_id.split("--", 1)
+        stream_info = await self._get_data("Tune.ashx", {"id": item_id})
         for stream in stream_info["body"]:
             if stream["media_type"] == media_type:
                 return StreamDetails(