# -*- coding: utf-8 -*-
-# Copyright (c) 2009, 2010, 2011, 2013 Jack Kaliko <kaliko@azylum.org>
+# Copyright (c) 2009-2021 kaliko <kaliko@azylum.org>
# Copyright (c) 2009 J. Alexander Treuman (Tag collapse method)
# Copyright (c) 2008 Rick van Hattem
#
import time
+from .meta import Artist, SEPARATOR
class Track:
"""
Track object.
- Instanciate with Player replies.
+ Instantiate with Player replies.
+
+ :param str file: media file, defaults to ``None``
+ :param int duration: duration in second, defaults to 0
+ :param int pos: position in queue, defaults to -1
+ :param str title|artist|album: defaults to ""
+ :param str musicbrainz_artistid|musicbrainz_albumartistid: MusicBrainz IDs, defaults to ``None``
"""
- def __init__(self, file=None, time=0, pos=-1, **kwargs):
+ def __init__(self, file=None, duration=0, pos=-1, **kwargs):
self.title = self.artist = self.album = self.albumartist = ''
+ self.musicbrainz_artistid = self.musicbrainz_albumartistid = None
self.pos = int(pos)
- self._empty = False
self._file = file
+ self._empty = False
+ self.duration = float(duration)
if not kwargs:
self._empty = True
- self._time = time
self.__dict__.update(**kwargs)
self.tags_to_collapse = ['artist', 'album', 'title', 'date',
- 'genre', 'albumartist']
+ 'genre', 'albumartist',
+ 'musicbrainz_artistid',
+ 'musicbrainz_albumartistid']
# have tags been collapsed?
- self.collapse_tags_bool = False
self.collapsed_tags = list()
# Needed for multiple tags which returns a list instead of a string
- self.collapse_tags()
+ self._collapse_tags()
- def collapse_tags(self):
+ def _collapse_tags(self):
"""
Necessary to deal with tags defined multiple times.
These entries are set as lists instead of strings.
if tag not in self.tags_to_collapse:
continue
if isinstance(value, list):
- self.collapse_tags_bool = True
self.collapsed_tags.append(tag)
- self.__dict__.update({tag: ', '.join(set(value))})
+ self.__dict__.update({tag: SEPARATOR.join(value)})
def __repr__(self):
- return '%s(artist="%s", album="%s", title="%s", filename="%s")' % (
+ return '%s(artist="%s", album="%s", title="%s", file="%s")' % (
self.__class__.__name__,
self.artist,
self.album,
)
def __str__(self):
- return '{artist} - {album} - {title} ({duration})'.format(
- duration=self.duration,
+ return '{artist} - {album} - {title} ({length})'.format(
+ length=self.length,
**self.__dict__
)
def __int__(self):
- return self.time
+ return int(self.duration)
def __add__(self, other):
- return Track(time=self.time + other.time)
+ return Track(duration=self.duration + other.duration)
def __sub__(self, other):
- return Track(time=self.time - other.time)
+ return Track(duration=self.duration - other.duration)
def __hash__(self):
if self.file:
return hash(self.file)
- else:
- return id(self)
+ return id(self)
def __eq__(self, other):
return hash(self) == hash(other)
return hash(self) != hash(other)
def __bool__(self):
+ if not self._file:
+ return False
return not self._empty
@property
"""file is an immutable attribute that's used for the hash method"""
return self._file
- def get_time(self):
- """get time property"""
- return self._time
-
- def set_time(self, value):
- """set time property"""
- self._time = int(value)
-
- time = property(get_time, set_time, doc='song duration in seconds')
-
@property
- def duration(self):
- """Compute fancy duration"""
- temps = time.gmtime(int(self.time))
+ def length(self):
+ """Get a fancy duration as ``%H:%M:%S`` (use :attr:`duration` to get duration in second only)"""
+ temps = time.gmtime(self.duration) #TODO: returns a date not a duration
if temps.tm_hour:
fmt = '%H:%M:%S'
else:
fmt = '%M:%S'
return time.strftime(fmt, temps)
+ @property
+ def genres(self):
+ """Fetches Genres for the track
+ Multivalue genre are dealt with:
+ * when genre tag is multivalued
+ * when single tag uses coma or semi-colon separator
+ """
+ if 'genre' not in self.__dict__:
+ return []
+ genres = self.genre.split(SEPARATOR)
+ for sep in [',', ';']:
+ if sep in self.genre:
+ genres = [g for multi in genres for g in multi.split(sep) if g]
+ return list(map(str.strip, genres))
+
+ @property
+ def Artist(self):
+ """Get the :class:`sima.lib.meta.Artist` associated to this track"""
+ if not self.artist:
+ if not self.musicbrainz_artistid:
+ return Artist(name='[unknown]',
+ mbid='125ec42a-7229-4250-afc5-e057484327fe')
+ return Artist(name='[unknown]', **self.__dict__)
+ return Artist(**self.__dict__)
+
# VIM MODLINE
# vim: ai ts=4 sw=4 sts=4 expandtab