Fix AirPlay branding (#2127)
authorLasse Bang Mikkelsen <lbm@lbm.dk>
Tue, 15 Apr 2025 11:32:53 +0000 (13:32 +0200)
committerGitHub <noreply@github.com>
Tue, 15 Apr 2025 11:32:53 +0000 (13:32 +0200)
The correct Apple branding is "AirPlay". Also fixed "macOS" a few places.

14 files changed:
DEVELOPMENT.md
music_assistant/providers/_template_music_provider/__init__.py
music_assistant/providers/_template_player_provider/__init__.py
music_assistant/providers/_template_plugin_provider/__init__.py
music_assistant/providers/airplay/__init__.py
music_assistant/providers/airplay/helpers.py
music_assistant/providers/airplay/manifest.json
music_assistant/providers/airplay/player.py
music_assistant/providers/airplay/provider.py
music_assistant/providers/airplay/raop.py
music_assistant/providers/filesystem_smb/__init__.py
music_assistant/providers/sonos/const.py
music_assistant/providers/sonos/provider.py
pyproject.toml

index ec29152e8d07910a3a1623bd95d81b21f3822c24..c5e65c9f45d2eb7f91cd376cbee1c6a93f3b50b8 100644 (file)
@@ -6,7 +6,7 @@ Developer docs
 * Python 3.12 is minimal required, 3.12 recommended (or check the pyproject for current required version)
 * [Python venv](https://docs.python.org/3/library/venv.html)
 
-We recommend developing on a (recent) MacOS or Linux machine.
+We recommend developing on a (recent) macOS or Linux machine.
 It is recommended to use Visual Studio Code as your IDE, since launch files to start Music Assistant are provided as part of the repository. Furthermore, the current code base is not verified to work on a native Windows machine. If you would like to develop on a Windows machine, install [WSL2](https://code.visualstudio.com/blogs/2019/09/03/wsl2) to increase your swag-level 🤘.
 
 ## 🚀 Setting up your development environment
@@ -25,7 +25,7 @@ NOTE: Always re-run the setup script after you fetch the latest code because req
 ### Using Devcontainer/Codespace
 We removed support for devcontainers because we do not have anyone willing to maintain it.
 It also is not very convenient due to all the port requirements, binaries etc.
-If somebody is willing to create and maintain a devcontainer with host networking and based on our base alpine image, we will add the support back. Until then: Develop with Python venv on a Linux or MacOS machine (see above).
+If somebody is willing to create and maintain a devcontainer with host networking and based on our base alpine image, we will add the support back. Until then: Develop with Python venv on a Linux or macOS machine (see above).
 
 ## Note on async Python
 The Music Assistant server is fully built in Python. The Python language has no real supported for multi-threading. This is why Music Assistant heavily relies on asyncio to handle blocking IO. It is important to get a good understanding of asynchronous programming before building your first provider. [This](https://www.youtube.com/watch?v=M-UcUs7IMIM) video is an excellent first step in the world of asyncio.
@@ -65,7 +65,7 @@ Create a file called `__init__.py` inside the folder of your provider. This file
 
 
 ## ▶️ Building your own Player Provider
-A Player Provider is the provider type that adds support for a 'target of playback' to Music Assistant. Sonos, Chromecast and Airplay are examples of a Player Provider.
+A Player Provider is the provider type that adds support for a 'target of playback' to Music Assistant. Sonos, Chromecast and AirPlay are examples of a Player Provider.
 All Providers (of all types) can be found in the `music_assistant/providers` folder.
 
 TIP: We have created a template/stub provider in `music_assistant/providers/_template_player_provider` to get you started fast!
index e00cde9d647750c2e8ef500d51af24fb8d133dfc..adfbe52e17fd7fd0393652590a2b72ad29771bbe 100644 (file)
@@ -28,7 +28,7 @@ Optional is an icon.svg file that will be used as the icon for the provider in t
 but we also support that you specify a material design icon in the manifest.json file.
 
 IMPORTANT NOTE:
-We strongly recommend developing on either MacOS or Linux and start your development
+We strongly recommend developing on either macOS or Linux and start your development
 environment by running the setup.sh script in the scripts folder of the repository.
 This will create a virtual environment and install all dependencies needed for development.
 See also our general DEVELOPMENT.md guide in the repository for more information.
index d6b8cc849b2cc9e3d63798bba2b28377e4fd5626..a2c37b05f800e5f54a4d220dfd6879323c7f0192 100644 (file)
@@ -22,7 +22,7 @@ Optional is an icon.svg file that will be used as the icon for the provider in t
 but we also support that you specify a material design icon in the manifest.json file.
 
 IMPORTANT NOTE:
-We strongly recommend developing on either MacOS or Linux and start your development
+We strongly recommend developing on either macOS or Linux and start your development
 environment by running the setup.sh scripts in the scripts folder of the repository.
 This will create a virtual environment and install all dependencies needed for development.
 See also our general DEVELOPMENT.md guide in the repository for more information.
@@ -323,7 +323,7 @@ class MyDemoPlayerprovider(PlayerProvider):
         # all songs in the playback queue into a single stream and send that to the player.
         # In that case the URI (and metadata) received here is that of the 'flow mode' stream.
 
-        # Examples of player providers that use flow mode for playback by default are Airplay,
+        # Examples of player providers that use flow mode for playback by default are AirPlay,
         # SnapCast and Fully Kiosk.
 
         # Examples of player providers that optionally use 'flow mode' are Google Cast and
index fbed240056b8c48b05ad90b7121f694ff49997be..27d9f67075117528b25325e395c5e0d44cc5ca3d 100644 (file)
@@ -25,7 +25,7 @@ Optional is an icon.svg file that will be used as the icon for the provider in t
 but we also support that you specify a material design icon in the manifest.json file.
 
 IMPORTANT NOTE:
-We strongly recommend developing on either MacOS or Linux and start your development
+We strongly recommend developing on either macOS or Linux and start your development
 environment by running the setup.sh scripts in the scripts folder of the repository.
 This will create a virtual environment and install all dependencies needed for development.
 See also our general DEVELOPMENT.md guide in the repository for more information.
index 752d21465cdac5fe9a5444e819701e3fd038fd23..ad7dfce16c926b6bb3d9ac8c16ae01f51f5676b0 100644 (file)
@@ -1,4 +1,4 @@
-"""Airplay Player provider for Music Assistant."""
+"""AirPlay Player provider for Music Assistant."""
 
 from __future__ import annotations
 
@@ -11,7 +11,7 @@ from music_assistant_models.provider import ProviderManifest
 from music_assistant.mass import MusicAssistant
 
 from .const import CONF_BIND_INTERFACE
-from .provider import AirplayProvider
+from .provider import AirPlayProvider
 
 if TYPE_CHECKING:
     from music_assistant_models.config_entries import ProviderConfig
@@ -40,7 +40,7 @@ async def get_config_entries(
             type=ConfigEntryType.STRING,
             default_value=cast("str", mass.streams.publish_ip),
             label="Bind interface",
-            description="Interface to bind to for Airplay streaming.",
+            description="Interface to bind to for AirPlay streaming.",
             category="advanced",
         ),
     )
@@ -50,4 +50,4 @@ async def setup(
     mass: MusicAssistant, manifest: ProviderManifest, config: ProviderConfig
 ) -> ProviderInstanceType:
     """Initialize provider(instance) with given configuration."""
-    return AirplayProvider(mass, manifest, config)
+    return AirPlayProvider(mass, manifest, config)
index 693cbe502a3f6432ad22e3c0d1032f9685a88d3b..f7f47f9cbf3678c5525e7927daf3013e85c45a81 100644 (file)
@@ -1,4 +1,4 @@
-"""Various helpers/utilities for the Airplay provider."""
+"""Various helpers/utilities for the AirPlay provider."""
 
 from __future__ import annotations
 
@@ -16,7 +16,7 @@ if TYPE_CHECKING:
 
 
 def convert_airplay_volume(value: float) -> int:
-    """Remap Airplay Volume to 0..100 scale."""
+    """Remap AirPlay Volume to 0..100 scale."""
     airplay_min = -30
     airplay_max = 0
     normal_min = 0
@@ -65,7 +65,7 @@ def get_model_info(info: AsyncServiceInfo) -> tuple[str, str]:
         model = "Apple TV"
         manufacturer = "Apple"
 
-    return (manufacturer or "Airplay", model)
+    return (manufacturer or "AirPlay", model)
 
 
 def get_primary_ip_address(discovery_info: AsyncServiceInfo) -> str | None:
index f465e59d266d2b7223597593f82ae6723b135b04..c67cd3ebd0db006869a81a2bf00023805f61fcb1 100644 (file)
@@ -1,8 +1,8 @@
 {
   "type": "player",
   "domain": "airplay",
-  "name": "Airplay",
-  "description": "Support for players that support the Airplay protocol.",
+  "name": "AirPlay",
+  "description": "Support for players that support the AirPlay protocol.",
   "codeowners": ["@music-assistant"],
   "requirements": [],
   "documentation": "https://music-assistant.io/player-support/airplay/",
index d13f7d72041bb39311ec45a8ed9dd6e574319ee6..84ea4ef1a36273f6aa2fbf2d177091cb3f7993a6 100644 (file)
@@ -10,15 +10,15 @@ from music_assistant_models.enums import PlayerState
 if TYPE_CHECKING:
     from zeroconf.asyncio import AsyncServiceInfo
 
-    from .provider import AirplayProvider
+    from .provider import AirPlayProvider
     from .raop import RaopStream
 
 
 class AirPlayPlayer:
-    """Holds the details of the (discovered) Airplay (RAOP) player."""
+    """Holds the details of the (discovered) AirPlay (RAOP) player."""
 
     def __init__(
-        self, prov: AirplayProvider, player_id: str, discovery_info: AsyncServiceInfo, address: str
+        self, prov: AirPlayProvider, player_id: str, discovery_info: AsyncServiceInfo, address: str
     ) -> None:
         """Initialize AirPlayPlayer."""
         self.prov = prov
index e514398fa4bcb2339ee319667ff306a25dcef69b..33d7011ea863ea1604fe95927c452e36a894a738 100644 (file)
@@ -1,4 +1,4 @@
-"""Airplay Player provider for Music Assistant."""
+"""AirPlay Player provider for Music Assistant."""
 
 from __future__ import annotations
 
@@ -116,7 +116,7 @@ PLAYER_CONFIG_ENTRIES = (
         type=ConfigEntryType.BOOLEAN,
         default_value=False,
         label="Ignore volume reports sent by the device itself",
-        description="The Airplay protocol allows devices to report their own volume level. \n"
+        description="The AirPlay protocol allows devices to report their own volume level. \n"
         "For some devices this is not reliable and can cause unexpected volume changes. \n"
         "Enable this option to ignore these reports.",
         category="airplay",
@@ -128,22 +128,22 @@ BROKEN_RAOP_WARN = ConfigEntry(
     type=ConfigEntryType.ALERT,
     default_value=None,
     required=False,
-    label="This player is known to have broken Airplay 1 (RAOP) support. "
+    label="This player is known to have broken AirPlay 1 (RAOP) support. "
     "Playback may fail or simply be silent. There is no workaround for this issue at the moment.",
 )
 
 
-# TODO: Airplay provider
+# TODO: AirPlay provider
 # - Implement authentication for Apple TV
 # - Implement volume control for Apple devices using pyatv
 # - Implement metadata for Apple Apple devices using pyatv
 # - Use pyatv for communicating with original Apple devices (and use cliraop for actual streaming)
-# - Implement Airplay 2 support
+# - Implement AirPlay 2 support
 # - Implement late joining to existing stream (instead of restarting it)
 
 
-class AirplayProvider(PlayerProvider):
-    """Player provider for Airplay based players."""
+class AirPlayProvider(PlayerProvider):
+    """Player provider for AirPlay based players."""
 
     cliraop_bin: str | None
     _players: dict[str, AirPlayPlayer]
@@ -478,7 +478,7 @@ class AirplayProvider(PlayerProvider):
         address = get_primary_ip_address(info)
         if address is None:
             return
-        self.logger.debug("Discovered Airplay device %s on %s", display_name, address)
+        self.logger.debug("Discovered AirPlay device %s on %s", display_name, address)
 
         # prefer airplay mdns info as it has more details
         # fallback to raop info if airplay info is not available
@@ -506,7 +506,7 @@ class AirplayProvider(PlayerProvider):
         # append airplay to the default display name for generic (non-apple) devices
         # this makes it easier for users to distinguish between airplay and non-airplay devices
         if manufacturer.lower() != "apple" and "airplay" not in display_name.lower():
-            display_name += " (Airplay)"
+            display_name += " (AirPlay)"
 
         self._players[player_id] = AirPlayPlayer(self, player_id, info, address)
         if not (volume := await self.mass.cache.get(player_id, base_key=CACHE_KEY_PREV_VOLUME)):
index 93151f2ba85adc72ea13e4262912f44fc2a34b1f..ad18e568e2f85fc22ad34298bc99c016eb6ebdab 100644 (file)
@@ -1,4 +1,4 @@
-"""Logic for RAOP (AirPlay 1) audio streaming to Airplay devices."""
+"""Logic for RAOP (AirPlay 1) audio streaming to AirPlay devices."""
 
 from __future__ import annotations
 
@@ -35,7 +35,7 @@ if TYPE_CHECKING:
     from music_assistant_models.player_queue import PlayerQueue
 
     from .player import AirPlayPlayer
-    from .provider import AirplayProvider
+    from .provider import AirPlayProvider
 
 
 class RaopStreamSession:
@@ -43,7 +43,7 @@ class RaopStreamSession:
 
     def __init__(
         self,
-        airplay_provider: AirplayProvider,
+        airplay_provider: AirPlayProvider,
         sync_clients: list[AirPlayPlayer],
         input_format: AudioFormat,
         audio_source: AsyncGenerator[bytes, None],
@@ -169,7 +169,7 @@ class RaopStreamSession:
 
 class RaopStream:
     """
-    RAOP (Airplay 1) Audio Streamer.
+    RAOP (AirPlay 1) Audio Streamer.
 
     Python is not suitable for realtime audio streaming so we do the actual streaming
     of (RAOP) audio using a small executable written in C based on libraop to do
index 606582c0f7810583102df328514e49fdcbd0b54b..130aeb6b744531c16c64998303db27b0ae9ed5ee 100644 (file)
@@ -199,7 +199,7 @@ class SMBFileSystemProvider(LocalFileSystemProvider):
         }
 
         if platform.system() == "Darwin":
-            # NOTE: MacOS does not support special characters in the username/password
+            # NOTE: macOS does not support special characters in the username/password
             password_str = f":{password}" if password else ""
             mount_cmd = [
                 "mount",
index cd8afb3b64efc8d9b1c3b5ca16a556b700928a02..fd3e91bb02dad047d1d0735695356556ce5e9153 100644 (file)
@@ -52,7 +52,7 @@ PLAYER_SOURCE_MAP = {
     ),
     SOURCE_AIRPLAY: PlayerSource(
         id=SOURCE_AIRPLAY,
-        name="Airplay",
+        name="AirPlay",
         passive=True,
         can_play_pause=True,
         can_next_previous=True,
index e7cf32511986af2a74be0571c8d162b14a875a3c..1e056d05704e73addb356421db1fe76db73a342b 100644 (file)
@@ -173,17 +173,17 @@ class SonosPlayerProvider(PlayerProvider):
             ConfigEntry(
                 key=CONF_AIRPLAY_MODE,
                 type=ConfigEntryType.BOOLEAN,
-                label="Enable Airplay mode",
-                description="Almost all newer Sonos speakers have Airplay support. "
-                "If you have the Airplay provider enabled in Music Assistant, "
-                "your Sonos speaker will also be detected as a Airplay speaker, meaning "
-                "you can group them with other Airplay speakers.\n\n"
+                label="Enable AirPlay mode",
+                description="Almost all newer Sonos speakers have AirPlay support. "
+                "If you have the AirPlay provider enabled in Music Assistant, "
+                "your Sonos speaker will also be detected as a AirPlay speaker, meaning "
+                "you can group them with other AirPlay speakers.\n\n"
                 "By default, Music Assistant uses the Sonos protocol for playback but with this "
-                "feature enabled, it will use the Airplay protocol instead by redirecting "
-                "the playback related commands to the linked Airplay player in Music Assistant, "
-                "allowing you to mix and match Sonos speakers with Airplay speakers. \n\n"
-                "NOTE: You need to have the Airplay provider enabled as well as "
-                "the Airplay version of this player.",
+                "feature enabled, it will use the AirPlay protocol instead by redirecting "
+                "the playback related commands to the linked AirPlay player in Music Assistant, "
+                "allowing you to mix and match Sonos speakers with AirPlay speakers. \n\n"
+                "NOTE: You need to have the AirPlay provider enabled as well as "
+                "the AirPlay version of this player.",
                 required=False,
                 default_value=False,
                 depends_on="airplay_detected",
@@ -256,7 +256,7 @@ class SonosPlayerProvider(PlayerProvider):
         sonos_player = self.sonos_players[target_player]
         if airplay_player := sonos_player.get_linked_airplay_player(False):
             # if airplay mode is enabled, we could possibly receive child player id's that are
-            # not Sonos players, but Airplay players. We redirect those.
+            # not Sonos players, but AirPlay players. We redirect those.
             airplay_child_ids = [x for x in child_player_ids if x.startswith("ap")]
             child_player_ids = [x for x in child_player_ids if x not in airplay_child_ids]
             if airplay_child_ids:
index bb399f8e885614d9caae80aadcda157d7ed1f39f..3cd71b2f0a049a9be81af1793ef8b4a200291c7f 100644 (file)
@@ -162,7 +162,7 @@ warn_unused_configs = true
 warn_unused_ignores = true
 
 [tool.ruff.format]
-# Force Linux/MacOS line endings
+# Force Linux/macOS line endings
 line-ending = "lf"
 
 [tool.pytest.ini_options]