# also fetch same album on all providers
await self._match(db_item)
db_item = await self.get_db_item(db_item.item_id)
- self.mass.signal_event(
- MassEvent(EventType.ALBUM_ADDED, object_id=db_item.uri, data=db_item)
- )
return db_item
async def get_provider_album_tracks(
item_id = new_item["item_id"]
self.logger.debug("added %s to database", album.name)
# return created object
- return await self.get_db_item(item_id, db=db)
+ db_item = await self.get_db_item(item_id, db=db)
+ self.mass.signal_event(
+ MassEvent(
+ EventType.MEDIA_ITEM_ADDED, object_id=db_item.uri, data=db_item
+ )
+ )
+ return db_item
async def update_db_item(
self,
db=db,
)
self.logger.debug("updated %s in database: %s", album.name, item_id)
- return await self.get_db_item(item_id, db=db)
+ db_item = await self.get_db_item(item_id, db=db)
+ self.mass.signal_event(
+ MassEvent(
+ EventType.MEDIA_ITEM_UPDATED, object_id=db_item.uri, data=db_item
+ )
+ )
+ return db_item
async def _match(self, db_album: Album) -> None:
"""
# also fetch same artist on all providers
await self.match_artist(db_item)
db_item = await self.get_db_item(db_item.item_id)
- self.mass.signal_event(
- MassEvent(EventType.ARTIST_ADDED, object_id=db_item.uri, data=db_item)
- )
return db_item
async def match_artist(self, db_artist: Artist):
item_id = new_item["item_id"]
self.logger.debug("added %s to database", artist.name)
# return created object
- return await self.get_db_item(item_id, db=db)
+ db_item = await self.get_db_item(item_id, db=db)
+ self.mass.signal_event(
+ MassEvent(
+ EventType.MEDIA_ITEM_ADDED, object_id=db_item.uri, data=db_item
+ )
+ )
+ return db_item
async def update_db_item(
self,
db=db,
)
self.logger.debug("updated %s in database: %s", artist.name, item_id)
- return await self.get_db_item(item_id, db=db)
+ db_item = await self.get_db_item(item_id, db=db)
+ self.mass.signal_event(
+ MassEvent(
+ EventType.MEDIA_ITEM_UPDATED, object_id=db_item.uri, data=db_item
+ )
+ )
+ return db_item
async def _match(self, db_artist: Artist, provider: MusicProvider) -> bool:
"""Try to find matching artists on given provider for the provided (database) artist."""
"""Add playlist to local db and return the new database item."""
item.metadata.last_refresh = int(time())
await self.mass.metadata.get_playlist_metadata(item)
- db_item = await self.add_db_item(item)
- self.mass.signal_event(
- MassEvent(EventType.PLAYLIST_ADDED, object_id=db_item.uri, data=db_item)
- )
- return db_item
+ return await self.add_db_item(item)
async def add_playlist_tracks(self, db_playlist_id: str, uris: List[str]) -> None:
"""Add multiple tracks to playlist. Creates background tasks to process the action."""
# update local db entry
self.mass.signal_event(
MassEvent(
- type=EventType.PLAYLIST_UPDATED, object_id=db_playlist_id, data=playlist
+ type=EventType.MEDIA_ITEM_UPDATED,
+ object_id=db_playlist_id,
+ data=playlist,
)
)
await provider.remove_playlist_tracks(prov.item_id, track_ids_to_remove)
self.mass.signal_event(
MassEvent(
- type=EventType.PLAYLIST_UPDATED, object_id=db_playlist_id, data=playlist
+ type=EventType.MEDIA_ITEM_UPDATED,
+ object_id=db_playlist_id,
+ data=playlist,
)
)
item_id = new_item["item_id"]
self.logger.debug("added %s to database", playlist.name)
# return created object
- return await self.get_db_item(item_id, db=db)
+ db_item = await self.get_db_item(item_id, db=db)
+ self.mass.signal_event(
+ MassEvent(
+ EventType.MEDIA_ITEM_ADDED, object_id=db_item.uri, data=db_item
+ )
+ )
+ return db_item
async def update_db_item(
self,
db_item = await self.get_db_item(item_id, db=db)
self.mass.signal_event(
MassEvent(
- type=EventType.PLAYLIST_UPDATED, object_id=item_id, data=playlist
+ EventType.MEDIA_ITEM_UPDATED, object_id=db_item.uri, data=db_item
)
)
return db_item
"""Add radio to local db and return the new database item."""
item.metadata.last_refresh = int(time())
await self.mass.metadata.get_radio_metadata(item)
- db_item = await self.add_db_item(item)
- self.mass.signal_event(
- MassEvent(EventType.RADIO_ADDED, object_id=db_item.uri, data=db_item)
- )
- return db_item
+ return await self.add_db_item(item)
async def add_db_item(self, radio: Radio, db: Optional[Db] = None) -> Radio:
"""Add a new radio record to the database."""
item_id = new_item["item_id"]
self.logger.debug("added %s to database", radio.name)
# return created object
- return await self.get_db_item(item_id, db=db)
+ db_item = await self.get_db_item(item_id, db=db)
+ self.mass.signal_event(
+ MassEvent(
+ EventType.MEDIA_ITEM_ADDED, object_id=db_item.uri, data=db_item
+ )
+ )
+ return db_item
async def update_db_item(
self,
db=db,
)
self.logger.debug("updated %s in database: %s", radio.name, item_id)
- return await self.get_db_item(item_id, db=db)
+ db_item = await self.get_db_item(item_id, db=db)
+ self.mass.signal_event(
+ MassEvent(
+ EventType.MEDIA_ITEM_UPDATED, object_id=db_item.uri, data=db_item
+ )
+ )
+ return db_item
db_item = await self.add_db_item(item)
# also fetch same track on all providers (will also get other quality versions)
await self._match(db_item)
- db_item = await self.get_db_item(db_item.item_id)
- self.mass.signal_event(
- MassEvent(EventType.TRACK_ADDED, object_id=db_item.uri, data=db_item)
- )
- return db_item
+ return await self.get_db_item(db_item.item_id)
async def versions(
self,
item_id = new_item["item_id"]
# return created object
self.logger.debug("added %s to database: %s", track.name, item_id)
- return await self.get_db_item(item_id, db=db)
+ db_item = await self.get_db_item(item_id, db=db)
+ self.mass.signal_event(
+ MassEvent(
+ EventType.MEDIA_ITEM_ADDED, object_id=db_item.uri, data=db_item
+ )
+ )
+ return db_item
async def update_db_item(
self,
db=db,
)
self.logger.debug("updated %s in database: %s", track.name, item_id)
- return await self.get_db_item(item_id, db=db)
+ db_item = await self.get_db_item(item_id, db=db)
+ self.mass.signal_event(
+ MassEvent(
+ EventType.MEDIA_ITEM_UPDATED, object_id=db_item.uri, data=db_item
+ )
+ )
+ return db_item
async def _get_track_artists(
self,
stdout=asyncio.subprocess.PIPE,
stdin=asyncio.subprocess.PIPE if audio_data else None,
)
- stdout, stderr = await proc.communicate(audio_data or None)
+ stdout, _ = await proc.communicate(audio_data or None)
try:
loudness = float(stdout.decode().strip())
except (ValueError, AttributeError):
LOGGER.warning(
- "Could not determine integrated loudness of %s/%s - %s %s",
+ "Could not determine integrated loudness of %s/%s - %s",
streamdetails.provider.value,
streamdetails.item_id,
- stdout.decode(),
- stderr.decode(),
+ stdout.decode() or "received empty value",
)
else:
await mass.music.set_track_loudness(
class EventType(Enum):
"""Enum with possible Events."""
- PLAYER_ADDED = "player added"
- PLAYER_UPDATED = "player updated"
- STREAM_STARTED = "streaming started"
- STREAM_ENDED = "streaming ended"
+ PLAYER_ADDED = "player_added"
+ PLAYER_UPDATED = "player_updated"
+ STREAM_STARTED = "streaming_started"
+ STREAM_ENDED = "streaming_ended"
QUEUE_ADDED = "queue_added"
- QUEUE_UPDATED = "queue updated"
- QUEUE_ITEMS_UPDATED = "queue items updated"
- QUEUE_TIME_UPDATED = "queue time updated"
- SHUTDOWN = "application shutdown"
- ARTIST_ADDED = "artist added"
- ALBUM_ADDED = "album added"
- TRACK_ADDED = "track added"
- PLAYLIST_ADDED = "playlist added"
- PLAYLIST_UPDATED = "playlist updated"
- RADIO_ADDED = "radio added"
+ QUEUE_UPDATED = "queue_updated"
+ QUEUE_ITEMS_UPDATED = "queue_items_updated"
+ QUEUE_TIME_UPDATED = "queue_time_updated"
+ SHUTDOWN = "application_shutdown"
+ MEDIA_ITEM_ADDED = "media_item_added"
+ MEDIA_ITEM_UPDATED = "media_item_updated"
BACKGROUND_JOB_UPDATED = "background_job_updated"
from databases import Database as Db
from music_assistant.models.errors import MediaNotFoundError, ProviderUnavailableError
+from music_assistant.models.event import MassEvent
-from .enums import MediaType, ProviderType
+from .enums import EventType, MediaType, ProviderType
from .media_items import MediaItemType
if TYPE_CHECKING:
await prov.library_add(prov_id.item_id, self.media_type)
# mark as library item in internal db
if not db_item.in_library:
+ db_item.in_library = True
await self.set_db_library(db_item.item_id, True)
+ self.mass.signal_event(
+ MassEvent(
+ EventType.MEDIA_ITEM_UPDATED, object_id=db_item.uri, data=db_item
+ )
+ )
async def remove_from_library(
self,
await prov.library_remove(prov_id.item_id, self.media_type)
# unmark as library item in internal db
if db_item.in_library:
+ db_item.in_library = False
await self.set_db_library(db_item.item_id, False)
+ self.mass.signal_event(
+ MassEvent(
+ EventType.MEDIA_ITEM_UPDATED, object_id=db_item.uri, data=db_item
+ )
+ )
async def get_provider_id(
self, item: ItemCls, db: Optional[Db] = None
from __future__ import annotations
from abc import abstractmethod
-from typing import TYPE_CHECKING, AsyncGenerator, List, Optional
+from typing import TYPE_CHECKING, Any, AsyncGenerator, Dict, List, Optional
from music_assistant.models.config import MusicProviderConfig
from music_assistant.models.enums import MediaType, ProviderType
"""Return unique provider id to distinguish multiple instances of the same provider."""
return self.config.id
+ def to_dict(self) -> Dict[str, Any]:
+ """Return (serializable) dict representation of MusicProvider."""
+ return {
+ "type": self.type.value,
+ "name": self.name,
+ "id": self.id,
+ "supported_mediatypes": [x.value for x in self.supported_mediatypes],
+ }
+
def _get_library_gen(self, media_type: MediaType) -> AsyncGenerator[MediaItemType]:
"""Return library generator for given media_type."""
if media_type == MediaType.ARTIST: