1 # -*- coding: utf-8 -*-
3 # Copyright (c) 2009-2021 kaliko <kaliko@azylum.org>
4 # Copyright (c) 2009 J. Alexander Treuman (Tag collapse method)
5 # Copyright (c) 2008 Rick van Hattem
7 # This file is part of sima
9 # sima is free software: you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation, either version 3 of the License, or
12 # (at your option) any later version.
14 # sima is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
19 # You should have received a copy of the GNU General Public License
20 # along with sima. If not, see <http://www.gnu.org/licenses/>.
26 from .meta import Artist, Album, SEPARATOR
32 Instantiate with Player replies.
34 :param str file: media file, defaults to ``None``
35 :param int duration: duration in second, defaults to 0
36 :param int pos: position in queue, defaults to -1
37 :param str title|artist|album|albumartist: defaults to ""
38 :param str musicbrainz_{artistid|albumartistid|albumid|trackid}: MusicBrainz IDs, defaults to ``None``
41 def __init__(self, file=None, duration=0, pos=-1, **kwargs):
42 self.title = self.artist = self.album = self.albumartist = ''
43 self.musicbrainz_artistid = self.musicbrainz_albumartistid = None
44 self.musicbrainz_albumid = self.musicbrainz_trackid = None
48 self.duration = float(duration)
51 self.__dict__.update(**kwargs)
52 self.tags_to_collapse = ['artist', 'album', 'title', 'date',
53 'genre', 'albumartist',
54 'musicbrainz_artistid',
55 'musicbrainz_albumartistid']
56 # Which tags have been collapsed?
57 self.collapsed_tags = list()
58 # Needed for multiple tags which returns a list instead of a string
61 def _collapse_tags(self):
63 Necessary to deal with tags defined multiple times.
64 These entries are set as lists instead of strings.
66 for tag, value in self.__dict__.items():
67 if tag not in self.tags_to_collapse:
69 if isinstance(value, list):
70 self.collapsed_tags.append(tag)
71 self.__dict__.update({tag: SEPARATOR.join(value)})
74 return '%s(artist="%s", album="%s", title="%s", file="%s")' % (
75 self.__class__.__name__,
83 return '{artist} - {album} - {title} ({length})'.format(
89 return int(self.duration)
91 def __add__(self, other):
92 return Track(duration=self.duration + other.duration)
94 def __sub__(self, other):
95 return Track(duration=self.duration - other.duration)
99 return hash(self.file)
102 def __eq__(self, other):
103 return hash(self) == hash(other)
105 def __ne__(self, other):
106 return hash(self) != hash(other)
111 return not self._empty
115 """file is an immutable attribute that's used for the hash method"""
120 """Get a fancy duration as ``%H:%M:%S`` (use :attr:`duration` to get duration in second only)"""
121 temps = time.gmtime(self.duration) #TODO: returns a date not a duration
126 return time.strftime(fmt, temps)
130 """Fetches Genres for the track
131 Multivalue genre are dealt with:
133 * when genre tag is multivalued
134 * when single tag uses coma or semi-colon separator
136 if 'genre' not in self.__dict__:
138 genres = self.genre.split(SEPARATOR)
139 for sep in [',', ';']:
140 if sep in self.genre:
141 genres = [g for multi in genres for g in multi.split(sep) if g]
142 return list(map(str.strip, genres))
146 """Get the :class:`sima.lib.meta.Artist` associated to this track"""
148 if not self.musicbrainz_artistid:
149 return Artist(name='[unknown]',
150 mbid='125ec42a-7229-4250-afc5-e057484327fe')
151 return Artist(name='[unknown]', **self.__dict__)
152 return Artist(**self.__dict__)
156 """Get the :class:`sima.lib.meta.Album` associated to this track"""
158 return Album(name='[unknown]', **self.__dict__)
159 return Album(name=self.album, **self.__dict__)
162 # vim: ai ts=4 sw=4 sts=4 expandtab