aboutsummaryrefslogtreecommitdiff
path: root/pydora
diff options
context:
space:
mode:
Diffstat (limited to 'pydora')
-rw-r--r--pydora/audio_backend.py7
-rw-r--r--pydora/configure.py15
-rw-r--r--pydora/player.py56
-rw-r--r--pydora/utils.py5
4 files changed, 55 insertions, 28 deletions
diff --git a/pydora/audio_backend.py b/pydora/audio_backend.py
index bd778ad..aecd87e 100644
--- a/pydora/audio_backend.py
+++ b/pydora/audio_backend.py
@@ -15,18 +15,21 @@ log = logging.getLogger("pydora.audio_backend")
15class PlayerException(Exception): 15class PlayerException(Exception):
16 """Base class for all player exceptions 16 """Base class for all player exceptions
17 """ 17 """
18
18 pass 19 pass
19 20
20 21
21class UnsupportedEncoding(PlayerException): 22class UnsupportedEncoding(PlayerException):
22 """Song encoding is not supported by player backend 23 """Song encoding is not supported by player backend
23 """ 24 """
25
24 pass 26 pass
25 27
26 28
27class PlayerUnusable(PlayerException): 29class PlayerUnusable(PlayerException):
28 """Player can not be used on this system 30 """Player can not be used on this system
29 """ 31 """
32
30 pass 33 pass
31 34
32 35
@@ -172,7 +175,8 @@ class BasePlayer:
172 self._loop_hook() 175 self._loop_hook()
173 176
174 readers, _, _ = select.select( 177 readers, _, _ = select.select(
175 self._get_select_readers(), [], [], 1) 178 self._get_select_readers(), [], [], 1
179 )
176 180
177 for handle in readers: 181 for handle in readers:
178 if handle.fileno() == self._control_fd: 182 if handle.fileno() == self._control_fd:
@@ -296,7 +300,6 @@ class VLCPlayer(BasePlayer):
296 300
297 301
298class RemoteVLC(VLCPlayer): 302class RemoteVLC(VLCPlayer):
299
300 def __init__(self, host, port, callbacks, control_channel): 303 def __init__(self, host, port, callbacks, control_channel):
301 self._connect_to = (host, int(port)) 304 self._connect_to = (host, int(port))
302 self._control_sock = None 305 self._control_sock = None
diff --git a/pydora/configure.py b/pydora/configure.py
index d31c097..d58d445 100644
--- a/pydora/configure.py
+++ b/pydora/configure.py
@@ -32,11 +32,13 @@ class PandoraKeysConfigParser:
32 the pandora API docs keys source file. 32 the pandora API docs keys source file.
33 """ 33 """
34 34
35 KEYS_URL = ("http://6xq.net/git/lars/pandora-apidoc.git/" 35 KEYS_URL = (
36 "plain/json/partners.rst") 36 "http://6xq.net/git/lars/pandora-apidoc.git/plain/json/partners.rst"
37 )
37 38
38 FIELD_RE = re.compile( 39 FIELD_RE = re.compile(
39 ":(?P<key>[^:]+): (?:`{2})?(?P<value>[^`\n]+)(?:`{2})?$") 40 ":(?P<key>[^:]+): (?:`{2})?(?P<value>[^`\n]+)(?:`{2})?$"
41 )
40 42
41 def _fixup_key(self, key): 43 def _fixup_key(self, key):
42 key = key.lower() 44 key = key.lower()
@@ -90,7 +92,7 @@ class PandoraKeysConfigParser:
90 key = self._clean_device_name(buffer.pop()) 92 key = self._clean_device_name(buffer.pop())
91 current_partner = partners[key] = { 93 current_partner = partners[key] = {
92 "api_host": self._format_api_host(api_host) 94 "api_host": self._format_api_host(api_host)
93 } 95 }
94 96
95 buffer.append(line.strip().lower()) 97 buffer.append(line.strip().lower())
96 98
@@ -165,8 +167,9 @@ class Configurator:
165 self.add_partner_config(self.get_partner_config()) 167 self.add_partner_config(self.get_partner_config())
166 self.get_value("user", "username", "Pandora Username: ") 168 self.get_value("user", "username", "Pandora Username: ")
167 self.get_password("user", "password", "Pandora Password: ") 169 self.get_password("user", "password", "Pandora Password: ")
168 self.set_static_value("api", "default_audio_quality", 170 self.set_static_value(
169 APIClient.HIGH_AUDIO_QUALITY) 171 "api", "default_audio_quality", APIClient.HIGH_AUDIO_QUALITY
172 )
170 173
171 self.write_config() 174 self.write_config()
172 175
diff --git a/pydora/player.py b/pydora/player.py
index fdacc63..c4ce2e0 100644
--- a/pydora/player.py
+++ b/pydora/player.py
@@ -132,8 +132,12 @@ class PlayerApp:
132 if song.is_ad: 132 if song.is_ad:
133 print("{} ".format(Colors.cyan("Advertisement"))) 133 print("{} ".format(Colors.cyan("Advertisement")))
134 else: 134 else:
135 print("{} by {}".format(Colors.cyan(song.song_name), 135 print(
136 Colors.yellow(song.artist_name))) 136 "{} by {}".format(
137 Colors.cyan(song.song_name),
138 Colors.yellow(song.artist_name),
139 )
140 )
137 141
138 def skip_song(self, song): 142 def skip_song(self, song):
139 if song.is_ad: 143 if song.is_ad:
@@ -183,13 +187,15 @@ class PlayerApp:
183 self.screen.print_error("Failed to bookmark artis") 187 self.screen.print_error("Failed to bookmark artis")
184 except NotImplementedError: 188 except NotImplementedError:
185 self.screen.print_error( 189 self.screen.print_error(
186 "Cannot bookmark artist for this type of track") 190 "Cannot bookmark artist for this type of track"
191 )
187 192
188 def sleep_song(self, song): 193 def sleep_song(self, song):
189 try: 194 try:
190 if song.sleep(): 195 if song.sleep():
191 self.screen.print_success( 196 self.screen.print_success(
192 "Song will not be played for 30 days") 197 "Song will not be played for 30 days"
198 )
193 self.player.stop() 199 self.player.stop()
194 else: 200 else:
195 self.screen.print_error("Failed to sleep song") 201 self.screen.print_error("Failed to sleep song")
@@ -214,10 +220,14 @@ class PlayerApp:
214 220
215 def help(self, song): 221 def help(self, song):
216 print("") 222 print("")
217 print("\n".join([ 223 print(
218 "\t{:>2} - {}".format(k, v[0]) 224 "\n".join(
219 for k, v in sorted(self.CMD_MAP.items()) 225 [
220 ])) 226 "\t{:>2} - {}".format(k, v[0])
227 for k, v in sorted(self.CMD_MAP.items())
228 ]
229 )
230 )
221 print("") 231 print("")
222 232
223 def input(self, input, song): 233 def input(self, input, song):
@@ -227,7 +237,8 @@ class PlayerApp:
227 cmd = getattr(self, self.CMD_MAP[input][1]) 237 cmd = getattr(self, self.CMD_MAP[input][1])
228 except (IndexError, KeyError): 238 except (IndexError, KeyError):
229 return self.screen.print_error( 239 return self.screen.print_error(
230 "Invalid command {!r}!".format(input)) 240 "Invalid command {!r}!".format(input)
241 )
231 242
232 cmd(song) 243 cmd(song)
233 244
@@ -240,21 +251,30 @@ class PlayerApp:
240 def pre_flight_checks(self): 251 def pre_flight_checks(self):
241 # See #52, this key no longer passes some server-side check 252 # See #52, this key no longer passes some server-side check
242 if self.client.partner_user == "iphone": 253 if self.client.partner_user == "iphone":
243 self.screen.print_error(( 254 self.screen.print_error(
244 "The `iphone` partner key set is no longer compatible with " 255 (
245 "pydora. Please re-run pydora-configure to re-generate " 256 "The `iphone` partner key set is no longer compatible "
246 "your config file before continuing.")) 257 "with pydora. Please re-run pydora-configure to "
258 "re-generate your config file before continuing."
259 )
260 )
247 sys.exit(1) 261 sys.exit(1)
248 262
249 def _parse_args(self): 263 def _parse_args(self):
250 parser = argparse.ArgumentParser( 264 parser = argparse.ArgumentParser(
251 description="command line Pandora player") 265 description="command line Pandora player"
266 )
252 parser.add_argument( 267 parser.add_argument(
253 "--vlc-net", dest="vlc_net", 268 "--vlc-net",
254 help="connect to VLC over the network (host:port)") 269 dest="vlc_net",
270 help="connect to VLC over the network (host:port)",
271 )
255 parser.add_argument( 272 parser.add_argument(
256 "-v", dest="verbose", action="store_true", 273 "-v",
257 help="enable verbose logging") 274 dest="verbose",
275 action="store_true",
276 help="enable verbose logging",
277 )
258 return parser.parse_args() 278 return parser.parse_args()
259 279
260 def run(self): 280 def run(self):
diff --git a/pydora/utils.py b/pydora/utils.py
index 6675773..5a96ff1 100644
--- a/pydora/utils.py
+++ b/pydora/utils.py
@@ -10,11 +10,11 @@ class TerminalPlatformUnsupported(Exception):
10 Raised by code that can not be used to interact with the terminal on this 10 Raised by code that can not be used to interact with the terminal on this
11 platform. 11 platform.
12 """ 12 """
13
13 pass 14 pass
14 15
15 16
16class Colors: 17class Colors:
17
18 def __wrap_with(raw_code): 18 def __wrap_with(raw_code):
19 @staticmethod 19 @staticmethod
20 def inner(text, bold=False): 20 def inner(text, bold=False):
@@ -22,6 +22,7 @@ class Colors:
22 if bold: 22 if bold:
23 code = "1;{}".format(code) 23 code = "1;{}".format(code)
24 return "\033[{}m{}\033[0m".format(code, text) 24 return "\033[{}m{}\033[0m".format(code, text)
25
25 return inner 26 return inner
26 27
27 red = __wrap_with("31") 28 red = __wrap_with("31")
@@ -44,6 +45,7 @@ class PosixEchoControl:
44 def __init__(self): 45 def __init__(self):
45 try: 46 try:
46 import termios 47 import termios
48
47 self.termios = termios 49 self.termios = termios
48 except ImportError: 50 except ImportError:
49 raise TerminalPlatformUnsupported("POSIX not supported") 51 raise TerminalPlatformUnsupported("POSIX not supported")
@@ -110,7 +112,6 @@ class Win32EchoControl:
110 112
111 113
112class Screen: 114class Screen:
113
114 def __init__(self): 115 def __init__(self):
115 try: 116 try:
116 self._echo_driver = PosixEchoControl() 117 self._echo_driver = PosixEchoControl()