diff --git a/bin/pylms b/bin/pylms index 8ee3722..4b6d9d0 100755 --- a/bin/pylms +++ b/bin/pylms @@ -1,7 +1,10 @@ #!/usr/bin/env python from __future__ import print_function -import os, sys, logging, optparse +import os +import sys +import logging +import optparse from pylms.server import Server from pylms.utils import clean_command @@ -15,36 +18,67 @@ PROJECT = "PyLMS" VERSION = "1.00" logger = logging.getLogger(__name__) -LOG_HELP = ','.join(["%d=%s" % (4-x, logging.getLevelName((x+1)*10)) for x in range(5)]) +LOG_HELP = ','.join( + ["%d=%s" % (4-x, logging.getLevelName((x+1)*10)) for x in range(5)]) LOG_FORMAT_CONS = '%(levelname)s: %(message)s' -LOG_FORMAT_FILE = '%(asctime)s %(name)s[%(process)d] %(levelname)10s %(message)s' -LOGLEVEL_DICT = { 1 : 50, 2:40, 3:20, 4:10, 5:1 } +LOG_FORMAT_FILE = '%(asctime)s %(name)s[%(process)d] ' \ + '%(levelname)10s %(message)s' +LOGLEVEL_DICT = {1: 50, 2: 40, 3: 20, 4: 10, 5: 1} DEFAULT_VERBOSITY = 3 VALID_COMMANDS = ["play", "stop", "pause", "unpause", "toggle", "next", "prev", "volume_up", "volume_down", "mute", "unmute", "seek_to", - "forward", "rewind", "set_power_state", "set_volume", "show", "display", "infos", - "get_ref", "get_uuid", "get_name", "get_ip_address", "get_model", "get_display_type", - "get_wifi_signal", "get_mode", "get_time_elapsed", "get_time_remaining", "get_power_state", - "get_ir_state", "get_volume", "get_bass", "get_treble", "get_pitch", "get_rate", "get_muting", - "get_track_genre", "get_track_artist", "get_track_album", "get_track_title", - "get_track_duration", "get_track_remote", "get_track_current_title", "get_track_path", - "randomplay", "search", "rescan", "rescanprogress"] + "forward", "rewind", "set_power_state", "set_volume", "show", + "display", "infos", "get_ref", "get_uuid", "get_name", + "get_ip_address", "get_model", "get_display_type", + "get_wifi_signal", "get_mode", "get_time_elapsed", + "get_time_remaining", "get_power_state", "get_ir_state", + "get_volume", "get_bass", "get_treble", "get_pitch", + "get_rate", "get_muting", "get_track_genre", + "get_track_artist", "get_track_album", "get_track_title", + "get_track_duration", "get_track_remote", + "get_track_current_title", "get_track_path", "randomplay", + "search", "rescan", "rescanprogress"] # Option Parsing -parser = optparse.OptionParser(usage="%prog or type %prog -h (--help) for help", description=__doc__, version=PROJECT + " v" + VERSION) - -parser.add_option("-v", action="count", dest="verbosity", default=DEFAULT_VERBOSITY, help="Verbosity. Add more -v to be more verbose (%s) [default: %%default]" % LOG_HELP) -parser.add_option("-l", "--logfile", dest="logfile", default=None, help = "Log to file instead of console" ) -parser.add_option("-s", "--host", dest="host", default="localhost", help="Specify Hostname of SqueezeCenter [default: %default]") -parser.add_option("-n", "--port", dest="port", default="9090", help="Specify Port of SqueezeCenter [default: %default]") -parser.add_option("-u", "--username", dest="username", default=None, help="Specify Authorisation Username") -parser.add_option("-p", "--password", dest="password", default=None, help="Specify Authorisation Password") -parser.add_option("-d", "--device", dest="device", default=None, help="Specify SqueezePlayer Device MAC Address") -parser.add_option("-i", "--info", dest="info", action="store_true", default=False, help="Show Server/Player Information") -parser.add_option("-r", "--raw", dest="raw", action="store_true", default=False, help="Output only minimal raw results (useful for scripts)") -parser.add_option("-q", "--quick", dest="quick", action="store_true", default=False, help="Perform a quick one-time action (does not query current device state)") +parser = optparse.OptionParser( + usage="%prog or type %prog -h (--help) for help", + description=__doc__, + version=PROJECT + " v" + VERSION) + +parser.add_option( + "-v", action="count", dest="verbosity", default=DEFAULT_VERBOSITY, + help="Verbosity. Add more -v to be more verbose (%s) " + "[default: %%default]" % LOG_HELP) +parser.add_option( + "-l", "--logfile", dest="logfile", default=None, + help="Log to file instead of console") +parser.add_option( + "-s", "--host", dest="host", default="localhost", + help="Specify Hostname of SqueezeCenter [default: %default]") +parser.add_option( + "-n", "--port", dest="port", default="9090", + help="Specify Port of SqueezeCenter [default: %default]") +parser.add_option( + "-u", "--username", dest="username", default=None, + help="Specify Authorisation Username") +parser.add_option( + "-p", "--password", dest="password", default=None, + help="Specify Authorisation Password") +parser.add_option( + "-d", "--device", dest="device", default=None, + help="Specify SqueezePlayer Device MAC Address") +parser.add_option( + "-i", "--info", dest="info", action="store_true", default=False, + help="Show Server/Player Information") +parser.add_option( + "-r", "--raw", dest="raw", action="store_true", default=False, + help="Output only minimal raw results (useful for scripts)") +parser.add_option( + "-q", "--quick", dest="quick", action="store_true", default=False, + help="Perform a quick one-time action (does not query " + "current device state)") (options, args) = parser.parse_args() @@ -57,12 +91,16 @@ if options.logfile is None: logging.basicConfig(level=verbosity, format=LOG_FORMAT_CONS) else: logfilename = os.path.normpath(options.logfile) - logging.basicConfig(level=verbosity, format=LOG_FORMAT_FILE, filename=logfilename, filemode='a') + logging.basicConfig( + level=verbosity, format=LOG_FORMAT_FILE, filename=logfilename, + filemode='a') print("Logging to %s" % logfilename, file=sys.stderr) # Main -sc = Server(hostname=options.host, port=options.port, username=options.username, password=options.password) +sc = Server( + hostname=options.host, port=options.port, username=options.username, + password=options.password) sc.logger = logger update_mode = not options.quick @@ -73,7 +111,8 @@ if options.info: try: sc.connect(update=update_mode) except: - logger.error("Cannot connect to server (%s:%s)" % (options.host, options.port)) + logger.error( + "Cannot connect to server (%s:%s)" % (options.host, options.port)) sys.exit(1) all_players = sc.players @@ -81,7 +120,10 @@ all_players = sc.players if options.info: logger.info("Server Version: %s" % (sc.get_version())) for p in all_players: - logger.info("Player: %s | %s | V: %i | M: %s | T: %s | C: %s | W: %s" % (p.ref, p.name, p.get_volume(), p.get_mode(), p.get_time_elapsed(), p.is_connected, p.get_wifi_signal_strength())) + logger.info( + "Player: %s | %s | V: %i | M: %s | T: %s | C: %s | W: %s" % + (p.ref, p.name, p.get_volume(), p.get_mode(), p.get_time_elapsed(), + p.is_connected, p.get_wifi_signal_strength())) players = [] if options.device == 'all': @@ -91,7 +133,7 @@ else: if sel_player: players.append(sel_player) -if options.device and len(players)==0: +if options.device and len(players) == 0: logger.error("Cannot find player %s" % (options.device)) sys.exit(1) @@ -102,8 +144,8 @@ if not args: command_map = {} for c in VALID_COMMANDS: - cleaned = clean_command(c) - command_map[cleaned] = c + cleaned = clean_command(c) + command_map[cleaned] = c cmd = clean_command(args[0]) @@ -114,12 +156,13 @@ except IndexError: raw_cmd = command_map.get(cmd) -if len(players)==0: +if len(players) == 0: #server command if cmd in command_map: func = getattr(sc, raw_cmd, None) try: - logger.debug("%s: %s [%s]" % ('server', raw_cmd.upper(), ", ".join(params))) + logger.debug( + "%s: %s [%s]" % ('server', raw_cmd.upper(), ", ".join(params))) result = func(*params) if options.raw: if result is not None: @@ -131,7 +174,8 @@ if len(players)==0: except ValueError: logger.error("Invalid parameter") except TypeError: - logger.error("Incorrect number of parameters or invalid type parameter") + logger.error( + "Incorrect number of parameters or invalid type parameter") else: @@ -140,7 +184,9 @@ else: if cmd in command_map: func = getattr(player, raw_cmd, None) try: - logger.debug("%s: %s [%s]" % (player.name, raw_cmd.upper(), ", ".join(params))) + logger.debug( + "%s: %s [%s]" % (player.name, raw_cmd.upper(), + ", ".join(params))) result = func(*params) if options.raw: if result is not None: @@ -148,11 +194,12 @@ else: else: if result is None: result = "No Output" - logger.info("[%s] %s" % (raw_cmd, result)) + logger.info("[%s] %s" % (raw_cmd, result)) except ValueError: logger.error("Invalid parameter") except TypeError: - logger.error("Incorrect number of parameters or invalid type parameter") + logger.error( + "Incorrect number of parameters or invalid " + "type parameter") else: logger.error("Invalid command or no device: %s" % (cmd)) - diff --git a/pylms/player.py b/pylms/player.py index 2a3a66b..7639f1f 100644 --- a/pylms/player.py +++ b/pylms/player.py @@ -21,13 +21,12 @@ class Player(object): - """ Player """ - + # internals - + def __init__(self, server=None, index=None, update=True, charset="utf8"): """ Constructor @@ -45,7 +44,7 @@ def __init__(self, server=None, index=None, update=True, charset="utf8"): self.is_player = None self.display_type = None self.can_power_off = None - self.wifi_signal_strength = None + self.wifi_signal_strength = None self.mode = None self.time = None self.power_state = None @@ -69,49 +68,46 @@ def __init__(self, server=None, index=None, update=True, charset="utf8"): def __repr__(self): return "Player: %s" % (self.ref) - + def request(self, command_string, preserve_encoding=False): """Executes Telnet Request via Server""" - return self.server.request("%s %s" % (self.ref, command_string), preserve_encoding) - + return self.server.request( + "%s %s" % (self.ref, command_string), preserve_encoding) + def update(self, index, update=True): """Update Player Properties from Server""" self.index = index - self.ref = str(self.__unquote( - self.server.request("player id %i ?" % index) - )) - self.name = str(self.__unquote( - self.server.request("player name %i ?" % index) - )) + self.ref = self.server.request("player id %i ?" % index) + self.name = self.server.request("player name %i ?" % index) if update: self.uuid = str(self.__unquote( self.server.request("player uuid %i ?" % index) )) self.ip_address = str(self.__unquote( self.server.request("player ip %i ?" % index) - )) + )) self.model = str(self.__unquote( self.server.request("player model %i ?" % index) - )) + )) self.display_type = str(self.__unquote( self.server.request("player displaytype %i ?" % index) )) self.can_power_off = bool(self.__unquote( self.server.request("player canpoweroff %i ?" % index) - )) + )) self.is_player = bool(self.__unquote( self.server.request("player isplayer %i ?" % index) - )) + )) self.is_connected = bool(self.__unquote( self.server.request("player connected %i ?" % index) - )) + )) ## getters/setters def get_ref(self): """Get Player Ref""" return self.ref - + def get_uuid(self): """Get Player UUID""" return self.uuid @@ -124,19 +120,19 @@ def set_name(self, name): """Set Player Name""" self.request("name %s" % (name)) self.update(self.index) - + def get_ip_address(self): """Get Player IP Address""" return self.ip_address - + def get_model(self): """Get Player Model String""" return self.model - + def get_display_type(self): """Get Player Display Type String""" return self.display_type - + def get_wifi_signal_strength(self): """Get Player WiFi Signal Strength""" self.wifi_signal_strength = self.request("signalstrength ?") @@ -147,7 +143,7 @@ def has_permission(self, request_terms): request_terms = self.__quote(request_terms) granted = int(self.request("can %s ?" % (request_terms))) return (granted == 1) - + def get_pref_value(self, name, namespace=None): """Get Player Preference Value""" pref_string = "" @@ -164,19 +160,19 @@ def set_pref_value(self, name, value, namespace=None): pref_string += namespace + ":" pref_string += name value = self.__quote(value) - valid = self.request("playerpref validate %s %s" % - (pref_string, value)) + valid = self.request( + "playerpref validate %s %s" % (pref_string, value)) if "valid:1" in valid: self.request("playerpref %s %s" % (pref_string, value)) return True else: return False - + def get_mode(self): """Get Player Mode""" self.mode = str(self.request("mode ?")) return self.mode - + def get_time_elapsed(self): """Get Player Time Elapsed""" try: @@ -184,7 +180,7 @@ def get_time_elapsed(self): except TypeError: self.time = float(0) return self.time - + def get_time_remaining(self): """Get Player Time Remaining""" if self.get_mode() == "play": @@ -192,17 +188,17 @@ def get_time_remaining(self): return remaining else: return 0 - + def get_power_state(self): """Get Player Power State""" state = int(self.request("power ?")) self.power_state = (state != 0) return self.power_state - + def set_power_state(self, state): """Set Player Power State""" self.request("power %i" % (int(state))) - self.get_power_state() + self.get_power_state() def get_ir_state(self): """Get Player Infrared State""" @@ -213,8 +209,8 @@ def get_ir_state(self): def set_ir_state(self, state): """Set Player Power State""" self.request("irenable %i" % (int(state))) - self.get_ir_state() - + self.get_ir_state() + def get_volume(self): """Get Player Volume""" try: @@ -223,27 +219,27 @@ def get_volume(self): self.volume = -1 except ValueError: self.volume = 0 - return self.volume + return self.volume def get_bass(self): """Get Player Bass""" self.bass = int(self.request("mixer bass ?")) - return self.bass + return self.bass def get_treble(self): """Get Player Treble""" self.treble = int(self.request("mixer treble ?")) - return self.treble + return self.treble def get_pitch(self): """Get Player Pitch""" self.pitch = int(self.request("mixer pitch ?")) return self.pitch - + def get_rate(self): """Get Player Rate""" self.rate = int(self.request("mixer rate ?")) - return self.rate + return self.rate def get_muting(self): """Get Player Muting Status""" @@ -255,7 +251,7 @@ def set_muting(self, state): """Set Player Muting Status""" self.request("mixer muting %i" % (int(state))) self.get_muting() - + def get_track_genre(self): """Get Players Current Track Genre""" self.track_genre = str(self.request("genre ?")) @@ -265,27 +261,27 @@ def get_track_artist(self): """Get Players Current Track Artist""" self.track_artist = str(self.request("artist ?")) return self.track_artist - + def get_track_album(self): """Get Players Current Track Album""" self.track_album = str(self.request("album ?")) return self.track_album - + def get_track_title(self): """Get Players Current Track Title""" self.track_title = str(self.request("title ?")) return self.track_title - + def get_track_duration(self): """Get Players Current Track Duration""" self.track_duration = float(self.request("duration ?")) - return self.track_duration - + return self.track_duration + def get_track_remote(self): """Is Players Current Track Remotely Hosted?""" remote = int(self.request("remote ?")) self.track_remote = (remote != 0) - return self.track_remote + return self.track_remote def get_track_current_title(self): """Get Players Current Track Current Title""" @@ -296,19 +292,19 @@ def get_track_path(self): """Get Players Current Track Path""" self.track_path = str(self.request("path ?")) return self.track_path - + # playlist - + def playlist_play(self, item): """Play Item Immediately""" item = self.__quote(item) - self.request("playlist play %s" % (item)) + self.request("playlist play %s" % (item)) def playlist_add(self, item): """Add Item To Playlist""" item = self.__quote(item) - self.request("playlist add %s" % (item)) - + self.request("playlist add %s" % (item)) + def playlist_insert(self, item): """Insert Item Into Playlist (After Current Track)""" item = self.__quote(item) @@ -318,7 +314,7 @@ def playlist_delete(self, item): """Delete Item From Playlist By Name""" item = self.__quote(item) self.request("playlist deleteitem %s" % (item)) - + def playlist_clear(self): """Clear the entire playlist. Will stop the player.""" self.request("playlist clear") @@ -326,19 +322,20 @@ def playlist_clear(self): def playlist_move(self, from_index, to_index): """Move Item In Playlist""" self.request("playlist move %i %i" % (from_index, to_index)) - + def playlist_erase(self, index): """Erase Item From Playlist""" self.request("playlist delete %i" % (index)) - + def playlist_track_count(self): """Get the amount of tracks in the current playlist""" return int(self.request('playlist tracks ?')) - + def playlist_play_index(self, index): - """Play track at a certain position in the current playlist (index is zero-based)""" + """Play track at a certain position in the current playlist + (index is zero-based)""" return self.request('playlist index %i' % index) - + def playlist_get_info(self): """Get info about the tracks in the current playlist""" amount = self.playlist_track_count() @@ -346,7 +343,8 @@ def playlist_get_info(self): encoded_list = response.split('playlist%20index')[1:] playlist = [] for encoded in encoded_list: - data = [self.__unquote(x) for x in ('position' + encoded).split(' ')] + data = [self.__unquote(x) for x in + ('position' + encoded).split(' ')] item = {} for info in data: info = info.split(':') @@ -358,31 +356,34 @@ def playlist_get_info(self): item['duration'] = float(item['duration']) playlist.append(item) return playlist - + # actions - - def show(self, line1="", - line2="", - duration=3, - brightness=4, - font="standard", - centered=False): + + def show( + self, + line1="", + line2="", + duration=3, + brightness=4, + font="standard", + centered=False): """Displays text on Player display""" if font == "huge": line1 = "" line1, line2 = self.__quote(line1), self.__quote(line2) req_string = "show line1:%s line2:%s duration:%s " req_string += "brightness:%s font:%s centered:%i" - self.request(req_string % - (line1, line2, str(duration), str(brightness), font, int(centered))) - - def display(self, line1="", - line2="", - duration=3): + self.request( + req_string % (line1, line2, str(duration), str(brightness), + font, int(centered))) + + def display(self, + line1="", + line2="", + duration=3): line1, line2 = self.__quote(line1), self.__quote(line2) req_string = "display %s %s %s" - self.request(req_string % - (line1, line2, str(duration))) + self.request(req_string % (line1, line2, str(duration))) def play(self): """Play""" @@ -411,14 +412,14 @@ def next(self): def prev(self): """Previous Track""" self.request("playlist jump -1") - + def set_volume(self, volume): """Set Player Volume""" try: - volume = int(volume) - if volume < 0: + volume = int(volume) + if volume < 0: volume = 0 - if volume > 100: + if volume > 100: volume = 100 self.request("mixer volume %i" % (volume)) except TypeError: @@ -428,9 +429,9 @@ def set_bass(self, bass): """Set Player Bass""" try: bass = int(bass) - if bass < -100: + if bass < -100: bass = -100 - if bass > 100: + if bass > 100: bass = 100 self.request("mixer bass %i" % (bass)) except TypeError: @@ -444,7 +445,7 @@ def bass_up(self, amount=5): def bass_down(self, amount=5): """Decrease Player Bass""" try: - amount = int(amount) + amount = int(amount) self.request("mixer bass -%i" % (amount)) self.get_bass() except TypeError: @@ -453,7 +454,7 @@ def bass_down(self, amount=5): def set_treble(self, treble): """Set Player Treble""" try: - treble = int(treble) + treble = int(treble) if treble < -100: treble = -100 if treble > 100: @@ -484,9 +485,9 @@ def set_pitch(self, pitch): """Set Player Pitch""" try: pitch = int(pitch) - if pitch < 80: + if pitch < 80: pitch = 80 - if pitch > 120: + if pitch > 120: pitch = 120 self.request("mixer pitch %i" % (pitch)) except TypeError: @@ -495,7 +496,7 @@ def set_pitch(self, pitch): def pitch_up(self, amount=5): """Increase Player Pitch""" try: - amount = int(amount) + amount = int(amount) self.request("mixer pitch +%i" % (amount)) self.get_pitch() except TypeError: @@ -504,7 +505,7 @@ def pitch_up(self, amount=5): def pitch_down(self, amount=5): """Decrease Player Pitch""" try: - amount = int(amount) + amount = int(amount) self.request("mixer pitch -%i" % (amount)) self.get_pitch() except TypeError: @@ -514,9 +515,9 @@ def set_rate(self, rate): """Set Player Rate""" try: rate = int(rate) - if rate < -4: + if rate < -4: rate = 4 - if rate > 4: + if rate > 4: rate = 4 self.request("mixer rate %i" % (rate)) except TypeError: @@ -552,20 +553,20 @@ def volume_up(self, amount=5): def volume_down(self, amount=5): """Decrease Player Volume""" try: - amount = int(amount) + amount = int(amount) self.request("mixer volume -%i" % (amount)) self.get_volume() except TypeError: pass - + def mute(self): """Mute Player""" self.set_muting(True) - + def unmute(self): """Unmute Player""" self.set_muting(False) - + def seek_to(self, seconds): """Seek Player""" try: @@ -573,12 +574,12 @@ def seek_to(self, seconds): self.request("time %s" % (seconds)) except TypeError: pass - + def forward(self, seconds=10): """Seek Player Forward""" try: seconds = int(seconds) - self.request("time +%s" % (seconds)) + self.request("time +%s" % (seconds)) except TypeError: pass @@ -586,13 +587,13 @@ def rewind(self, seconds=10): """Seek Player Backwards""" try: seconds = int(seconds) - self.request("time -%s" % (seconds)) + self.request("time -%s" % (seconds)) except TypeError: pass def ir_button(self, button): """Simulate IR Button Press""" - self.request("button %s" % (button)) + self.request("button %s" % (button)) def randomplay(self, type='tracks'): """play random mix""" @@ -605,7 +606,7 @@ def sync_to(self, other_player_ref): def unsync(self): """Unsync player""" self.request("sync -") - + def __quote(self, text): try: import urllib.parse diff --git a/pylms/server.py b/pylms/server.py index e68cdd1..b724686 100644 --- a/pylms/server.py +++ b/pylms/server.py @@ -22,7 +22,7 @@ import telnetlib import urllib from pylms.player import Player - + class Server(object): @@ -30,12 +30,14 @@ class Server(object): Server """ - def __init__(self, hostname="localhost", - port=9090, - username="", - password="", - charset="utf8"): - + def __init__( + self, + hostname="localhost", + port=9090, + username="", + password="", + charset="utf8"): + """ Constructor """ @@ -51,7 +53,7 @@ def __init__(self, hostname="localhost", self.player_count = 0 self.players = [] self.charset = charset - + def connect(self, update=True): """ Connect @@ -59,33 +61,37 @@ def connect(self, update=True): self.telnet_connect() self.login() self.get_players(update=update) - + def telnet_connect(self): """ Telnet Connect """ self.telnet = telnetlib.Telnet(self.hostname, self.port) - + def login(self): """ Login """ result = self.request("login %s %s" % (self.username, self.password)) self.logged_in = (result == "******") - + def request(self, command_string, preserve_encoding=False): """ Request """ # self.logger.debug("Telnet: %s" % (command_string)) self.telnet.write(self.__encode(command_string + "\n")) - response = self.__decode(self.telnet.read_until(self.__encode("\n"))[:-1]) + response = self.telnet.read_until(self.__encode("\n"))[:-1] if not preserve_encoding: - response = self.__unquote(response) + response = self.__decode(self.__unquote(response)) else: - command_string_quoted = command_string[0:command_string.find(':')] + command_string[command_string.find(':'):].replace(':',self.__quote(':')) + command_string_quoted = \ + command_string[0:command_string.find(':')] + \ + command_string[command_string.find(':'):].replace( + ':', self.__quote(':')) start = command_string.split(" ")[0] - if start in ["songinfo", "trackstat", "albums", "songs", "artists", "rescan", "rescanprogress"]: + if start in ["songinfo", "trackstat", "albums", "songs", "artists", + "rescan", "rescanprogress"]: if not preserve_encoding: result = response[len(command_string)+1:] else: @@ -95,13 +101,12 @@ def request(self, command_string, preserve_encoding=False): result = response[len(command_string)-1:] else: result = response[len(command_string_quoted)-1:] - result = result.strip() return result def request_with_results(self, command_string, preserve_encoding=False): """ Request with results - Return tuple (count, results, error_occured) + Return tuple (count, results, error_occurred) """ quotedColon = self.__quote(':') try: @@ -111,20 +116,23 @@ def request_with_results(self, command_string, preserve_encoding=False): resultStr = ' '+self.request(command_string, True) #get number of results count = 0 - if resultStr.rfind('count%s'%quotedColon)>=0: - count = int(resultStr[resultStr.rfind('count%s'%quotedColon):].replace('count%s'%quotedColon,'')) - #remove number of results from result string and cut result string by "id:" + if resultStr.rfind('count%s' % quotedColon) >= 0: + count = int(resultStr[resultStr.rfind( + 'count%s' % quotedColon):].replace( + 'count%s' % quotedColon, '')) + # remove number of results from result string and cut + # result string by "id:" idIsSep = True - if resultStr.find(' id%s'%quotedColon)<0: + if resultStr.find(' id%s' % quotedColon) < 0: idIsSep = False - if resultStr.find('count')>=0: + if resultStr.find('count') >= 0: resultStr = resultStr[:resultStr.rfind('count')-1] - results = resultStr.split(' id%s'%quotedColon) + results = resultStr.split(' id%s' % quotedColon) output = [] for result in results: result = result.strip() - if len(result)>0: + if len(result) > 0: if idIsSep: #fix missing 'id:' at beginning result = 'id%s%s' % (quotedColon, result) @@ -132,17 +140,16 @@ def request_with_results(self, command_string, preserve_encoding=False): item = {} for subResult in subResults: #save item - key,value = subResult.split(quotedColon,1) + key, value = subResult.split(quotedColon, 1) if not preserve_encoding: item[urllib.unquote(key)] = self.__unquote(value) else: item[key] = value output.append(item) - return count,output,False + return count, output, False except Exception as e: #error parsing results (not correct?) - return 0,[],True - + return 0, [], True def get_players(self, update=True): """ @@ -159,11 +166,13 @@ def get_player(self, ref=None): """ Get Player """ - ref = str(ref).lower() + if isinstance(ref, str): + ref = self.__decode(ref) + ref = ref.lower() if ref: for player in self.players: - player_name = str(player.name).lower() - player_ref = str(player.ref).lower() + player_name = player.name.lower() + player_ref = player.ref.lower() if ref == player_ref or ref in player_name: return player @@ -173,7 +182,7 @@ def get_version(self): """ self.version = self.request("version ?") return self.version - + def get_player_count(self): """ Get Number Of Players @@ -185,46 +194,50 @@ def search(self, term, mode='albums'): """ Search term in database """ - if mode=='albums': - return self.request_with_results("albums 0 50 tags:%s search:%s" % ("l", term)) - elif mode=='songs': - return self.request_with_results("songs 0 50 tags:%s search:%s" % ("", term)) - elif mode=='artists': - return self.request_with_results("artists 0 50 search:%s" % (term)) + if mode == 'albums': + return self.request_with_results( + "albums 0 50 tags:%s search:%s" % ("l", term)) + elif mode == 'songs': + return self.request_with_results( + "songs 0 50 tags:%s search:%s" % ("", term)) + elif mode == 'artists': + return self.request_with_results( + "artists 0 50 search:%s" % (term)) def rescan(self, mode='fast'): """ Rescan library - Mode can be 'fast' for update changes on library, 'full' for complete library scan and 'playlists' for playlists scan only + Mode can be 'fast' for update changes on library, 'full' for + complete library scan and 'playlists' for playlists scan only """ is_scanning = True try: is_scanning = bool(self.request("rescan ?")) except: pass - + if not is_scanning: - if mode=='fast': + if mode == 'fast': return self.request("rescan") - elif mode=='full': + elif mode == 'full': return self.request("wipecache") - elif mode=='playlists': + elif mode == 'playlists': return self.request("rescan playlists") else: return "" - + def rescanprogress(self): """ Return current rescan progress """ return self.request_with_results("rescanprogress") - + def __encode(self, text): return text.encode(self.charset) - + def __decode(self, bytes): return bytes.decode(self.charset) - + def __quote(self, text): try: import urllib.parse diff --git a/pylms/utils.py b/pylms/utils.py index 035dd60..4a1da30 100644 --- a/pylms/utils.py +++ b/pylms/utils.py @@ -2,4 +2,5 @@ def clean_command(value): """ Strips whitespace, underscores dashes and lowercases value """ - return value.strip().lower().replace("_", "").replace("-", "").replace(" ", "") \ No newline at end of file + return value.strip().lower().replace("_", "").replace("-", "")\ + .replace(" ", "")