1 3
from mopidy.models import fields
2 3
from mopidy.models.immutable import ImmutableObject, ValidatedImmutableObject
3 3
from mopidy.models.serialize import ModelJSONEncoder, model_json_decoder
4

5 3
__all__ = [
6
    "ImmutableObject",
7
    "Ref",
8
    "Image",
9
    "Artist",
10
    "Album",
11
    "Track",
12
    "TlTrack",
13
    "Playlist",
14
    "SearchResult",
15
    "model_json_decoder",
16
    "ModelJSONEncoder",
17
    "ValidatedImmutableObject",
18
]
19

20

21 3
class Ref(ValidatedImmutableObject):
22

23
    """
24
    Model to represent URI references with a human friendly name and type
25
    attached. This is intended for use a lightweight object "free" of metadata
26
    that can be passed around instead of using full blown models.
27

28
    :param uri: object URI
29
    :type uri: string
30
    :param name: object name
31
    :type name: string
32
    :param type: object type
33
    :type type: string
34
    """
35

36
    #: The object URI. Read-only.
37 3
    uri = fields.URI()
38

39
    #: The object name. Read-only.
40 3
    name = fields.String()
41

42
    #: The object type, e.g. "artist", "album", "track", "playlist",
43
    #: "directory". Read-only.
44 3
    type = fields.Identifier()  # TODO: consider locking this down.
45
    # type = fields.Field(choices=(ALBUM, ARTIST, DIRECTORY, PLAYLIST, TRACK))
46

47
    #: Constant used for comparison with the :attr:`type` field.
48 3
    ALBUM = "album"
49

50
    #: Constant used for comparison with the :attr:`type` field.
51 3
    ARTIST = "artist"
52

53
    #: Constant used for comparison with the :attr:`type` field.
54 3
    DIRECTORY = "directory"
55

56
    #: Constant used for comparison with the :attr:`type` field.
57 3
    PLAYLIST = "playlist"
58

59
    #: Constant used for comparison with the :attr:`type` field.
60 3
    TRACK = "track"
61

62 3
    @classmethod
63 2
    def album(cls, **kwargs):
64
        """Create a :class:`Ref` with ``type`` :attr:`ALBUM`."""
65 3
        kwargs["type"] = Ref.ALBUM
66 3
        return cls(**kwargs)
67

68 3
    @classmethod
69 2
    def artist(cls, **kwargs):
70
        """Create a :class:`Ref` with ``type`` :attr:`ARTIST`."""
71 3
        kwargs["type"] = Ref.ARTIST
72 3
        return cls(**kwargs)
73

74 3
    @classmethod
75 2
    def directory(cls, **kwargs):
76
        """Create a :class:`Ref` with ``type`` :attr:`DIRECTORY`."""
77 3
        kwargs["type"] = Ref.DIRECTORY
78 3
        return cls(**kwargs)
79

80 3
    @classmethod
81 2
    def playlist(cls, **kwargs):
82
        """Create a :class:`Ref` with ``type`` :attr:`PLAYLIST`."""
83 3
        kwargs["type"] = Ref.PLAYLIST
84 3
        return cls(**kwargs)
85

86 3
    @classmethod
87 2
    def track(cls, **kwargs):
88
        """Create a :class:`Ref` with ``type`` :attr:`TRACK`."""
89 3
        kwargs["type"] = Ref.TRACK
90 3
        return cls(**kwargs)
91

92

93 3
class Image(ValidatedImmutableObject):
94

95
    """
96
    :param string uri: URI of the image
97
    :param int width: Optional width of image or :class:`None`
98
    :param int height: Optional height of image or :class:`None`
99
    """
100

101
    #: The image URI. Read-only.
102 3
    uri = fields.URI()
103

104
    #: Optional width of the image or :class:`None`. Read-only.
105 3
    width = fields.Integer(min=0)
106

107
    #: Optional height of the image or :class:`None`. Read-only.
108 3
    height = fields.Integer(min=0)
109

110

111 3
class Artist(ValidatedImmutableObject):
112

