Skip to content

Commit

Permalink
Fix some bugs caused by regression (#1446)
Browse files Browse the repository at this point in the history
  • Loading branch information
marcelveldt authored Jul 5, 2024
1 parent 277f185 commit cbfa595
Show file tree
Hide file tree
Showing 9 changed files with 43 additions and 67 deletions.
13 changes: 2 additions & 11 deletions music_assistant/server/controllers/player_queues.py
Original file line number Diff line number Diff line change
Expand Up @@ -660,18 +660,9 @@ async def resume(self, queue_id: str, fade_in: bool | None = None) -> None:
queue = self._queues[queue_id]
queue_items = self._queue_items[queue_id]
resume_item = queue.current_item
next_item = queue.next_item
resume_pos = queue.elapsed_time
if (
resume_item
and next_item
and resume_item.duration
and resume_pos > (resume_item.duration * 0.9)
):
# track is already played for > 90% - skip to next
resume_item = next_item
resume_pos = 0
elif not resume_item and queue.current_index is not None and len(queue_items) > 0:

if not resume_item and queue.current_index is not None and len(queue_items) > 0:
resume_item = self.get_item(queue_id, queue.current_index)
resume_pos = 0
elif not resume_item and queue.current_index is None and len(queue_items) > 0:
Expand Down
2 changes: 1 addition & 1 deletion music_assistant/server/helpers/audio.py
Original file line number Diff line number Diff line change
Expand Up @@ -819,7 +819,7 @@ async def get_ffmpeg_stream(
async def check_audio_support() -> tuple[bool, bool, str]:
"""Check if ffmpeg is present (with/without libsoxr support)."""
# check for FFmpeg presence
returncode, output = await check_output(["ffmpeg", "-version"])
returncode, output = await check_output("ffmpeg", "-version")
ffmpeg_present = returncode == 0 and "FFmpeg" in output.decode()

# use globals as in-memory cache
Expand Down
41 changes: 13 additions & 28 deletions music_assistant/server/helpers/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,42 +257,27 @@ async def wait(self) -> int:
return self._returncode


async def check_output(args: str | list[str]) -> tuple[int, bytes]:
async def check_output(*args: str) -> tuple[int, bytes]:
"""Run subprocess and return returncode and output."""
if isinstance(args, str):
proc = await asyncio.create_subprocess_shell(
args,
stderr=asyncio.subprocess.STDOUT,
stdout=asyncio.subprocess.PIPE,
)
else:
proc = await asyncio.create_subprocess_exec(
*args,
stderr=asyncio.subprocess.STDOUT,
stdout=asyncio.subprocess.PIPE,
)
proc = await asyncio.create_subprocess_exec(
*args,
stderr=asyncio.subprocess.STDOUT,
stdout=asyncio.subprocess.PIPE,
)
stdout, _ = await proc.communicate()
return (proc.returncode, stdout)


async def communicate(
args: str | list[str],
args: list[str],
input: bytes | None = None, # noqa: A002
) -> tuple[int, bytes, bytes]:
"""Communicate with subprocess and return returncode, stdout and stderr output."""
if isinstance(args, str):
proc = await asyncio.create_subprocess_shell(
args,
stderr=asyncio.subprocess.PIPE,
stdout=asyncio.subprocess.PIPE,
stdin=asyncio.subprocess.PIPE if input is not None else None,
)
else:
proc = await asyncio.create_subprocess_exec(
*args,
stderr=asyncio.subprocess.PIPE,
stdout=asyncio.subprocess.PIPE,
stdin=asyncio.subprocess.PIPE if input is not None else None,
)
proc = await asyncio.create_subprocess_exec(
*args,
stderr=asyncio.subprocess.PIPE,
stdout=asyncio.subprocess.PIPE,
stdin=asyncio.subprocess.PIPE if input is not None else None,
)
stdout, stderr = await proc.communicate(input)
return (proc.returncode, stdout, stderr)
2 changes: 1 addition & 1 deletion music_assistant/server/helpers/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ async def install_package(package: str) -> None:
"""Install package with pip, raise when install failed."""
LOGGER.debug("Installing python package %s", package)
args = ["pip", "install", "--find-links", HA_WHEELS, package]
return_code, output = await check_output(args)
return_code, output = await check_output(*args)

if return_code != 0:
msg = f"Failed to install package {package}\n{output.decode()}"
Expand Down
3 changes: 2 additions & 1 deletion music_assistant/server/providers/airplay/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -818,7 +818,8 @@ async def _getcliraop_binary(self):
async def check_binary(cliraop_path: str) -> str | None:
try:
returncode, output = await check_output(
[cliraop_path, "-check"],
cliraop_path,
"-check",
)
if returncode == 0 and output.strip().decode() == "cliraop check":
self.cliraop_bin = cliraop_path
Expand Down
4 changes: 2 additions & 2 deletions music_assistant/server/providers/filesystem_smb/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,13 +225,13 @@ async def mount(self) -> None:
[m.replace(password, "########") if password else m for m in mount_cmd],
)

returncode, output = await check_output(mount_cmd)
returncode, output = await check_output(*mount_cmd)
if returncode != 0:
msg = f"SMB mount failed with error: {output.decode()}"
raise LoginFailed(msg)

async def unmount(self, ignore_error: bool = False) -> None:
"""Unmount the remote share."""
returncode, output = await check_output(["umount", self.base_path])
returncode, output = await check_output("umount", self.base_path)
if returncode != 0 and not ignore_error:
self.logger.warning("SMB unmount failed with error: %s", output.decode())
37 changes: 18 additions & 19 deletions music_assistant/server/providers/radiobrowser/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,14 @@ async def search(

return result

@use_cache(86400 * 7)
async def browse(self, path: str, offset: int, limit: int) -> list[MediaItemType]:
"""Browse this provider's items.
:param path: The path to browse, (e.g. provid://artists).
"""
if offset != 0:
# paging is broken on RadioBrowser, we just return some big lists
return []
subpath = path.split("://", 1)[1]
subsubpath = "" if "/" not in subpath else subpath.split("/")[-1]

Expand Down Expand Up @@ -138,13 +140,11 @@ async def browse(self, path: str, offset: int, limit: int) -> list[MediaItemType
]

if subpath == "popular":
return await self.get_by_popularity(limit=limit, offset=offset)
return await self.get_by_popularity()

if subpath == "tag":
tags = await self.radios.tags(
hide_broken=True,
limit=limit,
offset=offset,
order=Order.STATION_COUNT,
reverse=True,
)
Expand All @@ -161,9 +161,7 @@ async def browse(self, path: str, offset: int, limit: int) -> list[MediaItemType

if subpath == "country":
items: list[BrowseFolder | Radio] = []
for country in await self.radios.countries(
order=Order.NAME, hide_broken=True, limit=limit, offset=offset
):
for country in await self.radios.countries(order=Order.NAME, hide_broken=True):
folder = BrowseFolder(
item_id=country.code.lower(),
provider=self.domain,
Expand All @@ -181,19 +179,19 @@ async def browse(self, path: str, offset: int, limit: int) -> list[MediaItemType
items.append(folder)
return items

if subsubpath in await self.get_tag_names(limit=limit, offset=offset):
if subsubpath in await self.get_tag_names():
return await self.get_by_tag(subsubpath)

if subsubpath in await self.get_country_codes(limit=limit, offset=offset):
if subsubpath in await self.get_country_codes():
return await self.get_by_country(subsubpath)
return []

async def get_tag_names(self, limit: int, offset: int):
@use_cache(3600 * 24)
async def get_tag_names(self):
"""Get a list of tag names."""
tags = await self.radios.tags(
hide_broken=True,
limit=limit,
offset=offset,
limit=10000,
order=Order.STATION_COUNT,
reverse=True,
)
Expand All @@ -203,22 +201,21 @@ async def get_tag_names(self, limit: int, offset: int):
tag_names.append(tag.name.lower())
return tag_names

async def get_country_codes(self, limit: int, offset: int):
@use_cache(3600 * 24)
async def get_country_codes(self):
"""Get a list of country names."""
countries = await self.radios.countries(
order=Order.NAME, hide_broken=True, limit=limit, offset=offset
)
countries = await self.radios.countries(order=Order.NAME, hide_broken=True)
country_codes = []
for country in countries:
country_codes.append(country.code.lower())
return country_codes

async def get_by_popularity(self, limit: int, offset: int):
@use_cache(3600)
async def get_by_popularity(self):
"""Get radio stations by popularity."""
stations = await self.radios.stations(
hide_broken=True,
limit=limit,
offset=offset,
limit=5000,
order=Order.CLICK_COUNT,
reverse=True,
)
Expand All @@ -227,6 +224,7 @@ async def get_by_popularity(self, limit: int, offset: int):
items.append(await self._parse_radio(station))
return items

@use_cache(3600)
async def get_by_tag(self, tag: str):
"""Get radio stations by tag."""
items = []
Expand All @@ -241,6 +239,7 @@ async def get_by_tag(self, tag: str):
items.append(await self._parse_radio(station))
return items

@use_cache(3600)
async def get_by_country(self, country_code: str):
"""Get radio stations by country."""
items = []
Expand Down
2 changes: 1 addition & 1 deletion music_assistant/server/providers/snapcast/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ async def get_config_entries(
action: [optional] action key called from config entries UI.
values: the (intermediate) raw values for config entries sent with the action.
"""
returncode, output = await check_output(["snapserver", "-v"])
returncode, output = await check_output("snapserver", "-v")
snapserver_version = int(output.decode().split(".")[1]) if returncode == 0 else -1
local_snapserver_present = snapserver_version >= 27
if returncode == 0 and not local_snapserver_present:
Expand Down
6 changes: 3 additions & 3 deletions music_assistant/server/providers/spotify/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -696,7 +696,7 @@ async def _get_token(self):
]
if self._ap_workaround:
args += ["--ap-port", "12345"]
_returncode, output = await check_output(args)
_returncode, output = await check_output(*args)
if _returncode == 0 and output.decode().strip() != "authorized":
raise LoginFailed(f"Login failed for username {self.config.get_value(CONF_USERNAME)}")
# get token with (authorized) librespot
Expand Down Expand Up @@ -731,7 +731,7 @@ async def _get_token(self):
]
if self._ap_workaround:
args += ["--ap-port", "12345"]
_returncode, output = await check_output(args)
_returncode, output = await check_output(*args)
duration = round(time.time() - time_start, 2)
try:
result = json.loads(output)
Expand Down Expand Up @@ -873,7 +873,7 @@ async def get_librespot_binary(self):

async def check_librespot(librespot_path: str) -> str | None:
try:
returncode, output = await check_output([librespot_path, "--check"])
returncode, output = await check_output(librespot_path, "--check")
if returncode == 0 and b"ok spotty" in output and b"using librespot" in output:
self._librespot_bin = librespot_path
return librespot_path
Expand Down

0 comments on commit cbfa595

Please sign in to comment.