Source code for sima.lib.track

# -*- coding: utf-8 -*-

# Copyright (c) 2009-2021 kaliko <kaliko@azylum.org>
# Copyright (c) 2009 J. Alexander Treuman (Tag collapse method)
# Copyright (c) 2008 Rick van Hattem
#
#  This file is part of sima
#
#  sima is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  sima is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with sima.  If not, see <http://www.gnu.org/licenses/>.
#
#

import time

from .meta import Artist, Album, SEPARATOR


[docs]class Track: """ Track object. 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|albumartist: defaults to "" :param str musicbrainz_{artistid|albumartistid|albumid|trackid}: MusicBrainz IDs, defaults to ``None`` """ def __init__(self, file=None, duration=0, pos=-1, **kwargs): self.title = self.artist = self.album = self.albumartist = self.genre = '' self.musicbrainz_artistid = self.musicbrainz_albumartistid = None self.musicbrainz_albumid = self.musicbrainz_trackid = None self.pos = int(pos) self._file = file self._empty = False self.duration = float(duration) if not kwargs: self._empty = True self.__dict__.update(**kwargs) self.tags_to_collapse = ['artist', 'album', 'title', 'date', 'genre', 'albumartist', 'musicbrainz_artistid', 'musicbrainz_albumartistid'] # Which tags have been collapsed? self.collapsed_tags = [] # Needed for multiple tags which returns a list instead of a string self._collapse_tags() def _collapse_tags(self): """ Necessary to deal with tags defined multiple times. These entries are set as lists instead of strings. """ for tag, value in self.__dict__.items(): if tag not in self.tags_to_collapse: continue if isinstance(value, list): self.collapsed_tags.append(tag) self.__dict__.update({tag: SEPARATOR.join(value)}) def __repr__(self): return '%s(artist="%s", album="%s", title="%s", file="%s")' % ( self.__class__.__name__, self.artist, self.album, self.title, self.file, ) def __str__(self): return '{artist} - {album} - {title} ({length})'.format( length=self.length, **self.__dict__ ) def __int__(self): return int(self.duration) def __add__(self, other): return Track(duration=self.duration + other.duration) def __sub__(self, other): return Track(duration=self.duration - other.duration) def __hash__(self): if self.file: return hash(self.file) return id(self) def __eq__(self, other): return hash(self) == hash(other) def __ne__(self, other): return hash(self) != hash(other) def __bool__(self): if not self._file: return False return not self._empty @property def file(self): """file is an immutable attribute that's used for the hash method""" return self._file @property 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 not self.genre: 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__) @property def Album(self): """Get the :class:`sima.lib.meta.Album` associated to this track""" if not self.album: return Album(name='[unknown]', **self.__dict__) return Album(name=self.album, **self.__dict__)
# VIM MODLINE # vim: ai ts=4 sw=4 sts=4 expandtab