]> kaliko git repositories - mpd-sima.git/blobdiff - sima/lib/track.py
Mainly use literal for list/dict and f-strings when possible
[mpd-sima.git] / sima / lib / track.py
index 93aa350bbc4d24d612e2232e8c7a8d1de19d0a90..2df220cc849811e48ac95e342302f4a7257cbdf5 100644 (file)
@@ -1,53 +1,64 @@
 # -*- coding: utf-8 -*-
 
 # -*- coding: utf-8 -*-
 
-# Copyright (c) 2009, 2010, 2011, 2013 Jack Kaliko <efrim@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
 #
 # Copyright (c) 2009 J. Alexander Treuman (Tag collapse method)
 # Copyright (c) 2008 Rick van Hattem
 #
-#  This file is part of MPD_sima
+#  This file is part of sima
 #
 #
-#  MPD_sima is free software: you can redistribute it and/or modify
+#  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.
 #
 #  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.
 #
-#  MPD_sima is distributed in the hope that it will be useful,
+#  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
 #  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 MPD_sima.  If not, see <http://www.gnu.org/licenses/>.
+#  along with sima.  If not, see <http://www.gnu.org/licenses/>.
 #
 #
 
 import time
 
 #
 #
 
 import time
 
+from .meta import Artist, Album, SEPARATOR
 
 
-class Track(object):
+
+class Track:
     """
     Track object.
     """
     Track object.
-    Instanciate with mpd 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|albumartist: defaults to ""
+    :param str musicbrainz_{artistid|albumartistid|albumid|trackid}: MusicBrainz IDs, defaults to ``None``
     """
 
     """
 
-    def __init__(self, file=None, time=0, pos=0, **kwargs):
-        self.title = self.artist = self.album = self.albumartist = ''
-        self._pos = pos
-        self.empty = False
+    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._file = file
+        self._empty = False
+        self.duration = float(duration)
         if not kwargs:
         if not kwargs:
-            self.empty = True
-        self.time = time
+            self._empty = True
         self.__dict__.update(**kwargs)
         self.__dict__.update(**kwargs)
-        self.tags_to_collapse = list(['artist', 'album', 'title', 'date',
-            'genre', 'albumartist'])
-        #  have tags been collapsed?
-        self.collapse_tags_bool = False
-        self.collapsed_tags = list()
+        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
         # 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.
         """
         Necessary to deal with tags defined multiple times.
         These entries are set as lists instead of strings.
@@ -56,18 +67,11 @@ class Track(object):
             if tag not in self.tags_to_collapse:
                 continue
             if isinstance(value, list):
             if tag not in self.tags_to_collapse:
                 continue
             if isinstance(value, list):
-                self.collapse_tags_bool = True
                 self.collapsed_tags.append(tag)
                 self.collapsed_tags.append(tag)
-                self.__dict__.update({tag: ', '.join(set(value))})
-
-    def get_filename(self):
-        """return filename"""
-        if not self.file:
-            return None
-        return self.file
+                self.__dict__.update({tag: SEPARATOR.join(value)})
 
     def __repr__(self):
 
     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,
             self.__class__.__name__,
             self.artist,
             self.album,
@@ -76,25 +80,24 @@ class Track(object):
         )
 
     def __str__(self):
         )
 
     def __str__(self):
-        return '{artist} - {album} - {title} ({duration})'.format(
-                duration=self.duration,
-                **self.__dict__
-                )
+        return '{artist} - {album} - {title} ({length})'.format(
+            length=self.length,
+            **self.__dict__
+        )
 
     def __int__(self):
 
     def __int__(self):
-        return self.time
+        return int(self.duration)
 
     def __add__(self, other):
 
     def __add__(self, other):
-        return Track(time=self.time + other.time)
+        return Track(duration=self.duration + other.duration)
 
     def __sub__(self, other):
 
     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)
 
     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)
 
     def __eq__(self, other):
         return hash(self) == hash(other)
@@ -103,45 +106,58 @@ class Track(object):
         return hash(self) != hash(other)
 
     def __bool__(self):
         return hash(self) != hash(other)
 
     def __bool__(self):
-        return not self.empty
-
-    @property
-    def pos(self):
-        """return position of track in the playlist"""
-        return int(self._pos)
+        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 file(self):
         """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
     @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)
 
         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:
 
 
-def main():
-    pass
+        * 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))
 
 
-# Script starts here
-if __name__ == '__main__':
-    main()
+    @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
 
 # VIM MODLINE
 # vim: ai ts=4 sw=4 sts=4 expandtab