]> kaliko git repositories - mpd-sima.git/blob - sima/lib/player.py
Add trace level to the logger
[mpd-sima.git] / sima / lib / player.py
1 # -*- coding: utf-8 -*-
2 # Copyright (c) 2009-2014 Jack Kaliko <jack@azylum.org>
3 #
4 #  This file is part of sima
5 #
6 #  sima is free software: you can redistribute it and/or modify
7 #  it under the terms of the GNU General Public License as published by
8 #  the Free Software Foundation, either version 3 of the License, or
9 #  (at your option) any later version.
10 #
11 #  sima is distributed in the hope that it will be useful,
12 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 #  GNU General Public License for more details.
15 #
16 #  You should have received a copy of the GNU General Public License
17 #  along with sima.  If not, see <http://www.gnu.org/licenses/>.
18 #
19 #
20
21 # TODO:
22 # Add decorator to filter through history?
23
24 # standard library import
25 import logging
26 from difflib import get_close_matches
27 from itertools import dropwhile
28
29 # local import
30 from .meta import Artist
31 from .simastr import SimaStr
32 from ..utils.leven import levenshtein_ratio
33
34 def blacklist(artist=False, album=False, track=False):
35     #pylint: disable=C0111,W0212
36     field = (album, track)
37     def decorated(func):
38         def wrapper(*args, **kwargs):
39             if not args[0].database:
40                 return func(*args, **kwargs)
41             cls = args[0]
42             boolgen = (bl for bl in field)
43             bl_fun = (cls.database.get_bl_album,
44                       cls.database.get_bl_track,)
45             #bl_getter = next(fn for fn, bl in zip(bl_fun, boolgen) if bl is True)
46             bl_getter = next(dropwhile(lambda _: not next(boolgen), bl_fun))
47             #cls.log.debug('using {0} as bl filter'.format(bl_getter.__name__))
48             results = list()
49             for elem in func(*args, **kwargs):
50                 if bl_getter(elem, add_not=True):
51                     #cls.log.debug('Blacklisted "{0}"'.format(elem))
52                     continue
53                 if track and cls.database.get_bl_album(elem, add_not=True):
54                     # filter album as well in track mode
55                     # (artist have already been)
56                     cls.log.debug('Blacklisted alb. "{0.album}"'.format(elem))
57                     continue
58                 results.append(elem)
59             return results
60         return wrapper
61     return decorated
62
63
64 class Player(object):
65     """Player interface to inherit from.
66
67     When querying player music library for tracks, Player instance *must* return
68     Track objects (usually a list of them)
69
70     Player instance should expose the following immutable attributes:
71         * artists
72         * state
73         * current
74         * queue
75         * playlist
76     """
77
78     def __init__(self):
79         super().__init__()
80         self.log = logging.getLogger('sima')
81
82     def monitor(self):
83         """Monitor player for change
84         Returns :
85             * database  player media library has changed
86             * playlist  playlist modified
87             * options   player options changed: repeat mode, etc…
88             * player    player state changed: paused, stopped, skip track…
89         """
90         raise NotImplementedError
91
92     def clean(self):
93         """Any cleanup necessary"""
94         pass
95
96     def remove(self, position=0):
97         """Removes the oldest element of the playlist (index 0)
98         """
99         raise NotImplementedError
100
101     def find_track(self, artist, title=None):
102         """
103         Find tracks for a specific artist or filtering with a track title
104             >>> player.find_track(Artist('The Beatles'))
105             >>> player.find_track(Artist('Nirvana'), title='Smells Like Teen Spirit')
106
107         Returns a list of Track objects
108         """
109         raise NotImplementedError
110
111     def find_album(self, artist, album):
112         """
113         Find tracks by track's album name
114             >>> player.find_album('Nirvana', 'Nevermind')
115
116         Returns a list of Track objects
117         """
118         raise NotImplementedError
119
120     def search_albums(self, artist):
121         """
122         Find albums by artist's name
123             >>> art = Artist(name='Nirvana')
124             >>> player.search_albums(art)
125
126         Returns a list of string objects
127         """
128         raise NotImplementedError
129
130     def search_artist(self, artist):
131         """
132         Search artists based on a fuzzy search in the media library
133             >>> art = Artist(name='the beatles', mbid=<UUID4>) # mbid optional
134             >>> bea = player.search_artist(art)
135             >>> print(bea.names)
136             >>> ['The Beatles', 'Beatles', 'the beatles']
137
138         Returns an Artist object
139         """
140         raise NotImplementedError
141
142     def disconnect(self):
143         """Closing client connection with the Player
144         """
145         raise NotImplementedError
146
147     def connect(self):
148         """Connect client to the Player
149         """
150         raise NotImplementedError
151
152     @property
153     def artists(self):
154         raise NotImplementedError
155
156     @property
157     def state(self):
158         raise NotImplementedError
159
160     @property
161     def current(self):
162         raise NotImplementedError
163
164     @property
165     def queue(self):
166         raise NotImplementedError
167
168     @property
169     def playlist(self):
170         raise NotImplementedError
171
172 # VIM MODLINE
173 # vim: ai ts=4 sw=4 sts=4 expandtab