113
    """
114
    :param uri: artist URI
115
    :type uri: string
116
    :param name: artist name
117
    :type name: string
118
    :param sortname: artist name for sorting
119
    :type sortname: string
120
    :param musicbrainz_id: MusicBrainz ID
121
    :type musicbrainz_id: string
122
    """
123

124
    #: The artist URI. Read-only.
125 3
    uri = fields.URI()
126

127
    #: The artist name. Read-only.
128 3
    name = fields.String()
129

130
    #: Artist name for better sorting, e.g. with articles stripped
131 3
    sortname = fields.String()
132

133
    #: The MusicBrainz ID of the artist. Read-only.
134 3
    musicbrainz_id = fields.Identifier()
135

136

137 3
class Album(ValidatedImmutableObject):
138

139
    """
140
    :param uri: album URI
141
    :type uri: string
142
    :param name: album name
143
    :type name: string
144
    :param artists: album artists
145
    :type artists: list of :class:`Artist`
146
    :param num_tracks: number of tracks in album
147
    :type num_tracks: integer or :class:`None` if unknown
148
    :param num_discs: number of discs in album
149
    :type num_discs: integer or :class:`None` if unknown
150
    :param date: album release date (YYYY or YYYY-MM-DD)
151
    :type date: string
152
    :param musicbrainz_id: MusicBrainz ID
153
    :type musicbrainz_id: string
154
    """
155

156
    #: The album URI. Read-only.
157 3
    uri = fields.URI()
158

159
    #: The album name. Read-only.
160 3
    name = fields.String()
161

162
    #: A set of album artists. Read-only.
163 3
    artists = fields.Collection(type=Artist, container=frozenset)
164

165
    #: The number of tracks in the album. Read-only.
166 3
    num_tracks = fields.Integer(min=0)
167

168
    #: The number of discs in the album. Read-only.
169 3
    num_discs = fields.Integer(min=0)
170

171
    #: The album release date. Read-only.
172 3
    date = fields.Date()
173

174
    #: The MusicBrainz ID of the album. Read-only.
175 3
    musicbrainz_id = fields.Identifier()
176

177

178 3
class Track(ValidatedImmutableObject):
179

180
    """
181
    :param uri: track URI
182
    :type uri: string
183
    :param name: track name
184
    :type name: string
185
    :param artists: track artists
186
    :type artists: list of :class:`Artist`
187
    :param album: track album
188
    :type album: :class:`Album`
189
    :param composers: track composers
190
    :type composers: list of :class:`Artist`
191
    :param performers: track performers
192
    :type performers: list of :class:`Artist`
193
    :param genre: track genre
194
    :type genre: string
195
    :param track_no: track number in album
196
    :type track_no: integer or :class:`None` if unknown
197
    :param disc_no: disc number in album
198
    :type disc_no: integer or :class:`None` if unknown
199
    :param date: track release date (YYYY or YYYY-MM-DD)
200
    :type date: string
201
    :param length: track length in milliseconds
202
    :type length: integer or :class:`None` if there is no duration
203
    :param bitrate: bitrate in kbit/s
204
    :type bitrate: integer
205
    :param comment: track comment
206
    :type comment: string
207
    :param musicbrainz_id: MusicBrainz ID
208
    :type musicbrainz_id: string
209
    :param last_modified: Represents last modification time
210
    :type last_modified: integer or :class:`None` if unknown
211
    """
212

213
    #: The track URI. Read-only.
214 3
    uri = fields.URI()
215

216
    #: The track name. Read-only.
217 3
    name = fields.String()
218

219
    #: A set of track artists. Read-only.
220 3
    artists = fields.Collection(type=Artist, container=frozenset)
221

222
    #: The track :class:`Album`. Read-only.
223 3
    album = fields.Field(type=Album)
224

225
    #: A set of track composers. Read-only.
226 3
    composers = fields.Collection(type=Artist, container=frozenset)
227

228
    #: A set of track performers`. Read-only.
229 3
    performers = fields.Collection(type=Artist, container=frozenset)
230

231
    #: The track genre. Read-only.
232 3
    genre = fields.String()
233

234
    #: The track number in the album. Read-only.
235 3
    track_no = fields.Integer(min=0)
236

237
    #: The disc number in the album. Read-only.
238 3
    disc_no = fields.Integer(min=0)
