import argparse
import logging
import os
+import platform
+import webbrowser
from aiorun import run
from music_assistant.mass import MusicAssistant
mass = MusicAssistant(data_dir)
# run UI in browser on windows and macos only
- # if platform.system() in ["Windows", "Darwin"]:
- # import webbrowser
- # webbrowser.open(f"http://localhost:{mass.web.http_port}")
+ if platform.system() in ["Windows", "Darwin"]:
+ webbrowser.open(mass.web.internal_url)
def on_shutdown(loop):
logger.info("shutdown requested!")
loop.run_until_complete(mass.async_stop())
- run(mass.async_start(), use_uvloop=True, shutdown_callback=on_shutdown)
+ run(
+ mass.async_start(),
+ use_uvloop=True,
+ shutdown_callback=on_shutdown,
+ executor_workers=32,
+ )
if __name__ == "__main__":
for key, value in external_ids.items():
sql_query = """INSERT or REPLACE INTO external_ids
(item_id, media_type, key, value) VALUES(?,?,?,?);"""
- await db_conn.execute(sql_query, (item_id, int(media_type), key, value))
+ await db_conn.execute(
+ sql_query, (item_id, int(media_type), str(key), value)
+ )
async def __async_get_external_ids(
self, item_id: int, media_type: MediaType, db_conn: sqlite3.Connection
sql_query = "SELECT (item_id) FROM external_ids \
WHERE media_type=? AND key=? AND value=?;"
for db_row in await db_conn.execute_fetchall(
- sql_query, (int(media_item.media_type), key, value)
+ sql_query, (int(media_item.media_type), str(key), value)
):
if db_row:
return db_row[0]
import urllib
from contextlib import suppress
+import aiohttp
import pyloudnorm
import soundfile
from aiohttp import web
# let the streaming begin!
try:
await asyncio.gather(bg_task)
- except (asyncio.CancelledError, asyncio.TimeoutError) as exc:
+ except (
+ asyncio.CancelledError,
+ aiohttp.ClientConnectionError,
+ asyncio.TimeoutError,
+ ) as exc:
cancelled.set()
raise exc # re-raise
return resp
# let the streaming begin!
try:
await asyncio.gather(bg_task)
- except (asyncio.CancelledError, asyncio.TimeoutError) as exc:
+ except (
+ asyncio.CancelledError,
+ aiohttp.ClientConnectionError,
+ asyncio.TimeoutError,
+ ) as exc:
cancelled.set()
raise exc # re-raise
return resp
gain_correct = round(gain_correct, 2)
LOGGER.debug(
"Loudness level for track %s/%s is %s - calculated replayGain is %s",
- id,
+ provider_id,
item_id,
track_loudness,
gain_correct,
pychromecast.stop_discovery(self._browser)
# stop cast socket clients
for player in self._players.values():
- await player.async_disconnect()
+ player.disconnect()
async def async_cmd_play_uri(self, player_id: str, uri: str):
"""
chromecast.mz_controller = mz_controller
self._chromecast.start()
- async def async_disconnect(self):
+ def disconnect(self):
"""Disconnect Chromecast object if it is set."""
if self._chromecast is None:
return
"[%s] Disconnecting from chromecast socket", self._cast_info.friendly_name
)
self._available = False
- self.mass.add_job(self._chromecast.disconnect)
+ self._chromecast.disconnect()
self._invalidate()
def _invalidate(self):
return tempfile.NamedTemporaryFile(buffering=0)
-class CustomIntEnum(Enum):
+class CustomIntEnum(int, Enum):
"""Base for IntEnum with some helpers."""
# when serializing we prefer the string (name) representation