]> kaliko git repositories - mpd-sima.git/blob - sima/lib/track.py
Fixed a potential infinite loop
[mpd-sima.git] / sima / lib / track.py
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2009, 2010, 2011, 2013, 2014 Jack Kaliko <kaliko@azylum.org>
4 # Copyright (c) 2009 J. Alexander Treuman (Tag collapse method)
5 # Copyright (c) 2008 Rick van Hattem
6 #
7 #  This file is part of sima
8 #
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.
13 #
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.
18 #
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/>.
21 #
22 #
23
24 import time
25
26 from .meta import Artist
27
28 class Track:
29     """
30     Track object.
31     Instanciate with Player replies.
32     """
33
34     def __init__(self, file=None, time=0, pos=-1, **kwargs):
35         self.title = self.artist = self.album = self.albumartist = ''
36         self.musicbrainz_artistid = self.musicbrainz_albumartistid = None
37         self.pos = int(pos)
38         self._file = file
39         self._empty = False
40         self._time = time
41         if not kwargs:
42             self._empty = True
43         self.__dict__.update(**kwargs)
44         self.tags_to_collapse = ['artist', 'album', 'title', 'date',
45                                  'genre', 'albumartist',
46                                  'musicbrainz_artistid',
47                                  'musicbrainz_albumartistid']
48         #  have tags been collapsed?
49         self.collapsed_tags = list()
50         # Needed for multiple tags which returns a list instead of a string
51         self.collapse_tags()
52
53     def collapse_tags(self):
54         """
55         Necessary to deal with tags defined multiple times.
56         These entries are set as lists instead of strings.
57         """
58         for tag, value in self.__dict__.items():
59             if tag not in self.tags_to_collapse:
60                 continue
61             if isinstance(value, list):
62                 self.collapsed_tags.append(tag)
63                 self.__dict__.update({tag: ', '.join(set(value))})
64
65     def __repr__(self):
66         return '%s(artist="%s", album="%s", title="%s", file="%s")' % (
67             self.__class__.__name__,
68             self.artist,
69             self.album,
70             self.title,
71             self.file,
72         )
73
74     def __str__(self):
75         return '{artist} - {album} - {title} ({duration})'.format(
76                 duration=self.duration,
77                 **self.__dict__
78                 )
79
80     def __int__(self):
81         return self.time
82
83     def __add__(self, other):
84         return Track(time=self.time + other.time)
85
86     def __sub__(self, other):
87         return Track(time=self.time - other.time)
88
89     def __hash__(self):
90         if self.file:
91             return hash(self.file)
92         else:
93             return id(self)
94
95     def __eq__(self, other):
96         return hash(self) == hash(other)
97
98     def __ne__(self, other):
99         return hash(self) != hash(other)
100
101     def __bool__(self):
102         return not self._empty
103
104     @property
105     def file(self):
106         """file is an immutable attribute that's used for the hash method"""
107         return self._file
108
109     def get_time(self):
110         """get time property"""
111         return self._time
112
113     def set_time(self, value):
114         """set time property"""
115         self._time = int(value)
116
117     time = property(get_time, set_time, doc='song duration in seconds')
118
119     @property
120     def duration(self):
121         """Compute fancy duration"""
122         temps = time.gmtime(int(self.time))
123         if temps.tm_hour:
124             fmt = '%H:%M:%S'
125         else:
126             fmt = '%M:%S'
127         return time.strftime(fmt, temps)
128
129     @property
130     def Artist(self):
131         """Get artist object from track"""
132         if not self.artist:
133             if not self.musicbrainz_artistid:
134                 return Artist(name='[unknown]',
135                               mbid='125ec42a-7229-4250-afc5-e057484327fe')
136             return Artist(name='[unknown]', **self.__dict__)
137         return Artist(**self.__dict__)
138
139 # VIM MODLINE
140 # vim: ai ts=4 sw=4 sts=4 expandtab