239

240
    #: The track release date. Read-only.
241 3
    date = fields.Date()
242

243
    #: The track length in milliseconds. Read-only.
244 3
    length = fields.Integer(min=0)
245

246
    #: The track's bitrate in kbit/s. Read-only.
247 3
    bitrate = fields.Integer(min=0)
248

249
    #: The track comment. Read-only.
250 3
    comment = fields.String()
251

252
    #: The MusicBrainz ID of the track. Read-only.
253 3
    musicbrainz_id = fields.Identifier()
254

255
    #: Integer representing when the track was last modified. Exact meaning
256
    #: depends on source of track. For local files this is the modification
257
    #: time in milliseconds since Unix epoch. For other backends it could be an
258
    #: equivalent timestamp or simply a version counter.
259 3
    last_modified = fields.Integer(min=0)
260

261

262 3
class TlTrack(ValidatedImmutableObject):
263

264
    """
265
    A tracklist track. Wraps a regular track and it's tracklist ID.
266

267
    The use of :class:`TlTrack` allows the same track to appear multiple times
268
    in the tracklist.
269

270
    This class also accepts it's parameters as positional arguments. Both
271
    arguments must be provided, and they must appear in the order they are
272
    listed here.
273

274
    This class also supports iteration, so your extract its values like this::
275

276
        (tlid, track) = tl_track
277

278
    :param tlid: tracklist ID
279
    :type tlid: int
280
    :param track: the track
281
    :type track: :class:`Track`
282
    """
283

284
    #: The tracklist ID. Read-only.
285 3
    tlid = fields.Integer(min=0)
286

287
    #: The track. Read-only.
288 3
    track = fields.Field(type=Track)
289

290 3
    def __init__(self, *args, **kwargs):
291 3
        if len(args) == 2 and len(kwargs) == 0:
292 3
            kwargs["tlid"] = args[0]
293 3
            kwargs["track"] = args[1]
294 3
            args = []
295 3
        super().__init__(*args, **kwargs)
296

297 3
    def __iter__(self):
298 3
        return iter([self.tlid, self.track])
299

300

301 3
class Playlist(ValidatedImmutableObject):
302

303
    """
304
    :param uri: playlist URI
305
    :type uri: string
306
    :param name: playlist name
307
    :type name: string
308
    :param tracks: playlist's tracks
309
    :type tracks: list of :class:`Track` elements
310
    :param last_modified:
311
        playlist's modification time in milliseconds since Unix epoch
312
    :type last_modified: int
313
    """
314

315
    #: The playlist URI. Read-only.
316 3
    uri = fields.URI()
317

318
    #: The playlist name. Read-only.
319 3
    name = fields.String()
320

321
    #: The playlist's tracks. Read-only.
322 3
    tracks = fields.Collection(type=Track, container=tuple)
323

324
    #: The playlist modification time in milliseconds since Unix epoch.
325
    #: Read-only.
326
    #:
327
    #: Integer, or :class:`None` if unknown.
328 3
    last_modified = fields.Integer(min=0)
329

330
    # TODO: def insert(self, pos, track): ... ?
331

332 3
    @property
333 2
    def length(self):
334
        """The number of tracks in the playlist. Read-only."""
335 3
        return len(self.tracks)
336

337

338 3
class SearchResult(ValidatedImmutableObject):
339

340
    """
341
    :param uri: search result URI
342
    :type uri: string
343
    :param tracks: matching tracks
344
    :type tracks: list of :class:`Track` elements
345
    :param artists: matching artists
346
    :type artists: list of :class:`Artist` elements
347
    :param albums: matching albums
348
    :type albums: list of :class:`Album` elements
349
    """
350

351
    #: The search result URI. Read-only.
352 3
    uri = fields.URI()
353

354
    #: The tracks matching the search query. Read-only.
355 3
    tracks = fields.Collection(type=Track, container=tuple)
356

357
    #: The artists matching the search query. Read-only.
358 3
    artists = fields.Collection(type=Artist, container=tuple)
359

360
    #: The albums matching the search query. Read-only.
361 3
    albums = fields.Collection(type=Album, container=tuple)

Read our documentation on viewing source code .

Loading