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"
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
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 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()
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}) conn = httplib.HTTPConnection(domain) url = "/add_song?%s" % (params) print "posting..." conn.request('GET', url)
#!/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")
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 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)
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()