Skip to content

Commit

Permalink
Fix Airplay binary detection
Browse files Browse the repository at this point in the history
  • Loading branch information
marcelveldt committed Jan 10, 2025
1 parent 2a5f200 commit fcf3390
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 35 deletions.
31 changes: 31 additions & 0 deletions music_assistant/providers/airplay/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@

from __future__ import annotations

import os
import platform
from typing import TYPE_CHECKING

from zeroconf import IPVersion

from music_assistant.helpers.process import check_output
from music_assistant.providers.airplay.const import BROKEN_RAOP_MODELS

if TYPE_CHECKING:
Expand Down Expand Up @@ -84,3 +87,31 @@ def is_broken_raop_model(manufacturer: str, model: str) -> bool:
if broken_manufacturer in (manufacturer, "*") and broken_model in (model, "*"):
return True
return False


async def get_cliraop_binary() -> str:
"""Find the correct raop/airplay binary belonging to the platform."""

async def check_binary(cliraop_path: str) -> str | None:
try:
returncode, output = await check_output(
cliraop_path,
"-check",
)
if returncode == 0 and output.strip().decode() == "cliraop check":
return cliraop_path
except OSError:
pass
return None

base_path = os.path.join(os.path.dirname(__file__), "bin")
system = platform.system().lower().replace("darwin", "macos")
architecture = platform.machine().lower()

if bridge_binary := await check_binary(
os.path.join(base_path, f"cliraop-{system}-{architecture}")
):
return bridge_binary

msg = f"Unable to locate RAOP Play binary for {system}/{architecture}"
raise RuntimeError(msg)
37 changes: 2 additions & 35 deletions music_assistant/providers/airplay/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
from __future__ import annotations

import asyncio
import os
import platform
import socket
import time
from random import randrange
Expand Down Expand Up @@ -38,7 +36,6 @@
)
from music_assistant.helpers.datetime import utc
from music_assistant.helpers.ffmpeg import get_ffmpeg_stream
from music_assistant.helpers.process import check_output
from music_assistant.helpers.util import TaskManager, get_ip_pton, lock, select_free_port
from music_assistant.models.player_provider import PlayerProvider
from music_assistant.providers.airplay.raop import RaopStreamSession
Expand All @@ -56,6 +53,7 @@
)
from .helpers import (
convert_airplay_volume,
get_cliraop_binary,
get_model_info,
get_primary_ip_address,
is_broken_raop_model,
Expand Down Expand Up @@ -148,7 +146,7 @@ def supported_features(self) -> set[ProviderFeature]:
async def handle_async_init(self) -> None:
"""Handle async initialization of the provider."""
self._players = {}
self.cliraop_bin = await self._getcliraop_binary()
self.cliraop_bin: str | None = await get_cliraop_binary()
dacp_port = await select_free_port(39831, 49831)
self.dacp_id = dacp_id = f"{randrange(2 ** 64):X}"
self.logger.debug("Starting DACP ActiveRemote %s on port %s", dacp_id, dacp_port)
Expand Down Expand Up @@ -429,37 +427,6 @@ async def cmd_ungroup(self, player_id: str) -> None:
self.mass.players.update(mass_player.player_id, skip_forward=True)
self.mass.players.update(group_leader.player_id, skip_forward=True)

async def _getcliraop_binary(self) -> str:
"""Find the correct raop/airplay binary belonging to the platform."""
# ruff: noqa: SIM102
if self.cliraop_bin is not None:
return self.cliraop_bin

async def check_binary(cliraop_path: str) -> str | None:
try:
returncode, output = await check_output(
cliraop_path,
"-check",
)
if returncode == 0 and output.strip().decode() == "cliraop check":
self.cliraop_bin = cliraop_path
return cliraop_path
except OSError:
pass
return None

base_path = os.path.join(os.path.dirname(__file__), "bin")
system = platform.system().lower().replace("darwin", "macos")
architecture = platform.machine().lower()

if bridge_binary := await check_binary(
os.path.join(base_path, f"cliraop-{system}-{architecture}")
):
return bridge_binary

msg = f"Unable to locate RAOP Play binary for {system}/{architecture}"
raise RuntimeError(msg)

def _get_sync_clients(self, player_id: str) -> list[AirPlayPlayer]:
"""Get all sync clients for a player."""
mass_player = self.mass.players.get(player_id, True)
Expand Down

0 comments on commit fcf3390

Please sign in to comment.