Skip to content

Commit 0c61842

Browse files
committed
Refactor chapters and podcast episodes
1 parent 0a5f46b commit 0c61842

File tree

5 files changed

+30
-42
lines changed

5 files changed

+30
-42
lines changed

music_assistant_models/enums.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,8 @@ class MediaType(StrEnum, metaclass=MediaTypeMeta):
3232
PLAYLIST = "playlist"
3333
RADIO = "radio"
3434
AUDIOBOOK = "audiobook"
35-
CHAPTER = "chapter"
3635
PODCAST = "podcast"
37-
EPISODE = "episode"
36+
PODCAST_EPISODE = "podcast_episode"
3837
FOLDER = "folder"
3938
ANNOUNCEMENT = "announcement"
4039
FLOW_STREAM = "flow_stream"

music_assistant_models/media_items/__init__.py

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,11 @@
1818
Artist,
1919
Audiobook,
2020
BrowseFolder,
21-
Chapter,
22-
Episode,
2321
ItemMapping,
2422
MediaItem,
2523
Playlist,
2624
Podcast,
25+
PodcastEpisode,
2726
Radio,
2827
Track,
2928
)
@@ -36,8 +35,6 @@
3635
"AudioFormat",
3736
"Audiobook",
3837
"BrowseFolder",
39-
"Chapter",
40-
"Episode",
4138
"ItemMapping",
4239
"MediaItem",
4340
"MediaItemImage",
@@ -51,27 +48,19 @@
5148
"Playlist",
5249
"PlaylistTrack",
5350
"Podcast",
51+
"PodcastEpisode",
5452
"ProviderMapping",
5553
"Radio",
5654
"Track",
5755
"UniqueList",
5856
]
5957

6058
MediaItemType = (
61-
Artist
62-
| Album
63-
| Track
64-
| Radio
65-
| Playlist
66-
| Audiobook
67-
| Chapter
68-
| Podcast
69-
| Episode
70-
| BrowseFolder
59+
Artist | Album | Track | Radio | Playlist | Audiobook | Podcast | PodcastEpisode | BrowseFolder
7160
)
7261

7362
# directly playable media items
74-
PlayableMediaItemType = Track | Radio | Chapter | Episode
63+
PlayableMediaItemType = Track | Radio | Audiobook | PodcastEpisode
7564

7665

7766
@dataclass(kw_only=True)
@@ -103,12 +92,10 @@ def media_from_dict(media_item: dict[str, Any]) -> MediaItemType | ItemMapping:
10392
return Radio.from_dict(media_item)
10493
if media_item["media_type"] == "audiobook":
10594
return Audiobook.from_dict(media_item)
106-
if media_item["media_type"] == "chapter":
107-
return Chapter.from_dict(media_item)
10895
if media_item["media_type"] == "podcast":
10996
return Podcast.from_dict(media_item)
110-
if media_item["media_type"] == "episode":
111-
return Episode.from_dict(media_item)
97+
if media_item["media_type"] == "podcast_episode":
98+
return PodcastEpisode.from_dict(media_item)
11299
raise InvalidDataError("Unknown media type")
113100

114101

music_assistant_models/media_items/media_item.py

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -255,28 +255,16 @@ class Audiobook(MediaItem):
255255
__eq__ = _MediaItemBase.__eq__
256256

257257
publisher: str | None = None
258-
total_chapters: int | None = None
259258
authors: UniqueList[str] = field(default_factory=UniqueList)
260259
narrators: UniqueList[str] = field(default_factory=UniqueList)
261-
media_type: MediaType = MediaType.AUDIOBOOK
262-
263-
264-
@dataclass(kw_only=True)
265-
class Chapter(MediaItem):
266-
"""Model for an Audiobook Chapter."""
267-
268-
__hash__ = _MediaItemBase.__hash__
269-
__eq__ = _MediaItemBase.__eq__
270-
271-
position: int # sort position / chapter number
272-
audiobook: Audiobook | ItemMapping
273260
duration: int = 0
274261
# resume point info
275262
# set to None if unknown/unsupported by provider
276263
# which will let MA fallback to an internal resume point
277264
fully_played: bool | None = None
278265
resume_position_ms: int | None = None
279-
media_type: MediaType = MediaType.CHAPTER
266+
267+
media_type: MediaType = MediaType.AUDIOBOOK
280268

281269

282270
@dataclass(kw_only=True)
@@ -292,7 +280,7 @@ class Podcast(MediaItem):
292280

293281

294282
@dataclass(kw_only=True)
295-
class Episode(MediaItem):
283+
class PodcastEpisode(MediaItem):
296284
"""Model for a Podcast Episode."""
297285

298286
__hash__ = _MediaItemBase.__hash__
@@ -308,7 +296,7 @@ class Episode(MediaItem):
308296
fully_played: bool | None = None
309297
resume_position_ms: int | None = None
310298

311-
media_type: MediaType = MediaType.EPISODE
299+
media_type: MediaType = MediaType.PODCAST_EPISODE
312300

313301

314302
@dataclass(kw_only=True)

music_assistant_models/media_items/metadata.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,21 @@ def __eq__(self, other: object) -> bool:
4949
return self.__hash__() == other.__hash__()
5050

5151

52+
@dataclass(kw_only=True)
53+
class MediaItemChapter(DataClassDictMixin):
54+
"""Model for a MediaItem's chapter/bookmark."""
55+
56+
position: int # sort position/number
57+
name: str # friendly name
58+
start: float # start position in seconds
59+
end: float | None = None # start position in seconds if known
60+
61+
@property
62+
def duration(self) -> float:
63+
"""Return duration of chapter."""
64+
return self.end - self.start if self.end else 0
65+
66+
5267
@dataclass(kw_only=True)
5368
class MediaItemMetadata(DataClassDictMixin):
5469
"""Model for a MediaItem's metadata."""
@@ -70,6 +85,9 @@ class MediaItemMetadata(DataClassDictMixin):
7085
popularity: int | None = None
7186
release_date: str | None = None
7287
languages: UniqueList[str] | None = None
88+
# chapters is a list of available chapters, sorted by position
89+
# most commonly used for audiobooks and podcast episodes
90+
chapters: UniqueList[MediaItemChapter] | None = None
7391
# last_refresh: timestamp the (full) metadata was last collected
7492
last_refresh: int | None = None
7593

music_assistant_models/queue_item.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,7 @@ def get_image(media_item: PlayableMediaItemType | None) -> MediaItemImage | None
105105
return media_item.image
106106
if media_item.media_type == MediaType.TRACK and (album := getattr(media_item, "album", None)):
107107
return get_image(album)
108-
if media_item.media_type == MediaType.CHAPTER and (
109-
audiobook := getattr(media_item, "audiobook", None)
110-
):
111-
return get_image(audiobook)
112-
if media_item.media_type == MediaType.EPISODE and (
108+
if media_item.media_type == MediaType.PODCAST_EPISODE and (
113109
podcast := getattr(media_item, "podcast", None)
114110
):
115111
return get_image(podcast)

0 commit comments

Comments
 (0)