add config options for icy meta
authorMarcel van der Veldt <m.vanderveldt@outlook.com>
Wed, 28 Aug 2024 14:52:20 +0000 (16:52 +0200)
committerMarcel van der Veldt <m.vanderveldt@outlook.com>
Wed, 28 Aug 2024 14:52:20 +0000 (16:52 +0200)
music_assistant/common/models/config_entries.py
music_assistant/constants.py
music_assistant/server/controllers/players.py
music_assistant/server/controllers/streams.py
music_assistant/server/providers/dlna/__init__.py
music_assistant/server/providers/hass_players/__init__.py

index d4826fd4e4938e991d2a1fce437db475a1039f07..064ca3bedd6fb5cda43fc7a1469e0f9daeeb2e64 100644 (file)
@@ -21,6 +21,7 @@ from music_assistant.constants import (
     CONF_AUTO_PLAY,
     CONF_CROSSFADE,
     CONF_CROSSFADE_DURATION,
+    CONF_ENABLE_ICY_METADATA,
     CONF_ENFORCE_MP3,
     CONF_EQ_BASS,
     CONF_EQ_MID,
@@ -620,6 +621,24 @@ CONF_ENTRY_HTTP_PROFILE_FORCED_2 = ConfigEntry.from_dict(
     {**CONF_ENTRY_HTTP_PROFILE.to_dict(), "default_value": "no_content_length", "hidden": True}
 )
 
+CONF_ENTRY_ENABLE_ICY_METADATA = ConfigEntry(
+    key=CONF_ENABLE_ICY_METADATA,
+    type=ConfigEntryType.STRING,
+    options=(
+        ConfigValueOption("Disabled - do not send ICY metadata", "disabled"),
+        ConfigValueOption("Profile 1 - basic info", "basic"),
+        ConfigValueOption("Profile 2 - full info (including image)", "full"),
+    ),
+    depends_on=CONF_FLOW_MODE,
+    default_value="basic",
+    label="Try to ingest metadata into stream (ICY)",
+    category="advanced",
+    description="Try to ingest metadata into the stream (ICY) to show track info on the player, "
+    "even when flow mode is enabled.\n\nThis is called ICY metadata and its what is also used by "
+    "online radio station to inform you what is playing. \n\nBe aware that not all players support "
+    "this correctly. If you experience issues with playback, try to disable this setting.",
+)
+
 
 def create_sample_rates_config_entry(
     max_sample_rate: int,
index 3442884d4590b3f9286f06207f33ab5fb9e59554..3f76d6c4f30eb8fbe5867b3abfa149fa03e1e388 100644 (file)
@@ -70,6 +70,7 @@ CONF_BYPASS_NORMALIZATION_RADIO: Final[str] = "bypass_normalization_radio"
 CONF_BYPASS_NORMALIZATION_SHORT: Final[str] = "bypass_normalization_short"
 CONF_PREVENT_SYNC_LEADER_OFF: Final[str] = "prevent_sync_leader_off"
 CONF_SYNCGROUP_DEFAULT_ON: Final[str] = "syncgroup_default_on"
+CONF_ENABLE_ICY_METADATA: Final[str] = "enable_icy_metadata"
 
 # config default values
 DEFAULT_HOST: Final[str] = "0.0.0.0"
index 6a62ef6779b6d7a2832925ad06a54c1e34e0bee0..e3231a0cc3b733a37397adac2f58e1fbe1fa7e00 100644 (file)
@@ -928,7 +928,7 @@ class PlayerController(CoreController):
         changed_values = get_changed_values(
             prev_state,
             new_state,
-            ignore_keys=["elapsed_time", "elapsed_time_last_updated", "seq_no"],
+            ignore_keys=["elapsed_time", "elapsed_time_last_updated", "seq_no", "last_poll"],
         )
         self._prev_states[player_id] = new_state
 
index 1ab5e2c29b0102b54d531fb2b80bb16539c93500..6e4e36fe523fb0f3a0682932f06773057962f4a3 100644 (file)
@@ -36,6 +36,7 @@ from music_assistant.constants import (
     CONF_BYPASS_NORMALIZATION_SHORT,
     CONF_CROSSFADE,
     CONF_CROSSFADE_DURATION,
+    CONF_ENABLE_ICY_METADATA,
     CONF_HTTP_PROFILE,
     CONF_OUTPUT_CHANNELS,
     CONF_PUBLISH_IP,
@@ -375,10 +376,11 @@ class StreamsController(CoreController):
             default_sample_rate=flow_pcm_format.sample_rate,
             default_bit_depth=flow_pcm_format.bit_depth,
         )
-        # play it safe: only allow icy metadata for mp3 and aac
-        enable_icy = request.headers.get(
-            "Icy-MetaData", ""
-        ) == "1" and output_format.content_type in (ContentType.MP3, ContentType.AAC)
+        # work out ICY metadata support
+        icy_preference = self.mass.config.get_raw_player_config_value(
+            queue_id, CONF_ENABLE_ICY_METADATA, "basic"
+        )
+        enable_icy = request.headers.get("Icy-MetaData", "") == "1" and icy_preference != "disabled"
         icy_meta_interval = 16384
 
         # prepare request, add some DLNA/UPNP compatible headers
@@ -446,6 +448,8 @@ class StreamsController(CoreController):
             else:
                 title = "Music Assistant"
             metadata = f"StreamTitle='{title}';".encode()
+            if icy_preference == "full" and current_item and current_item.image:
+                metadata += f"StreamURL='{current_item.image.path}'".encode()
             while len(metadata) % 16 != 0:
                 metadata += b"\x00"
             length = len(metadata)
index 9446245e04eed8e37731b9b1b8d532376b080871..94901754f49e5503775fee2a9287bc21d5c8ff38 100644 (file)
@@ -26,6 +26,7 @@ from async_upnp_client.search import async_search
 from music_assistant.common.models.config_entries import (
     CONF_ENTRY_CROSSFADE_DURATION,
     CONF_ENTRY_CROSSFADE_FLOW_MODE_REQUIRED,
+    CONF_ENTRY_ENABLE_ICY_METADATA,
     CONF_ENTRY_ENFORCE_MP3,
     CONF_ENTRY_HTTP_PROFILE,
     ConfigEntry,
@@ -81,6 +82,7 @@ PLAYER_CONFIG_ENTRIES = (
     CONF_ENTRY_CROSSFADE_DURATION,
     CONF_ENTRY_ENFORCE_MP3,
     CONF_ENTRY_HTTP_PROFILE,
+    CONF_ENTRY_ENABLE_ICY_METADATA,
     create_sample_rates_config_entry(192000, 24, 96000, 24),
 )
 
index 713f31cc7e7b2d27e307d1de5c2a9a6aebdd0673..708bb711622ca2f207f3aea3680ac4da68cca377 100644 (file)
@@ -15,6 +15,7 @@ from music_assistant.common.helpers.datetime import from_iso_string
 from music_assistant.common.models.config_entries import (
     CONF_ENTRY_CROSSFADE_DURATION,
     CONF_ENTRY_CROSSFADE_FLOW_MODE_REQUIRED,
+    CONF_ENTRY_ENABLE_ICY_METADATA,
     CONF_ENTRY_ENFORCE_MP3_DEFAULT_ENABLED,
     CONF_ENTRY_FLOW_MODE_DEFAULT_ENABLED,
     CONF_ENTRY_HTTP_PROFILE,
@@ -96,6 +97,7 @@ PLAYER_CONFIG_ENTRIES = (
     CONF_ENTRY_CROSSFADE_DURATION,
     CONF_ENTRY_ENFORCE_MP3_DEFAULT_ENABLED,
     CONF_ENTRY_HTTP_PROFILE,
+    CONF_ENTRY_ENABLE_ICY_METADATA,
 )