class SqueezeBox(Plugin): def __init__(self): self.deviceManager = DeviceManager(self.context) self.loaded = False if self.config('hostname') != '': self.setHostname(self.config('hostname')) def configWasUpdated(self, key, value): if key == 'hostname': self.setHostname(value) def setHostname(self, hostname): if self.loaded: logging.warning('Cannot change hostname, without a restart') return self.sc = Server(hostname=hostname) try: self.sc.connect() except: logging.error("Cannot connect to squeezebox server") return for player in self.sc.players: self.deviceManager.addDevice(Player(player)) self.deviceManager.finishedLoading('squeezebox') self.loaded = True
def lmsLogon(self, host, port): try: sc = Server(hostname=host, port=port) sc.connect() except: sc = None return sc
def play_music(): sc = Server(hostname="10.0.0.1", port=9090, username="******", password="******") sc.connect() p=sc.get_player('00:04:20:17:5b:41') p.playlist_play("file:///volume1/hdtl/Music/H3MusicArchive/Amazon%20MP3/Sam%20The%20Sham%20&%20The%20Pharaohs/20th%20Century%20Masters_%20The%20Millenium%20Collection_%20Best%20Of%20Sam%20The%20Sham%20&%20The%20Pharaohs/02%20-%20Lil%27%20Red%20Riding%20Hood.mp3") p.play() p.seek_to(0)
def lmsLogon(self, host, port): """Log on to the Logitect Server and return a Server object.""" try: sc = LMSServer(hostname=host, port=port) sc.connect() except: sc = None return sc
def local_change_process(textSync, text2Sync, volumeSync, playingSync, MAC, host, port): try: sc = Server(hostname=host, port=port) sc.connect(update=False) print "Logged in: %s" % sc.logged_in print "Version: %s" % sc.get_version() localVolume = volumeSync.value localPlaying = playingSync.value player = sc.get_player(unicode(MAC)) if player: localVolume = player.get_volume() text2Sync.value = player.get_name() volumeSync.value = localVolume print player.get_mode() mode = player.get_mode() if mode == "play": localPlaying = 1 elif mode == "stop": localPlaying = -1 else: localPlaying = 0 playingSync.value = localPlaying print "Controlling player: %s (%s)" % (player.get_name(), MAC) else: print "No Player found" while (1): if player: if localVolume != volumeSync.value: # Volume Changed by hardware localVolume = volumeSync.value player.set_volume(localVolume) if localPlaying != playingSync.value: # State Changed by hardware localPlaying = playingSync.value if localPlaying == 1: player.unpause() elif localPlaying == 0: player.pause() elif localPlaying == -1: pass# stop time.sleep(0.5) except (KeyboardInterrupt, SystemExit): print "Exiting Player Update Process"
def connect_to_server(self): server = Server(hostname=self.server_hostname, port=self.server_port) server.connect() logger = logging.getLogger("LMS") logger.info("Logged in: %s" % server.logged_in) logger.info("Version: %s" % server.get_version()) return server
class MusicServer(object): """ @summary: Music server class that provides function to interrupt with new song """ def __init__(self): self.server = Server(hostname=SERVER, port=9090) self.server.connect() def interrupt(self, filename): players = self.server.get_players() for player in players: player.playlist_play(filename)
def setHostname(self, hostname): if self.loaded: logging.warning('Cannot change hostname, without a restart') return self.sc = Server(hostname=hostname) try: self.sc.connect() except: logging.error("Cannot connect to squeezebox server") return for player in self.sc.players: self.deviceManager.addDevice(Player(player)) self.deviceManager.finishedLoading('squeezebox') self.loaded = True
def connect_to_player_at_server(playername, hostname): """Connects to a Squeezbox player connected to a server by their name. Args: playername (string): name of player hostname (string): hostname of Squeezbox server Returns: pylms.player.Player """ server = Server(hostname=hostname) server.connect() players = [ply for ply in server.get_players() if ply.name == playername] if len(players) < 1: raise RuntimeError(('No player named %s connected to ' 'server named %s') % (playername, hostname)) return players[0]
def __init__(self,basicOnly=False): #optionally pass in a player MAC here to connect to a different player for the info display #if MAC is not None: # log("Using MAC " + MAC) # PLAYERMAC = MAC #serverIP still null, something went wrong... if SERVERIP=="": notify("Can't find LMS server","Try manually configuring one in XSqueeze settings") sys.exit() log("Attempting to connect to LMS named [" + SERVERNAME + "] at IP: " + SERVERIP + " on CLI port: " + SERVERPORT) try: self.sc = Server(hostname=SERVERIP, port=SERVERPORT, username=SERVERUSER, password=SERVERPASS) self.sc.connect() log( "LMS Logged in: %s" % self.sc.logged_in ) log( "LMS Version: %s" % self.sc.get_version() ) except: log(" Couldn't connect to server!") notify(LANGUAGE(19613),LANGUAGE(19614)) raise #connect to player log( "Attempting to connect to player: " + PLAYERMAC) try: self.sb = self.sc.get_player(PLAYERMAC) if self.sb: log( "Connected to: %s" % PLAYERMAC ) state = self.sb.get_power_state() log ( "Power state is: " + str (state) ) else: log( "Player is None! %s" % PLAYERMAC ) raise Exception except Exception as inst: log(" Couldn't connect to player: " + PLAYERMAC , inst) notify(LANGUAGE(19615),LANGUAGE(19616)) raise #initialise if we're called from XSqueeze as opposed to the chooser try: if not basicOnly: self.currentTrack = None self.coverURLs = None self.playlistDetails = None self.updatePlaylistDetails() self.updateCoverArtURLs() #if the user wants music to start straight away... if SENDPLAYONSTART: self.sb.request("play") except Exception as inst: log(" Error in initialisation of XSqueeze after connection to: " + PLAYERMAC , inst) raise
def player_change_process(textSync, volumeSync, playingSync, mac, host, port): try: # Http version sv = Server(hostname=host, port=port) sv.connect(update=False) # Telnet sc = RClient(hostname=host, port=port, mac_filter=mac, textSync=textSync, playingSync=playingSync, volumeSync=volumeSync) sc.connect(update=False) print "Logged in: %s" % sv.logged_in print "Version: %s" % sv.get_version() sc.hplayer = sv.get_player(mac) trackname = sc.hplayer.get_track_title().strip() artist = sc.hplayer.get_track_artist().strip() sc.setText(artist, trackname) sc.start() except (KeyboardInterrupt, SystemExit): print "Exiting LMS Telnet Process"
class SqueezyPiMonitor(threading.Thread): def __init__(self, status_deque): threading.Thread.__init__(self) self.status_deque = status_deque def connect_server(self, server_config): """Connect to a Logitech Media server.""" self.server = Server(hostname=server_config.hostname, port=server_config.port, username=server_config.username, password=server_config.password) self.server.connect() def connect_player(self, player_config): """Connect to the Squeezeslave player (must be connected to a server).""" self.player = self.server.get_player(player_config.name) def run(self): status = PlayerStatus() while True: status.update_track_artist(self.player.get_track_artist()) status.update_track_title(self.player.get_track_title()) status.update_time_elapsed(self.player.get_time_elapsed()) self.status_deque.append(status) time.sleep(1)
def local_change_process(textSync, text2Sync, volumeSync, playingSync, MAC, host, port): try: sc = Server(hostname=host, port=port) sc.connect(update=False) print "Logged in: %s" % sc.logged_in print "Version: %s" % sc.get_version() localVolume = volumeSync.value localPlaying = playingSync.value player = sc.get_player(unicode(MAC)) if player: localVolume = player.get_volume() text2Sync.value = player.get_name() volumeSync.value = localVolume print player.get_mode() mode = player.get_mode() if mode == "play": localPlaying = 1 elif mode == "stop": localPlaying = -1 else: localPlaying = 0 playingSync.value = localPlaying print "Controlling player: %s (%s)" % (player.get_name(), MAC) else: print "No Player found" while (1): if player: if localVolume != volumeSync.value: # Volume Changed by hardware localVolume = volumeSync.value player.set_volume(localVolume) if localPlaying != playingSync.value: # State Changed by hardware localPlaying = playingSync.value if localPlaying == 1: player.unpause() elif localPlaying == 0: player.pause() elif localPlaying == -1: pass # stop time.sleep(0.5) except (KeyboardInterrupt, SystemExit): print "Exiting Player Update Process"
class PySqueezelite(object): """A small wrapper for launching squeezelite from within python scripts. Optional keyword arguments: path: path to squeezelite (defaults to /usr/bin/squeezelite) plname: name of player mac: mac address server: ipaddress of LMS (if not set, squeezelite will use discovery) args: other command line args to pass to squeezelite. lmsport: LMS server port (default 9000) telnetport: port for telnet communication to LMS (default 9090) Will raise SqueezeliteError if unable to locate squeezelite at given path. Will also raise error if no server and lms port are set and the scripts cannot locate the server using ssdp discovery. Methods: start: starts the squeezelite process kill: terminate the squeezelite process connect: connects to the LMS server to get track info get_player_info: retrieve additional player attributes play_pause: toggle the playback stop: stop playback next_track: play next track in playlist prev_track: play previous track in playlist Properties: track_title: track name track_artist: artist name track_album: album name track_duration: length of track track_time: time elapsed """ def __init__(self, path="/usr/bin/squeezelite", plname="Squeezelite", mac="12:34:56:78:90:AB", server=None, args=None, lmsport=9000, telnetport=9090): # Set relevant constants for this player self.path = path self.playername = plname self.mac = mac self.server = server self.args = args self.lmsport=lmsport self.telnetport=telnetport # Check if squeezelite can be found and alert user if not if not os.path.isfile(self.path): raise PySqueezeliteError("Can't find " "squeezelite at {}".format(self.path)) def start(self): """Launches the squeezelite player.""" if not self.server: self.server = self.__discover_server() # Default command. "-z" flag daemonises process. command = [self.path, "-z"] # Set player name if self.playername: command += ["-n", self.playername] # Set MAC address if self.mac: command += ["-m", self.mac] # Set server address if self.server: command += ["-s", self.server] # Add other args if self.args: command += [self.args] # Launch player subprocess.call(command) self.connect(self.server, self.telnetport) def kill(self): """Kills all instances of squeezelite found on the machine.""" # Get the PIDs of all matching processes pids = subprocess.check_output(["pidof", self.path]).strip() # Loop through and kill them! for pid in pids.split(" "): subprocess.call(["kill", "-9", pid]) def __discover_server(self): self.devices = [x for x in discover("ssdp:all") if x] self.matches = [x.ip for x in self.devices if x.port == self.lmsport] if len(self.matches) > 1: raise PySqueezeliteError("Multiple servers found on " "port {}. Need to set server ip address " "when calling " "PySqueezelite.".format(self.lmsport)) elif len(self.matches) == 0: raise PySqueezeliteError("No servers found on " "port {}. Please check LMS is " "running and the correct " "port has been set.".format(self.lmsport)) else: return self.matches[0] def connect(self, hostname="localhost", port=9090): self.sc = Server(hostname=hostname, port=port) self.sc.connect() self.player = self.sc.get_player(self.mac) def get_player_info(self, info): if not self.player: self.connect if hasattr(self.player, info): return getattr(self.player, info)() else: return None def play_pause(self): self.player.toggle() def stop(self): self.player.stop() def next_track(self): self.player.next() def prev_track(self): self.player.prev() @property def track_title(self): return self.get_player_info("get_track_title") @property def track_artist(self): return self.get_player_info("get_track_artist") @property def track_album(self): return self.get_player_info("get_track_album") @property def track_duration(self): return self.get_player_info("get_track_duration") @property def track_time(self): return self.get_player_info("get_time_elapsed")
def connect(self, hostname="localhost", port=9090): self.sc = Server(hostname=hostname, port=port) self.sc.connect() self.player = self.sc.get_player(self.mac)
class SqueezePlayer: ############################################################################## #constructor - connect to the server and player so we can do stuff #other handy start up stuff def __init__(self,basicOnly=False): #optionally pass in a player MAC here to connect to a different player for the info display #if MAC is not None: # log("Using MAC " + MAC) # PLAYERMAC = MAC #serverIP still null, something went wrong... if SERVERIP=="": notify("Can't find LMS server","Try manually configuring one in XSqueeze settings") sys.exit() log("Attempting to connect to LMS named [" + SERVERNAME + "] at IP: " + SERVERIP + " on CLI port: " + SERVERPORT) try: self.sc = Server(hostname=SERVERIP, port=SERVERPORT, username=SERVERUSER, password=SERVERPASS) self.sc.connect() log( "LMS Logged in: %s" % self.sc.logged_in ) log( "LMS Version: %s" % self.sc.get_version() ) except: log(" Couldn't connect to server!") notify(LANGUAGE(19613),LANGUAGE(19614)) raise #connect to player log( "Attempting to connect to player: " + PLAYERMAC) try: self.sb = self.sc.get_player(PLAYERMAC) if self.sb: log( "Connected to: %s" % PLAYERMAC ) state = self.sb.get_power_state() log ( "Power state is: " + str (state) ) else: log( "Player is None! %s" % PLAYERMAC ) raise Exception except Exception as inst: log(" Couldn't connect to player: " + PLAYERMAC , inst) notify(LANGUAGE(19615),LANGUAGE(19616)) raise #initialise if we're called from XSqueeze as opposed to the chooser try: if not basicOnly: self.currentTrack = None self.coverURLs = None self.playlistDetails = None self.updatePlaylistDetails() self.updateCoverArtURLs() #if the user wants music to start straight away... if SENDPLAYONSTART: self.sb.request("play") except Exception as inst: log(" Error in initialisation of XSqueeze after connection to: " + PLAYERMAC , inst) raise ############################################################################## #get the current squeezebox two line display text and return it def getDisplay(self): displayText = self.sb.requestRaw("display ? ?", True) lines = displayText.split(" ") try: if lines[2] == "": lines[2] = "." except: lines[2] = "." try: if lines[3] == "": lines[3] = "." except: lines[3]="." cleanedLines=[] cleanedLines.append((lines[2])) cleanedLines.append((lines[3])) #print(cleanedLines) #clean out the wierd characters used to represent volume... newLines=[] for line in cleanedLines: line = line.replace(u'cursorpos', u"\u2334") line = line.replace(u'rightarrow', u"\u2192") line = line.replace(u'solidblock', u'*') line = line.replace(u'leftprogress4', u'*') line = line.replace(u'leftprogress2', u'*') line = line.replace(u'leftprogress0', u'(Mute)') line = line.replace(u'rightprogress0', u' ') line = line.replace(u'rightprogress4', u'(Max)') line = line.replace(u'middleprogress0', u' ') line = line.replace(u'%1E',u"") line = line.replace(u'%1F',u"") newLines.append(line) #print(newLines) return unquoteUni(newLines[0]), unquoteUni(newLines[1]) ############################################################################## # check if song changed and update local reference if so # returns boolean - but of course only once on each change # called every window update to see if the song has changed and only if it has # do we update the playlist and cover arts...reduces traffic a lot! def songChanged(self): oldSong = self.currentTrack newSong = self.sb.get_track_title() #log("New Song [" + newSong +"], Old song [" + oldSong + "]") if newSong != oldSong: log("### Detected song change to: " + repr(newSong) + " - triggering playlist and cover art updates...") self.currentTrack = newSong self.updatePlaylistDetails() self.updateCoverArtURLs() return True; else: return False ############################################################################## # returns the URLs for the current and next three track cover art images def updateCoverArtURLs(self): coverURLs = [] #print "Playlist is" + str(self.playlist) #start at this song , end at + 3 index = int(self.sb.request("playlist index ?")) upcomer = index end = index + 4 #currently uses the track_id in the url - works well #supposed to use the cover_id number but this doesn't work so well... for count in range(upcomer,end): if(count<len(self.playlist)): try: statusInfo = self.sb.request("status " + str(count) + " 1 tags:Kal") #log("Status info is " + str(statusInfo)) if("artwork_url" in statusInfo): statusArtwork = statusInfo.split('artwork_url:') statusArtwork = statusArtwork.pop(1) statusArtwork = statusArtwork.split(' ') statusArtwork = statusArtwork.pop(0) #log("statusArtwork is " + str(statusArtwork)) #check we have a full url.... if("http" not in statusArtwork): coverURL = "http://" + SERVERHTTPURL + "/" + statusArtwork else: coverURL = statusArtwork else: statusId = statusInfo.split('id:') statusId = statusId.pop(1) statusId = statusId.split(' ') statusId = statusId.pop(0) #log("StatusID is " + str(statusId)) coverURL = "http://" + SERVERHTTPURL + "/music/" + str(statusId) + "/cover.jpg" #now append the coverURL to our list of URLs #log ("Appending future cover: " + str(count) + " from " + coverURL) coverURLs.append(coverURL) #Something went wrong, go with null string just to be safe... except Exception as inst: log("No cover art so appending null string for playlist index " + str(count), inst) coverURLs.append("") self.coverURLs = coverURLs ## ############################################################################## ## # Gets more info about a particular song def getSongInfo(self, id): encoded = self.sb.requestRaw("songinfo 0 1000 track_id:" + str(id), True) #find the index of id: - track_id%3A start = encoded.find('track_id%3A') encoded = encoded[start:] #print(str(id) + " Encoded: " +str(encoded)) list = encoded.split(" ") #print("list: " + str(list)) decodedList = [] for item in list: cleanItem = unquoteUni(item) decodedList.append(cleanItem) #print("DecodedList: " +str(decodedList)) item = {} for info in decodedList: info = info.split(':') key = info.pop(0) if key: item[key] = ':'.join(info) # example... # 9 id:39 title:I'm Not The Man artist:10000 Maniacs coverid:94339a48 duration:226.36 album_id:4 filesize:22796274 genre:Pop coverart:1 artwork_track_id:94339a48 # album:MTV Unplugged modificationTime:Thursday, November 27, 2008, 5:24 PM type:flc genre_id:4 bitrate:805kbps VBR artist_id:11 tracknum:4 year:1993 compilation:0 # addedTime:Thursday, December 8, 2011, 11:15 PM channels:2 samplesize:16 samplerate:44100 lastUpdated:Thursday, December 8, 2011, 11:15 PM album_replay_gain:-6.46 replay_gain:-3.46 #print "Item" + str(item) #convert all the data to the right types - there is a much more pythomnesque way to right this I am sure... try: item['id'] = int(item['id']) except KeyError: pass try: item['duration'] = float(item['duration']) except KeyError: pass try: item['album_id'] = int(item['album_id']) except KeyError: pass try: item['filesize'] = int(item['filesize']) except KeyError: pass try: item['coverart'] = int(item['coverart']) except KeyError: pass try: item['genre_id'] = int(item['genre_id']) except KeyError: pass try: item['artist_id'] = int(item['artist_id']) except KeyError: pass try: item['tracknum'] = int(item['tracknum']) except KeyError: pass try: item['year'] = int(item['year']) except KeyError: pass try: item['compilation'] = int(item['compilation']) except KeyError: pass try: item['channels'] = int(item['channels']) except KeyError: pass try: item['samplesize'] = int(item['samplesize']) except KeyError: pass try: item['samplerate'] = int(item['samplerate']) except KeyError: pass try: item['album_replay_gain'] = float(item['album_replay_gain']) except KeyError: pass try: item['replay_gain'] = float(item['replay_gain']) except KeyError: pass return item ############################################################################## # Send a button command text, e.g. 'pause' - to the player def button(self, text): self.sb.ir_button(text) #something probably changed, trigger an update test self.songChanged() ############################################################################## # returns all the details of up to 10 tracks... def updatePlaylistDetails(self): self.playlist = self.sb.playlist_get_info() currentIndex = int(self.sb.request("playlist index ?")) #log ("Current index: " + str(currentIndex) + " len(playlist): " + str(len(self.playlist)) + " Playlist is: " + str(self.playlist)) playlistDetails = [] #retrieve a maxiumum of 10 tracks details for trackOffset in range(currentIndex,currentIndex+10): #don't go off the end of the playlist if trackOffset < len(self.playlist): trackID = self.playlist[trackOffset]['id'] #log("Getting full details for id: " + str(trackID)) playlistDetails.append(self.getSongInfo(trackID)) #the caller should check the length of the playlist and process all entries... self.playlistDetails = playlistDetails ############################################################################## # returns current track length if available (check for 0 etc. at other end) def getTrackLength(self): return self.sb.get_track_duration() ############################################################################## # Show some text on the player's screen def show(self,line1="", line2=""''"", duration=3, brightness=4, font="standard", centered=False): self.sb.show(line1,line2,duration,brightness,font,centered) def display(self, line1="", line2="", duration=1): self.sb.request("display " + line1 + " " + line2 + " " + str(duration)) ############################################################################## # returns current mode ('play' 'pause' or 'stop') def getMode(self): return self.sb.get_mode() ############################################################################## # returns length of time in seconds the current track has played for def getTrackElapsed(self): return self.sb.get_time_elapsed() ############################################################################## # returns the full album info given an ID def getAlbumInfo(self, albumID): fullAlbumInfo = self.sc.request_with_results('albums 0 1 album_id:' + albumID + ' tags:yajl') #log("Full Album Info: " + str(fullAlbumInfo)) return fullAlbumInfo[1][0] ############################################################################## # returns the latest 50 albums def getNewMusic(self): fullAlbums = [] albums = self.sc.request_with_results("albums 0 50 sort:new") for album in albums[1]: fullAlbumInfo = self.getAlbumInfo(album['id']) fullAlbums.append(fullAlbumInfo) return fullAlbums ############################################################################## # returns all albums def getAlbums(self): fullAlbums = [] albums = self.sc.request_with_results("albums 0 100000") for album in albums[1]: fullAlbumInfo = self.getAlbumInfo(album['id']) fullAlbums.append(fullAlbumInfo) return fullAlbums ############################################################################## # returns all artists def getArtists(self): artists = self.sc.request_with_results("artists 0 100000") #log(str(artists)) return artists[1] ############################################################################## # returns all albums by a particular artist given an artist_id def getAlbumsByArtistID(self,artistID): fullAlbums = [] albums = self.sc.request_with_results("albums 0 100000 artist_id:" + str(artistID)) #log(str(albums)) for album in albums[1]: fullAlbumInfo = self.getAlbumInfo(album['id']) fullAlbums.append(fullAlbumInfo) return fullAlbums ############################################################################## # returns all albums in a particular genre given a genre_id def getAlbumsByGenreID(self,genreID): fullAlbums = [] albums = self.sc.request_with_results("albums 0 100000 genre_id:" + str(genreID)) #log(str(albums)) for album in albums[1]: fullAlbumInfo = self.getAlbumInfo(album['id']) fullAlbums.append(fullAlbumInfo) return fullAlbums ############################################################################## # returns all albums for a given year def getAlbumsByYear(self,year): fullAlbums = [] albums = self.sc.request_with_results("albums 0 100000 year:" + str(year)) #log(str(albums)) for album in albums[1]: fullAlbumInfo = self.getAlbumInfo(album['id']) fullAlbums.append(fullAlbumInfo) return fullAlbums ############################################################################## # returns all genres def getGenres(self): genres = self.sc.request_with_results("genres 0 100000") log(str(genres)) return genres[1][1:] ############################################################################## # returns all years def getYears(self): years = self.parseSpecial("years 0 100000", "year", True) #log(str(years)) years.reverse() return years ############################################################################## # returns radios root menu def parseSpecial(self, cmdString, splitOn, playerRequest=False): quotedColon = urllib.quote(':') if playerRequest: log("Player Request: " + str(cmdString)) results = self.sb.requestRaw(cmdString) else: log("Server Request: " + str(cmdString)) results = self.sc.requestRaw(cmdString) log("Result string: "+ pprint.pformat(results)) #strip off the request stuff at the start resultStr = results[results.find(splitOn):] log("Split string: "+ pprint.pformat(resultStr)) #ok now split the string on 'splitOn' to get each radio station chunks = resultStr.split(splitOn + "%3A")[1:] log("Processed Chunks: " + pprint.pformat(chunks)) output=[] for chunk in chunks: chunk = chunk.strip() subResults = chunk.split(" ") #log("SUB: " + str(subResults)) #fix missing splitOn post split subResults[0] = splitOn + "%3A" + subResults[0] #log("SUB + splitOn: " + str(subResults)) item={} for subResult in subResults: #save item key,value = subResult.split(quotedColon,1) item[unquoteUni(key)] = unquoteUni(value) output.append(item) return output def getRadios(self): return self.parseSpecial("radios 0 100000", "icon", playerRequest=True) def getRadioStations(self, cmd, itemid): if(itemid)!="" and itemid is not None: return self.parseSpecial(urllib.quote(cmd) + " items 0 100000 item_id:" + itemid,"id",playerRequest=True) else: return self.parseSpecial(urllib.quote(cmd) + " items 0 100000","id",playerRequest=True) def getAppItemsList(self, cmd, itemid): if(itemid)!="" and itemid is not None: return self.parseSpecial(urllib.quote(cmd) + " items 0 100000 item_id:" + itemid,"id",playerRequest=True) else: return self.parseSpecial(urllib.quote(cmd) + " items 0 100000","id",playerRequest=True) def getFavouritesSub(self, itemid): return self.parseSpecial("favorites items 0 100000 item_id:" + itemid,"id",playerRequest=True) def queueRadio(self, cmd, itemid): self.sb.request(urllib.quote(cmd) + " playlist play item_id:" + itemid) def getApps(self): return self.parseSpecial("apps 0 100000","cmd", playerRequest=True) def getFavourites(self): return self.parseSpecial("favorites items 0 100000","id", playerRequest=True) def getPlaylists(self): #return self.parseSpecial("playlists 0 100000","id", playerRequest=True) pls = self.sc.request_with_results("playlists 0 100000 tags:u") log(str(pls)) return pls[1][1:] ############################################################################## # Clear playlist and queue up a favourite item given def queueFavourite(self, item_id): self.sb.request("favorites playlist play item_id:" + item_id) ############################################################################## # Clear playlist and queue up a playlist item given def queuePlaylist(self, item_id, url): self.sb.request("playlist play " + url) ############################################################################## # Clear playlist and queue up an album given an album title and artist def queueAlbum(self, title, artist): if artist=="Various Artists": self.sb.request("playlist loadalbum * * " + urllib.quote(title)) else: self.sb.request("playlist loadalbum * " + urllib.quote(artist) + " " + urllib.quote(title)) ############################################################################## # Clear playlist and queue up random albums def playRandomAlbums(self): self.sb.request("randomplay albums") ############################################################################## # Clear playlist and queue up random songs def playRandomTracks(self): self.sb.request("randomplay tracks") ############################################################################## # Clear playlist and queue up random songs def getShuffle(self): state = int(self.sb.request("playlist shuffle ?")) if state==0: return False else: return True def setShuffle(self): state = int(self.sb.request("playlist shuffle ?")) if state==0: state = 1 notify("Shuffle Playlist: ON","") else: state = 0 notify("Shuffle Playlist: OFF","") self.sb.request("playlist shuffle "+ str(state), debug=True) self.updatePlaylistDetails() def getRepeat(self): state = int(self.sb.request("playlist repeat ?")) if state==0: return False else: return True def setRepeat(self): state = int(self.sb.request("playlist repeat ?")) if state==0: state = 2 notify("Repeat Playlist: ON") else: state = 0 notify("Repeat Playlist: OFF") self.sb.request("playlist repeat "+ str(state), debug=True) def rewind(self): self.sb.rewind() def forward(self): self.sb.forward() def getVolume(self): return self.sb.get_volume() def getPowerState(self): return self.sb.get_power_state()
def __init__(self): self.server = Server(hostname=SERVER, port=9090) self.server.connect()
#!/usr/bin/env python from pylms.server import Server from pylms.player import Player sc = Server(hostname="192.168.16.2", port=9090) sc.connect() print "Logged in: %s" % sc.logged_in print "Version: %s" % sc.get_version() sq = sc.get_player("00:00:00:00:00:44") #print "Name: %s | Mode: %s | Time: %s | Connected: %s | WiFi: %s" % (sq.get_name(), sq.get_mode(), sq.get_time_elapsed(), sq.is_connected, sq.get_wifi_signal_strength()) #print sc.request("radios 0 100000") #print sq.request("local items 0 100000") #print sq.request("local playlist play item_id:7cec804f.15") print sq.request("playlist play file:///E:/Public%20Shares/Music/Playlists/Test%20JD.m3u")
#!/usr/bin/env python from pylms.server import Server from pylms.player import Player sc = Server(hostname="10.0.0.1", port=9090, username="******", password="******") sc.connect() print "Logged in: %s" % sc.logged_in print "Version: %s" % sc.get_version() print "Num players: %s" % sc.get_player_count() print "Players: %s" % sc.get_players() players = sc.get_players() print ("Type of player = %s" % type(players)) for p in players: print "Player number %s" % p #sq = sc.get_player("00:11:22:33:44:55") print "Name: %s | Mode: %s | Time: %s | Connected: %s | WiFi: %s" % (p.get_name(), p.get_mode(), p.get_time_elapsed(), p.is_connected, p.get_wifi_signal_strength()) print p.get_track_title() print p.get_time_remaining() p=sc.get_player('00:04:20:17:5b:41') print("Current path = %s" % p.get_track_path()) with open('z.txt','w') as f: f.write("Current path = %s" % p.get_track_path()) p.playlist_play("file:///volume1/hdtl/Music/H3MusicArchive/Amazon%20MP3/Sam%20The%20Sham%20&%20The%20Pharaohs/20th%20Century%20Masters_%20The%20Millenium%20Collection_%20Best%20Of%20Sam%20The%20Sham%20&%20The%20Pharaohs/02%20-%20Lil%27%20Red%20Riding%20Hood.mp3")
# If not, see <https://creativecommons.org/licenses/by-sa/3.0/> from pylms.server import Server from pylms.player import Player import subprocess HOST = '192.168.1.30' PORT = 9090 USER = '' PW = '' SPI_DEV = '/dev/spidev0.1' SPI_ADR = '00' BW_TOOLS = '/home/pi/bw_rpi_tools/bw_spi/bw_lcd' PLAYER_ID = '00:04:20:26:97:a0' sc = Server(hostname=HOST, port=PORT, username=USER, password=PW) sc.connect() sq = sc.get_player(PLAYER_ID) title = sq.get_track_title()[0:20] artist = sq.get_track_artist()[0:20] def write_lcd(pos, content): subprocess.call(['sudo', BW_TOOLS, '-a', SPI_ADR, '-D', SPI_DEV, '-T', pos, content]) def clear_lcd(): subprocess.call(['sudo', BW_TOOLS, '-a', SPI_ADR, '-D', SPI_DEV, '-C']) clear_lcd() write_lcd('0,0', 'Title: ')
#!/usr/bin/env python from pylms.server import Server from pylms.player import Player sc = Server(hostname="192.168.16.2", port=9090) sc.connect() print "Logged in: %s" % sc.logged_in print "Version: %s" % sc.get_version() sq = sc.get_player("00:00:00:00:00:44") #print "Name: %s | Mode: %s | Time: %s | Connected: %s | WiFi: %s" % (sq.get_name(), sq.get_mode(), sq.get_time_elapsed(), sq.is_connected, sq.get_wifi_signal_strength()) #print sc.request("radios 0 100000") #print sq.request("local items 0 100000") #print sq.request("local playlist play item_id:7cec804f.15") print sq.request( "playlist play file:///E:/Public%20Shares/Music/Playlists/Test%20JD.m3u")
#!/usr/bin/env python3 import RPi.GPIO as GPIO import time from pylms.server import Server from pylms.player import Player sc = Server(hostname="192.168.2.109", port=9090, username="", password="") sc.connect() #print "Logged in: %s" % sc.logged_in #print "Version: %s" % sc.get_version() sq = sc.get_player("b8:27:eb:3c:1b:be") phatbeat.set_all(0,128,0,0.1) phatbeat.show() time.sleep(1) phatbeat.clear() phatbeat.show() GPIO.setmode(GPIO.BCM) GPIO.setup(5, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(6, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(13, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(26, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(12, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(16, GPIO.IN, pull_up_down=GPIO.PUD_UP) def myCallback(channel): if channel == 6:
class CommonNetLMS(object): def __init__(self, hostname="192.168.1.1", port=9090, username="******", password="******"): self.lms_device = Server(hostname=hostname, port=port, username=username, password=password) self.lms_device.connect() def com_net_lms_version(self): return self.lms_device.get_version() def com_net_lms_logged_in(self): return self.lms_device.logged_in def com_net_lms_close(self): self.lms_device.disconnect() def com_net_lms_play_count(self): return self.lms_device.get_player_count() def com_net_lms_get_players(self, update=True): return self.lms_device.get_players(update=update) def com_net_lms_connect(self): self.lms_device.login() def com_net_lms_request(self, command_string, preserve_encoding=False): self.lms_device.request( command_string, preserve_encoding=preserve_encoding) def com_net_lms_request_results(self, command_string, preserve_encoding=False): self.lms_device.request_with_results( command_string, preserve_encoding=preserve_encoding) def com_net_lms_rescan(self, mode='fast'): # ‘fast’ for update changes on library, ‘full’ for complete library scan # and ‘playlists’ for playlists scan only self.lms_device.rescan(mode=mode) def com_net_lms_rescanprogress(self): self.lms_device.rescanprogress() def com_net_lms_search(self, search_term, mode='albums'): self.lms_device.search(search_term, mode=mode) def com_net_lms_telnet_connect(self): self.lms_device.telnet_connect()
import sys reload(sys) sys.setdefaultencoding('utf-8') from pylms.server import Server from pylms.player import Player #def lmstest(): sc = Server(hostname="192.168.178.24", port=9090) sc.connect() print "Logged in: %s" % sc.logged_in print "Version: %s" % sc.get_version() from flask import Flask, render_template app = Flask(__name__) commands = ('play', 'pause', 'stop', 'volume_up', 'volume_down') def player_info_string(player): return "Name: %s | Mode: %s | Time: %s | Connected: %s | WiFi: %s" % (player.get_name(), player.get_mode(), player.get_time_elapsed(), player.is_connected, player.get_wifi_signal_strength()) @app.route('/') def hello_world(): return render_template('lmsflask.html', players=sc.get_players())
def main(argv): """LCD MANAGER APP FOR LMS""" lmsserver = "127.0.0.1" lmsplayer = "" lcd_address = "0x3f" lcd_w = 20 verbose = True clock_mode = False try: opts, args = getopt.getopt(argv,"hs:p:w:l:c",["server=","player=","lcd_width=","lcd_address=","clock"]) except getopt.GetoptError: printhelp() sys.exit(2) for opt, arg in opts: if opt == '-h': printhelp() sys.exit() elif opt in ("-s", "--server"): lmsserver = arg elif opt in ("-p", "--player"): lmsplayer = arg elif opt in("-w","--lcd_width"): lcd_w = int(arg) elif opt in("-l","--lcd_address"): lcd_address = arg elif opt in("-c","--clock"): clock_mode = True myLCD = LCD(int(lcd_address,16), lcd_w) #myLCD.lcd_string"1234567890123456",1) myLCD.lcd_string(" TVC Audio ",1) myLCD.lcd_string(" LMS LCD INFO ",2) sleep(2) myLCD.lcd_string("(C)2017 Renaud ",1) myLCD.lcd_string("Coustellier ",2) sleep(1) sc = Server(hostname=lmsserver, port=9090, username="******", password="******") # Server connection # Clock mode waiting connection connected = False while connected <> True: try: sc.connect() sleep(1) connected = True except Exception as e: LCDTime(myLCD, lcd_w) #myLCD.lcd_string(str(e),1) myLCD.lcd_string("LMS SERVER",1) myLCD.lcd_string("LMS v.: %s" % sc.get_version(),2) sleep(2) while sc.get_player_count() == 0: LCDTime(myLCD, lcd_w) sleep(2) if lmsplayer <> "": while True: LCDTime(myLCD, lcd_w) sq = playerAutodetect(sc, myLCD) ipPlayer = str(sq.get_ip_address()) ipPlayer = ipPlayer[0:ipPlayer.find(":")] if ipPlayer == lmsplayer: break sleep(3) else: myLCD.lcd_string("autodetect player",3) myLCD.lcd_string("in play mode",3) sq = playerAutodetect(sc, myLCD) playerName = sq.get_name() playerModel = sq.get_model() if lcd_w == 20: myLCD.lcd_string(playerName,3) myLCD.lcd_string(playerModel,4) sleep(2) if lcd_w == 16: # 16x2 LCD Code while True: try: modePlayer = sq.get_mode() if modePlayer == "pause": myLCD.lcd_string("mode = pause",1) myLCD.lcd_string(time.strftime('%Y-%m-%d %H:%M:%S'),2) sleep(2) elif modePlayer == "stop": LCDTime(myLCD, lcd_w) sleep(2) # when "stop", looking for a running player except if player defined by user... if lmsplayer == "": sq = playerAutodetect(sc, myLCD) elif modePlayer == "play": trackAlbum = sq.get_track_album() currentTrack = sq.get_track_current_title() trackArtist = sq.get_track_artist() currentVolume = sq.get_volume() print ("") print ("album:" + trackAlbum) print ("artist:" + trackArtist) print ("title:" + currentTrack) myLCD.lcd_string("Alb." + trackAlbum,1) myLCD.lcd_string("Art." + trackArtist,2) sleep(2) myLCD.lcd_string(trackAlbum,1) myLCD.lcd_string(trackArtist,2) td = "/" + lms_time_to_string(sq.get_track_duration()) ptc = str(sq.playlist_track_count()) linestatus = 0 charOffset = 0 while True: linestatus = linestatus + 1 volume = (" - Volume %" + str(sq.get_volume()) ) #te = "time " + lms_time_to_string(sq.get_time_elapsed()) te = lms_time_to_string(sq.get_time_elapsed()) te = te + td cti = str(sq.playlist_current_track_index()) if len(cti) > 1 and len(ptc) > 1: if linestatus % 4 == 0: te = te + " /" + ptc else: te = te + " " + cti + "/" else: te = te + " " + cti + "/" + ptc while currentVolume != sq.get_volume(): # Volume currentVolume = sq.get_volume() myLCD.lcd_string("Volume %" + str(currentVolume), 1) sleep(0.3) if linestatus < 2: myLCD.lcd_string("tle:" + currentTrack, 1) myLCD.lcd_string(te, 2) else: # Track Name if len(currentTrack) <= lcd_w: # LENGHT is < LCD LCD_WIDTH myLCD.lcd_string(currentTrack, 1) else: # LENGHT is > LCD_WIDTH charOffset = linestatus - 2 myLCD.lcd_string(currentTrack[charOffset:], 1) if linestatus + lcd_w > len(currentTrack): linestatus = 0 myLCD.lcd_string(te, 2) if sq.get_track_current_title() != currentTrack or sq.get_mode() !="play" : # change detected myLCD.lcd_string("Track/mode chang", 1) myLCD.lcd_string("pls wait... ", 2) linestatus = 0 break sleep(0.65) except: lcd(lcd_w) else: # 20x4 LCD Code while True: try: #if True == True: modePlayer = sq.get_mode() if modePlayer == "pause": myLCD.lcd_string(sq.get_name(),1) myLCD.lcd_string("Mode = Pause",2) line3 = "RJ45" ipPlayer = sq.get_ip_address() ipPlayer = ipPlayer[0:ipPlayer.find(":")] if int(sq.get_wifi_signal_strength()) > 1: line3 = "wifi" + str(sq.get_wifi_signal_strength()) line3 = line3 + " " + ipPlayer myLCD.lcd_string(line3,3) myLCD.lcd_string(time.strftime('%Y-%m-%d %H:%M:%S'),4) sleep(0.5) elif modePlayer == "stop": LCDTime(myLCD, lcd_w) sleep(2) if lmsplayer == "": # when player mode is stop, looking for another running player except if... sq = playerAutodetect(sc, myLCD) elif modePlayer == "play" and lmsplayer == "": trackAlbum = sq.get_track_album() currentTrack = sq.get_track_current_title() trackArtist = sq.get_track_artist() currentVolume = sq.get_volume() if verbose == True: print ("") print ("album:" + trackAlbum) print ("artist:" + trackArtist) print ("title:" + currentTrack) td = "/" + lms_time_to_string(sq.get_track_duration()) linestatus = 0 charOffset = 0 while True: if modePlayer <> "play": break linestatus = linestatus + 1 volume = (" - Volume %" + str(sq.get_volume()) ) te = lms_time_to_string(sq.get_time_elapsed()) te = te + td te = te + " " + str(sq.playlist_current_track_index()) + "/" + str(sq.playlist_track_count()) while currentVolume != sq.get_volume(): # Volume currentVolume = sq.get_volume() myLCD.lcd_string("Volume %" + str(currentVolume), 1) sleep(.25) if sq.get_track_current_title() != currentTrack or sq.get_mode() !="play" : # change detected myLCD.lcd_string("Track/mode chang", 1) #myLCD.lcd_string("pls wait... ", 2) break # Track Name myLCD.lcd_string(trackArtist, 1) myLCD.lcd_string(trackAlbum, 2) #---------------------------- if len(currentTrack) <= lcd_w: # LENGHT is < LCD LCD_WIDTH myLCD.lcd_string(currentTrack, 3) else: # LENGHT is > LCD_WIDTH charOffset = linestatus - 1 myLCD.lcd_string(currentTrack[charOffset:], 3) if linestatus + lcd_w > len(currentTrack): linestatus = 0 #myLCD.lcd_string(currentTrack, 3) if clock_mode != True: myLCD.lcd_string(te, 4) sleep(0.5) else: myLCD.lcd_string(time.strftime('%Y-%m-%d %H:%M:%S'),4) sleep(0.5) except: #Exception as e: #else: #myLCD.lcd_string(str(e), 3) sq = playerAutodetect(sc, myLCD) sleep(2)
# If not, see <https://creativecommons.org/licenses/by-sa/3.0/> from pylms.server import Server from pylms.player import Player import subprocess HOST = '192.168.1.30' PORT = 9090 USER = '' PW = '' SPI_DEV = '/dev/spidev0.1' SPI_ADR = '00' BW_TOOLS = '/home/pi/bw_rpi_tools/bw_spi/bw_lcd' PLAYER_ID = '00:04:20:26:97:a0' sc = Server(hostname=HOST, port=PORT, username=USER, password=PW) sc.connect() sq = sc.get_player(PLAYER_ID) title = sq.get_track_title()[0:20] artist = sq.get_track_artist()[0:20] def write_lcd(pos, content): subprocess.call( ['sudo', BW_TOOLS, '-a', SPI_ADR, '-D', SPI_DEV, '-T', pos, content]) def clear_lcd(): subprocess.call(['sudo', BW_TOOLS, '-a', SPI_ADR, '-D', SPI_DEV, '-C'])
os.chdir(os.path.dirname(os.path.realpath(__file__))) os.system("python buttonWatch.py &") ########################### 16 x 2 display ############################ # set up the 16x2 display - 4 bit to save pins - apparently slower but marginal # https://projects.drogon.net/raspberry-pi/wiringpi/lcd-library/ wp.wiringPiSetup(); lcd = wp.lcdInit (2, 16, 4, 11,10 , 0,1,2,3,0,0,0,0) wp.lcdClear(lcd) # clear the lcd wp.lcdPosition(lcd, 0, 0) # cursor to start of row ################################# LMS ################################ # connect to the LMS sc = Server(hostname=getExternalIP("eth0"), port=RPizeBox.scPort, username=RPizeBox.scUser, password=RPizeBox.scPassword) # log in to the LMS server - can't do much until that has happened. while RPizeBox.loggedin != True: try: sc.connect() #throws ugly error if LMS not there RPizeBox.loggedin = sc.logged_in logging.debug('Success: Logged in to LMS.') except: logging.debug('LMS not there. Trying again in %i seconds.' % RPizeBox.logInWait) wp.lcdPosition(lcd, 0, 0) wp.lcdPuts(lcd,welcomeMessage[0][:16]) wp.lcdPosition(lcd, 0, 1) wp.lcdPuts(lcd,welcomeMessage[1][:16]) time.sleep(RPizeBox.logInWait)
def connect_server(self, server_config): """Connect to a Logitech Media server.""" self.server = Server(hostname=server_config.hostname, port=server_config.port, username=server_config.username, password=server_config.password) self.server.connect()
from PIL import Image, ImageDraw from time import sleep from rotary_class import RotaryEncoder from pylms.server import Server from pylms.player import Player import textwrap #sc = Server(hostname="192.168.0.211", port=9090, username="******", password="******") # CHANGE the following to your LMS IP Address: hostIP, player_id hostIP = '192.168.0.211' # Change to the IP Address of your Logitech Media Server (LMS) - check your router # insert miniz player MAC address here from LMS/Settings/Information player_id = 'b8:27:eb:93:bb:81' sc = Server(hostname=hostIP, port=9090) # used for volume and play/pause scNP = Server(hostname=hostIP, port=9090) # used only to get Now Playing cover.jpg sleep(60) # allow time for LMS to start, otherwise get ConnectionError 111 sc.connect() scNP.connect() sq = sc.get_player(player_id) sqNP = scNP.get_player( player_id ) # UGLY KLUDGE! Avoids conflict with volume routine which caused bad refresh on album cover.jpg DISPLAY = pi3d.Display.create(use_pygame=True, samples=4) DISPLAY.set_background(0, 0, 0, 1) #r,g,b and alpha shader = pi3d.Shader("uv_flat")
def get_squeeze_player(server, player): print 'Connecting to server[%s] player[%s]' % (server, player) sc = Server(hostname=server, port=9090) sc.connect() return sc.get_player(player)
def __init__(self, hostname="192.168.1.1", port=9090, username="******", password="******"): self.lms_device = Server(hostname=hostname, port=port, username=username, password=password) self.lms_device.connect()
sys.exit(-1) else: setattr(namespace, self.dest, values) agi = AGI() parser = argparse.ArgumentParser(description='Process LMS commands.') parser.add_argument('player', type=str, nargs=1, help="MAC adress of player", action=VerifyMacaddressAction) parser.add_argument('command', type=str, nargs=1, default="mode", choices=['mode', 'start', 'stop', 'toggle', 'pause', 'unpause'], help='Command to execute on LMS player') args = parser.parse_args() sc = Server(hostname="lms.wi.kettenbach-it.de", port=9090) sc.connect() sq = sc.get_player(args.player[0]) # type: Player if sq is None: sys.stderr.write("Player not found") sys.exit(-1) if args.command[0] == "mode": # agi.set_variable("LMSSTATUS", str(sq.get_mode())) # agi_set_varaible is broken: https://github.com/rdegges/pyst2/issues/19 print("SET VARIABLE LMSSTATUS " + sq.get_mode()) if args.command[0] == "stop": sq.stop()
print u"\u03A9" # get the secret key f = open('/Users/mgeraci/Web/Now-Playing/secretkey.txt', 'r') secret = f.readline().strip() # set the domain (pass test in as an arg to get localhost) domain = "now-playing.meteor.com" if len(sys.argv[1:]) > 0: if sys.argv[1:][0] == 'test': domain = "127.0.0.1:3000" # connect to the squeezebox sc = Server(hostname="192.168.1.111", port=9090) sc.connect() sq = sc.get_player("00:04:20:07:98:43") print "Logged in: %s" % sc.logged_in print "Version: %s" % sc.get_version() if sq.get_mode() == 'play': artist = sq.get_track_artist() album = sq.get_track_album() title = sq.get_track_title() print "%s - %s - %s" % (artist, album, title) print "" params = urllib.urlencode({'artist': artist, 'album': album, 'title': title, 'secret': secret})
class SqueezePlayer: ############################################################################## #constructor - connect to the server and player so we can do stuff #other handy start up stuff def __init__(self, basicOnly=False): #optionally pass in a player MAC here to connect to a different player for the info display #if MAC is not None: # log("Using MAC " + MAC) # PLAYERMAC = MAC #serverIP still null, something went wrong... if SERVERIP == "": notify("Can't find LMS server", "Try manually configuring one in XSqueeze settings") sys.exit() log("Attempting to connect to LMS named [" + SERVERNAME + "] at IP: " + SERVERIP + " on CLI port: " + SERVERPORT) try: self.sc = Server(hostname=SERVERIP, port=SERVERPORT, username=SERVERUSER, password=SERVERPASS) self.sc.connect() log("LMS Logged in: %s" % self.sc.logged_in) log("LMS Version: %s" % self.sc.get_version()) except: log(" Couldn't connect to server!") notify(LANGUAGE(19613), LANGUAGE(19614)) raise #connect to player log("Attempting to connect to player: " + PLAYERMAC) try: self.sb = self.sc.get_player(PLAYERMAC) if self.sb: log("Connected to: %s" % PLAYERMAC) state = self.sb.get_power_state() log("Power state is: " + str(state)) else: log("Player is None! %s" % PLAYERMAC) raise Exception except Exception as inst: log(" Couldn't connect to player: " + PLAYERMAC, inst) notify(LANGUAGE(19615), LANGUAGE(19616)) raise #initialise if we're called from XSqueeze as opposed to the chooser try: if not basicOnly: self.currentTrack = None self.coverURLs = None self.playlistDetails = None self.updatePlaylistDetails() self.updateCoverArtURLs() #if the user wants music to start straight away... if SENDPLAYONSTART: self.sb.request("play") except Exception as inst: log( " Error in initialisation of XSqueeze after connection to: " + PLAYERMAC, inst) raise ############################################################################## #get the current squeezebox two line display text and return it def getDisplay(self): displayText = self.sb.requestRaw("display ? ?", True) lines = displayText.split(" ") try: if lines[2] == "": lines[2] = "." except: lines[2] = "." try: if lines[3] == "": lines[3] = "." except: lines[3] = "." cleanedLines = [] cleanedLines.append((lines[2])) cleanedLines.append((lines[3])) #print(cleanedLines) #clean out the wierd characters used to represent volume... newLines = [] for line in cleanedLines: line = line.replace(u'cursorpos', u"\u2334") line = line.replace(u'rightarrow', u"\u2192") line = line.replace(u'solidblock', u'*') line = line.replace(u'leftprogress4', u'*') line = line.replace(u'leftprogress2', u'*') line = line.replace(u'leftprogress0', u'(Mute)') line = line.replace(u'rightprogress0', u' ') line = line.replace(u'rightprogress4', u'(Max)') line = line.replace(u'middleprogress0', u' ') line = line.replace(u'%1E', u"") line = line.replace(u'%1F', u"") newLines.append(line) #print(newLines) return unquoteUni(newLines[0]), unquoteUni(newLines[1]) ############################################################################## # check if song changed and update local reference if so # returns boolean - but of course only once on each change # called every window update to see if the song has changed and only if it has # do we update the playlist and cover arts...reduces traffic a lot! def songChanged(self): oldSong = self.currentTrack newSong = self.sb.get_track_title() #log("New Song [" + newSong +"], Old song [" + oldSong + "]") if newSong != oldSong: log("### Detected song change to: " + repr(newSong) + " - triggering playlist and cover art updates...") self.currentTrack = newSong self.updatePlaylistDetails() self.updateCoverArtURLs() return True else: return False ############################################################################## # returns the URLs for the current and next three track cover art images def updateCoverArtURLs(self): coverURLs = [] #print "Playlist is" + str(self.playlist) #start at this song , end at + 3 index = int(self.sb.request("playlist index ?")) upcomer = index end = index + 4 #currently uses the track_id in the url - works well #supposed to use the cover_id number but this doesn't work so well... for count in range(upcomer, end): if (count < len(self.playlist)): try: statusInfo = self.sb.request("status " + str(count) + " 1 tags:Kal") #log("Status info is " + str(statusInfo)) if ("artwork_url" in statusInfo): statusArtwork = statusInfo.split('artwork_url:') statusArtwork = statusArtwork.pop(1) statusArtwork = statusArtwork.split(' ') statusArtwork = statusArtwork.pop(0) #log("statusArtwork is " + str(statusArtwork)) #check we have a full url.... if ("http" not in statusArtwork): coverURL = "http://" + SERVERHTTPURL + "/" + statusArtwork else: coverURL = statusArtwork else: statusId = statusInfo.split('id:') statusId = statusId.pop(1) statusId = statusId.split(' ') statusId = statusId.pop(0) #log("StatusID is " + str(statusId)) coverURL = "http://" + SERVERHTTPURL + "/music/" + str( statusId) + "/cover.jpg" #now append the coverURL to our list of URLs #log ("Appending future cover: " + str(count) + " from " + coverURL) coverURLs.append(coverURL) #Something went wrong, go with null string just to be safe... except Exception as inst: log( "No cover art so appending null string for playlist index " + str(count), inst) coverURLs.append("") self.coverURLs = coverURLs ## ############################################################################## ## # Gets more info about a particular song def getSongInfo(self, id): encoded = self.sb.requestRaw("songinfo 0 1000 track_id:" + str(id), True) #find the index of id: - track_id%3A start = encoded.find('track_id%3A') encoded = encoded[start:] #print(str(id) + " Encoded: " +str(encoded)) list = encoded.split(" ") #print("list: " + str(list)) decodedList = [] for item in list: cleanItem = unquoteUni(item) decodedList.append(cleanItem) #print("DecodedList: " +str(decodedList)) item = {} for info in decodedList: info = info.split(':') key = info.pop(0) if key: item[key] = ':'.join(info) # example... # 9 id:39 title:I'm Not The Man artist:10000 Maniacs coverid:94339a48 duration:226.36 album_id:4 filesize:22796274 genre:Pop coverart:1 artwork_track_id:94339a48 # album:MTV Unplugged modificationTime:Thursday, November 27, 2008, 5:24 PM type:flc genre_id:4 bitrate:805kbps VBR artist_id:11 tracknum:4 year:1993 compilation:0 # addedTime:Thursday, December 8, 2011, 11:15 PM channels:2 samplesize:16 samplerate:44100 lastUpdated:Thursday, December 8, 2011, 11:15 PM album_replay_gain:-6.46 replay_gain:-3.46 #print "Item" + str(item) #convert all the data to the right types - there is a much more pythomnesque way to right this I am sure... try: item['id'] = int(item['id']) except KeyError: pass try: item['duration'] = float(item['duration']) except KeyError: pass try: item['album_id'] = int(item['album_id']) except KeyError: pass try: item['filesize'] = int(item['filesize']) except KeyError: pass try: item['coverart'] = int(item['coverart']) except KeyError: pass try: item['genre_id'] = int(item['genre_id']) except KeyError: pass try: item['artist_id'] = int(item['artist_id']) except KeyError: pass try: item['tracknum'] = int(item['tracknum']) except KeyError: pass try: item['year'] = int(item['year']) except KeyError: pass try: item['compilation'] = int(item['compilation']) except KeyError: pass try: item['channels'] = int(item['channels']) except KeyError: pass try: item['samplesize'] = int(item['samplesize']) except KeyError: pass try: item['samplerate'] = int(item['samplerate']) except KeyError: pass try: item['album_replay_gain'] = float(item['album_replay_gain']) except KeyError: pass try: item['replay_gain'] = float(item['replay_gain']) except KeyError: pass return item ############################################################################## # Send a button command text, e.g. 'pause' - to the player def button(self, text): self.sb.ir_button(text) #something probably changed, trigger an update test self.songChanged() ############################################################################## # returns all the details of up to 10 tracks... def updatePlaylistDetails(self): self.playlist = self.sb.playlist_get_info() currentIndex = int(self.sb.request("playlist index ?")) #log ("Current index: " + str(currentIndex) + " len(playlist): " + str(len(self.playlist)) + " Playlist is: " + str(self.playlist)) playlistDetails = [] #retrieve a maxiumum of 10 tracks details for trackOffset in range(currentIndex, currentIndex + 10): #don't go off the end of the playlist if trackOffset < len(self.playlist): trackID = self.playlist[trackOffset]['id'] #log("Getting full details for id: " + str(trackID)) playlistDetails.append(self.getSongInfo(trackID)) #the caller should check the length of the playlist and process all entries... self.playlistDetails = playlistDetails ############################################################################## # returns current track length if available (check for 0 etc. at other end) def getTrackLength(self): return self.sb.get_track_duration() ############################################################################## # Show some text on the player's screen def show(self, line1="", line2="" '' "", duration=3, brightness=4, font="standard", centered=False): self.sb.show(line1, line2, duration, brightness, font, centered) def display(self, line1="", line2="", duration=1): self.sb.request("display " + line1 + " " + line2 + " " + str(duration)) ############################################################################## # returns current mode ('play' 'pause' or 'stop') def getMode(self): return self.sb.get_mode() ############################################################################## # returns length of time in seconds the current track has played for def getTrackElapsed(self): return self.sb.get_time_elapsed() ############################################################################## # returns the full album info given an ID def getAlbumInfo(self, albumID): fullAlbumInfo = self.sc.request_with_results('albums 0 1 album_id:' + albumID + ' tags:yajl') #log("Full Album Info: " + str(fullAlbumInfo)) return fullAlbumInfo[1][0] ############################################################################## # returns the latest 50 albums def getNewMusic(self): fullAlbums = [] albums = self.sc.request_with_results("albums 0 50 sort:new") for album in albums[1]: fullAlbumInfo = self.getAlbumInfo(album['id']) fullAlbums.append(fullAlbumInfo) return fullAlbums ############################################################################## # returns all albums def getAlbums(self): fullAlbums = [] albums = self.sc.request_with_results("albums 0 100000") for album in albums[1]: fullAlbumInfo = self.getAlbumInfo(album['id']) fullAlbums.append(fullAlbumInfo) return fullAlbums ############################################################################## # returns all artists def getArtists(self): artists = self.sc.request_with_results("artists 0 100000") #log(str(artists)) return artists[1] ############################################################################## # returns all albums by a particular artist given an artist_id def getAlbumsByArtistID(self, artistID): fullAlbums = [] albums = self.sc.request_with_results("albums 0 100000 artist_id:" + str(artistID)) #log(str(albums)) for album in albums[1]: fullAlbumInfo = self.getAlbumInfo(album['id']) fullAlbums.append(fullAlbumInfo) return fullAlbums ############################################################################## # returns all albums in a particular genre given a genre_id def getAlbumsByGenreID(self, genreID): fullAlbums = [] albums = self.sc.request_with_results("albums 0 100000 genre_id:" + str(genreID)) #log(str(albums)) for album in albums[1]: fullAlbumInfo = self.getAlbumInfo(album['id']) fullAlbums.append(fullAlbumInfo) return fullAlbums ############################################################################## # returns all albums for a given year def getAlbumsByYear(self, year): fullAlbums = [] albums = self.sc.request_with_results("albums 0 100000 year:" + str(year)) #log(str(albums)) for album in albums[1]: fullAlbumInfo = self.getAlbumInfo(album['id']) fullAlbums.append(fullAlbumInfo) return fullAlbums ############################################################################## # returns all genres def getGenres(self): genres = self.sc.request_with_results("genres 0 100000") log(str(genres)) return genres[1][1:] ############################################################################## # returns all years def getYears(self): years = self.parseSpecial("years 0 100000", "year", True) #log(str(years)) years.reverse() return years ############################################################################## # returns radios root menu def parseSpecial(self, cmdString, splitOn, playerRequest=False): quotedColon = urllib.quote(':') if playerRequest: log("Player Request: " + str(cmdString)) results = self.sb.requestRaw(cmdString) else: log("Server Request: " + str(cmdString)) results = self.sc.requestRaw(cmdString) log("Result string: " + pprint.pformat(results)) #strip off the request stuff at the start resultStr = results[results.find(splitOn):] log("Split string: " + pprint.pformat(resultStr)) #ok now split the string on 'splitOn' to get each radio station chunks = resultStr.split(splitOn + "%3A")[1:] log("Processed Chunks: " + pprint.pformat(chunks)) output = [] for chunk in chunks: chunk = chunk.strip() subResults = chunk.split(" ") #log("SUB: " + str(subResults)) #fix missing splitOn post split subResults[0] = splitOn + "%3A" + subResults[0] #log("SUB + splitOn: " + str(subResults)) item = {} for subResult in subResults: #save item key, value = subResult.split(quotedColon, 1) item[unquoteUni(key)] = unquoteUni(value) output.append(item) return output def getRadios(self): return self.parseSpecial("radios 0 100000", "icon", playerRequest=True) def getRadioStations(self, cmd, itemid): if (itemid) != "" and itemid is not None: return self.parseSpecial(urllib.quote(cmd) + " items 0 100000 item_id:" + itemid, "id", playerRequest=True) else: return self.parseSpecial(urllib.quote(cmd) + " items 0 100000", "id", playerRequest=True) def getAppItemsList(self, cmd, itemid): if (itemid) != "" and itemid is not None: return self.parseSpecial(urllib.quote(cmd) + " items 0 100000 item_id:" + itemid, "id", playerRequest=True) else: return self.parseSpecial(urllib.quote(cmd) + " items 0 100000", "id", playerRequest=True) def getFavouritesSub(self, itemid): return self.parseSpecial("favorites items 0 100000 item_id:" + itemid, "id", playerRequest=True) def queueRadio(self, cmd, itemid): self.sb.request(urllib.quote(cmd) + " playlist play item_id:" + itemid) def getApps(self): return self.parseSpecial("apps 0 100000", "cmd", playerRequest=True) def getFavourites(self): return self.parseSpecial("favorites items 0 100000", "id", playerRequest=True) def getPlaylists(self): #return self.parseSpecial("playlists 0 100000","id", playerRequest=True) pls = self.sc.request_with_results("playlists 0 100000 tags:u") log(str(pls)) return pls[1][1:] ############################################################################## # Clear playlist and queue up a favourite item given def queueFavourite(self, item_id): self.sb.request("favorites playlist play item_id:" + item_id) ############################################################################## # Clear playlist and queue up a playlist item given def queuePlaylist(self, item_id, url): self.sb.request("playlist play " + url) ############################################################################## # Clear playlist and queue up an album given an album title and artist def queueAlbum(self, title, artist): if artist == "Various Artists": self.sb.request("playlist loadalbum * * " + urllib.quote(title)) else: self.sb.request("playlist loadalbum * " + urllib.quote(artist) + " " + urllib.quote(title)) ############################################################################## # Clear playlist and queue up random albums def playRandomAlbums(self): self.sb.request("randomplay albums") ############################################################################## # Clear playlist and queue up random songs def playRandomTracks(self): self.sb.request("randomplay tracks") ############################################################################## # Clear playlist and queue up random songs def getShuffle(self): state = int(self.sb.request("playlist shuffle ?")) if state == 0: return False else: return True def setShuffle(self): state = int(self.sb.request("playlist shuffle ?")) if state == 0: state = 1 notify("Shuffle Playlist: ON", "") else: state = 0 notify("Shuffle Playlist: OFF", "") self.sb.request("playlist shuffle " + str(state), debug=True) self.updatePlaylistDetails() def getRepeat(self): state = int(self.sb.request("playlist repeat ?")) if state == 0: return False else: return True def setRepeat(self): state = int(self.sb.request("playlist repeat ?")) if state == 0: state = 2 notify("Repeat Playlist: ON") else: state = 0 notify("Repeat Playlist: OFF") self.sb.request("playlist repeat " + str(state), debug=True) def rewind(self): self.sb.rewind() def forward(self): self.sb.forward() def getVolume(self): return self.sb.get_volume() def getPowerState(self): return self.sb.get_power_state()
def __init__(self, basicOnly=False): #optionally pass in a player MAC here to connect to a different player for the info display #if MAC is not None: # log("Using MAC " + MAC) # PLAYERMAC = MAC #serverIP still null, something went wrong... if SERVERIP == "": notify("Can't find LMS server", "Try manually configuring one in XSqueeze settings") sys.exit() log("Attempting to connect to LMS named [" + SERVERNAME + "] at IP: " + SERVERIP + " on CLI port: " + SERVERPORT) try: self.sc = Server(hostname=SERVERIP, port=SERVERPORT, username=SERVERUSER, password=SERVERPASS) self.sc.connect() log("LMS Logged in: %s" % self.sc.logged_in) log("LMS Version: %s" % self.sc.get_version()) except: log(" Couldn't connect to server!") notify(LANGUAGE(19613), LANGUAGE(19614)) raise #connect to player log("Attempting to connect to player: " + PLAYERMAC) try: self.sb = self.sc.get_player(PLAYERMAC) if self.sb: log("Connected to: %s" % PLAYERMAC) state = self.sb.get_power_state() log("Power state is: " + str(state)) else: log("Player is None! %s" % PLAYERMAC) raise Exception except Exception as inst: log(" Couldn't connect to player: " + PLAYERMAC, inst) notify(LANGUAGE(19615), LANGUAGE(19616)) raise #initialise if we're called from XSqueeze as opposed to the chooser try: if not basicOnly: self.currentTrack = None self.coverURLs = None self.playlistDetails = None self.updatePlaylistDetails() self.updateCoverArtURLs() #if the user wants music to start straight away... if SENDPLAYONSTART: self.sb.request("play") except Exception as inst: log( " Error in initialisation of XSqueeze after connection to: " + PLAYERMAC, inst) raise